diff --git a/apps/ecash-herald/index.js b/apps/ecash-herald/index.js
--- a/apps/ecash-herald/index.js
+++ b/apps/ecash-herald/index.js
@@ -4,9 +4,9 @@
 
 'use strict';
 const config = require('./config');
-const { ChronikClientNode } = require('chronik-client');
+const { ChronikClient } = require('chronik-client');
 // Initialize chronik on app startup
-const chronik = new ChronikClientNode(config.chronik);
+const chronik = new ChronikClient(config.chronik);
 // Initialize telegram bot on app startup
 const secrets = require('./secrets');
 const TelegramBot = require('node-telegram-bot-api');
diff --git a/apps/ecash-herald/scripts/generateMock.js b/apps/ecash-herald/scripts/generateMock.js
--- a/apps/ecash-herald/scripts/generateMock.js
+++ b/apps/ecash-herald/scripts/generateMock.js
@@ -5,8 +5,8 @@
 const config = require('../config');
 const fs = require('fs');
 const path = require('path');
-const { ChronikClientNode } = require('chronik-client');
-const chronik = new ChronikClientNode(config.chronik);
+const { ChronikClient } = require('chronik-client');
+const chronik = new ChronikClient(config.chronik);
 const { MockChronikClient } = require('../../../modules/mock-chronik-client');
 const mockedChronik = new MockChronikClient();
 const { jsonReplacer, getCoingeckoApiUrl } = require('../src/utils');
diff --git a/apps/ecash-herald/scripts/sendMsgByBlock.js b/apps/ecash-herald/scripts/sendMsgByBlock.js
--- a/apps/ecash-herald/scripts/sendMsgByBlock.js
+++ b/apps/ecash-herald/scripts/sendMsgByBlock.js
@@ -48,8 +48,8 @@
 
 // Initialize chronik
 const config = require('../config');
-const { ChronikClientNode } = require('chronik-client');
-const chronik = new ChronikClientNode(config.chronik);
+const { ChronikClient } = require('chronik-client');
+const chronik = new ChronikClient(config.chronik);
 
 // Initialize telegram bot to send msgs to dev channel
 const secrets = require('../secrets');
diff --git a/apps/ecash-herald/src/chronik.js b/apps/ecash-herald/src/chronik.js
--- a/apps/ecash-herald/src/chronik.js
+++ b/apps/ecash-herald/src/chronik.js
@@ -124,7 +124,7 @@
     /**
      * Get all txs in a block
      * Txs are paginated so this may require more than one API call
-     * @param {ChronikClientNode} chronik
+     * @param {ChronikClient} chronik
      * @param {number} blockHeight
      * @throws {err} on chronik error
      * @returns {Tx_InNode[]}
diff --git a/apps/ecash-herald/src/events.js b/apps/ecash-herald/src/events.js
--- a/apps/ecash-herald/src/events.js
+++ b/apps/ecash-herald/src/events.js
@@ -16,7 +16,7 @@
     /**
      * Callback function for a new finalized block on the eCash blockchain
      * Summarize on-chain activity in this block
-     * @param {ChronikClientNode} chronik
+     * @param {ChronikClient} chronik
      * @param {object} telegramBot A connected telegramBot instance
      * @param {number} channelId The channel ID where the telegram msg(s) will be sent
      * @param {number} height blockheight
diff --git a/apps/token-server/index.ts b/apps/token-server/index.ts
--- a/apps/token-server/index.ts
+++ b/apps/token-server/index.ts
@@ -6,13 +6,13 @@
 import secrets from './secrets';
 import 'dotenv/config';
 import { startExpressServer } from './src/routes';
-import { ChronikClientNode } from 'chronik-client';
+import { ChronikClient } from 'chronik-client';
 import { initializeTelegramBot } from './src/telegram';
 import fs from 'fs';
 import { Ecc, initWasm } from 'ecash-lib';
 
 // Connect to available in-node chronik servers
-const chronik = new ChronikClientNode(config.chronikUrls);
+const chronik = new ChronikClient(config.chronikUrls);
 
 // Initialize websocket connection and log incoming blocks
 initWasm().then(
diff --git a/apps/token-server/scripts/getHistoryAfterTimestamp.ts b/apps/token-server/scripts/getHistoryAfterTimestamp.ts
--- a/apps/token-server/scripts/getHistoryAfterTimestamp.ts
+++ b/apps/token-server/scripts/getHistoryAfterTimestamp.ts
@@ -16,12 +16,12 @@
  */
 
 import config from '../config';
-import { ChronikClientNode } from 'chronik-client';
+import { ChronikClient } from 'chronik-client';
 import { getHistoryAfterTimestamp } from '../src/chronik/clientHandler';
 import { getTxTimestamp } from '../src/chronik/parse';
 
 // Initialize new in-node chronik connection
-const chronik = new ChronikClientNode(config.chronikUrls);
+const chronik = new ChronikClient(config.chronikUrls);
 
 // Get input from bash or use defaults
 const address =
diff --git a/apps/token-server/scripts/getWallet.ts b/apps/token-server/scripts/getWallet.ts
--- a/apps/token-server/scripts/getWallet.ts
+++ b/apps/token-server/scripts/getWallet.ts
@@ -14,12 +14,12 @@
  */
 
 import config from '../config';
-import { ChronikClientNode } from 'chronik-client';
+import { ChronikClient } from 'chronik-client';
 import * as bip39 from 'bip39';
 import { ServerWallet, getWalletFromSeed, syncWallet } from '../src/wallet';
 
 // Initialize new in-node chronik connection
-const chronik = new ChronikClientNode(config.chronikUrls);
+const chronik = new ChronikClient(config.chronikUrls);
 
 // Get input from bash or use defaults
 const mnemonic =
@@ -37,7 +37,7 @@
  * @param mnemonic
  */
 async function getWallet(
-    chronik: ChronikClientNode,
+    chronik: ChronikClient,
     mnemonic?: string,
 ): Promise<WalletReturn> {
     const makingNewWallet = typeof mnemonic === 'undefined';
diff --git a/apps/token-server/src/chronik/clientHandler.ts b/apps/token-server/src/chronik/clientHandler.ts
--- a/apps/token-server/src/chronik/clientHandler.ts
+++ b/apps/token-server/src/chronik/clientHandler.ts
@@ -2,11 +2,7 @@
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
-import {
-    ChronikClientNode,
-    TxHistoryPage_InNode,
-    Tx_InNode,
-} from 'chronik-client';
+import { ChronikClient, TxHistoryPage, Tx } from 'chronik-client';
 import { getTxTimestamp } from './parse';
 
 /**
@@ -15,18 +11,18 @@
  */
 
 /**
- * @param chronik initialized ChronikClientNode
+ * @param chronik initialized ChronikClient
  * @param address a valid ecash address
  * @param timestamp timestamp in seconds.
  * We only return txs with timestamp >= this value, i.e. txs that were broadcast after timestamp
  * @param pageSize txs per page, chronik defaults to 25
  */
 export async function getHistoryAfterTimestamp(
-    chronik: ChronikClientNode,
+    chronik: ChronikClient,
     address: string,
     timestamp: number,
     pageSize = 25,
-): Promise<Tx_InNode[]> {
+): Promise<Tx[]> {
     // The history endpoint is called with (pageNumber, pageSize), where 0 is the first page
     const firstPageHistory = await getTxHistoryPage(
         chronik,
@@ -81,10 +77,10 @@
  * @returns
  */
 async function getTxHistoryPage(
-    chronik: ChronikClientNode,
+    chronik: ChronikClient,
     address: string,
     pageNumber: number,
     pageSize = 25,
-): Promise<TxHistoryPage_InNode> {
+): Promise<TxHistoryPage> {
     return await chronik.address(address).history(pageNumber, pageSize);
 }
diff --git a/apps/token-server/src/chronik/parse.ts b/apps/token-server/src/chronik/parse.ts
--- a/apps/token-server/src/chronik/parse.ts
+++ b/apps/token-server/src/chronik/parse.ts
@@ -2,12 +2,12 @@
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
-import { Tx_InNode } from 'chronik-client';
+import { Tx } from 'chronik-client';
 import cashaddr from 'ecashaddrjs';
 
 /**
  * parse.ts
- * Parse data returned by ChronikClientNode for token-server purposes
+ * Parse data returned by ChronikClient for token-server purposes
  */
 
 /**
@@ -20,10 +20,10 @@
  * @param outputScript outputScript we are checking
  */
 export function hasInputsFromOutputScript(
-    tx: Tx_InNode,
+    tx: Tx,
     outputScript: string,
 ): boolean {
-    const { inputs } = tx; // TxInput_InNode[]
+    const { inputs } = tx; // TxInput[]
     for (const input of inputs) {
         if (input.outputScript === outputScript) {
             return true;
@@ -39,11 +39,11 @@
  * @param tokenId
  */
 export function addressReceivedToken(
-    tx: Tx_InNode,
+    tx: Tx,
     address: string,
     tokenId: string,
 ): boolean {
-    // Tx_InNode outputs have outputScript as a key, not address
+    // Tx outputs have outputScript as a key, not address
     const outputScript = cashaddr.getOutputScriptFromAddress(address);
 
     const { outputs } = tx;
@@ -74,7 +74,7 @@
  * @param tx
  * @returns timestamp (seconds)
  */
-export function getTxTimestamp(tx: Tx_InNode): number {
+export function getTxTimestamp(tx: Tx): number {
     const { timeFirstSeen } = tx;
 
     if (timeFirstSeen !== 0) {
diff --git a/apps/token-server/src/chronik/wsHandler.ts b/apps/token-server/src/chronik/wsHandler.ts
--- a/apps/token-server/src/chronik/wsHandler.ts
+++ b/apps/token-server/src/chronik/wsHandler.ts
@@ -2,15 +2,11 @@
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
-import {
-    ChronikClientNode,
-    WsEndpoint_InNode,
-    WsMsgClient,
-} from 'chronik-client';
+import { ChronikClient, WsEndpoint, WsMsgClient } from 'chronik-client';
 
 /**
  * wsHandler.ts
- * Methods to work with the ChronikClientNode websocket connection
+ * Methods to work with the ChronikClient websocket connection
  */
 
 /**
@@ -19,9 +15,9 @@
  * @returns {object} connected websocket
  */
 export const initializeWebsocket = async (
-    chronik: ChronikClientNode,
-): Promise<WsEndpoint_InNode> => {
-    const ws: WsEndpoint_InNode = chronik.ws({
+    chronik: ChronikClient,
+): Promise<WsEndpoint> => {
+    const ws: WsEndpoint = chronik.ws({
         onMessage: msg => {
             handleWsMsg(msg);
         },
@@ -35,6 +31,6 @@
 
 /**
  * Handle msgs received from the websocket
- * @param {object} msg type WsMsgClient from ChronikClientNode
+ * @param {object} msg type WsMsgClient from ChronikClient
  */
 export const handleWsMsg = (msg: WsMsgClient) => {};
diff --git a/apps/token-server/src/rewards.ts b/apps/token-server/src/rewards.ts
--- a/apps/token-server/src/rewards.ts
+++ b/apps/token-server/src/rewards.ts
@@ -2,7 +2,7 @@
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
-import { Tx_InNode } from 'chronik-client';
+import { Tx } from 'chronik-client';
 import {
     hasInputsFromOutputScript,
     addressReceivedToken,
@@ -32,7 +32,7 @@
     address: string,
     tokenId: string,
     tokenServerOutputScript: string,
-    historySinceEligibilityTimestamp: Tx_InNode[],
+    historySinceEligibilityTimestamp: Tx[],
 ): boolean | number {
     // If there is no tx history, the checkedOutputScript is eligible
     if (historySinceEligibilityTimestamp.length === 0) {
diff --git a/apps/token-server/src/routes.ts b/apps/token-server/src/routes.ts
--- a/apps/token-server/src/routes.ts
+++ b/apps/token-server/src/routes.ts
@@ -13,7 +13,7 @@
 import { getHistoryAfterTimestamp } from './chronik/clientHandler';
 import { isAddressEligibleForTokenReward } from './rewards';
 import { sendReward } from './transactions';
-import { ChronikClientNode } from 'chronik-client';
+import { ChronikClient } from 'chronik-client';
 import { isTokenImageRequest } from './validation';
 import makeBlockie from 'ethereum-blockies-base64';
 import TelegramBot from 'node-telegram-bot-api';
@@ -60,7 +60,7 @@
 
 export const startExpressServer = (
     port: Number,
-    chronik: ChronikClientNode,
+    chronik: ChronikClient,
     telegramBot: TelegramBot,
     fs: any,
     ecc: Ecc,
diff --git a/apps/token-server/src/transactions.ts b/apps/token-server/src/transactions.ts
--- a/apps/token-server/src/transactions.ts
+++ b/apps/token-server/src/transactions.ts
@@ -7,7 +7,7 @@
  * methods for building token reward transtaction
  */
 
-import { ChronikClientNode, ScriptUtxo_InNode } from 'chronik-client';
+import { ChronikClient, ScriptUtxo } from 'chronik-client';
 import { syncWallet, ServerWallet } from './wallet';
 import {
     Script,
@@ -30,7 +30,7 @@
 const SLP_1_PROTOCOL_NUMBER = 1;
 
 export interface SlpInputsAndOutputs {
-    slpInputs: ScriptUtxo_InNode[];
+    slpInputs: ScriptUtxo[];
     slpOutputs: TxOutput[];
 }
 
@@ -45,10 +45,10 @@
     rewardAmountTokenSats: bigint,
     destinationAddress: string,
     tokenId: string,
-    utxos: ScriptUtxo_InNode[],
+    utxos: ScriptUtxo[],
     changeAddress: string,
 ): SlpInputsAndOutputs {
-    const slpInputs: ScriptUtxo_InNode[] = [];
+    const slpInputs: ScriptUtxo[] = [];
 
     let totalSendQty = 0n;
     let change = 0n;
@@ -122,7 +122,7 @@
  * @returns
  */
 export const sendReward = async (
-    chronik: ChronikClientNode,
+    chronik: ChronikClient,
     ecc: Ecc,
     wallet: ServerWallet,
     tokenId: string,
diff --git a/apps/token-server/src/wallet.ts b/apps/token-server/src/wallet.ts
--- a/apps/token-server/src/wallet.ts
+++ b/apps/token-server/src/wallet.ts
@@ -7,7 +7,7 @@
  * methods for working with a server-based hotwallet
  */
 
-import { ChronikClientNode, ScriptUtxo_InNode } from 'chronik-client';
+import { ChronikClient, ScriptUtxo } from 'chronik-client';
 import BIP32Factory from 'bip32';
 import * as ecc from 'tiny-secp256k1';
 import * as bip39 from 'bip39';
@@ -17,7 +17,7 @@
 export interface ServerWallet {
     address: string;
     sk: Uint8Array;
-    utxos?: ScriptUtxo_InNode[];
+    utxos?: ScriptUtxo[];
 }
 
 /**
@@ -59,7 +59,7 @@
  * @throws if error in chronik call
  */
 export async function syncWallet(
-    chronik: ChronikClientNode,
+    chronik: ChronikClient,
     wallet: ServerWallet,
 ): Promise<ServerWallet> {
     const { address } = wallet;
diff --git a/apps/token-server/test/vectors.ts b/apps/token-server/test/vectors.ts
--- a/apps/token-server/test/vectors.ts
+++ b/apps/token-server/test/vectors.ts
@@ -4,12 +4,12 @@
 
 import {
     OutPoint,
-    TxInput_InNode,
-    TxOutput_InNode,
-    Token_InNode,
-    Tx_InNode,
-    BlockMetadata_InNode,
-    ScriptUtxo_InNode,
+    TxInput,
+    TxOutput,
+    Token,
+    Tx,
+    BlockMetadata,
+    ScriptUtxo,
     TokenType,
 } from 'chronik-client';
 import { ServerWallet } from '../src/wallet';
@@ -54,7 +54,7 @@
     outIdx: 0,
 };
 
-const MOCK_TX_INPUT: TxInput_InNode = {
+const MOCK_TX_INPUT: TxInput = {
     outputScript: 'should be overwritten in tests',
     prevOut: MOCK_OUTPOINT,
     inputScript: '',
@@ -62,12 +62,12 @@
     sequenceNo: 100,
 };
 
-const MOCK_TX_OUTPUT: TxOutput_InNode = {
+const MOCK_TX_OUTPUT: TxOutput = {
     value: 546,
     outputScript: 'to be updated in test',
 };
 
-const MOCK_TX_INNODE: Tx_InNode = {
+const MOCK_TX: Tx = {
     txid: 'n/a',
     version: 2,
     inputs: [MOCK_TX_INPUT],
@@ -81,7 +81,7 @@
     tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
 };
 
-export const MOCK_SCRIPT_UTXO: ScriptUtxo_InNode = {
+export const MOCK_SCRIPT_UTXO: ScriptUtxo = {
     outpoint: MOCK_OUTPOINT,
     blockHeight: 800000,
     isCoinbase: false,
@@ -94,17 +94,17 @@
     type: 'SLP_TOKEN_TYPE_FUNGIBLE',
     number: 1,
 };
-export const MOCK_UTXO_TOKEN: Token_InNode = {
+export const MOCK_UTXO_TOKEN: Token = {
     tokenId: MOCK_TOKENID_ONES,
     tokenType: MOCK_TOKEN_TYPE,
     amount: '1',
     isMintBaton: false,
 };
-export const MOCK_SPENDABLE_TOKEN_UTXO: ScriptUtxo_InNode = {
+export const MOCK_SPENDABLE_TOKEN_UTXO: ScriptUtxo = {
     ...MOCK_SCRIPT_UTXO,
     token: MOCK_UTXO_TOKEN,
 };
-const MOCK_MINT_BATON_TOKEN_UTXO: ScriptUtxo_InNode = {
+const MOCK_MINT_BATON_TOKEN_UTXO: ScriptUtxo = {
     ...MOCK_SPENDABLE_TOKEN_UTXO,
     token: {
         ...MOCK_UTXO_TOKEN,
@@ -113,13 +113,13 @@
     },
 };
 
-const MOCK_BLOCK_METADATA_INNODE: BlockMetadata_InNode = {
+const MOCK_BLOCK_METADATA: BlockMetadata = {
     hash: '0000000000000000115e051672e3d4a6c523598594825a1194862937941296fe',
     height: 800000,
     timestamp: 1688808780,
 };
 
-const MOCK_TX_OUTPUT_TOKEN: Token_InNode = {
+const MOCK_TX_OUTPUT_TOKEN: Token = {
     tokenId: 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
     tokenType: {
         protocol: 'SLP',
@@ -137,7 +137,7 @@
 
 interface HasInputsFromOutputScriptReturn {
     description: string;
-    tx: Tx_InNode;
+    tx: Tx;
     outputScript: string;
     returned: boolean;
 }
@@ -148,7 +148,7 @@
 
 interface AddressReceivedTokenReturn {
     description: string;
-    tx: Tx_InNode;
+    tx: Tx;
     address: string;
     tokenId: string;
     returned: boolean;
@@ -160,7 +160,7 @@
 
 interface GetTxTimestampReturn {
     description: string;
-    tx: Tx_InNode;
+    tx: Tx;
     timestamp: number;
 }
 
@@ -175,7 +175,7 @@
     address: string;
     timestamp: number;
     pageSize: number;
-    returned: Tx_InNode[];
+    returned: Tx[];
 }
 
 interface GetHistoryAfterTimestampError {
@@ -188,7 +188,7 @@
 }
 
 interface ChronikMock {
-    history: Tx_InNode[] | Error;
+    history: Tx[] | Error;
 }
 
 interface isAddressEligibleForTokenRewardVector {
@@ -199,7 +199,7 @@
     address: string;
     tokenId: string;
     tokenServerOutputScript: string;
-    historySinceEligibilityTimestamp: Tx_InNode[];
+    historySinceEligibilityTimestamp: Tx[];
     returned: boolean | number;
 }
 
@@ -238,7 +238,7 @@
 interface SyncWalletReturn {
     description: string;
     wallet: ServerWallet;
-    mockUtxos: ScriptUtxo_InNode[];
+    mockUtxos: ScriptUtxo[];
     returned: ServerWallet;
 }
 
@@ -258,7 +258,7 @@
     rewardAmountTokenSats: bigint;
     destinationAddress: string;
     tokenId: string;
-    utxos: ScriptUtxo_InNode[];
+    utxos: ScriptUtxo[];
     changeAddress: string;
     returned: SlpInputsAndOutputs;
 }
@@ -268,7 +268,7 @@
     rewardAmountTokenSats: bigint;
     destinationAddress: string;
     tokenId: string;
-    utxos: ScriptUtxo_InNode[];
+    utxos: ScriptUtxo[];
     changeAddress: string;
     error: Error;
 }
@@ -281,7 +281,7 @@
 interface SendRewardReturn {
     description: string;
     wallet: ServerWallet;
-    utxos: ScriptUtxo_InNode[];
+    utxos: ScriptUtxo[];
     tokenId: string;
     rewardAmountTokenSats: bigint;
     destinationAddress: string;
@@ -290,7 +290,7 @@
 interface SendRewardError {
     description: string;
     wallet: ServerWallet;
-    utxos: Error | ScriptUtxo_InNode[];
+    utxos: Error | ScriptUtxo[];
     tokenId: string;
     rewardAmountTokenSats: bigint;
     destinationAddress: string;
@@ -318,7 +318,7 @@
                 description:
                     'Returns true for a tx with one input from the given outputScript',
                 tx: {
-                    ...MOCK_TX_INNODE,
+                    ...MOCK_TX,
                     inputs: [
                         {
                             ...MOCK_TX_INPUT,
@@ -333,7 +333,7 @@
                 description:
                     'Returns false for a tx with one input not from given outputScript',
                 tx: {
-                    ...MOCK_TX_INNODE,
+                    ...MOCK_TX,
                     inputs: [
                         {
                             ...MOCK_TX_INPUT,
@@ -348,7 +348,7 @@
                 description:
                     'Returns true for a multi-input tx with the last input from given outputScript',
                 tx: {
-                    ...MOCK_TX_INNODE,
+                    ...MOCK_TX,
                     inputs: [
                         {
                             ...MOCK_TX_INPUT,
@@ -371,7 +371,7 @@
                 description:
                     'Returns false for a multi-input tx with the no inputs from the given outputScript',
                 tx: {
-                    ...MOCK_TX_INNODE,
+                    ...MOCK_TX,
                     inputs: [
                         {
                             ...MOCK_TX_INPUT,
@@ -398,7 +398,7 @@
                 description:
                     'Returns true for a one-output tx that includes the given tokenId at the given outputScript',
                 tx: {
-                    ...MOCK_TX_INNODE,
+                    ...MOCK_TX,
                     outputs: [
                         {
                             ...MOCK_TX_OUTPUT,
@@ -418,7 +418,7 @@
                 description:
                     'Returns true for tx with multiple outputs that includes an output with the given tokenId at the given outputScript',
                 tx: {
-                    ...MOCK_TX_INNODE,
+                    ...MOCK_TX,
                     outputs: [
                         {
                             ...MOCK_TX_OUTPUT,
@@ -451,7 +451,7 @@
                 description:
                     'Returns false for a one-output tx that does not include a token output',
                 tx: {
-                    ...MOCK_TX_INNODE,
+                    ...MOCK_TX,
                     outputs: [
                         {
                             ...MOCK_TX_OUTPUT,
@@ -468,7 +468,7 @@
                 description:
                     'Returns false for a one-output tx that includes a token not of the given tokenId',
                 tx: {
-                    ...MOCK_TX_INNODE,
+                    ...MOCK_TX,
                     outputs: [
                         {
                             ...MOCK_TX_OUTPUT,
@@ -488,7 +488,7 @@
                 description:
                     'Returns false for a tx with outputs array of length > 1 that includes a token not of the given tokenId and a non-token output',
                 tx: {
-                    ...MOCK_TX_INNODE,
+                    ...MOCK_TX,
                     outputs: [
                         {
                             ...MOCK_TX_OUTPUT,
@@ -515,17 +515,17 @@
         returns: [
             {
                 description: 'Returns timeFirstSeen if it is not 0',
-                tx: { ...MOCK_TX_INNODE, timeFirstSeen: 2222222222 },
+                tx: { ...MOCK_TX, timeFirstSeen: 2222222222 },
                 timestamp: 2222222222,
             },
             {
                 description:
                     'Returns block.timestamp if timeFirstSeen is 0 and the tx has confirmed',
                 tx: {
-                    ...MOCK_TX_INNODE,
+                    ...MOCK_TX,
                     timeFirstSeen: 0,
                     block: {
-                        ...MOCK_BLOCK_METADATA_INNODE,
+                        ...MOCK_BLOCK_METADATA,
                         timestamp: 1111111111,
                     },
                 },
@@ -534,7 +534,7 @@
             {
                 description:
                     'Returns -1 for edge case of timeFirstSeen 0 and unconfirmed tx',
-                tx: { ...MOCK_TX_INNODE, timeFirstSeen: 0 },
+                tx: { ...MOCK_TX, timeFirstSeen: 0 },
                 timestamp: -1,
             },
         ],
@@ -544,15 +544,15 @@
         returns: [
             {
                 description: 'A tx exactly at the given timestamp is returned',
-                mocks: { history: [{ ...MOCK_TX_INNODE, timeFirstSeen: 10 }] },
+                mocks: { history: [{ ...MOCK_TX, timeFirstSeen: 10 }] },
                 address: IFP_ADDRESS,
                 timestamp: 10,
                 pageSize: 2,
-                returned: [{ ...MOCK_TX_INNODE, timeFirstSeen: 10 }],
+                returned: [{ ...MOCK_TX, timeFirstSeen: 10 }],
             },
             {
                 description: 'A tx before the given timestamp is ignored',
-                mocks: { history: [{ ...MOCK_TX_INNODE, timeFirstSeen: 9 }] },
+                mocks: { history: [{ ...MOCK_TX, timeFirstSeen: 9 }] },
                 address: IFP_ADDRESS,
                 timestamp: 10,
                 pageSize: 2,
@@ -563,8 +563,8 @@
                     'If all txs on first page are at or before the given timestamp, we return an empty array',
                 mocks: {
                     history: [
-                        { ...MOCK_TX_INNODE, timeFirstSeen: 9 },
-                        { ...MOCK_TX_INNODE, timeFirstSeen: 8 },
+                        { ...MOCK_TX, timeFirstSeen: 9 },
+                        { ...MOCK_TX, timeFirstSeen: 8 },
                     ],
                 },
                 address: IFP_ADDRESS,
@@ -577,18 +577,18 @@
                     'If all txs on first page are at or after the given timestamp, we get the next page and return the ones there that are also after',
                 mocks: {
                     history: [
-                        { ...MOCK_TX_INNODE, timeFirstSeen: 12 },
-                        { ...MOCK_TX_INNODE, timeFirstSeen: 11 },
-                        { ...MOCK_TX_INNODE, timeFirstSeen: 10 },
+                        { ...MOCK_TX, timeFirstSeen: 12 },
+                        { ...MOCK_TX, timeFirstSeen: 11 },
+                        { ...MOCK_TX, timeFirstSeen: 10 },
                     ],
                 },
                 address: IFP_ADDRESS,
                 timestamp: 10,
                 pageSize: 2,
                 returned: [
-                    { ...MOCK_TX_INNODE, timeFirstSeen: 12 },
-                    { ...MOCK_TX_INNODE, timeFirstSeen: 11 },
-                    { ...MOCK_TX_INNODE, timeFirstSeen: 10 },
+                    { ...MOCK_TX, timeFirstSeen: 12 },
+                    { ...MOCK_TX, timeFirstSeen: 11 },
+                    { ...MOCK_TX, timeFirstSeen: 10 },
                 ],
             },
             {
@@ -596,19 +596,19 @@
                     'If all txs on first page are at or after the given timestamp, and some are and some arent on the 2nd page, we only return the txs after expected timestamp',
                 mocks: {
                     history: [
-                        { ...MOCK_TX_INNODE, timeFirstSeen: 12 },
-                        { ...MOCK_TX_INNODE, timeFirstSeen: 11 },
-                        { ...MOCK_TX_INNODE, timeFirstSeen: 10 },
-                        { ...MOCK_TX_INNODE, timeFirstSeen: 9 },
+                        { ...MOCK_TX, timeFirstSeen: 12 },
+                        { ...MOCK_TX, timeFirstSeen: 11 },
+                        { ...MOCK_TX, timeFirstSeen: 10 },
+                        { ...MOCK_TX, timeFirstSeen: 9 },
                     ],
                 },
                 address: IFP_ADDRESS,
                 timestamp: 10,
                 pageSize: 2,
                 returned: [
-                    { ...MOCK_TX_INNODE, timeFirstSeen: 12 },
-                    { ...MOCK_TX_INNODE, timeFirstSeen: 11 },
-                    { ...MOCK_TX_INNODE, timeFirstSeen: 10 },
+                    { ...MOCK_TX, timeFirstSeen: 12 },
+                    { ...MOCK_TX, timeFirstSeen: 11 },
+                    { ...MOCK_TX, timeFirstSeen: 10 },
                 ],
             },
         ],
@@ -644,7 +644,7 @@
                 tokenServerOutputScript: IFP_OUTPUTSCRIPT,
                 historySinceEligibilityTimestamp: [
                     {
-                        ...MOCK_TX_INNODE,
+                        ...MOCK_TX,
                         inputs: [
                             {
                                 ...MOCK_TX_INPUT,
@@ -670,7 +670,7 @@
                 tokenServerOutputScript: IFP_OUTPUTSCRIPT,
                 historySinceEligibilityTimestamp: [
                     {
-                        ...MOCK_TX_INNODE,
+                        ...MOCK_TX,
                         inputs: [
                             {
                                 ...MOCK_TX_INPUT,
@@ -700,7 +700,7 @@
                 tokenServerOutputScript: IFP_OUTPUTSCRIPT,
                 historySinceEligibilityTimestamp: [
                     {
-                        ...MOCK_TX_INNODE,
+                        ...MOCK_TX,
                         inputs: [
                             {
                                 ...MOCK_TX_INPUT,
diff --git a/cashtab/src/chronik/index.js b/cashtab/src/chronik/index.js
--- a/cashtab/src/chronik/index.js
+++ b/cashtab/src/chronik/index.js
@@ -68,7 +68,7 @@
  * Return a promise to fetch all utxos at an address (and add a 'path' key to them)
  * We need the path key so that we know which wif to sign this utxo with
  * If we add HD wallet support, we will need to add an address key, and change the structure of wallet.paths
- * @param {ChronikClientNode} chronik
+ * @param {ChronikClient} chronik
  * @param {string} address
  * @param {number} path
  * @returns {Promise}
@@ -94,7 +94,7 @@
 
 /**
  * Get all utxos for a given wallet
- * @param {ChronikClientNode} chronik
+ * @param {ChronikClient} chronik
  * @param {object} wallet a cashtab wallet
  * @returns
  */
@@ -116,7 +116,7 @@
 /**
  * Organize utxos by token and non-token
  * TODO deprecate this and use better coinselect methods
- * @param {Tx_InNode[]} chronikUtxos
+ * @param {Tx[]} chronikUtxos
  * @returns {object} {slpUtxos: [], nonSlpUtxos: []}
  */
 export const organizeUtxosByType = chronikUtxos => {
@@ -136,8 +136,8 @@
 
 /**
  * Get just the tx objects from chronik history() responses
- * @param {TxHistoryPage_InNode[]} txHistoryOfAllAddresses
- * @returns {Tx_InNode[]}
+ * @param {TxHistoryPage[]} txHistoryOfAllAddresses
+ * @returns {Tx[]}
  */
 export const flattenChronikTxHistory = txHistoryOfAllAddresses => {
     let flatTxHistoryArray = [];
@@ -151,7 +151,7 @@
 
 /**
  * Sort an array of chronik txs chronologically and return the first renderedCount of them
- * @param {Tx_InNode[]} txs
+ * @param {Tx[]} txs
  * @param {number} renderedCount how many txs to return
  * @returns
  */
@@ -192,9 +192,9 @@
 };
 
 /**
- * Parse a Tx_InNode object for rendering in Cashtab
+ * Parse a Tx object for rendering in Cashtab
  * TODO Potentially more efficient to do this calculation in the Tx.js component
- * @param {Tx_InNode} tx
+ * @param {Tx} tx
  * @param {object} wallet cashtab wallet
  * @param {Map} cachedTokens
  * @returns
@@ -276,10 +276,10 @@
     const satoshisSent = selfSendTx
         ? outputSatoshis
         : isCoinbase
-          ? change
-          : incoming
-            ? receivedSatoshis
-            : outputSatoshis - change;
+        ? change
+        : incoming
+        ? receivedSatoshis
+        : outputSatoshis - change;
 
     let xecTxType = incoming ? 'Received' : 'Sent';
 
@@ -325,10 +325,10 @@
  * - Trim to number of txs Cashtab renders
  * - Parse txs for rendering in Cashtab
  * - Update cachedTokens with any new tokenIds
- * @param {ChronikClientNode} chronik chronik-client instance
+ * @param {ChronikClient} chronik chronik-client instance
  * @param {object} wallet cashtab wallet
  * @param {Map} cachedTokens the map stored at cashtabCache.tokens
- * @returns {array} Tx_InNode[], each tx also has a 'parsed' key with other rendering info
+ * @returns {array} Tx[], each tx also has a 'parsed' key with other rendering info
  */
 export const getHistory = async (chronik, wallet, cachedTokens) => {
     const txHistoryPromises = [];
@@ -390,7 +390,7 @@
 
 /**
  * Get all info about a token used in Cashtab's token cache
- * @param {ChronikClientNode} chronik
+ * @param {ChronikClient} chronik
  * @param {string} tokenId
  * @returns {object}
  */
@@ -493,7 +493,7 @@
 /**
  * Get decimalized balance of every token held by a wallet
  * Update Cashtab's tokenCache if any tokens are uncached
- * @param {ChronikClientNode} chronik
+ * @param {ChronikClient} chronik
  * @param {array} slpUtxos array of token utxos from chronik
  * @param {Map} tokenCache Cashtab's token cache
  * @returns {Map} Map of tokenId => token balance as decimalized string
@@ -541,7 +541,7 @@
 
 /**
  *
- * @param {ChronikClientNode} chronik
+ * @param {ChronikClient} chronik
  * @param {string} tokenId
  * @param {number} pageSize usually 200, the chronik max, but accept a parameter to simplify unit testing
  * @returns
@@ -591,7 +591,7 @@
  * Get all child NFTs from a given parent tokenId
  * i.e. get all NFTs in an NFT collection *
  * @param {string} parentTokenId
- * @param {Tx_InNode[]} allParentTokenTxHistory
+ * @param {Tx[]} allParentTokenTxHistory
  */
 export const getChildNftsFromParent = (
     parentTokenId,
@@ -619,7 +619,7 @@
  * Get all tx history of a lokad id
  * In Cashtab, this is used to get NFT listings
  * Tx history is paginated by chronik, so we need to get all the pages
- * @param {ChronikClientNode} chronik
+ * @param {ChronikClient} chronik
  * @param {string} lokadId
  * @param {number} pageSize usually 200, the chronik max, but accept a parameter to simplify unit testing
  * @returns
diff --git a/cashtab/src/components/Home/Tx/index.js b/cashtab/src/components/Home/Tx/index.js
--- a/cashtab/src/components/Home/Tx/index.js
+++ b/cashtab/src/components/Home/Tx/index.js
@@ -627,7 +627,7 @@
             }
         }
 
-        // Ref TokenTxType in ChronikClientNode
+        // Ref TokenTxType in ChronikClient
         if (txType === 'NONE' || txType === 'UNKNOWN') {
             // Handle special case of burning qty 1 NFT Parent token utxo for an NFT mint
             // Assume when you see txType === 'NONE' for an SLP 1 NFT Parent, that this is burning an NFT mint
@@ -669,16 +669,16 @@
             parsedTokenType !== 'NFT Collection'
                 ? xecTxType
                 : // Note the only type of SEND tx for NFT Collection that Cashtab supports is a fan-out tx
-                  txType !== 'GENESIS' && parsedTokenType === 'NFT Collection'
-                  ? 'Fan-out'
-                  : txType === 'GENESIS' && parsedTokenType !== 'NFT'
-                    ? 'Created'
-                    : isUnintentionalBurn || txType === 'BURN'
-                      ? 'Burned'
-                      : txType === 'MINT' ||
-                          (txType === 'GENESIS' && parsedTokenType === 'NFT')
-                        ? 'Minted'
-                        : txType;
+                txType !== 'GENESIS' && parsedTokenType === 'NFT Collection'
+                ? 'Fan-out'
+                : txType === 'GENESIS' && parsedTokenType !== 'NFT'
+                ? 'Created'
+                : isUnintentionalBurn || txType === 'BURN'
+                ? 'Burned'
+                : txType === 'MINT' ||
+                  (txType === 'GENESIS' && parsedTokenType === 'NFT')
+                ? 'Minted'
+                : txType;
         if (typeof cachedTokenInfo === 'undefined') {
             tokenActions.push(
                 <TokenAction tokenTxType={renderedTxType}>
@@ -724,7 +724,7 @@
                         output.token.entryIdx === i
                     ) {
                         // Get the amount associated with this token entry
-                        // Per ChronikClientNode, we will always have amount as a string in
+                        // Per ChronikClient, we will always have amount as a string in
                         // the token key of an output, see type Token_InNode
                         amountTotal += BigInt(output.token.amount);
                         for (const hash of hashes) {
@@ -747,9 +747,9 @@
                 renderedTxType === 'Received'
                     ? amountThisWallet
                     : renderedTxType === 'Created' ||
-                        renderedTxType === 'Minted'
-                      ? amountTotal
-                      : amountTotal - amountThisWallet;
+                      renderedTxType === 'Minted'
+                    ? amountTotal
+                    : amountTotal - amountThisWallet;
 
             const decimalizedAmount = decimalizeTokenAmount(
                 renderedTokenAmount.toString(),
diff --git a/cashtab/src/index.js b/cashtab/src/index.js
--- a/cashtab/src/index.js
+++ b/cashtab/src/index.js
@@ -8,7 +8,7 @@
 import { WalletProvider } from 'wallet/context';
 import { HashRouter as Router } from 'react-router-dom';
 import GA from 'components/Common/GoogleAnalytics';
-import { ChronikClientNode } from 'chronik-client';
+import { ChronikClient } from 'chronik-client';
 import { chronik as chronikConfig } from 'config/chronik';
 import { Ecc, initWasm } from 'ecash-lib';
 
@@ -18,7 +18,7 @@
         // Initialize Ecc (used for signing txs) at app startup
         const ecc = new Ecc();
         // Initialize chronik-client at app startup
-        const chronik = new ChronikClientNode(chronikConfig.urls);
+        const chronik = new ChronikClient(chronikConfig.urls);
 
         const container = document.getElementById('root');
         const root = createRoot(container);
diff --git a/cashtab/src/slpv1/__tests__/index.test.js b/cashtab/src/slpv1/__tests__/index.test.js
--- a/cashtab/src/slpv1/__tests__/index.test.js
+++ b/cashtab/src/slpv1/__tests__/index.test.js
@@ -69,7 +69,7 @@
             });
         });
     });
-    describe('Get all slpv1 SEND utxos from a mixed utxo set from ChronikClientNode', () => {
+    describe('Get all slpv1 SEND utxos from a mixed utxo set from ChronikClient', () => {
         const { expectedReturns } = vectors.getAllSendUtxos;
         expectedReturns.forEach(expectedReturn => {
             const { description, utxos, tokenId, tokenUtxos } = expectedReturn;
diff --git a/cashtab/src/slpv1/index.js b/cashtab/src/slpv1/index.js
--- a/cashtab/src/slpv1/index.js
+++ b/cashtab/src/slpv1/index.js
@@ -123,7 +123,7 @@
 
 /**
  * Get all available token utxos for an SLP v1 SEND tx from in-node formatted chronik utxos
- * @param {ScriptUtxo_InNode[]} utxos array of utxos from an in-node instance of chronik
+ * @param {ScriptUtxo[]} utxos array of utxos from an in-node instance of chronik
  * @param {string} tokenId
  * @returns {array} tokenUtxos, all utxos that can be used for slpv1 send tx
  * mint batons are intentionally excluded
@@ -143,7 +143,7 @@
 
 /**
  * Get send token inputs from in-node input data
- * @param {ScriptUtxo_InNode[]} utxos
+ * @param {ScriptUtxo[]} utxos
  * @param {string} tokenId tokenId of the token you want to send
  * @param {string} sendQty
  * @param {number} decimals 0-9 inclusive, integer. Decimals of this token.
@@ -246,9 +246,9 @@
 
 /**
  * Get mint baton(s) for a given token
- * @param {ScriptUtxo_InNode[]} utxos
+ * @param {ScriptUtxo[]} utxos
  * @param {string} tokenId
- * @returns {ScriptUtxo_InNode[]}
+ * @returns {ScriptUtxo[]}
  */
 export const getMintBatons = (utxos, tokenId) => {
     // From an array of chronik utxos, return only token utxos related to a given tokenId
diff --git a/cashtab/src/transactions/index.js b/cashtab/src/transactions/index.js
--- a/cashtab/src/transactions/index.js
+++ b/cashtab/src/transactions/index.js
@@ -29,7 +29,7 @@
 
 /**
  * Build and broadcast an eCash tx
- * @param {ChronikClientNode} chronik
+ * @param {ChronikClient} chronik
  * @param {Ecc} ecc
  * @param {object} wallet
  * @param {array} targetOutputs
diff --git a/modules/chronik-client/README.md b/modules/chronik-client/README.md
--- a/modules/chronik-client/README.md
+++ b/modules/chronik-client/README.md
@@ -10,22 +10,20 @@
 
 ## Usage
 
+Please review the integration tests for an exhaustive set of usage examples.
+
 ```js
 import { ChronikClient } from 'chronik-client';
-// For XEC, eCash chain:
-const chronik = new ChronikClient('https://chronik.be.cash/xec');
-// For XPI, Lotus chain:
-const chronik = new ChronikClient('https://chronik.be.cash/xpi');
 
-As of version 0.9.0, the ChronikClient constructor can also optionally
-accept an array of chronik urls. e.g.
 const chronik = new ChronikClient([
-    'https://chronik.be.cash/xec',
-    'https://chronik.fabien.cash',
+    'https://chronik-native1.fabien.cash',
+    'https://chronik-native2.fabien.cash',
+    'https://chronik.pay2stay.com/xec',
 ]);
-If the first url is non-responsive it will cycle through the rest of the array.
 
-// Get Genesis block (on eCash):
+// If the first url is non-responsive it will cycle through the rest of the array.
+
+// Get Genesis block:
 const block = await chronik.block(
     '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f',
 );
@@ -33,7 +31,7 @@
 // Get the first 11 blocks of the chain:
 const blocks = await chronik.blocks(0, 10);
 
-// Get SLP tx details on eCash:
+// Get SLP tx details:
 const tx = await chronik.tx(
     '0f3c3908a2ddec8dea91d2fe1f77295bbbb158af869bff345d44ae800f0a5498',
 );
@@ -43,21 +41,15 @@
     '0daf200e3418f2df1158efef36fbb507f12928f1fdcf3543703e64e75a4a9073',
 );
 
-// Validate Genesis UTXO (considered 'unspent' by Chronik):
-const validationResult = await chronik.validateUtxos([
-    {
-        txid: '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b',
-        outIdx: 0,
-    },
-]);
-
 const GENESIS_PK =
     '04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc' +
     '3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f';
+
 // Get first page of tx history of the Genesis pubkey, most recent first:
 const history = await chronik
     .script('p2pk', GENESIS_PK)
     .history(/*page=*/ 0, /*page_size=*/ 10);
+
 // Get all UTXOs of the Genesis pubkey:
 const utxos = await chronik.script('p2pk', GENESIS_PK).utxos();
 
@@ -73,13 +65,19 @@
     // Optional: ping the ws every 30s to reduce disconnects
     keepAlive: true,
 });
+
 // Wait for WS to be connected:
 await ws.waitForOpen();
-// Subscribe to scripts (on Lotus, current ABC payout address):
-// Will give a message on avg every 2 minutes
-ws.subscribe('p2pkh', 'b8ae1c47effb58f72f7bca819fe7fc252f9e852e');
+
+// Subscribe to blocks
+ws.subscribeToBlocks();
+
+// Subscribe to scripts:
+ws.subscribeToScript('p2pkh', 'b8ae1c47effb58f72f7bca819fe7fc252f9e852e');
 // Unsubscribe:
-ws.unsubscribe('p2pkh', 'b8ae1c47effb58f72f7bca819fe7fc252f9e852e');
+ws.unsubscribeFromScript('p2pkh', 'b8ae1c47effb58f72f7bca819fe7fc252f9e852e');
+
+// You may also subscribe to addresses, tokenIds, and lokadIds. See integration tests.
 ```
 
 ## Changelog
@@ -112,3 +110,4 @@
 -   0.28.1 - Upgrading dependencies [D16375](https://reviews.bitcoinabc.org/D16375)
 -   0.28.2 - Improve failoverProxy to switch servers on error state [D16584](https://reviews.bitcoinabc.org/D16584)
 -   0.29.0 - Support for `plugins` endpoints: `utxos` and `groups` [D16605](https://reviews.bitcoinabc.org/D16605)
+-   1.0.0 - Deprecate NNG chronik and rename all `InNode` classes and types [D16627](https://reviews.bitcoinabc.org/D16627)
diff --git a/modules/chronik-client/index.ts b/modules/chronik-client/index.ts
--- a/modules/chronik-client/index.ts
+++ b/modules/chronik-client/index.ts
@@ -3,4 +3,3 @@
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 export * from './src/ChronikClient';
-export * from './src/ChronikClientNode';
diff --git a/modules/chronik-client/package.json b/modules/chronik-client/package.json
--- a/modules/chronik-client/package.json
+++ b/modules/chronik-client/package.json
@@ -7,7 +7,7 @@
     "author": "Tobias Ruck",
     "license": "MIT",
     "scripts": {
-        "build-proto": "protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=proto/ ../../chronik/chronik-proto/proto/chronik.proto -I=../../chronik/chronik-proto/proto/ --ts_proto_opt=esModuleInterop=true --ts_proto_opt=forceLong=string && mv proto/chronik.ts proto/chronikNode.ts",
+        "build-proto": "protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=proto/ ../../chronik/chronik-proto/proto/chronik.proto -I=../../chronik/chronik-proto/proto/ --ts_proto_opt=esModuleInterop=true --ts_proto_opt=forceLong=string",
         "build": "tsc",
         "build-docs": "typedoc --out docs index.ts",
         "test": "mocha -r ts-node/register test/test.ts",
diff --git a/modules/chronik-client/proto/chronik.ts b/modules/chronik-client/proto/chronik.ts
--- a/modules/chronik-client/proto/chronik.ts
+++ b/modules/chronik-client/proto/chronik.ts
@@ -1,31 +1,116 @@
 /* eslint-disable */
 import Long from 'long';
-import * as _m0 from 'protobufjs/minimal';
+import _m0 from 'protobufjs/minimal';
 
 export const protobufPackage = 'chronik';
 
+/** Status of a token tx */
+export enum TokenStatus {
+    /**
+     * TOKEN_STATUS_NON_TOKEN - Tx involves no tokens whatsover, i.e. neither any burns nor any failed
+     * parsing/coloring or any tokens being created / moved.
+     */
+    TOKEN_STATUS_NON_TOKEN = 0,
+    /** TOKEN_STATUS_NORMAL - Tx involves tokens but no unintentional burns or failed parsings/colorings */
+    TOKEN_STATUS_NORMAL = 1,
+    /** TOKEN_STATUS_NOT_NORMAL - Tx involves tokens but contains unintentional burns or failed parsings/colorings */
+    TOKEN_STATUS_NOT_NORMAL = 2,
+    UNRECOGNIZED = -1,
+}
+
+export function tokenStatusFromJSON(object: any): TokenStatus {
+    switch (object) {
+        case 0:
+        case 'TOKEN_STATUS_NON_TOKEN':
+            return TokenStatus.TOKEN_STATUS_NON_TOKEN;
+        case 1:
+        case 'TOKEN_STATUS_NORMAL':
+            return TokenStatus.TOKEN_STATUS_NORMAL;
+        case 2:
+        case 'TOKEN_STATUS_NOT_NORMAL':
+            return TokenStatus.TOKEN_STATUS_NOT_NORMAL;
+        case -1:
+        case 'UNRECOGNIZED':
+        default:
+            return TokenStatus.UNRECOGNIZED;
+    }
+}
+
+export function tokenStatusToJSON(object: TokenStatus): string {
+    switch (object) {
+        case TokenStatus.TOKEN_STATUS_NON_TOKEN:
+            return 'TOKEN_STATUS_NON_TOKEN';
+        case TokenStatus.TOKEN_STATUS_NORMAL:
+            return 'TOKEN_STATUS_NORMAL';
+        case TokenStatus.TOKEN_STATUS_NOT_NORMAL:
+            return 'TOKEN_STATUS_NOT_NORMAL';
+        case TokenStatus.UNRECOGNIZED:
+        default:
+            return 'UNRECOGNIZED';
+    }
+}
+
+/** ALP token type */
+export enum AlpTokenType {
+    /** ALP_TOKEN_TYPE_STANDARD - Standard ALP token type */
+    ALP_TOKEN_TYPE_STANDARD = 0,
+    UNRECOGNIZED = -1,
+}
+
+export function alpTokenTypeFromJSON(object: any): AlpTokenType {
+    switch (object) {
+        case 0:
+        case 'ALP_TOKEN_TYPE_STANDARD':
+            return AlpTokenType.ALP_TOKEN_TYPE_STANDARD;
+        case -1:
+        case 'UNRECOGNIZED':
+        default:
+            return AlpTokenType.UNRECOGNIZED;
+    }
+}
+
+export function alpTokenTypeToJSON(object: AlpTokenType): string {
+    switch (object) {
+        case AlpTokenType.ALP_TOKEN_TYPE_STANDARD:
+            return 'ALP_TOKEN_TYPE_STANDARD';
+        case AlpTokenType.UNRECOGNIZED:
+        default:
+            return 'UNRECOGNIZED';
+    }
+}
+
+/** SLP token type */
 export enum SlpTokenType {
-    FUNGIBLE = 0,
-    NFT1_GROUP = 1,
-    NFT1_CHILD = 2,
-    UNKNOWN_TOKEN_TYPE = 3,
+    /** SLP_TOKEN_TYPE_NONE - Unknown "0" token type */
+    SLP_TOKEN_TYPE_NONE = 0,
+    /** SLP_TOKEN_TYPE_FUNGIBLE - SLP V1 token type */
+    SLP_TOKEN_TYPE_FUNGIBLE = 1,
+    /** SLP_TOKEN_TYPE_MINT_VAULT - SLP V2 mint vault token type */
+    SLP_TOKEN_TYPE_MINT_VAULT = 2,
+    /** SLP_TOKEN_TYPE_NFT1_GROUP - NFT1 group token type */
+    SLP_TOKEN_TYPE_NFT1_GROUP = 129,
+    /** SLP_TOKEN_TYPE_NFT1_CHILD - NFT1 child token type */
+    SLP_TOKEN_TYPE_NFT1_CHILD = 65,
     UNRECOGNIZED = -1,
 }
 
 export function slpTokenTypeFromJSON(object: any): SlpTokenType {
     switch (object) {
         case 0:
-        case 'FUNGIBLE':
-            return SlpTokenType.FUNGIBLE;
+        case 'SLP_TOKEN_TYPE_NONE':
+            return SlpTokenType.SLP_TOKEN_TYPE_NONE;
         case 1:
-        case 'NFT1_GROUP':
-            return SlpTokenType.NFT1_GROUP;
+        case 'SLP_TOKEN_TYPE_FUNGIBLE':
+            return SlpTokenType.SLP_TOKEN_TYPE_FUNGIBLE;
         case 2:
-        case 'NFT1_CHILD':
-            return SlpTokenType.NFT1_CHILD;
-        case 3:
-        case 'UNKNOWN_TOKEN_TYPE':
-            return SlpTokenType.UNKNOWN_TOKEN_TYPE;
+        case 'SLP_TOKEN_TYPE_MINT_VAULT':
+            return SlpTokenType.SLP_TOKEN_TYPE_MINT_VAULT;
+        case 129:
+        case 'SLP_TOKEN_TYPE_NFT1_GROUP':
+            return SlpTokenType.SLP_TOKEN_TYPE_NFT1_GROUP;
+        case 65:
+        case 'SLP_TOKEN_TYPE_NFT1_CHILD':
+            return SlpTokenType.SLP_TOKEN_TYPE_NFT1_CHILD;
         case -1:
         case 'UNRECOGNIZED':
         default:
@@ -35,229 +120,231 @@
 
 export function slpTokenTypeToJSON(object: SlpTokenType): string {
     switch (object) {
-        case SlpTokenType.FUNGIBLE:
-            return 'FUNGIBLE';
-        case SlpTokenType.NFT1_GROUP:
-            return 'NFT1_GROUP';
-        case SlpTokenType.NFT1_CHILD:
-            return 'NFT1_CHILD';
-        case SlpTokenType.UNKNOWN_TOKEN_TYPE:
-            return 'UNKNOWN_TOKEN_TYPE';
+        case SlpTokenType.SLP_TOKEN_TYPE_NONE:
+            return 'SLP_TOKEN_TYPE_NONE';
+        case SlpTokenType.SLP_TOKEN_TYPE_FUNGIBLE:
+            return 'SLP_TOKEN_TYPE_FUNGIBLE';
+        case SlpTokenType.SLP_TOKEN_TYPE_MINT_VAULT:
+            return 'SLP_TOKEN_TYPE_MINT_VAULT';
+        case SlpTokenType.SLP_TOKEN_TYPE_NFT1_GROUP:
+            return 'SLP_TOKEN_TYPE_NFT1_GROUP';
+        case SlpTokenType.SLP_TOKEN_TYPE_NFT1_CHILD:
+            return 'SLP_TOKEN_TYPE_NFT1_CHILD';
+        case SlpTokenType.UNRECOGNIZED:
         default:
-            return 'UNKNOWN';
+            return 'UNRECOGNIZED';
     }
 }
 
-export enum SlpTxType {
-    GENESIS = 0,
-    SEND = 1,
-    MINT = 2,
-    BURN = 4,
-    UNKNOWN_TX_TYPE = 3,
+/** SLP/ALP tx type */
+export enum TokenTxType {
+    /** NONE - No tx type, e.g. when input tokens are burned */
+    NONE = 0,
+    /** UNKNOWN - Unknown tx type, i.e. for unknown token types */
+    UNKNOWN = 1,
+    /** GENESIS - GENESIS tx */
+    GENESIS = 2,
+    /** SEND - SEND tx */
+    SEND = 3,
+    /** MINT - MINT tx */
+    MINT = 4,
+    /** BURN - BURN tx */
+    BURN = 5,
     UNRECOGNIZED = -1,
 }
 
-export function slpTxTypeFromJSON(object: any): SlpTxType {
+export function tokenTxTypeFromJSON(object: any): TokenTxType {
     switch (object) {
         case 0:
-        case 'GENESIS':
-            return SlpTxType.GENESIS;
+        case 'NONE':
+            return TokenTxType.NONE;
         case 1:
-        case 'SEND':
-            return SlpTxType.SEND;
+        case 'UNKNOWN':
+            return TokenTxType.UNKNOWN;
         case 2:
-        case 'MINT':
-            return SlpTxType.MINT;
+        case 'GENESIS':
+            return TokenTxType.GENESIS;
+        case 3:
+        case 'SEND':
+            return TokenTxType.SEND;
         case 4:
+        case 'MINT':
+            return TokenTxType.MINT;
+        case 5:
         case 'BURN':
-            return SlpTxType.BURN;
-        case 3:
-        case 'UNKNOWN_TX_TYPE':
-            return SlpTxType.UNKNOWN_TX_TYPE;
+            return TokenTxType.BURN;
         case -1:
         case 'UNRECOGNIZED':
         default:
-            return SlpTxType.UNRECOGNIZED;
+            return TokenTxType.UNRECOGNIZED;
     }
 }
 
-export function slpTxTypeToJSON(object: SlpTxType): string {
+export function tokenTxTypeToJSON(object: TokenTxType): string {
     switch (object) {
-        case SlpTxType.GENESIS:
+        case TokenTxType.NONE:
+            return 'NONE';
+        case TokenTxType.UNKNOWN:
+            return 'UNKNOWN';
+        case TokenTxType.GENESIS:
             return 'GENESIS';
-        case SlpTxType.SEND:
+        case TokenTxType.SEND:
             return 'SEND';
-        case SlpTxType.MINT:
+        case TokenTxType.MINT:
             return 'MINT';
-        case SlpTxType.BURN:
+        case TokenTxType.BURN:
             return 'BURN';
-        case SlpTxType.UNKNOWN_TX_TYPE:
-            return 'UNKNOWN_TX_TYPE';
+        case TokenTxType.UNRECOGNIZED:
         default:
-            return 'UNKNOWN';
+            return 'UNRECOGNIZED';
     }
 }
 
-export enum Network {
-    BCH = 0,
-    XEC = 1,
-    XPI = 2,
-    XRG = 3,
+/** Type of message for the block */
+export enum BlockMsgType {
+    /** BLK_CONNECTED - Block connected to the blockchain */
+    BLK_CONNECTED = 0,
+    /** BLK_DISCONNECTED - Block disconnected from the blockchain */
+    BLK_DISCONNECTED = 1,
+    /** BLK_FINALIZED - Block has been finalized by Avalanche */
+    BLK_FINALIZED = 2,
     UNRECOGNIZED = -1,
 }
 
-export function networkFromJSON(object: any): Network {
+export function blockMsgTypeFromJSON(object: any): BlockMsgType {
     switch (object) {
         case 0:
-        case 'BCH':
-            return Network.BCH;
+        case 'BLK_CONNECTED':
+            return BlockMsgType.BLK_CONNECTED;
         case 1:
-        case 'XEC':
-            return Network.XEC;
+        case 'BLK_DISCONNECTED':
+            return BlockMsgType.BLK_DISCONNECTED;
         case 2:
-        case 'XPI':
-            return Network.XPI;
-        case 3:
-        case 'XRG':
-            return Network.XRG;
+        case 'BLK_FINALIZED':
+            return BlockMsgType.BLK_FINALIZED;
         case -1:
         case 'UNRECOGNIZED':
         default:
-            return Network.UNRECOGNIZED;
+            return BlockMsgType.UNRECOGNIZED;
     }
 }
 
-export function networkToJSON(object: Network): string {
+export function blockMsgTypeToJSON(object: BlockMsgType): string {
     switch (object) {
-        case Network.BCH:
-            return 'BCH';
-        case Network.XEC:
-            return 'XEC';
-        case Network.XPI:
-            return 'XPI';
-        case Network.XRG:
-            return 'XRG';
+        case BlockMsgType.BLK_CONNECTED:
+            return 'BLK_CONNECTED';
+        case BlockMsgType.BLK_DISCONNECTED:
+            return 'BLK_DISCONNECTED';
+        case BlockMsgType.BLK_FINALIZED:
+            return 'BLK_FINALIZED';
+        case BlockMsgType.UNRECOGNIZED:
         default:
-            return 'UNKNOWN';
+            return 'UNRECOGNIZED';
     }
 }
 
-export enum UtxoStateVariant {
-    UNSPENT = 0,
-    SPENT = 1,
-    NO_SUCH_TX = 2,
-    NO_SUCH_OUTPUT = 3,
+/** Type of message for a tx */
+export enum TxMsgType {
+    /** TX_ADDED_TO_MEMPOOL - Tx added to the mempool */
+    TX_ADDED_TO_MEMPOOL = 0,
+    /** TX_REMOVED_FROM_MEMPOOL - Tx removed from the mempool */
+    TX_REMOVED_FROM_MEMPOOL = 1,
+    /** TX_CONFIRMED - Tx confirmed in a block */
+    TX_CONFIRMED = 2,
+    /** TX_FINALIZED - Tx finalized by Avalanche */
+    TX_FINALIZED = 3,
     UNRECOGNIZED = -1,
 }
 
-export function utxoStateVariantFromJSON(object: any): UtxoStateVariant {
+export function txMsgTypeFromJSON(object: any): TxMsgType {
     switch (object) {
         case 0:
-        case 'UNSPENT':
-            return UtxoStateVariant.UNSPENT;
+        case 'TX_ADDED_TO_MEMPOOL':
+            return TxMsgType.TX_ADDED_TO_MEMPOOL;
         case 1:
-        case 'SPENT':
-            return UtxoStateVariant.SPENT;
+        case 'TX_REMOVED_FROM_MEMPOOL':
+            return TxMsgType.TX_REMOVED_FROM_MEMPOOL;
         case 2:
-        case 'NO_SUCH_TX':
-            return UtxoStateVariant.NO_SUCH_TX;
+        case 'TX_CONFIRMED':
+            return TxMsgType.TX_CONFIRMED;
         case 3:
-        case 'NO_SUCH_OUTPUT':
-            return UtxoStateVariant.NO_SUCH_OUTPUT;
+        case 'TX_FINALIZED':
+            return TxMsgType.TX_FINALIZED;
         case -1:
         case 'UNRECOGNIZED':
         default:
-            return UtxoStateVariant.UNRECOGNIZED;
+            return TxMsgType.UNRECOGNIZED;
     }
 }
 
-export function utxoStateVariantToJSON(object: UtxoStateVariant): string {
+export function txMsgTypeToJSON(object: TxMsgType): string {
     switch (object) {
-        case UtxoStateVariant.UNSPENT:
-            return 'UNSPENT';
-        case UtxoStateVariant.SPENT:
-            return 'SPENT';
-        case UtxoStateVariant.NO_SUCH_TX:
-            return 'NO_SUCH_TX';
-        case UtxoStateVariant.NO_SUCH_OUTPUT:
-            return 'NO_SUCH_OUTPUT';
+        case TxMsgType.TX_ADDED_TO_MEMPOOL:
+            return 'TX_ADDED_TO_MEMPOOL';
+        case TxMsgType.TX_REMOVED_FROM_MEMPOOL:
+            return 'TX_REMOVED_FROM_MEMPOOL';
+        case TxMsgType.TX_CONFIRMED:
+            return 'TX_CONFIRMED';
+        case TxMsgType.TX_FINALIZED:
+            return 'TX_FINALIZED';
+        case TxMsgType.UNRECOGNIZED:
         default:
-            return 'UNKNOWN';
+            return 'UNRECOGNIZED';
     }
 }
 
-export interface ValidateUtxoRequest {
-    outpoints: OutPoint[];
-}
-
-export interface ValidateUtxoResponse {
-    utxoStates: UtxoState[];
-}
-
-export interface BroadcastTxRequest {
-    rawTx: Uint8Array;
-    skipSlpCheck: boolean;
+/** Block on the blockchain */
+export interface Block {
+    /** Info about the block */
+    blockInfo: BlockInfo | undefined;
 }
 
-export interface BroadcastTxResponse {
-    txid: Uint8Array;
+/** Range of blocks */
+export interface Blocks {
+    /** Queried blocks */
+    blocks: BlockInfo[];
 }
 
-export interface BroadcastTxsRequest {
-    rawTxs: Uint8Array[];
-    skipSlpCheck: boolean;
+/** Header on the blockchain */
+export interface BlockHeader {
+    /** Raw data */
+    rawHeader: Uint8Array;
 }
 
-export interface BroadcastTxsResponse {
-    txids: Uint8Array[];
+/** Range of headers */
+export interface BlockHeaders {
+    /** Queried headers */
+    headers: BlockHeader[];
 }
 
+/** Info about the state of the blockchain. */
 export interface BlockchainInfo {
+    /** Hash (little-endian) of the current tip */
     tipHash: Uint8Array;
+    /** Height of the current tip (genesis has height = 0) */
     tipHeight: number;
 }
 
-export interface Tx {
-    txid: Uint8Array;
-    version: number;
-    inputs: TxInput[];
-    outputs: TxOutput[];
-    lockTime: number;
-    slpTxData: SlpTxData | undefined;
-    slpErrorMsg: string;
-    block: BlockMetadata | undefined;
-    timeFirstSeen: string;
-    size: number;
-    isCoinbase: boolean;
-    network: Network;
-}
-
-export interface Utxo {
-    outpoint: OutPoint | undefined;
-    blockHeight: number;
-    isCoinbase: boolean;
-    value: string;
-    slpMeta: SlpMeta | undefined;
-    slpToken: SlpToken | undefined;
-    network: Network;
-}
-
-export interface Token {
-    slpTxData: SlpTxData | undefined;
-    tokenStats: TokenStats | undefined;
-    block: BlockMetadata | undefined;
-    timeFirstSeen: string;
-    initialTokenQuantity: string;
-    containsBaton: boolean;
-    network: Network;
+/** Info about the chronik software this server is running */
+export interface ChronikInfo {
+    /** chronik server version from chronik-http/Cargo.toml */
+    version: string;
 }
 
+/** Info about a block */
 export interface BlockInfo {
+    /** Hash (little-endian) */
     hash: Uint8Array;
+    /** Hash of the previous block (little-endian) */
     prevHash: Uint8Array;
+    /** Height in the chain */
     height: number;
+    /** nBits field encoding the target */
     nBits: number;
+    /** Timestamp field of the block */
     timestamp: string;
+    /** Whether the block has been finalized by Avalanche */
+    isFinal: boolean;
     /** Block size of this block in bytes (including headers etc.) */
     blockSize: string;
     /** Number of txs in this block */
@@ -276,664 +363,1206 @@
     sumBurnedSats: string;
 }
 
-export interface BlockDetails {
+/** Details about a transaction */
+export interface Tx {
+    /** TxId (little-endian) of the tx */
+    txid: Uint8Array;
+    /** nVersion */
     version: number;
-    merkleRoot: Uint8Array;
-    nonce: string;
-    medianTimestamp: string;
-}
-
-export interface Block {
-    blockInfo: BlockInfo | undefined;
-    blockDetails: BlockDetails | undefined;
-    rawHeader: Uint8Array;
-    txs: Tx[];
-}
-
-export interface ScriptUtxos {
-    outputScript: Uint8Array;
-    utxos: Utxo[];
+    /** Inputs of the tx (aka. `vin`) */
+    inputs: TxInput[];
+    /** Outputs of the tx (aka. `vout`) */
+    outputs: TxOutput[];
+    /** nLockTime */
+    lockTime: number;
+    /** Which block this tx is in, or None, if in the mempool */
+    block: BlockMetadata | undefined;
+    /** Time this tx has first been added to the mempool, or 0 if unknown */
+    timeFirstSeen: string;
+    /** Serialized size of the tx */
+    size: number;
+    /** Whether this tx is a coinbase tx */
+    isCoinbase: boolean;
+    /** Tokens involved in this txs */
+    tokenEntries: TokenEntry[];
+    /** Failed parsing attempts of this tx */
+    tokenFailedParsings: TokenFailedParsing[];
+    /**
+     * Token status, i.e. whether this tx has any tokens or unintentional token burns
+     * or something unexpected, like failed parsings etc.
+     */
+    tokenStatus: TokenStatus;
 }
 
-export interface TxHistoryPage {
-    txs: Tx[];
-    numPages: number;
+/** UTXO of a script. */
+export interface ScriptUtxo {
+    /** txid and out_idx of the unspent output. */
+    outpoint: OutPoint | undefined;
+    /** Block height of the UTXO, or -1 if in mempool. */
+    blockHeight: number;
+    /** Whether the UTXO has been created in a coinbase tx. */
+    isCoinbase: boolean;
+    /** Value of the output, in satoshis. */
+    value: string;
+    /** Whether the UTXO has been finalized by Avalanche. */
+    isFinal: boolean;
+    /** Token value attached to this UTXO */
+    token: Token | undefined;
+    /** Data attached to this output by plugins */
+    plugins: { [key: string]: PluginEntry };
 }
 
-export interface Utxos {
-    scriptUtxos: ScriptUtxos[];
+export interface ScriptUtxo_PluginsEntry {
+    key: string;
+    value: PluginEntry | undefined;
 }
 
-export interface Blocks {
-    blocks: BlockInfo[];
+/** UTXO, but with a script attached. */
+export interface Utxo {
+    /** txid and out_idx of the unspent output. */
+    outpoint: OutPoint | undefined;
+    /** Block height of the UTXO, or -1 if in mempool. */
+    blockHeight: number;
+    /** Whether the UTXO has been created in a coinbase tx. */
+    isCoinbase: boolean;
+    /** Value of the output, in satoshis. */
+    value: string;
+    /** Bytecode of the script of the output */
+    script: Uint8Array;
+    /** Whether the UTXO has been finalized by Avalanche. */
+    isFinal: boolean;
+    /** Token value attached to this UTXO */
+    token: Token | undefined;
+    /** Data attached to this output by plugins */
+    plugins: { [key: string]: PluginEntry };
 }
 
-export interface SlpTxData {
-    slpMeta: SlpMeta | undefined;
-    genesisInfo: SlpGenesisInfo | undefined;
+export interface Utxo_PluginsEntry {
+    key: string;
+    value: PluginEntry | undefined;
 }
 
-export interface SlpMeta {
-    tokenType: SlpTokenType;
-    txType: SlpTxType;
-    tokenId: Uint8Array;
-    groupTokenId: Uint8Array;
+/** COutPoint, points to a coin being spent by an input. */
+export interface OutPoint {
+    /** TxId of the tx of the output being spent. */
+    txid: Uint8Array;
+    /** Index of the output spent within the transaction. */
+    outIdx: number;
 }
 
-export interface TokenStats {
-    /**
-     * This doesn't fit into uint64, so we use a string with the decimal
-     * representation. If available, use i128 to parse, otherwise some
-     * BigNumber library.
-     */
-    totalMinted: string;
-    totalBurned: string;
+/** Points to an input spending a coin. */
+export interface SpentBy {
+    /** TxId of the tx with the input. */
+    txid: Uint8Array;
+    /** Index in the inputs of the tx. */
+    inputIdx: number;
 }
 
+/** CTxIn, spends a coin. */
 export interface TxInput {
+    /** Reference to the coin being spent. */
     prevOut: OutPoint | undefined;
+    /** scriptSig, script unlocking the coin. */
     inputScript: Uint8Array;
+    /** scriptPubKey, script of the output locking the coin. */
     outputScript: Uint8Array;
+    /** value of the output being spent, in satoshis. */
     value: string;
+    /** nSequence of the input. */
     sequenceNo: number;
-    slpBurn: SlpBurn | undefined;
-    slpToken: SlpToken | undefined;
+    /** Token value attached to this input */
+    token: Token | undefined;
+    /** Data attached to this output by plugins */
+    plugins: { [key: string]: PluginEntry };
+}
+
+export interface TxInput_PluginsEntry {
+    key: string;
+    value: PluginEntry | undefined;
 }
 
+/** CTxOut, creates a new coin. */
 export interface TxOutput {
+    /** Value of the coin, in satoshis. */
     value: string;
+    /** scriptPubKey, script locking the output. */
     outputScript: Uint8Array;
-    slpToken: SlpToken | undefined;
-    spentBy: OutPoint | undefined;
+    /** Which tx and input spent this output, if any. */
+    spentBy: SpentBy | undefined;
+    /** Token value attached to this output */
+    token: Token | undefined;
+    /** Data attached to this output by plugins */
+    plugins: { [key: string]: PluginEntry };
+}
+
+export interface TxOutput_PluginsEntry {
+    key: string;
+    value: PluginEntry | undefined;
 }
 
+/** Data about a block which a Tx is in. */
 export interface BlockMetadata {
+    /** Height of the block the tx is in. */
     height: number;
+    /** Hash of the block the tx is in. */
     hash: Uint8Array;
+    /** nTime of the block the tx is in. */
     timestamp: string;
+    /** Whether the block has been finalized by Avalanche. */
+    isFinal: boolean;
 }
 
-export interface OutPoint {
-    txid: Uint8Array;
-    outIdx: number;
+/** SLP/ALP token type */
+export interface TokenType {
+    /** SLP token type. Can have unknown values for unknown token types */
+    slp?: SlpTokenType | undefined;
+    /** ALP token type. Can have unknown values for unknown token types */
+    alp?: AlpTokenType | undefined;
 }
 
-export interface SlpToken {
-    amount: string;
-    isMintBaton: boolean;
+/** Info about a token */
+export interface TokenInfo {
+    /**
+     * Hex token_id (in big-endian, like usually displayed to users) of the token.
+     * This is not `bytes` because SLP and ALP use different endiannnes, so to avoid this we use hex, which conventionally implies big-endian in a bitcoin context.
+     */
+    tokenId: string;
+    /** Token type of the token */
+    tokenType: TokenType | undefined;
+    /** Info found in the token's GENESIS tx */
+    genesisInfo: GenesisInfo | undefined;
+    /** Block of the GENESIS tx, if it's mined already */
+    block: BlockMetadata | undefined;
+    /** Time the GENESIS tx has first been seen by the indexer */
+    timeFirstSeen: string;
 }
 
-export interface SlpBurn {
-    token: SlpToken | undefined;
-    tokenId: Uint8Array;
+/** Token involved in a transaction */
+export interface TokenEntry {
+    /**
+     * Hex token_id (in big-endian, like usually displayed to users) of the token.
+     * This is not `bytes` because SLP and ALP use different endiannes, so to avoid
+     * this we use hex, which conventionally implies big-endian in a bitcoin context.
+     */
+    tokenId: string;
+    /** Token type of the token */
+    tokenType: TokenType | undefined;
+    /** Tx type of the token; NONE if there's no section that introduced it (e.g. in an accidental burn) */
+    txType: TokenTxType;
+    /** For NFT1 Child tokens: group ID */
+    groupTokenId: string;
+    /** Whether the validation rules have been violated for this section */
+    isInvalid: boolean;
+    /** Human-readable error message of why this entry burned tokens */
+    burnSummary: string;
+    /** Human-readable error messages of why colorings failed */
+    failedColorings: TokenFailedColoring[];
+    /**
+     * Number of actually burned tokens (as decimal integer string, e.g. "2000").
+     * This is because burns can exceed the 64-bit range of values and protobuf doesn't have a nice type to encode this.
+     */
+    actualBurnAmount: string;
+    /** Burn amount the user explicitly opted into */
+    intentionalBurn: string;
+    /** Whether any mint batons have been burned of this token */
+    burnsMintBatons: boolean;
 }
 
-export interface SlpGenesisInfo {
+/** Genesis info found in GENESIS txs of tokens */
+export interface GenesisInfo {
+    /** token_ticker of the token */
     tokenTicker: Uint8Array;
+    /** token_name of the token */
     tokenName: Uint8Array;
-    tokenDocumentUrl: Uint8Array;
-    tokenDocumentHash: Uint8Array;
+    /** URL of the token */
+    url: Uint8Array;
+    /** token_document_hash of the token (only on SLP) */
+    hash: Uint8Array;
+    /** mint_vault_scripthash (only on SLP V2 Mint Vault) */
+    mintVaultScripthash: Uint8Array;
+    /** Arbitray payload data of the token (only on ALP) */
+    data: Uint8Array;
+    /** auth_pubkey of the token (only on ALP) */
+    authPubkey: Uint8Array;
+    /** decimals of the token, i.e. how many decimal places the token should be displayed with. */
     decimals: number;
 }
 
-export interface UtxoState {
-    height: number;
-    isConfirmed: boolean;
-    state: UtxoStateVariant;
+/** Token coloring an input or output */
+export interface Token {
+    /** Hex token_id of the token, see `TokenInfo` for details */
+    tokenId: string;
+    /** Token type of the token */
+    tokenType: TokenType | undefined;
+    /** Index into `token_entries` for `Tx`. -1 for UTXOs */
+    entryIdx: number;
+    /** Base token amount of the input/output */
+    amount: string;
+    /** Whether the token is a mint baton */
+    isMintBaton: boolean;
 }
 
-export interface Subscription {
-    scriptType: string;
-    payload: Uint8Array;
-    isSubscribe: boolean;
+/**
+ * A report of a failed parsing attempt of SLP/ALP.
+ * This should always indicate something went wrong when building the tx.
+ */
+export interface TokenFailedParsing {
+    /**
+     * For ALP, the index of the pushdata in the OP_RETURN that failed parsing.
+     * -1 if the whole OP_RETURN failed, e.g. for SLP or eMPP
+     */
+    pushdataIdx: number;
+    /** The bytes that failed parsing, useful for debugging */
+    bytes: Uint8Array;
+    /** Human-readable message of what went wrong */
+    error: string;
 }
 
-export interface SubscribeMsg {
-    error: Error | undefined;
-    AddedToMempool: MsgAddedToMempool | undefined;
-    RemovedFromMempool: MsgRemovedFromMempool | undefined;
-    Confirmed: MsgConfirmed | undefined;
-    Reorg: MsgReorg | undefined;
-    BlockConnected: MsgBlockConnected | undefined;
-    BlockDisconnected: MsgBlockDisconnected | undefined;
+/**
+ * A report of a failed coloring attempt of SLP/ALP.
+ * This should always indicate something went wrong when building the tx.
+ */
+export interface TokenFailedColoring {
+    /** For ALP, the index of the pushdata in the OP_RETURN that failed parsing. */
+    pushdataIdx: number;
+    /** Human-readable message of what went wrong */
+    error: string;
 }
 
-export interface MsgAddedToMempool {
-    txid: Uint8Array;
+/** Data attached by a plugin to an output */
+export interface PluginEntry {
+    /** Groups assigned to this output */
+    groups: Uint8Array[];
+    /** Data assigned to the output */
+    data: Uint8Array[];
 }
 
-export interface MsgRemovedFromMempool {
-    txid: Uint8Array;
+/** Data about a plugin group */
+export interface PluginGroup {
+    /** Group bytes */
+    group: Uint8Array;
 }
 
-export interface MsgConfirmed {
-    txid: Uint8Array;
+/** List of plugin groups */
+export interface PluginGroups {
+    /** Groups */
+    groups: PluginGroup[];
+    /**
+     * Group that if specified as `start` will give us the next groups,
+     * or empty if groups have been exausted.
+     */
+    nextStart: Uint8Array;
+}
+
+/** Page with txs */
+export interface TxHistoryPage {
+    /** Txs of the page */
+    txs: Tx[];
+    /** How many pages there are total */
+    numPages: number;
+    /** How many txs there are total */
+    numTxs: number;
+}
+
+/** List of UTXOs of a script */
+export interface ScriptUtxos {
+    /** The serialized script of the UTXOs */
+    script: Uint8Array;
+    /** UTXOs of the script. */
+    utxos: ScriptUtxo[];
+}
+
+/** List of UTXOs */
+export interface Utxos {
+    /** UTXOs */
+    utxos: Utxo[];
 }
 
-export interface MsgReorg {
+/** Broadcast a single tx */
+export interface BroadcastTxRequest {
+    /** Serialized tx */
+    rawTx: Uint8Array;
+    /** Whether to skip token checks and broadcast even if tokens are unintentionally burned */
+    skipTokenChecks: boolean;
+}
+
+/** Response of broadcasting the tx */
+export interface BroadcastTxResponse {
+    /** TxId of the broadcast tx */
     txid: Uint8Array;
 }
 
-export interface MsgBlockConnected {
-    blockHash: Uint8Array;
+/** Broadcast multiple txs. If one of the txs fails token validation, the entire batch will not be broadcast. */
+export interface BroadcastTxsRequest {
+    /** Serialized txs. */
+    rawTxs: Uint8Array[];
+    /** Whether to skip token checks and broadcast even if tokens are unintentionally burned */
+    skipTokenChecks: boolean;
+}
+
+/** Response of broadcasting txs */
+export interface BroadcastTxsResponse {
+    /** TxIds of the broadcast txs */
+    txids: Uint8Array[];
+}
+
+/** Raw serialized tx. */
+export interface RawTx {
+    /** Bytes of the serialized tx. */
+    rawTx: Uint8Array;
+}
+
+/** Subscription to WebSocket updates. */
+export interface WsSub {
+    /** Set this to `true` to unsubscribe from the event. */
+    isUnsub: boolean;
+    /** Subscription to block updates */
+    blocks?: WsSubBlocks | undefined;
+    /** Subscription to a script */
+    script?: WsSubScript | undefined;
+    /** Subscription to a token ID */
+    tokenId?: WsSubTokenId | undefined;
+    /** Subscription to a lokad ID */
+    lokadId?: WsSubLokadId | undefined;
+}
+
+/**
+ * Subscription to blocks. They will be sent any time a block got connected,
+ * disconnected or finalized.
+ */
+export interface WsSubBlocks {}
+
+/**
+ * Subscription to a script. They will be sent every time a tx spending the
+ * given script or sending to the given script has been added to/removed from
+ * the mempool, or confirmed in a block.
+ */
+export interface WsSubScript {
+    /** Script type to subscribe to ("p2pkh", "p2sh", "p2pk", "other"). */
+    scriptType: string;
+    /**
+     * Payload for the given script type:
+     * - 20-byte hash for "p2pkh" and "p2sh"
+     * - 33-byte or 65-byte pubkey for "p2pk"
+     * - Serialized script for "other"
+     */
+    payload: Uint8Array;
+}
+
+/**
+ * Subscription to a token ID. They will be sent every time a tx spending or
+ * sending tokens with the token ID.
+ */
+export interface WsSubTokenId {
+    /** Hex token ID to subscribe to. */
+    tokenId: string;
+}
+
+/**
+ * Subscription to a LOKAD ID. They will be sent every time a tx matches the given LOKAD ID in one of the following ways:
+ * - `OP_RETURN <LOKAD ID> ...`: The first output has an OP_RETURN with the given LOKAD ID as first pushop
+ * - `OP_RETURN OP_RESERVED "<LOKAD_ID>..." "<LOKAD_ID>..." ...`: The first output has an eMPP encoded OP_RETURN, and one (or more) of the pushops has the LOKAD ID as prefix.
+ * - `<LOKAD ID> ...`: An input's scriptSig has the given LOKAD ID as the first pushop
+ */
+export interface WsSubLokadId {
+    /** 4-byte LOKAD ID. */
+    lokadId: Uint8Array;
+}
+
+/** Message coming from the WebSocket */
+export interface WsMsg {
+    /** Error, e.g. when a bad message has been sent into the WebSocket. */
+    error?: Error | undefined;
+    /** Block got connected, disconnected, finalized, etc. */
+    block?: MsgBlock | undefined;
+    /** Tx got added to/removed from the mempool, or confirmed in a block. */
+    tx?: MsgTx | undefined;
 }
 
-export interface MsgBlockDisconnected {
+/** Block got connected, disconnected, finalized, etc. */
+export interface MsgBlock {
+    /** What happened to the block */
+    msgType: BlockMsgType;
+    /** Hash of the block (little-endian) */
     blockHash: Uint8Array;
+    /** Height of the block */
+    blockHeight: number;
+}
+
+/** Tx got added to/removed from mempool, or confirmed in a block, etc. */
+export interface MsgTx {
+    /** What happened to the tx */
+    msgType: TxMsgType;
+    /** Txid of the tx (little-endian) */
+    txid: Uint8Array;
 }
 
+/** Empty msg without any data */
+export interface Empty {}
+
+/** Error message returned from our APIs. */
 export interface Error {
-    errorCode: string;
+    /** 2, as legacy chronik uses this for the message so we're still compatible. */
     msg: string;
-    isUserError: boolean;
 }
 
-function createBaseValidateUtxoRequest(): ValidateUtxoRequest {
-    return { outpoints: [] };
+function createBaseBlock(): Block {
+    return { blockInfo: undefined };
 }
 
-export const ValidateUtxoRequest = {
+export const Block = {
     encode(
-        message: ValidateUtxoRequest,
+        message: Block,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        for (const v of message.outpoints) {
-            OutPoint.encode(v!, writer.uint32(10).fork()).ldelim();
+        if (message.blockInfo !== undefined) {
+            BlockInfo.encode(
+                message.blockInfo,
+                writer.uint32(10).fork(),
+            ).ldelim();
         }
         return writer;
     },
 
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): ValidateUtxoRequest {
+    decode(input: _m0.Reader | Uint8Array, length?: number): Block {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseValidateUtxoRequest();
+        const message = createBaseBlock();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.outpoints.push(
-                        OutPoint.decode(reader, reader.uint32()),
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.blockInfo = BlockInfo.decode(
+                        reader,
+                        reader.uint32(),
                     );
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): ValidateUtxoRequest {
+    fromJSON(object: any): Block {
         return {
-            outpoints: Array.isArray(object?.outpoints)
-                ? object.outpoints.map((e: any) => OutPoint.fromJSON(e))
-                : [],
+            blockInfo: isSet(object.blockInfo)
+                ? BlockInfo.fromJSON(object.blockInfo)
+                : undefined,
         };
     },
 
-    toJSON(message: ValidateUtxoRequest): unknown {
+    toJSON(message: Block): unknown {
         const obj: any = {};
-        if (message.outpoints) {
-            obj.outpoints = message.outpoints.map(e =>
-                e ? OutPoint.toJSON(e) : undefined,
-            );
-        } else {
-            obj.outpoints = [];
+        if (message.blockInfo !== undefined) {
+            obj.blockInfo = BlockInfo.toJSON(message.blockInfo);
         }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<ValidateUtxoRequest>, I>>(
-        object: I,
-    ): ValidateUtxoRequest {
-        const message = createBaseValidateUtxoRequest();
-        message.outpoints =
-            object.outpoints?.map(e => OutPoint.fromPartial(e)) || [];
+    create<I extends Exact<DeepPartial<Block>, I>>(base?: I): Block {
+        return Block.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<Block>, I>>(object: I): Block {
+        const message = createBaseBlock();
+        message.blockInfo =
+            object.blockInfo !== undefined && object.blockInfo !== null
+                ? BlockInfo.fromPartial(object.blockInfo)
+                : undefined;
         return message;
     },
 };
 
-function createBaseValidateUtxoResponse(): ValidateUtxoResponse {
-    return { utxoStates: [] };
+function createBaseBlocks(): Blocks {
+    return { blocks: [] };
 }
 
-export const ValidateUtxoResponse = {
+export const Blocks = {
     encode(
-        message: ValidateUtxoResponse,
+        message: Blocks,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        for (const v of message.utxoStates) {
-            UtxoState.encode(v!, writer.uint32(10).fork()).ldelim();
+        for (const v of message.blocks) {
+            BlockInfo.encode(v!, writer.uint32(10).fork()).ldelim();
         }
         return writer;
     },
 
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): ValidateUtxoResponse {
+    decode(input: _m0.Reader | Uint8Array, length?: number): Blocks {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseValidateUtxoResponse();
+        const message = createBaseBlocks();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.utxoStates.push(
-                        UtxoState.decode(reader, reader.uint32()),
-                    );
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.blocks.push(
+                        BlockInfo.decode(reader, reader.uint32()),
+                    );
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): ValidateUtxoResponse {
+    fromJSON(object: any): Blocks {
         return {
-            utxoStates: Array.isArray(object?.utxoStates)
-                ? object.utxoStates.map((e: any) => UtxoState.fromJSON(e))
+            blocks: globalThis.Array.isArray(object?.blocks)
+                ? object.blocks.map((e: any) => BlockInfo.fromJSON(e))
                 : [],
         };
     },
 
-    toJSON(message: ValidateUtxoResponse): unknown {
+    toJSON(message: Blocks): unknown {
         const obj: any = {};
-        if (message.utxoStates) {
-            obj.utxoStates = message.utxoStates.map(e =>
-                e ? UtxoState.toJSON(e) : undefined,
-            );
-        } else {
-            obj.utxoStates = [];
+        if (message.blocks?.length) {
+            obj.blocks = message.blocks.map(e => BlockInfo.toJSON(e));
         }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<ValidateUtxoResponse>, I>>(
-        object: I,
-    ): ValidateUtxoResponse {
-        const message = createBaseValidateUtxoResponse();
-        message.utxoStates =
-            object.utxoStates?.map(e => UtxoState.fromPartial(e)) || [];
+    create<I extends Exact<DeepPartial<Blocks>, I>>(base?: I): Blocks {
+        return Blocks.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<Blocks>, I>>(object: I): Blocks {
+        const message = createBaseBlocks();
+        message.blocks =
+            object.blocks?.map(e => BlockInfo.fromPartial(e)) || [];
         return message;
     },
 };
 
-function createBaseBroadcastTxRequest(): BroadcastTxRequest {
-    return { rawTx: new Uint8Array(), skipSlpCheck: false };
+function createBaseBlockHeader(): BlockHeader {
+    return { rawHeader: new Uint8Array(0) };
 }
 
-export const BroadcastTxRequest = {
+export const BlockHeader = {
     encode(
-        message: BroadcastTxRequest,
+        message: BlockHeader,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.rawTx.length !== 0) {
-            writer.uint32(10).bytes(message.rawTx);
-        }
-        if (message.skipSlpCheck === true) {
-            writer.uint32(16).bool(message.skipSlpCheck);
+        if (message.rawHeader.length !== 0) {
+            writer.uint32(10).bytes(message.rawHeader);
         }
         return writer;
     },
 
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): BroadcastTxRequest {
+    decode(input: _m0.Reader | Uint8Array, length?: number): BlockHeader {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBroadcastTxRequest();
+        const message = createBaseBlockHeader();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.rawTx = reader.bytes();
-                    break;
-                case 2:
-                    message.skipSlpCheck = reader.bool();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.rawHeader = reader.bytes();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): BroadcastTxRequest {
+    fromJSON(object: any): BlockHeader {
         return {
-            rawTx: isSet(object.rawTx)
-                ? bytesFromBase64(object.rawTx)
-                : new Uint8Array(),
-            skipSlpCheck: isSet(object.skipSlpCheck)
-                ? Boolean(object.skipSlpCheck)
-                : false,
+            rawHeader: isSet(object.rawHeader)
+                ? bytesFromBase64(object.rawHeader)
+                : new Uint8Array(0),
         };
     },
 
-    toJSON(message: BroadcastTxRequest): unknown {
+    toJSON(message: BlockHeader): unknown {
         const obj: any = {};
-        message.rawTx !== undefined &&
-            (obj.rawTx = base64FromBytes(
-                message.rawTx !== undefined ? message.rawTx : new Uint8Array(),
-            ));
-        message.skipSlpCheck !== undefined &&
-            (obj.skipSlpCheck = message.skipSlpCheck);
+        if (message.rawHeader.length !== 0) {
+            obj.rawHeader = base64FromBytes(message.rawHeader);
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<BroadcastTxRequest>, I>>(
+    create<I extends Exact<DeepPartial<BlockHeader>, I>>(
+        base?: I,
+    ): BlockHeader {
+        return BlockHeader.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<BlockHeader>, I>>(
         object: I,
-    ): BroadcastTxRequest {
-        const message = createBaseBroadcastTxRequest();
-        message.rawTx = object.rawTx ?? new Uint8Array();
-        message.skipSlpCheck = object.skipSlpCheck ?? false;
+    ): BlockHeader {
+        const message = createBaseBlockHeader();
+        message.rawHeader = object.rawHeader ?? new Uint8Array(0);
         return message;
     },
 };
 
-function createBaseBroadcastTxResponse(): BroadcastTxResponse {
-    return { txid: new Uint8Array() };
+function createBaseBlockHeaders(): BlockHeaders {
+    return { headers: [] };
 }
 
-export const BroadcastTxResponse = {
+export const BlockHeaders = {
     encode(
-        message: BroadcastTxResponse,
+        message: BlockHeaders,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.txid.length !== 0) {
-            writer.uint32(10).bytes(message.txid);
+        for (const v of message.headers) {
+            BlockHeader.encode(v!, writer.uint32(10).fork()).ldelim();
         }
         return writer;
     },
 
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): BroadcastTxResponse {
+    decode(input: _m0.Reader | Uint8Array, length?: number): BlockHeaders {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBroadcastTxResponse();
+        const message = createBaseBlockHeaders();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.txid = reader.bytes();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.headers.push(
+                        BlockHeader.decode(reader, reader.uint32()),
+                    );
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): BroadcastTxResponse {
+    fromJSON(object: any): BlockHeaders {
         return {
-            txid: isSet(object.txid)
-                ? bytesFromBase64(object.txid)
-                : new Uint8Array(),
+            headers: globalThis.Array.isArray(object?.headers)
+                ? object.headers.map((e: any) => BlockHeader.fromJSON(e))
+                : [],
         };
     },
 
-    toJSON(message: BroadcastTxResponse): unknown {
+    toJSON(message: BlockHeaders): unknown {
         const obj: any = {};
-        message.txid !== undefined &&
-            (obj.txid = base64FromBytes(
-                message.txid !== undefined ? message.txid : new Uint8Array(),
-            ));
+        if (message.headers?.length) {
+            obj.headers = message.headers.map(e => BlockHeader.toJSON(e));
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<BroadcastTxResponse>, I>>(
+    create<I extends Exact<DeepPartial<BlockHeaders>, I>>(
+        base?: I,
+    ): BlockHeaders {
+        return BlockHeaders.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<BlockHeaders>, I>>(
         object: I,
-    ): BroadcastTxResponse {
-        const message = createBaseBroadcastTxResponse();
-        message.txid = object.txid ?? new Uint8Array();
+    ): BlockHeaders {
+        const message = createBaseBlockHeaders();
+        message.headers =
+            object.headers?.map(e => BlockHeader.fromPartial(e)) || [];
         return message;
     },
 };
 
-function createBaseBroadcastTxsRequest(): BroadcastTxsRequest {
-    return { rawTxs: [], skipSlpCheck: false };
+function createBaseBlockchainInfo(): BlockchainInfo {
+    return { tipHash: new Uint8Array(0), tipHeight: 0 };
 }
 
-export const BroadcastTxsRequest = {
+export const BlockchainInfo = {
     encode(
-        message: BroadcastTxsRequest,
+        message: BlockchainInfo,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        for (const v of message.rawTxs) {
-            writer.uint32(10).bytes(v!);
+        if (message.tipHash.length !== 0) {
+            writer.uint32(10).bytes(message.tipHash);
         }
-        if (message.skipSlpCheck === true) {
-            writer.uint32(16).bool(message.skipSlpCheck);
+        if (message.tipHeight !== 0) {
+            writer.uint32(16).int32(message.tipHeight);
         }
         return writer;
     },
 
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): BroadcastTxsRequest {
+    decode(input: _m0.Reader | Uint8Array, length?: number): BlockchainInfo {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBroadcastTxsRequest();
+        const message = createBaseBlockchainInfo();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.rawTxs.push(reader.bytes());
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.tipHash = reader.bytes();
+                    continue;
                 case 2:
-                    message.skipSlpCheck = reader.bool();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 16) {
+                        break;
+                    }
+
+                    message.tipHeight = reader.int32();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): BroadcastTxsRequest {
+    fromJSON(object: any): BlockchainInfo {
         return {
-            rawTxs: Array.isArray(object?.rawTxs)
-                ? object.rawTxs.map((e: any) => bytesFromBase64(e))
-                : [],
-            skipSlpCheck: isSet(object.skipSlpCheck)
-                ? Boolean(object.skipSlpCheck)
-                : false,
+            tipHash: isSet(object.tipHash)
+                ? bytesFromBase64(object.tipHash)
+                : new Uint8Array(0),
+            tipHeight: isSet(object.tipHeight)
+                ? globalThis.Number(object.tipHeight)
+                : 0,
         };
     },
 
-    toJSON(message: BroadcastTxsRequest): unknown {
+    toJSON(message: BlockchainInfo): unknown {
         const obj: any = {};
-        if (message.rawTxs) {
-            obj.rawTxs = message.rawTxs.map(e =>
-                base64FromBytes(e !== undefined ? e : new Uint8Array()),
-            );
-        } else {
-            obj.rawTxs = [];
+        if (message.tipHash.length !== 0) {
+            obj.tipHash = base64FromBytes(message.tipHash);
+        }
+        if (message.tipHeight !== 0) {
+            obj.tipHeight = Math.round(message.tipHeight);
         }
-        message.skipSlpCheck !== undefined &&
-            (obj.skipSlpCheck = message.skipSlpCheck);
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<BroadcastTxsRequest>, I>>(
+    create<I extends Exact<DeepPartial<BlockchainInfo>, I>>(
+        base?: I,
+    ): BlockchainInfo {
+        return BlockchainInfo.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<BlockchainInfo>, I>>(
         object: I,
-    ): BroadcastTxsRequest {
-        const message = createBaseBroadcastTxsRequest();
-        message.rawTxs = object.rawTxs?.map(e => e) || [];
-        message.skipSlpCheck = object.skipSlpCheck ?? false;
+    ): BlockchainInfo {
+        const message = createBaseBlockchainInfo();
+        message.tipHash = object.tipHash ?? new Uint8Array(0);
+        message.tipHeight = object.tipHeight ?? 0;
         return message;
     },
 };
 
-function createBaseBroadcastTxsResponse(): BroadcastTxsResponse {
-    return { txids: [] };
+function createBaseChronikInfo(): ChronikInfo {
+    return { version: '' };
 }
 
-export const BroadcastTxsResponse = {
+export const ChronikInfo = {
     encode(
-        message: BroadcastTxsResponse,
+        message: ChronikInfo,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        for (const v of message.txids) {
-            writer.uint32(10).bytes(v!);
+        if (message.version !== '') {
+            writer.uint32(10).string(message.version);
         }
         return writer;
     },
 
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): BroadcastTxsResponse {
+    decode(input: _m0.Reader | Uint8Array, length?: number): ChronikInfo {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBroadcastTxsResponse();
+        const message = createBaseChronikInfo();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.txids.push(reader.bytes());
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.version = reader.string();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): BroadcastTxsResponse {
+    fromJSON(object: any): ChronikInfo {
         return {
-            txids: Array.isArray(object?.txids)
-                ? object.txids.map((e: any) => bytesFromBase64(e))
-                : [],
+            version: isSet(object.version)
+                ? globalThis.String(object.version)
+                : '',
         };
     },
 
-    toJSON(message: BroadcastTxsResponse): unknown {
+    toJSON(message: ChronikInfo): unknown {
         const obj: any = {};
-        if (message.txids) {
-            obj.txids = message.txids.map(e =>
-                base64FromBytes(e !== undefined ? e : new Uint8Array()),
-            );
-        } else {
-            obj.txids = [];
+        if (message.version !== '') {
+            obj.version = message.version;
         }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<BroadcastTxsResponse>, I>>(
+    create<I extends Exact<DeepPartial<ChronikInfo>, I>>(
+        base?: I,
+    ): ChronikInfo {
+        return ChronikInfo.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<ChronikInfo>, I>>(
         object: I,
-    ): BroadcastTxsResponse {
-        const message = createBaseBroadcastTxsResponse();
-        message.txids = object.txids?.map(e => e) || [];
+    ): ChronikInfo {
+        const message = createBaseChronikInfo();
+        message.version = object.version ?? '';
         return message;
     },
 };
 
-function createBaseBlockchainInfo(): BlockchainInfo {
-    return { tipHash: new Uint8Array(), tipHeight: 0 };
+function createBaseBlockInfo(): BlockInfo {
+    return {
+        hash: new Uint8Array(0),
+        prevHash: new Uint8Array(0),
+        height: 0,
+        nBits: 0,
+        timestamp: '0',
+        isFinal: false,
+        blockSize: '0',
+        numTxs: '0',
+        numInputs: '0',
+        numOutputs: '0',
+        sumInputSats: '0',
+        sumCoinbaseOutputSats: '0',
+        sumNormalOutputSats: '0',
+        sumBurnedSats: '0',
+    };
 }
 
-export const BlockchainInfo = {
+export const BlockInfo = {
     encode(
-        message: BlockchainInfo,
+        message: BlockInfo,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.tipHash.length !== 0) {
-            writer.uint32(10).bytes(message.tipHash);
+        if (message.hash.length !== 0) {
+            writer.uint32(10).bytes(message.hash);
         }
-        if (message.tipHeight !== 0) {
-            writer.uint32(16).int32(message.tipHeight);
+        if (message.prevHash.length !== 0) {
+            writer.uint32(18).bytes(message.prevHash);
+        }
+        if (message.height !== 0) {
+            writer.uint32(24).int32(message.height);
+        }
+        if (message.nBits !== 0) {
+            writer.uint32(32).uint32(message.nBits);
+        }
+        if (message.timestamp !== '0') {
+            writer.uint32(40).int64(message.timestamp);
+        }
+        if (message.isFinal === true) {
+            writer.uint32(112).bool(message.isFinal);
+        }
+        if (message.blockSize !== '0') {
+            writer.uint32(48).uint64(message.blockSize);
+        }
+        if (message.numTxs !== '0') {
+            writer.uint32(56).uint64(message.numTxs);
+        }
+        if (message.numInputs !== '0') {
+            writer.uint32(64).uint64(message.numInputs);
+        }
+        if (message.numOutputs !== '0') {
+            writer.uint32(72).uint64(message.numOutputs);
+        }
+        if (message.sumInputSats !== '0') {
+            writer.uint32(80).int64(message.sumInputSats);
+        }
+        if (message.sumCoinbaseOutputSats !== '0') {
+            writer.uint32(88).int64(message.sumCoinbaseOutputSats);
+        }
+        if (message.sumNormalOutputSats !== '0') {
+            writer.uint32(96).int64(message.sumNormalOutputSats);
+        }
+        if (message.sumBurnedSats !== '0') {
+            writer.uint32(104).int64(message.sumBurnedSats);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): BlockchainInfo {
+    decode(input: _m0.Reader | Uint8Array, length?: number): BlockInfo {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBlockchainInfo();
+        const message = createBaseBlockInfo();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.tipHash = reader.bytes();
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.hash = reader.bytes();
+                    continue;
                 case 2:
-                    message.tipHeight = reader.int32();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.prevHash = reader.bytes();
+                    continue;
+                case 3:
+                    if (tag !== 24) {
+                        break;
+                    }
+
+                    message.height = reader.int32();
+                    continue;
+                case 4:
+                    if (tag !== 32) {
+                        break;
+                    }
+
+                    message.nBits = reader.uint32();
+                    continue;
+                case 5:
+                    if (tag !== 40) {
+                        break;
+                    }
+
+                    message.timestamp = longToString(reader.int64() as Long);
+                    continue;
+                case 14:
+                    if (tag !== 112) {
+                        break;
+                    }
+
+                    message.isFinal = reader.bool();
+                    continue;
+                case 6:
+                    if (tag !== 48) {
+                        break;
+                    }
+
+                    message.blockSize = longToString(reader.uint64() as Long);
+                    continue;
+                case 7:
+                    if (tag !== 56) {
+                        break;
+                    }
+
+                    message.numTxs = longToString(reader.uint64() as Long);
+                    continue;
+                case 8:
+                    if (tag !== 64) {
+                        break;
+                    }
+
+                    message.numInputs = longToString(reader.uint64() as Long);
+                    continue;
+                case 9:
+                    if (tag !== 72) {
+                        break;
+                    }
+
+                    message.numOutputs = longToString(reader.uint64() as Long);
+                    continue;
+                case 10:
+                    if (tag !== 80) {
+                        break;
+                    }
+
+                    message.sumInputSats = longToString(reader.int64() as Long);
+                    continue;
+                case 11:
+                    if (tag !== 88) {
+                        break;
+                    }
+
+                    message.sumCoinbaseOutputSats = longToString(
+                        reader.int64() as Long,
+                    );
+                    continue;
+                case 12:
+                    if (tag !== 96) {
+                        break;
+                    }
+
+                    message.sumNormalOutputSats = longToString(
+                        reader.int64() as Long,
+                    );
+                    continue;
+                case 13:
+                    if (tag !== 104) {
+                        break;
+                    }
+
+                    message.sumBurnedSats = longToString(
+                        reader.int64() as Long,
+                    );
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): BlockchainInfo {
+    fromJSON(object: any): BlockInfo {
         return {
-            tipHash: isSet(object.tipHash)
-                ? bytesFromBase64(object.tipHash)
-                : new Uint8Array(),
-            tipHeight: isSet(object.tipHeight) ? Number(object.tipHeight) : 0,
+            hash: isSet(object.hash)
+                ? bytesFromBase64(object.hash)
+                : new Uint8Array(0),
+            prevHash: isSet(object.prevHash)
+                ? bytesFromBase64(object.prevHash)
+                : new Uint8Array(0),
+            height: isSet(object.height) ? globalThis.Number(object.height) : 0,
+            nBits: isSet(object.nBits) ? globalThis.Number(object.nBits) : 0,
+            timestamp: isSet(object.timestamp)
+                ? globalThis.String(object.timestamp)
+                : '0',
+            isFinal: isSet(object.isFinal)
+                ? globalThis.Boolean(object.isFinal)
+                : false,
+            blockSize: isSet(object.blockSize)
+                ? globalThis.String(object.blockSize)
+                : '0',
+            numTxs: isSet(object.numTxs)
+                ? globalThis.String(object.numTxs)
+                : '0',
+            numInputs: isSet(object.numInputs)
+                ? globalThis.String(object.numInputs)
+                : '0',
+            numOutputs: isSet(object.numOutputs)
+                ? globalThis.String(object.numOutputs)
+                : '0',
+            sumInputSats: isSet(object.sumInputSats)
+                ? globalThis.String(object.sumInputSats)
+                : '0',
+            sumCoinbaseOutputSats: isSet(object.sumCoinbaseOutputSats)
+                ? globalThis.String(object.sumCoinbaseOutputSats)
+                : '0',
+            sumNormalOutputSats: isSet(object.sumNormalOutputSats)
+                ? globalThis.String(object.sumNormalOutputSats)
+                : '0',
+            sumBurnedSats: isSet(object.sumBurnedSats)
+                ? globalThis.String(object.sumBurnedSats)
+                : '0',
         };
     },
 
-    toJSON(message: BlockchainInfo): unknown {
+    toJSON(message: BlockInfo): unknown {
         const obj: any = {};
-        message.tipHash !== undefined &&
-            (obj.tipHash = base64FromBytes(
-                message.tipHash !== undefined
-                    ? message.tipHash
-                    : new Uint8Array(),
-            ));
-        message.tipHeight !== undefined &&
-            (obj.tipHeight = Math.round(message.tipHeight));
+        if (message.hash.length !== 0) {
+            obj.hash = base64FromBytes(message.hash);
+        }
+        if (message.prevHash.length !== 0) {
+            obj.prevHash = base64FromBytes(message.prevHash);
+        }
+        if (message.height !== 0) {
+            obj.height = Math.round(message.height);
+        }
+        if (message.nBits !== 0) {
+            obj.nBits = Math.round(message.nBits);
+        }
+        if (message.timestamp !== '0') {
+            obj.timestamp = message.timestamp;
+        }
+        if (message.isFinal === true) {
+            obj.isFinal = message.isFinal;
+        }
+        if (message.blockSize !== '0') {
+            obj.blockSize = message.blockSize;
+        }
+        if (message.numTxs !== '0') {
+            obj.numTxs = message.numTxs;
+        }
+        if (message.numInputs !== '0') {
+            obj.numInputs = message.numInputs;
+        }
+        if (message.numOutputs !== '0') {
+            obj.numOutputs = message.numOutputs;
+        }
+        if (message.sumInputSats !== '0') {
+            obj.sumInputSats = message.sumInputSats;
+        }
+        if (message.sumCoinbaseOutputSats !== '0') {
+            obj.sumCoinbaseOutputSats = message.sumCoinbaseOutputSats;
+        }
+        if (message.sumNormalOutputSats !== '0') {
+            obj.sumNormalOutputSats = message.sumNormalOutputSats;
+        }
+        if (message.sumBurnedSats !== '0') {
+            obj.sumBurnedSats = message.sumBurnedSats;
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<BlockchainInfo>, I>>(
+    create<I extends Exact<DeepPartial<BlockInfo>, I>>(base?: I): BlockInfo {
+        return BlockInfo.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<BlockInfo>, I>>(
         object: I,
-    ): BlockchainInfo {
-        const message = createBaseBlockchainInfo();
-        message.tipHash = object.tipHash ?? new Uint8Array();
-        message.tipHeight = object.tipHeight ?? 0;
+    ): BlockInfo {
+        const message = createBaseBlockInfo();
+        message.hash = object.hash ?? new Uint8Array(0);
+        message.prevHash = object.prevHash ?? new Uint8Array(0);
+        message.height = object.height ?? 0;
+        message.nBits = object.nBits ?? 0;
+        message.timestamp = object.timestamp ?? '0';
+        message.isFinal = object.isFinal ?? false;
+        message.blockSize = object.blockSize ?? '0';
+        message.numTxs = object.numTxs ?? '0';
+        message.numInputs = object.numInputs ?? '0';
+        message.numOutputs = object.numOutputs ?? '0';
+        message.sumInputSats = object.sumInputSats ?? '0';
+        message.sumCoinbaseOutputSats = object.sumCoinbaseOutputSats ?? '0';
+        message.sumNormalOutputSats = object.sumNormalOutputSats ?? '0';
+        message.sumBurnedSats = object.sumBurnedSats ?? '0';
         return message;
     },
 };
 
 function createBaseTx(): Tx {
     return {
-        txid: new Uint8Array(),
+        txid: new Uint8Array(0),
         version: 0,
         inputs: [],
         outputs: [],
         lockTime: 0,
-        slpTxData: undefined,
-        slpErrorMsg: '',
         block: undefined,
         timeFirstSeen: '0',
         size: 0,
         isCoinbase: false,
-        network: 0,
+        tokenEntries: [],
+        tokenFailedParsings: [],
+        tokenStatus: 0,
     };
 }
 
@@ -954,15 +1583,6 @@
         if (message.lockTime !== 0) {
             writer.uint32(40).uint32(message.lockTime);
         }
-        if (message.slpTxData !== undefined) {
-            SlpTxData.encode(
-                message.slpTxData,
-                writer.uint32(50).fork(),
-            ).ldelim();
-        }
-        if (message.slpErrorMsg !== '') {
-            writer.uint32(58).string(message.slpErrorMsg);
-        }
         if (message.block !== undefined) {
             BlockMetadata.encode(
                 message.block,
@@ -978,72 +1598,128 @@
         if (message.isCoinbase === true) {
             writer.uint32(96).bool(message.isCoinbase);
         }
-        if (message.network !== 0) {
-            writer.uint32(80).int32(message.network);
+        for (const v of message.tokenEntries) {
+            TokenEntry.encode(v!, writer.uint32(106).fork()).ldelim();
+        }
+        for (const v of message.tokenFailedParsings) {
+            TokenFailedParsing.encode(v!, writer.uint32(114).fork()).ldelim();
+        }
+        if (message.tokenStatus !== 0) {
+            writer.uint32(120).int32(message.tokenStatus);
         }
         return writer;
     },
 
     decode(input: _m0.Reader | Uint8Array, length?: number): Tx {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
         const message = createBaseTx();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
+                    if (tag !== 10) {
+                        break;
+                    }
+
                     message.txid = reader.bytes();
-                    break;
+                    continue;
                 case 2:
+                    if (tag !== 16) {
+                        break;
+                    }
+
                     message.version = reader.int32();
-                    break;
+                    continue;
                 case 3:
+                    if (tag !== 26) {
+                        break;
+                    }
+
                     message.inputs.push(
                         TxInput.decode(reader, reader.uint32()),
                     );
-                    break;
+                    continue;
                 case 4:
+                    if (tag !== 34) {
+                        break;
+                    }
+
                     message.outputs.push(
                         TxOutput.decode(reader, reader.uint32()),
                     );
-                    break;
+                    continue;
                 case 5:
+                    if (tag !== 40) {
+                        break;
+                    }
+
                     message.lockTime = reader.uint32();
-                    break;
-                case 6:
-                    message.slpTxData = SlpTxData.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    break;
-                case 7:
-                    message.slpErrorMsg = reader.string();
-                    break;
+                    continue;
                 case 8:
+                    if (tag !== 66) {
+                        break;
+                    }
+
                     message.block = BlockMetadata.decode(
                         reader,
                         reader.uint32(),
                     );
-                    break;
+                    continue;
                 case 9:
+                    if (tag !== 72) {
+                        break;
+                    }
+
                     message.timeFirstSeen = longToString(
                         reader.int64() as Long,
                     );
-                    break;
+                    continue;
                 case 11:
+                    if (tag !== 88) {
+                        break;
+                    }
+
                     message.size = reader.uint32();
-                    break;
+                    continue;
                 case 12:
+                    if (tag !== 96) {
+                        break;
+                    }
+
                     message.isCoinbase = reader.bool();
-                    break;
-                case 10:
-                    message.network = reader.int32() as any;
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    continue;
+                case 13:
+                    if (tag !== 106) {
+                        break;
+                    }
+
+                    message.tokenEntries.push(
+                        TokenEntry.decode(reader, reader.uint32()),
+                    );
+                    continue;
+                case 14:
+                    if (tag !== 114) {
+                        break;
+                    }
+
+                    message.tokenFailedParsings.push(
+                        TokenFailedParsing.decode(reader, reader.uint32()),
+                    );
+                    continue;
+                case 15:
+                    if (tag !== 120) {
+                        break;
+                    }
+
+                    message.tokenStatus = reader.int32() as any;
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
@@ -1052,94 +1728,101 @@
         return {
             txid: isSet(object.txid)
                 ? bytesFromBase64(object.txid)
-                : new Uint8Array(),
-            version: isSet(object.version) ? Number(object.version) : 0,
-            inputs: Array.isArray(object?.inputs)
+                : new Uint8Array(0),
+            version: isSet(object.version)
+                ? globalThis.Number(object.version)
+                : 0,
+            inputs: globalThis.Array.isArray(object?.inputs)
                 ? object.inputs.map((e: any) => TxInput.fromJSON(e))
                 : [],
-            outputs: Array.isArray(object?.outputs)
+            outputs: globalThis.Array.isArray(object?.outputs)
                 ? object.outputs.map((e: any) => TxOutput.fromJSON(e))
                 : [],
-            lockTime: isSet(object.lockTime) ? Number(object.lockTime) : 0,
-            slpTxData: isSet(object.slpTxData)
-                ? SlpTxData.fromJSON(object.slpTxData)
-                : undefined,
-            slpErrorMsg: isSet(object.slpErrorMsg)
-                ? String(object.slpErrorMsg)
-                : '',
+            lockTime: isSet(object.lockTime)
+                ? globalThis.Number(object.lockTime)
+                : 0,
             block: isSet(object.block)
                 ? BlockMetadata.fromJSON(object.block)
                 : undefined,
             timeFirstSeen: isSet(object.timeFirstSeen)
-                ? String(object.timeFirstSeen)
+                ? globalThis.String(object.timeFirstSeen)
                 : '0',
-            size: isSet(object.size) ? Number(object.size) : 0,
+            size: isSet(object.size) ? globalThis.Number(object.size) : 0,
             isCoinbase: isSet(object.isCoinbase)
-                ? Boolean(object.isCoinbase)
+                ? globalThis.Boolean(object.isCoinbase)
                 : false,
-            network: isSet(object.network)
-                ? networkFromJSON(object.network)
+            tokenEntries: globalThis.Array.isArray(object?.tokenEntries)
+                ? object.tokenEntries.map((e: any) => TokenEntry.fromJSON(e))
+                : [],
+            tokenFailedParsings: globalThis.Array.isArray(
+                object?.tokenFailedParsings,
+            )
+                ? object.tokenFailedParsings.map((e: any) =>
+                      TokenFailedParsing.fromJSON(e),
+                  )
+                : [],
+            tokenStatus: isSet(object.tokenStatus)
+                ? tokenStatusFromJSON(object.tokenStatus)
                 : 0,
         };
     },
 
     toJSON(message: Tx): unknown {
         const obj: any = {};
-        message.txid !== undefined &&
-            (obj.txid = base64FromBytes(
-                message.txid !== undefined ? message.txid : new Uint8Array(),
-            ));
-        message.version !== undefined &&
-            (obj.version = Math.round(message.version));
-        if (message.inputs) {
-            obj.inputs = message.inputs.map(e =>
-                e ? TxInput.toJSON(e) : undefined,
+        if (message.txid.length !== 0) {
+            obj.txid = base64FromBytes(message.txid);
+        }
+        if (message.version !== 0) {
+            obj.version = Math.round(message.version);
+        }
+        if (message.inputs?.length) {
+            obj.inputs = message.inputs.map(e => TxInput.toJSON(e));
+        }
+        if (message.outputs?.length) {
+            obj.outputs = message.outputs.map(e => TxOutput.toJSON(e));
+        }
+        if (message.lockTime !== 0) {
+            obj.lockTime = Math.round(message.lockTime);
+        }
+        if (message.block !== undefined) {
+            obj.block = BlockMetadata.toJSON(message.block);
+        }
+        if (message.timeFirstSeen !== '0') {
+            obj.timeFirstSeen = message.timeFirstSeen;
+        }
+        if (message.size !== 0) {
+            obj.size = Math.round(message.size);
+        }
+        if (message.isCoinbase === true) {
+            obj.isCoinbase = message.isCoinbase;
+        }
+        if (message.tokenEntries?.length) {
+            obj.tokenEntries = message.tokenEntries.map(e =>
+                TokenEntry.toJSON(e),
             );
-        } else {
-            obj.inputs = [];
         }
-        if (message.outputs) {
-            obj.outputs = message.outputs.map(e =>
-                e ? TxOutput.toJSON(e) : undefined,
+        if (message.tokenFailedParsings?.length) {
+            obj.tokenFailedParsings = message.tokenFailedParsings.map(e =>
+                TokenFailedParsing.toJSON(e),
             );
-        } else {
-            obj.outputs = [];
-        }
-        message.lockTime !== undefined &&
-            (obj.lockTime = Math.round(message.lockTime));
-        message.slpTxData !== undefined &&
-            (obj.slpTxData = message.slpTxData
-                ? SlpTxData.toJSON(message.slpTxData)
-                : undefined);
-        message.slpErrorMsg !== undefined &&
-            (obj.slpErrorMsg = message.slpErrorMsg);
-        message.block !== undefined &&
-            (obj.block = message.block
-                ? BlockMetadata.toJSON(message.block)
-                : undefined);
-        message.timeFirstSeen !== undefined &&
-            (obj.timeFirstSeen = message.timeFirstSeen);
-        message.size !== undefined && (obj.size = Math.round(message.size));
-        message.isCoinbase !== undefined &&
-            (obj.isCoinbase = message.isCoinbase);
-        message.network !== undefined &&
-            (obj.network = networkToJSON(message.network));
+        }
+        if (message.tokenStatus !== 0) {
+            obj.tokenStatus = tokenStatusToJSON(message.tokenStatus);
+        }
         return obj;
     },
 
+    create<I extends Exact<DeepPartial<Tx>, I>>(base?: I): Tx {
+        return Tx.fromPartial(base ?? ({} as any));
+    },
     fromPartial<I extends Exact<DeepPartial<Tx>, I>>(object: I): Tx {
         const message = createBaseTx();
-        message.txid = object.txid ?? new Uint8Array();
+        message.txid = object.txid ?? new Uint8Array(0);
         message.version = object.version ?? 0;
         message.inputs = object.inputs?.map(e => TxInput.fromPartial(e)) || [];
         message.outputs =
             object.outputs?.map(e => TxOutput.fromPartial(e)) || [];
         message.lockTime = object.lockTime ?? 0;
-        message.slpTxData =
-            object.slpTxData !== undefined && object.slpTxData !== null
-                ? SlpTxData.fromPartial(object.slpTxData)
-                : undefined;
-        message.slpErrorMsg = object.slpErrorMsg ?? '';
         message.block =
             object.block !== undefined && object.block !== null
                 ? BlockMetadata.fromPartial(object.block)
@@ -1147,26 +1830,32 @@
         message.timeFirstSeen = object.timeFirstSeen ?? '0';
         message.size = object.size ?? 0;
         message.isCoinbase = object.isCoinbase ?? false;
-        message.network = object.network ?? 0;
+        message.tokenEntries =
+            object.tokenEntries?.map(e => TokenEntry.fromPartial(e)) || [];
+        message.tokenFailedParsings =
+            object.tokenFailedParsings?.map(e =>
+                TokenFailedParsing.fromPartial(e),
+            ) || [];
+        message.tokenStatus = object.tokenStatus ?? 0;
         return message;
     },
 };
 
-function createBaseUtxo(): Utxo {
+function createBaseScriptUtxo(): ScriptUtxo {
     return {
         outpoint: undefined,
         blockHeight: 0,
         isCoinbase: false,
         value: '0',
-        slpMeta: undefined,
-        slpToken: undefined,
-        network: 0,
+        isFinal: false,
+        token: undefined,
+        plugins: {},
     };
 }
 
-export const Utxo = {
+export const ScriptUtxo = {
     encode(
-        message: Utxo,
+        message: ScriptUtxo,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
         if (message.outpoint !== undefined) {
@@ -1184,108 +1873,161 @@
         if (message.value !== '0') {
             writer.uint32(40).int64(message.value);
         }
-        if (message.slpMeta !== undefined) {
-            SlpMeta.encode(message.slpMeta, writer.uint32(50).fork()).ldelim();
+        if (message.isFinal === true) {
+            writer.uint32(80).bool(message.isFinal);
         }
-        if (message.slpToken !== undefined) {
-            SlpToken.encode(
-                message.slpToken,
-                writer.uint32(58).fork(),
-            ).ldelim();
-        }
-        if (message.network !== 0) {
-            writer.uint32(72).int32(message.network);
+        if (message.token !== undefined) {
+            Token.encode(message.token, writer.uint32(90).fork()).ldelim();
         }
+        Object.entries(message.plugins).forEach(([key, value]) => {
+            ScriptUtxo_PluginsEntry.encode(
+                { key: key as any, value },
+                writer.uint32(98).fork(),
+            ).ldelim();
+        });
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): Utxo {
+    decode(input: _m0.Reader | Uint8Array, length?: number): ScriptUtxo {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseUtxo();
+        const message = createBaseScriptUtxo();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
+                    if (tag !== 10) {
+                        break;
+                    }
+
                     message.outpoint = OutPoint.decode(reader, reader.uint32());
-                    break;
+                    continue;
                 case 2:
+                    if (tag !== 16) {
+                        break;
+                    }
+
                     message.blockHeight = reader.int32();
-                    break;
+                    continue;
                 case 3:
+                    if (tag !== 24) {
+                        break;
+                    }
+
                     message.isCoinbase = reader.bool();
-                    break;
+                    continue;
                 case 5:
+                    if (tag !== 40) {
+                        break;
+                    }
+
                     message.value = longToString(reader.int64() as Long);
-                    break;
-                case 6:
-                    message.slpMeta = SlpMeta.decode(reader, reader.uint32());
-                    break;
-                case 7:
-                    message.slpToken = SlpToken.decode(reader, reader.uint32());
-                    break;
-                case 9:
-                    message.network = reader.int32() as any;
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    continue;
+                case 10:
+                    if (tag !== 80) {
+                        break;
+                    }
+
+                    message.isFinal = reader.bool();
+                    continue;
+                case 11:
+                    if (tag !== 90) {
+                        break;
+                    }
+
+                    message.token = Token.decode(reader, reader.uint32());
+                    continue;
+                case 12:
+                    if (tag !== 98) {
+                        break;
+                    }
+
+                    const entry12 = ScriptUtxo_PluginsEntry.decode(
+                        reader,
+                        reader.uint32(),
+                    );
+                    if (entry12.value !== undefined) {
+                        message.plugins[entry12.key] = entry12.value;
+                    }
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): Utxo {
+    fromJSON(object: any): ScriptUtxo {
         return {
             outpoint: isSet(object.outpoint)
                 ? OutPoint.fromJSON(object.outpoint)
                 : undefined,
             blockHeight: isSet(object.blockHeight)
-                ? Number(object.blockHeight)
+                ? globalThis.Number(object.blockHeight)
                 : 0,
             isCoinbase: isSet(object.isCoinbase)
-                ? Boolean(object.isCoinbase)
+                ? globalThis.Boolean(object.isCoinbase)
                 : false,
-            value: isSet(object.value) ? String(object.value) : '0',
-            slpMeta: isSet(object.slpMeta)
-                ? SlpMeta.fromJSON(object.slpMeta)
-                : undefined,
-            slpToken: isSet(object.slpToken)
-                ? SlpToken.fromJSON(object.slpToken)
+            value: isSet(object.value) ? globalThis.String(object.value) : '0',
+            isFinal: isSet(object.isFinal)
+                ? globalThis.Boolean(object.isFinal)
+                : false,
+            token: isSet(object.token)
+                ? Token.fromJSON(object.token)
                 : undefined,
-            network: isSet(object.network)
-                ? networkFromJSON(object.network)
-                : 0,
+            plugins: isObject(object.plugins)
+                ? Object.entries(object.plugins).reduce<{
+                      [key: string]: PluginEntry;
+                  }>((acc, [key, value]) => {
+                      acc[key] = PluginEntry.fromJSON(value);
+                      return acc;
+                  }, {})
+                : {},
         };
     },
 
-    toJSON(message: Utxo): unknown {
+    toJSON(message: ScriptUtxo): unknown {
         const obj: any = {};
-        message.outpoint !== undefined &&
-            (obj.outpoint = message.outpoint
-                ? OutPoint.toJSON(message.outpoint)
-                : undefined);
-        message.blockHeight !== undefined &&
-            (obj.blockHeight = Math.round(message.blockHeight));
-        message.isCoinbase !== undefined &&
-            (obj.isCoinbase = message.isCoinbase);
-        message.value !== undefined && (obj.value = message.value);
-        message.slpMeta !== undefined &&
-            (obj.slpMeta = message.slpMeta
-                ? SlpMeta.toJSON(message.slpMeta)
-                : undefined);
-        message.slpToken !== undefined &&
-            (obj.slpToken = message.slpToken
-                ? SlpToken.toJSON(message.slpToken)
-                : undefined);
-        message.network !== undefined &&
-            (obj.network = networkToJSON(message.network));
+        if (message.outpoint !== undefined) {
+            obj.outpoint = OutPoint.toJSON(message.outpoint);
+        }
+        if (message.blockHeight !== 0) {
+            obj.blockHeight = Math.round(message.blockHeight);
+        }
+        if (message.isCoinbase === true) {
+            obj.isCoinbase = message.isCoinbase;
+        }
+        if (message.value !== '0') {
+            obj.value = message.value;
+        }
+        if (message.isFinal === true) {
+            obj.isFinal = message.isFinal;
+        }
+        if (message.token !== undefined) {
+            obj.token = Token.toJSON(message.token);
+        }
+        if (message.plugins) {
+            const entries = Object.entries(message.plugins);
+            if (entries.length > 0) {
+                obj.plugins = {};
+                entries.forEach(([k, v]) => {
+                    obj.plugins[k] = PluginEntry.toJSON(v);
+                });
+            }
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<Utxo>, I>>(object: I): Utxo {
-        const message = createBaseUtxo();
+    create<I extends Exact<DeepPartial<ScriptUtxo>, I>>(base?: I): ScriptUtxo {
+        return ScriptUtxo.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<ScriptUtxo>, I>>(
+        object: I,
+    ): ScriptUtxo {
+        const message = createBaseScriptUtxo();
         message.outpoint =
             object.outpoint !== undefined && object.outpoint !== null
                 ? OutPoint.fromPartial(object.outpoint)
@@ -1293,2603 +2035,3998 @@
         message.blockHeight = object.blockHeight ?? 0;
         message.isCoinbase = object.isCoinbase ?? false;
         message.value = object.value ?? '0';
-        message.slpMeta =
-            object.slpMeta !== undefined && object.slpMeta !== null
-                ? SlpMeta.fromPartial(object.slpMeta)
-                : undefined;
-        message.slpToken =
-            object.slpToken !== undefined && object.slpToken !== null
-                ? SlpToken.fromPartial(object.slpToken)
+        message.isFinal = object.isFinal ?? false;
+        message.token =
+            object.token !== undefined && object.token !== null
+                ? Token.fromPartial(object.token)
                 : undefined;
-        message.network = object.network ?? 0;
+        message.plugins = Object.entries(object.plugins ?? {}).reduce<{
+            [key: string]: PluginEntry;
+        }>((acc, [key, value]) => {
+            if (value !== undefined) {
+                acc[key] = PluginEntry.fromPartial(value);
+            }
+            return acc;
+        }, {});
         return message;
     },
 };
 
-function createBaseToken(): Token {
-    return {
-        slpTxData: undefined,
-        tokenStats: undefined,
-        block: undefined,
-        timeFirstSeen: '0',
-        initialTokenQuantity: '0',
-        containsBaton: false,
-        network: 0,
-    };
+function createBaseScriptUtxo_PluginsEntry(): ScriptUtxo_PluginsEntry {
+    return { key: '', value: undefined };
 }
 
-export const Token = {
+export const ScriptUtxo_PluginsEntry = {
     encode(
-        message: Token,
+        message: ScriptUtxo_PluginsEntry,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.slpTxData !== undefined) {
-            SlpTxData.encode(
-                message.slpTxData,
-                writer.uint32(10).fork(),
-            ).ldelim();
+        if (message.key !== '') {
+            writer.uint32(10).string(message.key);
         }
-        if (message.tokenStats !== undefined) {
-            TokenStats.encode(
-                message.tokenStats,
+        if (message.value !== undefined) {
+            PluginEntry.encode(
+                message.value,
                 writer.uint32(18).fork(),
             ).ldelim();
         }
-        if (message.block !== undefined) {
-            BlockMetadata.encode(
-                message.block,
-                writer.uint32(26).fork(),
-            ).ldelim();
-        }
-        if (message.timeFirstSeen !== '0') {
-            writer.uint32(32).int64(message.timeFirstSeen);
-        }
-        if (message.initialTokenQuantity !== '0') {
-            writer.uint32(40).uint64(message.initialTokenQuantity);
-        }
-        if (message.containsBaton === true) {
-            writer.uint32(48).bool(message.containsBaton);
-        }
-        if (message.network !== 0) {
-            writer.uint32(56).int32(message.network);
-        }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): Token {
+    decode(
+        input: _m0.Reader | Uint8Array,
+        length?: number,
+    ): ScriptUtxo_PluginsEntry {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseToken();
+        const message = createBaseScriptUtxo_PluginsEntry();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.slpTxData = SlpTxData.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.key = reader.string();
+                    continue;
                 case 2:
-                    message.tokenStats = TokenStats.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    break;
-                case 3:
-                    message.block = BlockMetadata.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    break;
-                case 4:
-                    message.timeFirstSeen = longToString(
-                        reader.int64() as Long,
-                    );
-                    break;
-                case 5:
-                    message.initialTokenQuantity = longToString(
-                        reader.uint64() as Long,
-                    );
-                    break;
-                case 6:
-                    message.containsBaton = reader.bool();
-                    break;
-                case 7:
-                    message.network = reader.int32() as any;
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.value = PluginEntry.decode(reader, reader.uint32());
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): Token {
+    fromJSON(object: any): ScriptUtxo_PluginsEntry {
         return {
-            slpTxData: isSet(object.slpTxData)
-                ? SlpTxData.fromJSON(object.slpTxData)
-                : undefined,
-            tokenStats: isSet(object.tokenStats)
-                ? TokenStats.fromJSON(object.tokenStats)
-                : undefined,
-            block: isSet(object.block)
-                ? BlockMetadata.fromJSON(object.block)
+            key: isSet(object.key) ? globalThis.String(object.key) : '',
+            value: isSet(object.value)
+                ? PluginEntry.fromJSON(object.value)
                 : undefined,
-            timeFirstSeen: isSet(object.timeFirstSeen)
-                ? String(object.timeFirstSeen)
-                : '0',
-            initialTokenQuantity: isSet(object.initialTokenQuantity)
-                ? String(object.initialTokenQuantity)
-                : '0',
-            containsBaton: isSet(object.containsBaton)
-                ? Boolean(object.containsBaton)
-                : false,
-            network: isSet(object.network)
-                ? networkFromJSON(object.network)
-                : 0,
         };
     },
 
-    toJSON(message: Token): unknown {
+    toJSON(message: ScriptUtxo_PluginsEntry): unknown {
         const obj: any = {};
-        message.slpTxData !== undefined &&
-            (obj.slpTxData = message.slpTxData
-                ? SlpTxData.toJSON(message.slpTxData)
-                : undefined);
-        message.tokenStats !== undefined &&
-            (obj.tokenStats = message.tokenStats
-                ? TokenStats.toJSON(message.tokenStats)
-                : undefined);
-        message.block !== undefined &&
-            (obj.block = message.block
-                ? BlockMetadata.toJSON(message.block)
-                : undefined);
-        message.timeFirstSeen !== undefined &&
-            (obj.timeFirstSeen = message.timeFirstSeen);
-        message.initialTokenQuantity !== undefined &&
-            (obj.initialTokenQuantity = message.initialTokenQuantity);
-        message.containsBaton !== undefined &&
-            (obj.containsBaton = message.containsBaton);
-        message.network !== undefined &&
-            (obj.network = networkToJSON(message.network));
+        if (message.key !== '') {
+            obj.key = message.key;
+        }
+        if (message.value !== undefined) {
+            obj.value = PluginEntry.toJSON(message.value);
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<Token>, I>>(object: I): Token {
-        const message = createBaseToken();
-        message.slpTxData =
-            object.slpTxData !== undefined && object.slpTxData !== null
-                ? SlpTxData.fromPartial(object.slpTxData)
-                : undefined;
-        message.tokenStats =
-            object.tokenStats !== undefined && object.tokenStats !== null
-                ? TokenStats.fromPartial(object.tokenStats)
-                : undefined;
-        message.block =
-            object.block !== undefined && object.block !== null
-                ? BlockMetadata.fromPartial(object.block)
+    create<I extends Exact<DeepPartial<ScriptUtxo_PluginsEntry>, I>>(
+        base?: I,
+    ): ScriptUtxo_PluginsEntry {
+        return ScriptUtxo_PluginsEntry.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<ScriptUtxo_PluginsEntry>, I>>(
+        object: I,
+    ): ScriptUtxo_PluginsEntry {
+        const message = createBaseScriptUtxo_PluginsEntry();
+        message.key = object.key ?? '';
+        message.value =
+            object.value !== undefined && object.value !== null
+                ? PluginEntry.fromPartial(object.value)
                 : undefined;
-        message.timeFirstSeen = object.timeFirstSeen ?? '0';
-        message.initialTokenQuantity = object.initialTokenQuantity ?? '0';
-        message.containsBaton = object.containsBaton ?? false;
-        message.network = object.network ?? 0;
         return message;
     },
 };
 
-function createBaseBlockInfo(): BlockInfo {
+function createBaseUtxo(): Utxo {
     return {
-        hash: new Uint8Array(),
-        prevHash: new Uint8Array(),
-        height: 0,
-        nBits: 0,
-        timestamp: '0',
-        blockSize: '0',
-        numTxs: '0',
-        numInputs: '0',
-        numOutputs: '0',
-        sumInputSats: '0',
-        sumCoinbaseOutputSats: '0',
-        sumNormalOutputSats: '0',
-        sumBurnedSats: '0',
+        outpoint: undefined,
+        blockHeight: 0,
+        isCoinbase: false,
+        value: '0',
+        script: new Uint8Array(0),
+        isFinal: false,
+        token: undefined,
+        plugins: {},
+    };
+}
+
+export const Utxo = {
+    encode(
+        message: Utxo,
+        writer: _m0.Writer = _m0.Writer.create(),
+    ): _m0.Writer {
+        if (message.outpoint !== undefined) {
+            OutPoint.encode(
+                message.outpoint,
+                writer.uint32(10).fork(),
+            ).ldelim();
+        }
+        if (message.blockHeight !== 0) {
+            writer.uint32(16).int32(message.blockHeight);
+        }
+        if (message.isCoinbase === true) {
+            writer.uint32(24).bool(message.isCoinbase);
+        }
+        if (message.value !== '0') {
+            writer.uint32(32).int64(message.value);
+        }
+        if (message.script.length !== 0) {
+            writer.uint32(42).bytes(message.script);
+        }
+        if (message.isFinal === true) {
+            writer.uint32(48).bool(message.isFinal);
+        }
+        if (message.token !== undefined) {
+            Token.encode(message.token, writer.uint32(58).fork()).ldelim();
+        }
+        Object.entries(message.plugins).forEach(([key, value]) => {
+            Utxo_PluginsEntry.encode(
+                { key: key as any, value },
+                writer.uint32(66).fork(),
+            ).ldelim();
+        });
+        return writer;
+    },
+
+    decode(input: _m0.Reader | Uint8Array, length?: number): Utxo {
+        const reader =
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
+        let end = length === undefined ? reader.len : reader.pos + length;
+        const message = createBaseUtxo();
+        while (reader.pos < end) {
+            const tag = reader.uint32();
+            switch (tag >>> 3) {
+                case 1:
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.outpoint = OutPoint.decode(reader, reader.uint32());
+                    continue;
+                case 2:
+                    if (tag !== 16) {
+                        break;
+                    }
+
+                    message.blockHeight = reader.int32();
+                    continue;
+                case 3:
+                    if (tag !== 24) {
+                        break;
+                    }
+
+                    message.isCoinbase = reader.bool();
+                    continue;
+                case 4:
+                    if (tag !== 32) {
+                        break;
+                    }
+
+                    message.value = longToString(reader.int64() as Long);
+                    continue;
+                case 5:
+                    if (tag !== 42) {
+                        break;
+                    }
+
+                    message.script = reader.bytes();
+                    continue;
+                case 6:
+                    if (tag !== 48) {
+                        break;
+                    }
+
+                    message.isFinal = reader.bool();
+                    continue;
+                case 7:
+                    if (tag !== 58) {
+                        break;
+                    }
+
+                    message.token = Token.decode(reader, reader.uint32());
+                    continue;
+                case 8:
+                    if (tag !== 66) {
+                        break;
+                    }
+
+                    const entry8 = Utxo_PluginsEntry.decode(
+                        reader,
+                        reader.uint32(),
+                    );
+                    if (entry8.value !== undefined) {
+                        message.plugins[entry8.key] = entry8.value;
+                    }
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
+        }
+        return message;
+    },
+
+    fromJSON(object: any): Utxo {
+        return {
+            outpoint: isSet(object.outpoint)
+                ? OutPoint.fromJSON(object.outpoint)
+                : undefined,
+            blockHeight: isSet(object.blockHeight)
+                ? globalThis.Number(object.blockHeight)
+                : 0,
+            isCoinbase: isSet(object.isCoinbase)
+                ? globalThis.Boolean(object.isCoinbase)
+                : false,
+            value: isSet(object.value) ? globalThis.String(object.value) : '0',
+            script: isSet(object.script)
+                ? bytesFromBase64(object.script)
+                : new Uint8Array(0),
+            isFinal: isSet(object.isFinal)
+                ? globalThis.Boolean(object.isFinal)
+                : false,
+            token: isSet(object.token)
+                ? Token.fromJSON(object.token)
+                : undefined,
+            plugins: isObject(object.plugins)
+                ? Object.entries(object.plugins).reduce<{
+                      [key: string]: PluginEntry;
+                  }>((acc, [key, value]) => {
+                      acc[key] = PluginEntry.fromJSON(value);
+                      return acc;
+                  }, {})
+                : {},
+        };
+    },
+
+    toJSON(message: Utxo): unknown {
+        const obj: any = {};
+        if (message.outpoint !== undefined) {
+            obj.outpoint = OutPoint.toJSON(message.outpoint);
+        }
+        if (message.blockHeight !== 0) {
+            obj.blockHeight = Math.round(message.blockHeight);
+        }
+        if (message.isCoinbase === true) {
+            obj.isCoinbase = message.isCoinbase;
+        }
+        if (message.value !== '0') {
+            obj.value = message.value;
+        }
+        if (message.script.length !== 0) {
+            obj.script = base64FromBytes(message.script);
+        }
+        if (message.isFinal === true) {
+            obj.isFinal = message.isFinal;
+        }
+        if (message.token !== undefined) {
+            obj.token = Token.toJSON(message.token);
+        }
+        if (message.plugins) {
+            const entries = Object.entries(message.plugins);
+            if (entries.length > 0) {
+                obj.plugins = {};
+                entries.forEach(([k, v]) => {
+                    obj.plugins[k] = PluginEntry.toJSON(v);
+                });
+            }
+        }
+        return obj;
+    },
+
+    create<I extends Exact<DeepPartial<Utxo>, I>>(base?: I): Utxo {
+        return Utxo.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<Utxo>, I>>(object: I): Utxo {
+        const message = createBaseUtxo();
+        message.outpoint =
+            object.outpoint !== undefined && object.outpoint !== null
+                ? OutPoint.fromPartial(object.outpoint)
+                : undefined;
+        message.blockHeight = object.blockHeight ?? 0;
+        message.isCoinbase = object.isCoinbase ?? false;
+        message.value = object.value ?? '0';
+        message.script = object.script ?? new Uint8Array(0);
+        message.isFinal = object.isFinal ?? false;
+        message.token =
+            object.token !== undefined && object.token !== null
+                ? Token.fromPartial(object.token)
+                : undefined;
+        message.plugins = Object.entries(object.plugins ?? {}).reduce<{
+            [key: string]: PluginEntry;
+        }>((acc, [key, value]) => {
+            if (value !== undefined) {
+                acc[key] = PluginEntry.fromPartial(value);
+            }
+            return acc;
+        }, {});
+        return message;
+    },
+};
+
+function createBaseUtxo_PluginsEntry(): Utxo_PluginsEntry {
+    return { key: '', value: undefined };
+}
+
+export const Utxo_PluginsEntry = {
+    encode(
+        message: Utxo_PluginsEntry,
+        writer: _m0.Writer = _m0.Writer.create(),
+    ): _m0.Writer {
+        if (message.key !== '') {
+            writer.uint32(10).string(message.key);
+        }
+        if (message.value !== undefined) {
+            PluginEntry.encode(
+                message.value,
+                writer.uint32(18).fork(),
+            ).ldelim();
+        }
+        return writer;
+    },
+
+    decode(input: _m0.Reader | Uint8Array, length?: number): Utxo_PluginsEntry {
+        const reader =
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
+        let end = length === undefined ? reader.len : reader.pos + length;
+        const message = createBaseUtxo_PluginsEntry();
+        while (reader.pos < end) {
+            const tag = reader.uint32();
+            switch (tag >>> 3) {
+                case 1:
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.key = reader.string();
+                    continue;
+                case 2:
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.value = PluginEntry.decode(reader, reader.uint32());
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
+        }
+        return message;
+    },
+
+    fromJSON(object: any): Utxo_PluginsEntry {
+        return {
+            key: isSet(object.key) ? globalThis.String(object.key) : '',
+            value: isSet(object.value)
+                ? PluginEntry.fromJSON(object.value)
+                : undefined,
+        };
+    },
+
+    toJSON(message: Utxo_PluginsEntry): unknown {
+        const obj: any = {};
+        if (message.key !== '') {
+            obj.key = message.key;
+        }
+        if (message.value !== undefined) {
+            obj.value = PluginEntry.toJSON(message.value);
+        }
+        return obj;
+    },
+
+    create<I extends Exact<DeepPartial<Utxo_PluginsEntry>, I>>(
+        base?: I,
+    ): Utxo_PluginsEntry {
+        return Utxo_PluginsEntry.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<Utxo_PluginsEntry>, I>>(
+        object: I,
+    ): Utxo_PluginsEntry {
+        const message = createBaseUtxo_PluginsEntry();
+        message.key = object.key ?? '';
+        message.value =
+            object.value !== undefined && object.value !== null
+                ? PluginEntry.fromPartial(object.value)
+                : undefined;
+        return message;
+    },
+};
+
+function createBaseOutPoint(): OutPoint {
+    return { txid: new Uint8Array(0), outIdx: 0 };
+}
+
+export const OutPoint = {
+    encode(
+        message: OutPoint,
+        writer: _m0.Writer = _m0.Writer.create(),
+    ): _m0.Writer {
+        if (message.txid.length !== 0) {
+            writer.uint32(10).bytes(message.txid);
+        }
+        if (message.outIdx !== 0) {
+            writer.uint32(16).uint32(message.outIdx);
+        }
+        return writer;
+    },
+
+    decode(input: _m0.Reader | Uint8Array, length?: number): OutPoint {
+        const reader =
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
+        let end = length === undefined ? reader.len : reader.pos + length;
+        const message = createBaseOutPoint();
+        while (reader.pos < end) {
+            const tag = reader.uint32();
+            switch (tag >>> 3) {
+                case 1:
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.txid = reader.bytes();
+                    continue;
+                case 2:
+                    if (tag !== 16) {
+                        break;
+                    }
+
+                    message.outIdx = reader.uint32();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
+        }
+        return message;
+    },
+
+    fromJSON(object: any): OutPoint {
+        return {
+            txid: isSet(object.txid)
+                ? bytesFromBase64(object.txid)
+                : new Uint8Array(0),
+            outIdx: isSet(object.outIdx) ? globalThis.Number(object.outIdx) : 0,
+        };
+    },
+
+    toJSON(message: OutPoint): unknown {
+        const obj: any = {};
+        if (message.txid.length !== 0) {
+            obj.txid = base64FromBytes(message.txid);
+        }
+        if (message.outIdx !== 0) {
+            obj.outIdx = Math.round(message.outIdx);
+        }
+        return obj;
+    },
+
+    create<I extends Exact<DeepPartial<OutPoint>, I>>(base?: I): OutPoint {
+        return OutPoint.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<OutPoint>, I>>(
+        object: I,
+    ): OutPoint {
+        const message = createBaseOutPoint();
+        message.txid = object.txid ?? new Uint8Array(0);
+        message.outIdx = object.outIdx ?? 0;
+        return message;
+    },
+};
+
+function createBaseSpentBy(): SpentBy {
+    return { txid: new Uint8Array(0), inputIdx: 0 };
+}
+
+export const SpentBy = {
+    encode(
+        message: SpentBy,
+        writer: _m0.Writer = _m0.Writer.create(),
+    ): _m0.Writer {
+        if (message.txid.length !== 0) {
+            writer.uint32(10).bytes(message.txid);
+        }
+        if (message.inputIdx !== 0) {
+            writer.uint32(16).uint32(message.inputIdx);
+        }
+        return writer;
+    },
+
+    decode(input: _m0.Reader | Uint8Array, length?: number): SpentBy {
+        const reader =
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
+        let end = length === undefined ? reader.len : reader.pos + length;
+        const message = createBaseSpentBy();
+        while (reader.pos < end) {
+            const tag = reader.uint32();
+            switch (tag >>> 3) {
+                case 1:
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.txid = reader.bytes();
+                    continue;
+                case 2:
+                    if (tag !== 16) {
+                        break;
+                    }
+
+                    message.inputIdx = reader.uint32();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
+        }
+        return message;
+    },
+
+    fromJSON(object: any): SpentBy {
+        return {
+            txid: isSet(object.txid)
+                ? bytesFromBase64(object.txid)
+                : new Uint8Array(0),
+            inputIdx: isSet(object.inputIdx)
+                ? globalThis.Number(object.inputIdx)
+                : 0,
+        };
+    },
+
+    toJSON(message: SpentBy): unknown {
+        const obj: any = {};
+        if (message.txid.length !== 0) {
+            obj.txid = base64FromBytes(message.txid);
+        }
+        if (message.inputIdx !== 0) {
+            obj.inputIdx = Math.round(message.inputIdx);
+        }
+        return obj;
+    },
+
+    create<I extends Exact<DeepPartial<SpentBy>, I>>(base?: I): SpentBy {
+        return SpentBy.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<SpentBy>, I>>(object: I): SpentBy {
+        const message = createBaseSpentBy();
+        message.txid = object.txid ?? new Uint8Array(0);
+        message.inputIdx = object.inputIdx ?? 0;
+        return message;
+    },
+};
+
+function createBaseTxInput(): TxInput {
+    return {
+        prevOut: undefined,
+        inputScript: new Uint8Array(0),
+        outputScript: new Uint8Array(0),
+        value: '0',
+        sequenceNo: 0,
+        token: undefined,
+        plugins: {},
     };
 }
 
-export const BlockInfo = {
-    encode(
-        message: BlockInfo,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.hash.length !== 0) {
-            writer.uint32(10).bytes(message.hash);
+export const TxInput = {
+    encode(
+        message: TxInput,
+        writer: _m0.Writer = _m0.Writer.create(),
+    ): _m0.Writer {
+        if (message.prevOut !== undefined) {
+            OutPoint.encode(message.prevOut, writer.uint32(10).fork()).ldelim();
+        }
+        if (message.inputScript.length !== 0) {
+            writer.uint32(18).bytes(message.inputScript);
+        }
+        if (message.outputScript.length !== 0) {
+            writer.uint32(26).bytes(message.outputScript);
+        }
+        if (message.value !== '0') {
+            writer.uint32(32).int64(message.value);
+        }
+        if (message.sequenceNo !== 0) {
+            writer.uint32(40).uint32(message.sequenceNo);
+        }
+        if (message.token !== undefined) {
+            Token.encode(message.token, writer.uint32(66).fork()).ldelim();
+        }
+        Object.entries(message.plugins).forEach(([key, value]) => {
+            TxInput_PluginsEntry.encode(
+                { key: key as any, value },
+                writer.uint32(74).fork(),
+            ).ldelim();
+        });
+        return writer;
+    },
+
+    decode(input: _m0.Reader | Uint8Array, length?: number): TxInput {
+        const reader =
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
+        let end = length === undefined ? reader.len : reader.pos + length;
+        const message = createBaseTxInput();
+        while (reader.pos < end) {
+            const tag = reader.uint32();
+            switch (tag >>> 3) {
+                case 1:
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.prevOut = OutPoint.decode(reader, reader.uint32());
+                    continue;
+                case 2:
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.inputScript = reader.bytes();
+                    continue;
+                case 3:
+                    if (tag !== 26) {
+                        break;
+                    }
+
+                    message.outputScript = reader.bytes();
+                    continue;
+                case 4:
+                    if (tag !== 32) {
+                        break;
+                    }
+
+                    message.value = longToString(reader.int64() as Long);
+                    continue;
+                case 5:
+                    if (tag !== 40) {
+                        break;
+                    }
+
+                    message.sequenceNo = reader.uint32();
+                    continue;
+                case 8:
+                    if (tag !== 66) {
+                        break;
+                    }
+
+                    message.token = Token.decode(reader, reader.uint32());
+                    continue;
+                case 9:
+                    if (tag !== 74) {
+                        break;
+                    }
+
+                    const entry9 = TxInput_PluginsEntry.decode(
+                        reader,
+                        reader.uint32(),
+                    );
+                    if (entry9.value !== undefined) {
+                        message.plugins[entry9.key] = entry9.value;
+                    }
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
+        }
+        return message;
+    },
+
+    fromJSON(object: any): TxInput {
+        return {
+            prevOut: isSet(object.prevOut)
+                ? OutPoint.fromJSON(object.prevOut)
+                : undefined,
+            inputScript: isSet(object.inputScript)
+                ? bytesFromBase64(object.inputScript)
+                : new Uint8Array(0),
+            outputScript: isSet(object.outputScript)
+                ? bytesFromBase64(object.outputScript)
+                : new Uint8Array(0),
+            value: isSet(object.value) ? globalThis.String(object.value) : '0',
+            sequenceNo: isSet(object.sequenceNo)
+                ? globalThis.Number(object.sequenceNo)
+                : 0,
+            token: isSet(object.token)
+                ? Token.fromJSON(object.token)
+                : undefined,
+            plugins: isObject(object.plugins)
+                ? Object.entries(object.plugins).reduce<{
+                      [key: string]: PluginEntry;
+                  }>((acc, [key, value]) => {
+                      acc[key] = PluginEntry.fromJSON(value);
+                      return acc;
+                  }, {})
+                : {},
+        };
+    },
+
+    toJSON(message: TxInput): unknown {
+        const obj: any = {};
+        if (message.prevOut !== undefined) {
+            obj.prevOut = OutPoint.toJSON(message.prevOut);
+        }
+        if (message.inputScript.length !== 0) {
+            obj.inputScript = base64FromBytes(message.inputScript);
+        }
+        if (message.outputScript.length !== 0) {
+            obj.outputScript = base64FromBytes(message.outputScript);
+        }
+        if (message.value !== '0') {
+            obj.value = message.value;
+        }
+        if (message.sequenceNo !== 0) {
+            obj.sequenceNo = Math.round(message.sequenceNo);
+        }
+        if (message.token !== undefined) {
+            obj.token = Token.toJSON(message.token);
+        }
+        if (message.plugins) {
+            const entries = Object.entries(message.plugins);
+            if (entries.length > 0) {
+                obj.plugins = {};
+                entries.forEach(([k, v]) => {
+                    obj.plugins[k] = PluginEntry.toJSON(v);
+                });
+            }
+        }
+        return obj;
+    },
+
+    create<I extends Exact<DeepPartial<TxInput>, I>>(base?: I): TxInput {
+        return TxInput.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<TxInput>, I>>(object: I): TxInput {
+        const message = createBaseTxInput();
+        message.prevOut =
+            object.prevOut !== undefined && object.prevOut !== null
+                ? OutPoint.fromPartial(object.prevOut)
+                : undefined;
+        message.inputScript = object.inputScript ?? new Uint8Array(0);
+        message.outputScript = object.outputScript ?? new Uint8Array(0);
+        message.value = object.value ?? '0';
+        message.sequenceNo = object.sequenceNo ?? 0;
+        message.token =
+            object.token !== undefined && object.token !== null
+                ? Token.fromPartial(object.token)
+                : undefined;
+        message.plugins = Object.entries(object.plugins ?? {}).reduce<{
+            [key: string]: PluginEntry;
+        }>((acc, [key, value]) => {
+            if (value !== undefined) {
+                acc[key] = PluginEntry.fromPartial(value);
+            }
+            return acc;
+        }, {});
+        return message;
+    },
+};
+
+function createBaseTxInput_PluginsEntry(): TxInput_PluginsEntry {
+    return { key: '', value: undefined };
+}
+
+export const TxInput_PluginsEntry = {
+    encode(
+        message: TxInput_PluginsEntry,
+        writer: _m0.Writer = _m0.Writer.create(),
+    ): _m0.Writer {
+        if (message.key !== '') {
+            writer.uint32(10).string(message.key);
+        }
+        if (message.value !== undefined) {
+            PluginEntry.encode(
+                message.value,
+                writer.uint32(18).fork(),
+            ).ldelim();
+        }
+        return writer;
+    },
+
+    decode(
+        input: _m0.Reader | Uint8Array,
+        length?: number,
+    ): TxInput_PluginsEntry {
+        const reader =
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
+        let end = length === undefined ? reader.len : reader.pos + length;
+        const message = createBaseTxInput_PluginsEntry();
+        while (reader.pos < end) {
+            const tag = reader.uint32();
+            switch (tag >>> 3) {
+                case 1:
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.key = reader.string();
+                    continue;
+                case 2:
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.value = PluginEntry.decode(reader, reader.uint32());
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
+        }
+        return message;
+    },
+
+    fromJSON(object: any): TxInput_PluginsEntry {
+        return {
+            key: isSet(object.key) ? globalThis.String(object.key) : '',
+            value: isSet(object.value)
+                ? PluginEntry.fromJSON(object.value)
+                : undefined,
+        };
+    },
+
+    toJSON(message: TxInput_PluginsEntry): unknown {
+        const obj: any = {};
+        if (message.key !== '') {
+            obj.key = message.key;
+        }
+        if (message.value !== undefined) {
+            obj.value = PluginEntry.toJSON(message.value);
+        }
+        return obj;
+    },
+
+    create<I extends Exact<DeepPartial<TxInput_PluginsEntry>, I>>(
+        base?: I,
+    ): TxInput_PluginsEntry {
+        return TxInput_PluginsEntry.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<TxInput_PluginsEntry>, I>>(
+        object: I,
+    ): TxInput_PluginsEntry {
+        const message = createBaseTxInput_PluginsEntry();
+        message.key = object.key ?? '';
+        message.value =
+            object.value !== undefined && object.value !== null
+                ? PluginEntry.fromPartial(object.value)
+                : undefined;
+        return message;
+    },
+};
+
+function createBaseTxOutput(): TxOutput {
+    return {
+        value: '0',
+        outputScript: new Uint8Array(0),
+        spentBy: undefined,
+        token: undefined,
+        plugins: {},
+    };
+}
+
+export const TxOutput = {
+    encode(
+        message: TxOutput,
+        writer: _m0.Writer = _m0.Writer.create(),
+    ): _m0.Writer {
+        if (message.value !== '0') {
+            writer.uint32(8).int64(message.value);
+        }
+        if (message.outputScript.length !== 0) {
+            writer.uint32(18).bytes(message.outputScript);
+        }
+        if (message.spentBy !== undefined) {
+            SpentBy.encode(message.spentBy, writer.uint32(34).fork()).ldelim();
+        }
+        if (message.token !== undefined) {
+            Token.encode(message.token, writer.uint32(42).fork()).ldelim();
+        }
+        Object.entries(message.plugins).forEach(([key, value]) => {
+            TxOutput_PluginsEntry.encode(
+                { key: key as any, value },
+                writer.uint32(50).fork(),
+            ).ldelim();
+        });
+        return writer;
+    },
+
+    decode(input: _m0.Reader | Uint8Array, length?: number): TxOutput {
+        const reader =
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
+        let end = length === undefined ? reader.len : reader.pos + length;
+        const message = createBaseTxOutput();
+        while (reader.pos < end) {
+            const tag = reader.uint32();
+            switch (tag >>> 3) {
+                case 1:
+                    if (tag !== 8) {
+                        break;
+                    }
+
+                    message.value = longToString(reader.int64() as Long);
+                    continue;
+                case 2:
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.outputScript = reader.bytes();
+                    continue;
+                case 4:
+                    if (tag !== 34) {
+                        break;
+                    }
+
+                    message.spentBy = SpentBy.decode(reader, reader.uint32());
+                    continue;
+                case 5:
+                    if (tag !== 42) {
+                        break;
+                    }
+
+                    message.token = Token.decode(reader, reader.uint32());
+                    continue;
+                case 6:
+                    if (tag !== 50) {
+                        break;
+                    }
+
+                    const entry6 = TxOutput_PluginsEntry.decode(
+                        reader,
+                        reader.uint32(),
+                    );
+                    if (entry6.value !== undefined) {
+                        message.plugins[entry6.key] = entry6.value;
+                    }
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
-        if (message.prevHash.length !== 0) {
-            writer.uint32(18).bytes(message.prevHash);
+        return message;
+    },
+
+    fromJSON(object: any): TxOutput {
+        return {
+            value: isSet(object.value) ? globalThis.String(object.value) : '0',
+            outputScript: isSet(object.outputScript)
+                ? bytesFromBase64(object.outputScript)
+                : new Uint8Array(0),
+            spentBy: isSet(object.spentBy)
+                ? SpentBy.fromJSON(object.spentBy)
+                : undefined,
+            token: isSet(object.token)
+                ? Token.fromJSON(object.token)
+                : undefined,
+            plugins: isObject(object.plugins)
+                ? Object.entries(object.plugins).reduce<{
+                      [key: string]: PluginEntry;
+                  }>((acc, [key, value]) => {
+                      acc[key] = PluginEntry.fromJSON(value);
+                      return acc;
+                  }, {})
+                : {},
+        };
+    },
+
+    toJSON(message: TxOutput): unknown {
+        const obj: any = {};
+        if (message.value !== '0') {
+            obj.value = message.value;
         }
-        if (message.height !== 0) {
-            writer.uint32(24).int32(message.height);
+        if (message.outputScript.length !== 0) {
+            obj.outputScript = base64FromBytes(message.outputScript);
         }
-        if (message.nBits !== 0) {
-            writer.uint32(32).uint32(message.nBits);
+        if (message.spentBy !== undefined) {
+            obj.spentBy = SpentBy.toJSON(message.spentBy);
         }
-        if (message.timestamp !== '0') {
-            writer.uint32(40).int64(message.timestamp);
+        if (message.token !== undefined) {
+            obj.token = Token.toJSON(message.token);
+        }
+        if (message.plugins) {
+            const entries = Object.entries(message.plugins);
+            if (entries.length > 0) {
+                obj.plugins = {};
+                entries.forEach(([k, v]) => {
+                    obj.plugins[k] = PluginEntry.toJSON(v);
+                });
+            }
         }
-        if (message.blockSize !== '0') {
-            writer.uint32(48).uint64(message.blockSize);
+        return obj;
+    },
+
+    create<I extends Exact<DeepPartial<TxOutput>, I>>(base?: I): TxOutput {
+        return TxOutput.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<TxOutput>, I>>(
+        object: I,
+    ): TxOutput {
+        const message = createBaseTxOutput();
+        message.value = object.value ?? '0';
+        message.outputScript = object.outputScript ?? new Uint8Array(0);
+        message.spentBy =
+            object.spentBy !== undefined && object.spentBy !== null
+                ? SpentBy.fromPartial(object.spentBy)
+                : undefined;
+        message.token =
+            object.token !== undefined && object.token !== null
+                ? Token.fromPartial(object.token)
+                : undefined;
+        message.plugins = Object.entries(object.plugins ?? {}).reduce<{
+            [key: string]: PluginEntry;
+        }>((acc, [key, value]) => {
+            if (value !== undefined) {
+                acc[key] = PluginEntry.fromPartial(value);
+            }
+            return acc;
+        }, {});
+        return message;
+    },
+};
+
+function createBaseTxOutput_PluginsEntry(): TxOutput_PluginsEntry {
+    return { key: '', value: undefined };
+}
+
+export const TxOutput_PluginsEntry = {
+    encode(
+        message: TxOutput_PluginsEntry,
+        writer: _m0.Writer = _m0.Writer.create(),
+    ): _m0.Writer {
+        if (message.key !== '') {
+            writer.uint32(10).string(message.key);
         }
-        if (message.numTxs !== '0') {
-            writer.uint32(56).uint64(message.numTxs);
+        if (message.value !== undefined) {
+            PluginEntry.encode(
+                message.value,
+                writer.uint32(18).fork(),
+            ).ldelim();
         }
-        if (message.numInputs !== '0') {
-            writer.uint32(64).uint64(message.numInputs);
+        return writer;
+    },
+
+    decode(
+        input: _m0.Reader | Uint8Array,
+        length?: number,
+    ): TxOutput_PluginsEntry {
+        const reader =
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
+        let end = length === undefined ? reader.len : reader.pos + length;
+        const message = createBaseTxOutput_PluginsEntry();
+        while (reader.pos < end) {
+            const tag = reader.uint32();
+            switch (tag >>> 3) {
+                case 1:
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.key = reader.string();
+                    continue;
+                case 2:
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.value = PluginEntry.decode(reader, reader.uint32());
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
-        if (message.numOutputs !== '0') {
-            writer.uint32(72).uint64(message.numOutputs);
+        return message;
+    },
+
+    fromJSON(object: any): TxOutput_PluginsEntry {
+        return {
+            key: isSet(object.key) ? globalThis.String(object.key) : '',
+            value: isSet(object.value)
+                ? PluginEntry.fromJSON(object.value)
+                : undefined,
+        };
+    },
+
+    toJSON(message: TxOutput_PluginsEntry): unknown {
+        const obj: any = {};
+        if (message.key !== '') {
+            obj.key = message.key;
         }
-        if (message.sumInputSats !== '0') {
-            writer.uint32(80).int64(message.sumInputSats);
+        if (message.value !== undefined) {
+            obj.value = PluginEntry.toJSON(message.value);
         }
-        if (message.sumCoinbaseOutputSats !== '0') {
-            writer.uint32(88).int64(message.sumCoinbaseOutputSats);
+        return obj;
+    },
+
+    create<I extends Exact<DeepPartial<TxOutput_PluginsEntry>, I>>(
+        base?: I,
+    ): TxOutput_PluginsEntry {
+        return TxOutput_PluginsEntry.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<TxOutput_PluginsEntry>, I>>(
+        object: I,
+    ): TxOutput_PluginsEntry {
+        const message = createBaseTxOutput_PluginsEntry();
+        message.key = object.key ?? '';
+        message.value =
+            object.value !== undefined && object.value !== null
+                ? PluginEntry.fromPartial(object.value)
+                : undefined;
+        return message;
+    },
+};
+
+function createBaseBlockMetadata(): BlockMetadata {
+    return {
+        height: 0,
+        hash: new Uint8Array(0),
+        timestamp: '0',
+        isFinal: false,
+    };
+}
+
+export const BlockMetadata = {
+    encode(
+        message: BlockMetadata,
+        writer: _m0.Writer = _m0.Writer.create(),
+    ): _m0.Writer {
+        if (message.height !== 0) {
+            writer.uint32(8).int32(message.height);
         }
-        if (message.sumNormalOutputSats !== '0') {
-            writer.uint32(96).int64(message.sumNormalOutputSats);
+        if (message.hash.length !== 0) {
+            writer.uint32(18).bytes(message.hash);
         }
-        if (message.sumBurnedSats !== '0') {
-            writer.uint32(104).int64(message.sumBurnedSats);
+        if (message.timestamp !== '0') {
+            writer.uint32(24).int64(message.timestamp);
+        }
+        if (message.isFinal === true) {
+            writer.uint32(32).bool(message.isFinal);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): BlockInfo {
+    decode(input: _m0.Reader | Uint8Array, length?: number): BlockMetadata {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBlockInfo();
+        const message = createBaseBlockMetadata();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.hash = reader.bytes();
-                    break;
+                    if (tag !== 8) {
+                        break;
+                    }
+
+                    message.height = reader.int32();
+                    continue;
                 case 2:
-                    message.prevHash = reader.bytes();
-                    break;
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.hash = reader.bytes();
+                    continue;
                 case 3:
-                    message.height = reader.int32();
-                    break;
-                case 4:
-                    message.nBits = reader.uint32();
-                    break;
-                case 5:
+                    if (tag !== 24) {
+                        break;
+                    }
+
                     message.timestamp = longToString(reader.int64() as Long);
-                    break;
-                case 6:
-                    message.blockSize = longToString(reader.uint64() as Long);
-                    break;
-                case 7:
-                    message.numTxs = longToString(reader.uint64() as Long);
-                    break;
-                case 8:
-                    message.numInputs = longToString(reader.uint64() as Long);
-                    break;
-                case 9:
-                    message.numOutputs = longToString(reader.uint64() as Long);
-                    break;
-                case 10:
-                    message.sumInputSats = longToString(reader.int64() as Long);
-                    break;
-                case 11:
-                    message.sumCoinbaseOutputSats = longToString(
-                        reader.int64() as Long,
-                    );
-                    break;
-                case 12:
-                    message.sumNormalOutputSats = longToString(
-                        reader.int64() as Long,
-                    );
-                    break;
-                case 13:
-                    message.sumBurnedSats = longToString(
-                        reader.int64() as Long,
-                    );
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    continue;
+                case 4:
+                    if (tag !== 32) {
+                        break;
+                    }
+
+                    message.isFinal = reader.bool();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): BlockInfo {
+    fromJSON(object: any): BlockMetadata {
         return {
+            height: isSet(object.height) ? globalThis.Number(object.height) : 0,
             hash: isSet(object.hash)
                 ? bytesFromBase64(object.hash)
-                : new Uint8Array(),
-            prevHash: isSet(object.prevHash)
-                ? bytesFromBase64(object.prevHash)
-                : new Uint8Array(),
-            height: isSet(object.height) ? Number(object.height) : 0,
-            nBits: isSet(object.nBits) ? Number(object.nBits) : 0,
-            timestamp: isSet(object.timestamp) ? String(object.timestamp) : '0',
-            blockSize: isSet(object.blockSize) ? String(object.blockSize) : '0',
-            numTxs: isSet(object.numTxs) ? String(object.numTxs) : '0',
-            numInputs: isSet(object.numInputs) ? String(object.numInputs) : '0',
-            numOutputs: isSet(object.numOutputs)
-                ? String(object.numOutputs)
-                : '0',
-            sumInputSats: isSet(object.sumInputSats)
-                ? String(object.sumInputSats)
-                : '0',
-            sumCoinbaseOutputSats: isSet(object.sumCoinbaseOutputSats)
-                ? String(object.sumCoinbaseOutputSats)
-                : '0',
-            sumNormalOutputSats: isSet(object.sumNormalOutputSats)
-                ? String(object.sumNormalOutputSats)
-                : '0',
-            sumBurnedSats: isSet(object.sumBurnedSats)
-                ? String(object.sumBurnedSats)
+                : new Uint8Array(0),
+            timestamp: isSet(object.timestamp)
+                ? globalThis.String(object.timestamp)
                 : '0',
+            isFinal: isSet(object.isFinal)
+                ? globalThis.Boolean(object.isFinal)
+                : false,
         };
     },
 
-    toJSON(message: BlockInfo): unknown {
+    toJSON(message: BlockMetadata): unknown {
         const obj: any = {};
-        message.hash !== undefined &&
-            (obj.hash = base64FromBytes(
-                message.hash !== undefined ? message.hash : new Uint8Array(),
-            ));
-        message.prevHash !== undefined &&
-            (obj.prevHash = base64FromBytes(
-                message.prevHash !== undefined
-                    ? message.prevHash
-                    : new Uint8Array(),
-            ));
-        message.height !== undefined &&
-            (obj.height = Math.round(message.height));
-        message.nBits !== undefined && (obj.nBits = Math.round(message.nBits));
-        message.timestamp !== undefined && (obj.timestamp = message.timestamp);
-        message.blockSize !== undefined && (obj.blockSize = message.blockSize);
-        message.numTxs !== undefined && (obj.numTxs = message.numTxs);
-        message.numInputs !== undefined && (obj.numInputs = message.numInputs);
-        message.numOutputs !== undefined &&
-            (obj.numOutputs = message.numOutputs);
-        message.sumInputSats !== undefined &&
-            (obj.sumInputSats = message.sumInputSats);
-        message.sumCoinbaseOutputSats !== undefined &&
-            (obj.sumCoinbaseOutputSats = message.sumCoinbaseOutputSats);
-        message.sumNormalOutputSats !== undefined &&
-            (obj.sumNormalOutputSats = message.sumNormalOutputSats);
-        message.sumBurnedSats !== undefined &&
-            (obj.sumBurnedSats = message.sumBurnedSats);
+        if (message.height !== 0) {
+            obj.height = Math.round(message.height);
+        }
+        if (message.hash.length !== 0) {
+            obj.hash = base64FromBytes(message.hash);
+        }
+        if (message.timestamp !== '0') {
+            obj.timestamp = message.timestamp;
+        }
+        if (message.isFinal === true) {
+            obj.isFinal = message.isFinal;
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<BlockInfo>, I>>(
+    create<I extends Exact<DeepPartial<BlockMetadata>, I>>(
+        base?: I,
+    ): BlockMetadata {
+        return BlockMetadata.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<BlockMetadata>, I>>(
         object: I,
-    ): BlockInfo {
-        const message = createBaseBlockInfo();
-        message.hash = object.hash ?? new Uint8Array();
-        message.prevHash = object.prevHash ?? new Uint8Array();
+    ): BlockMetadata {
+        const message = createBaseBlockMetadata();
         message.height = object.height ?? 0;
-        message.nBits = object.nBits ?? 0;
+        message.hash = object.hash ?? new Uint8Array(0);
         message.timestamp = object.timestamp ?? '0';
-        message.blockSize = object.blockSize ?? '0';
-        message.numTxs = object.numTxs ?? '0';
-        message.numInputs = object.numInputs ?? '0';
-        message.numOutputs = object.numOutputs ?? '0';
-        message.sumInputSats = object.sumInputSats ?? '0';
-        message.sumCoinbaseOutputSats = object.sumCoinbaseOutputSats ?? '0';
-        message.sumNormalOutputSats = object.sumNormalOutputSats ?? '0';
-        message.sumBurnedSats = object.sumBurnedSats ?? '0';
+        message.isFinal = object.isFinal ?? false;
         return message;
     },
 };
 
-function createBaseBlockDetails(): BlockDetails {
-    return {
-        version: 0,
-        merkleRoot: new Uint8Array(),
-        nonce: '0',
-        medianTimestamp: '0',
-    };
+function createBaseTokenType(): TokenType {
+    return { slp: undefined, alp: undefined };
 }
 
-export const BlockDetails = {
+export const TokenType = {
     encode(
-        message: BlockDetails,
+        message: TokenType,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.version !== 0) {
-            writer.uint32(8).int32(message.version);
-        }
-        if (message.merkleRoot.length !== 0) {
-            writer.uint32(18).bytes(message.merkleRoot);
-        }
-        if (message.nonce !== '0') {
-            writer.uint32(24).uint64(message.nonce);
+        if (message.slp !== undefined) {
+            writer.uint32(8).int32(message.slp);
         }
-        if (message.medianTimestamp !== '0') {
-            writer.uint32(32).int64(message.medianTimestamp);
+        if (message.alp !== undefined) {
+            writer.uint32(16).int32(message.alp);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): BlockDetails {
+    decode(input: _m0.Reader | Uint8Array, length?: number): TokenType {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBlockDetails();
+        const message = createBaseTokenType();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.version = reader.int32();
-                    break;
+                    if (tag !== 8) {
+                        break;
+                    }
+
+                    message.slp = reader.int32() as any;
+                    continue;
                 case 2:
-                    message.merkleRoot = reader.bytes();
-                    break;
-                case 3:
-                    message.nonce = longToString(reader.uint64() as Long);
-                    break;
-                case 4:
-                    message.medianTimestamp = longToString(
-                        reader.int64() as Long,
-                    );
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 16) {
+                        break;
+                    }
+
+                    message.alp = reader.int32() as any;
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): BlockDetails {
+    fromJSON(object: any): TokenType {
         return {
-            version: isSet(object.version) ? Number(object.version) : 0,
-            merkleRoot: isSet(object.merkleRoot)
-                ? bytesFromBase64(object.merkleRoot)
-                : new Uint8Array(),
-            nonce: isSet(object.nonce) ? String(object.nonce) : '0',
-            medianTimestamp: isSet(object.medianTimestamp)
-                ? String(object.medianTimestamp)
-                : '0',
+            slp: isSet(object.slp)
+                ? slpTokenTypeFromJSON(object.slp)
+                : undefined,
+            alp: isSet(object.alp)
+                ? alpTokenTypeFromJSON(object.alp)
+                : undefined,
         };
     },
 
-    toJSON(message: BlockDetails): unknown {
+    toJSON(message: TokenType): unknown {
         const obj: any = {};
-        message.version !== undefined &&
-            (obj.version = Math.round(message.version));
-        message.merkleRoot !== undefined &&
-            (obj.merkleRoot = base64FromBytes(
-                message.merkleRoot !== undefined
-                    ? message.merkleRoot
-                    : new Uint8Array(),
-            ));
-        message.nonce !== undefined && (obj.nonce = message.nonce);
-        message.medianTimestamp !== undefined &&
-            (obj.medianTimestamp = message.medianTimestamp);
+        if (message.slp !== undefined) {
+            obj.slp = slpTokenTypeToJSON(message.slp);
+        }
+        if (message.alp !== undefined) {
+            obj.alp = alpTokenTypeToJSON(message.alp);
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<BlockDetails>, I>>(
+    create<I extends Exact<DeepPartial<TokenType>, I>>(base?: I): TokenType {
+        return TokenType.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<TokenType>, I>>(
         object: I,
-    ): BlockDetails {
-        const message = createBaseBlockDetails();
-        message.version = object.version ?? 0;
-        message.merkleRoot = object.merkleRoot ?? new Uint8Array();
-        message.nonce = object.nonce ?? '0';
-        message.medianTimestamp = object.medianTimestamp ?? '0';
+    ): TokenType {
+        const message = createBaseTokenType();
+        message.slp = object.slp ?? undefined;
+        message.alp = object.alp ?? undefined;
         return message;
     },
 };
 
-function createBaseBlock(): Block {
+function createBaseTokenInfo(): TokenInfo {
     return {
-        blockInfo: undefined,
-        blockDetails: undefined,
-        rawHeader: new Uint8Array(),
-        txs: [],
+        tokenId: '',
+        tokenType: undefined,
+        genesisInfo: undefined,
+        block: undefined,
+        timeFirstSeen: '0',
     };
 }
 
-export const Block = {
+export const TokenInfo = {
     encode(
-        message: Block,
+        message: TokenInfo,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.blockInfo !== undefined) {
-            BlockInfo.encode(
-                message.blockInfo,
-                writer.uint32(10).fork(),
+        if (message.tokenId !== '') {
+            writer.uint32(10).string(message.tokenId);
+        }
+        if (message.tokenType !== undefined) {
+            TokenType.encode(
+                message.tokenType,
+                writer.uint32(18).fork(),
             ).ldelim();
         }
-        if (message.blockDetails !== undefined) {
-            BlockDetails.encode(
-                message.blockDetails,
+        if (message.genesisInfo !== undefined) {
+            GenesisInfo.encode(
+                message.genesisInfo,
                 writer.uint32(26).fork(),
             ).ldelim();
         }
-        if (message.rawHeader.length !== 0) {
-            writer.uint32(34).bytes(message.rawHeader);
+        if (message.block !== undefined) {
+            BlockMetadata.encode(
+                message.block,
+                writer.uint32(34).fork(),
+            ).ldelim();
         }
-        for (const v of message.txs) {
-            Tx.encode(v!, writer.uint32(18).fork()).ldelim();
+        if (message.timeFirstSeen !== '0') {
+            writer.uint32(40).int64(message.timeFirstSeen);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): Block {
+    decode(input: _m0.Reader | Uint8Array, length?: number): TokenInfo {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBlock();
+        const message = createBaseTokenInfo();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.blockInfo = BlockInfo.decode(
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.tokenId = reader.string();
+                    continue;
+                case 2:
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.tokenType = TokenType.decode(
                         reader,
                         reader.uint32(),
                     );
-                    break;
+                    continue;
                 case 3:
-                    message.blockDetails = BlockDetails.decode(
+                    if (tag !== 26) {
+                        break;
+                    }
+
+                    message.genesisInfo = GenesisInfo.decode(
                         reader,
                         reader.uint32(),
                     );
-                    break;
+                    continue;
                 case 4:
-                    message.rawHeader = reader.bytes();
-                    break;
-                case 2:
-                    message.txs.push(Tx.decode(reader, reader.uint32()));
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 34) {
+                        break;
+                    }
+
+                    message.block = BlockMetadata.decode(
+                        reader,
+                        reader.uint32(),
+                    );
+                    continue;
+                case 5:
+                    if (tag !== 40) {
+                        break;
+                    }
+
+                    message.timeFirstSeen = longToString(
+                        reader.int64() as Long,
+                    );
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): Block {
+    fromJSON(object: any): TokenInfo {
         return {
-            blockInfo: isSet(object.blockInfo)
-                ? BlockInfo.fromJSON(object.blockInfo)
+            tokenId: isSet(object.tokenId)
+                ? globalThis.String(object.tokenId)
+                : '',
+            tokenType: isSet(object.tokenType)
+                ? TokenType.fromJSON(object.tokenType)
                 : undefined,
-            blockDetails: isSet(object.blockDetails)
-                ? BlockDetails.fromJSON(object.blockDetails)
+            genesisInfo: isSet(object.genesisInfo)
+                ? GenesisInfo.fromJSON(object.genesisInfo)
                 : undefined,
-            rawHeader: isSet(object.rawHeader)
-                ? bytesFromBase64(object.rawHeader)
-                : new Uint8Array(),
-            txs: Array.isArray(object?.txs)
-                ? object.txs.map((e: any) => Tx.fromJSON(e))
-                : [],
+            block: isSet(object.block)
+                ? BlockMetadata.fromJSON(object.block)
+                : undefined,
+            timeFirstSeen: isSet(object.timeFirstSeen)
+                ? globalThis.String(object.timeFirstSeen)
+                : '0',
         };
     },
 
-    toJSON(message: Block): unknown {
+    toJSON(message: TokenInfo): unknown {
         const obj: any = {};
-        message.blockInfo !== undefined &&
-            (obj.blockInfo = message.blockInfo
-                ? BlockInfo.toJSON(message.blockInfo)
-                : undefined);
-        message.blockDetails !== undefined &&
-            (obj.blockDetails = message.blockDetails
-                ? BlockDetails.toJSON(message.blockDetails)
-                : undefined);
-        message.rawHeader !== undefined &&
-            (obj.rawHeader = base64FromBytes(
-                message.rawHeader !== undefined
-                    ? message.rawHeader
-                    : new Uint8Array(),
-            ));
-        if (message.txs) {
-            obj.txs = message.txs.map(e => (e ? Tx.toJSON(e) : undefined));
-        } else {
-            obj.txs = [];
+        if (message.tokenId !== '') {
+            obj.tokenId = message.tokenId;
+        }
+        if (message.tokenType !== undefined) {
+            obj.tokenType = TokenType.toJSON(message.tokenType);
+        }
+        if (message.genesisInfo !== undefined) {
+            obj.genesisInfo = GenesisInfo.toJSON(message.genesisInfo);
+        }
+        if (message.block !== undefined) {
+            obj.block = BlockMetadata.toJSON(message.block);
+        }
+        if (message.timeFirstSeen !== '0') {
+            obj.timeFirstSeen = message.timeFirstSeen;
         }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<Block>, I>>(object: I): Block {
-        const message = createBaseBlock();
-        message.blockInfo =
-            object.blockInfo !== undefined && object.blockInfo !== null
-                ? BlockInfo.fromPartial(object.blockInfo)
+    create<I extends Exact<DeepPartial<TokenInfo>, I>>(base?: I): TokenInfo {
+        return TokenInfo.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<TokenInfo>, I>>(
+        object: I,
+    ): TokenInfo {
+        const message = createBaseTokenInfo();
+        message.tokenId = object.tokenId ?? '';
+        message.tokenType =
+            object.tokenType !== undefined && object.tokenType !== null
+                ? TokenType.fromPartial(object.tokenType)
                 : undefined;
-        message.blockDetails =
-            object.blockDetails !== undefined && object.blockDetails !== null
-                ? BlockDetails.fromPartial(object.blockDetails)
+        message.genesisInfo =
+            object.genesisInfo !== undefined && object.genesisInfo !== null
+                ? GenesisInfo.fromPartial(object.genesisInfo)
                 : undefined;
-        message.rawHeader = object.rawHeader ?? new Uint8Array();
-        message.txs = object.txs?.map(e => Tx.fromPartial(e)) || [];
+        message.block =
+            object.block !== undefined && object.block !== null
+                ? BlockMetadata.fromPartial(object.block)
+                : undefined;
+        message.timeFirstSeen = object.timeFirstSeen ?? '0';
         return message;
     },
 };
 
-function createBaseScriptUtxos(): ScriptUtxos {
-    return { outputScript: new Uint8Array(), utxos: [] };
+function createBaseTokenEntry(): TokenEntry {
+    return {
+        tokenId: '',
+        tokenType: undefined,
+        txType: 0,
+        groupTokenId: '',
+        isInvalid: false,
+        burnSummary: '',
+        failedColorings: [],
+        actualBurnAmount: '',
+        intentionalBurn: '0',
+        burnsMintBatons: false,
+    };
 }
 
-export const ScriptUtxos = {
+export const TokenEntry = {
     encode(
-        message: ScriptUtxos,
+        message: TokenEntry,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.outputScript.length !== 0) {
-            writer.uint32(10).bytes(message.outputScript);
+        if (message.tokenId !== '') {
+            writer.uint32(10).string(message.tokenId);
         }
-        for (const v of message.utxos) {
-            Utxo.encode(v!, writer.uint32(18).fork()).ldelim();
+        if (message.tokenType !== undefined) {
+            TokenType.encode(
+                message.tokenType,
+                writer.uint32(18).fork(),
+            ).ldelim();
+        }
+        if (message.txType !== 0) {
+            writer.uint32(24).int32(message.txType);
+        }
+        if (message.groupTokenId !== '') {
+            writer.uint32(34).string(message.groupTokenId);
+        }
+        if (message.isInvalid === true) {
+            writer.uint32(40).bool(message.isInvalid);
+        }
+        if (message.burnSummary !== '') {
+            writer.uint32(50).string(message.burnSummary);
+        }
+        for (const v of message.failedColorings) {
+            TokenFailedColoring.encode(v!, writer.uint32(58).fork()).ldelim();
+        }
+        if (message.actualBurnAmount !== '') {
+            writer.uint32(66).string(message.actualBurnAmount);
+        }
+        if (message.intentionalBurn !== '0') {
+            writer.uint32(72).uint64(message.intentionalBurn);
+        }
+        if (message.burnsMintBatons === true) {
+            writer.uint32(80).bool(message.burnsMintBatons);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): ScriptUtxos {
+    decode(input: _m0.Reader | Uint8Array, length?: number): TokenEntry {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseScriptUtxos();
+        const message = createBaseTokenEntry();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.outputScript = reader.bytes();
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.tokenId = reader.string();
+                    continue;
                 case 2:
-                    message.utxos.push(Utxo.decode(reader, reader.uint32()));
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.tokenType = TokenType.decode(
+                        reader,
+                        reader.uint32(),
+                    );
+                    continue;
+                case 3:
+                    if (tag !== 24) {
+                        break;
+                    }
+
+                    message.txType = reader.int32() as any;
+                    continue;
+                case 4:
+                    if (tag !== 34) {
+                        break;
+                    }
+
+                    message.groupTokenId = reader.string();
+                    continue;
+                case 5:
+                    if (tag !== 40) {
+                        break;
+                    }
+
+                    message.isInvalid = reader.bool();
+                    continue;
+                case 6:
+                    if (tag !== 50) {
+                        break;
+                    }
+
+                    message.burnSummary = reader.string();
+                    continue;
+                case 7:
+                    if (tag !== 58) {
+                        break;
+                    }
+
+                    message.failedColorings.push(
+                        TokenFailedColoring.decode(reader, reader.uint32()),
+                    );
+                    continue;
+                case 8:
+                    if (tag !== 66) {
+                        break;
+                    }
+
+                    message.actualBurnAmount = reader.string();
+                    continue;
+                case 9:
+                    if (tag !== 72) {
+                        break;
+                    }
+
+                    message.intentionalBurn = longToString(
+                        reader.uint64() as Long,
+                    );
+                    continue;
+                case 10:
+                    if (tag !== 80) {
+                        break;
+                    }
+
+                    message.burnsMintBatons = reader.bool();
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): ScriptUtxos {
+    fromJSON(object: any): TokenEntry {
         return {
-            outputScript: isSet(object.outputScript)
-                ? bytesFromBase64(object.outputScript)
-                : new Uint8Array(),
-            utxos: Array.isArray(object?.utxos)
-                ? object.utxos.map((e: any) => Utxo.fromJSON(e))
+            tokenId: isSet(object.tokenId)
+                ? globalThis.String(object.tokenId)
+                : '',
+            tokenType: isSet(object.tokenType)
+                ? TokenType.fromJSON(object.tokenType)
+                : undefined,
+            txType: isSet(object.txType)
+                ? tokenTxTypeFromJSON(object.txType)
+                : 0,
+            groupTokenId: isSet(object.groupTokenId)
+                ? globalThis.String(object.groupTokenId)
+                : '',
+            isInvalid: isSet(object.isInvalid)
+                ? globalThis.Boolean(object.isInvalid)
+                : false,
+            burnSummary: isSet(object.burnSummary)
+                ? globalThis.String(object.burnSummary)
+                : '',
+            failedColorings: globalThis.Array.isArray(object?.failedColorings)
+                ? object.failedColorings.map((e: any) =>
+                      TokenFailedColoring.fromJSON(e),
+                  )
                 : [],
+            actualBurnAmount: isSet(object.actualBurnAmount)
+                ? globalThis.String(object.actualBurnAmount)
+                : '',
+            intentionalBurn: isSet(object.intentionalBurn)
+                ? globalThis.String(object.intentionalBurn)
+                : '0',
+            burnsMintBatons: isSet(object.burnsMintBatons)
+                ? globalThis.Boolean(object.burnsMintBatons)
+                : false,
         };
     },
 
-    toJSON(message: ScriptUtxos): unknown {
+    toJSON(message: TokenEntry): unknown {
         const obj: any = {};
-        message.outputScript !== undefined &&
-            (obj.outputScript = base64FromBytes(
-                message.outputScript !== undefined
-                    ? message.outputScript
-                    : new Uint8Array(),
-            ));
-        if (message.utxos) {
-            obj.utxos = message.utxos.map(e =>
-                e ? Utxo.toJSON(e) : undefined,
+        if (message.tokenId !== '') {
+            obj.tokenId = message.tokenId;
+        }
+        if (message.tokenType !== undefined) {
+            obj.tokenType = TokenType.toJSON(message.tokenType);
+        }
+        if (message.txType !== 0) {
+            obj.txType = tokenTxTypeToJSON(message.txType);
+        }
+        if (message.groupTokenId !== '') {
+            obj.groupTokenId = message.groupTokenId;
+        }
+        if (message.isInvalid === true) {
+            obj.isInvalid = message.isInvalid;
+        }
+        if (message.burnSummary !== '') {
+            obj.burnSummary = message.burnSummary;
+        }
+        if (message.failedColorings?.length) {
+            obj.failedColorings = message.failedColorings.map(e =>
+                TokenFailedColoring.toJSON(e),
             );
-        } else {
-            obj.utxos = [];
+        }
+        if (message.actualBurnAmount !== '') {
+            obj.actualBurnAmount = message.actualBurnAmount;
+        }
+        if (message.intentionalBurn !== '0') {
+            obj.intentionalBurn = message.intentionalBurn;
+        }
+        if (message.burnsMintBatons === true) {
+            obj.burnsMintBatons = message.burnsMintBatons;
         }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<ScriptUtxos>, I>>(
+    create<I extends Exact<DeepPartial<TokenEntry>, I>>(base?: I): TokenEntry {
+        return TokenEntry.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<TokenEntry>, I>>(
         object: I,
-    ): ScriptUtxos {
-        const message = createBaseScriptUtxos();
-        message.outputScript = object.outputScript ?? new Uint8Array();
-        message.utxos = object.utxos?.map(e => Utxo.fromPartial(e)) || [];
+    ): TokenEntry {
+        const message = createBaseTokenEntry();
+        message.tokenId = object.tokenId ?? '';
+        message.tokenType =
+            object.tokenType !== undefined && object.tokenType !== null
+                ? TokenType.fromPartial(object.tokenType)
+                : undefined;
+        message.txType = object.txType ?? 0;
+        message.groupTokenId = object.groupTokenId ?? '';
+        message.isInvalid = object.isInvalid ?? false;
+        message.burnSummary = object.burnSummary ?? '';
+        message.failedColorings =
+            object.failedColorings?.map(e =>
+                TokenFailedColoring.fromPartial(e),
+            ) || [];
+        message.actualBurnAmount = object.actualBurnAmount ?? '';
+        message.intentionalBurn = object.intentionalBurn ?? '0';
+        message.burnsMintBatons = object.burnsMintBatons ?? false;
         return message;
     },
 };
 
-function createBaseTxHistoryPage(): TxHistoryPage {
-    return { txs: [], numPages: 0 };
+function createBaseGenesisInfo(): GenesisInfo {
+    return {
+        tokenTicker: new Uint8Array(0),
+        tokenName: new Uint8Array(0),
+        url: new Uint8Array(0),
+        hash: new Uint8Array(0),
+        mintVaultScripthash: new Uint8Array(0),
+        data: new Uint8Array(0),
+        authPubkey: new Uint8Array(0),
+        decimals: 0,
+    };
 }
 
-export const TxHistoryPage = {
+export const GenesisInfo = {
     encode(
-        message: TxHistoryPage,
+        message: GenesisInfo,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        for (const v of message.txs) {
-            Tx.encode(v!, writer.uint32(10).fork()).ldelim();
+        if (message.tokenTicker.length !== 0) {
+            writer.uint32(10).bytes(message.tokenTicker);
         }
-        if (message.numPages !== 0) {
-            writer.uint32(16).uint32(message.numPages);
+        if (message.tokenName.length !== 0) {
+            writer.uint32(18).bytes(message.tokenName);
+        }
+        if (message.url.length !== 0) {
+            writer.uint32(26).bytes(message.url);
+        }
+        if (message.hash.length !== 0) {
+            writer.uint32(34).bytes(message.hash);
+        }
+        if (message.mintVaultScripthash.length !== 0) {
+            writer.uint32(42).bytes(message.mintVaultScripthash);
+        }
+        if (message.data.length !== 0) {
+            writer.uint32(50).bytes(message.data);
+        }
+        if (message.authPubkey.length !== 0) {
+            writer.uint32(58).bytes(message.authPubkey);
+        }
+        if (message.decimals !== 0) {
+            writer.uint32(64).uint32(message.decimals);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): TxHistoryPage {
+    decode(input: _m0.Reader | Uint8Array, length?: number): GenesisInfo {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTxHistoryPage();
+        const message = createBaseGenesisInfo();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.txs.push(Tx.decode(reader, reader.uint32()));
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.tokenTicker = reader.bytes();
+                    continue;
                 case 2:
-                    message.numPages = reader.uint32();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.tokenName = reader.bytes();
+                    continue;
+                case 3:
+                    if (tag !== 26) {
+                        break;
+                    }
+
+                    message.url = reader.bytes();
+                    continue;
+                case 4:
+                    if (tag !== 34) {
+                        break;
+                    }
+
+                    message.hash = reader.bytes();
+                    continue;
+                case 5:
+                    if (tag !== 42) {
+                        break;
+                    }
+
+                    message.mintVaultScripthash = reader.bytes();
+                    continue;
+                case 6:
+                    if (tag !== 50) {
+                        break;
+                    }
+
+                    message.data = reader.bytes();
+                    continue;
+                case 7:
+                    if (tag !== 58) {
+                        break;
+                    }
+
+                    message.authPubkey = reader.bytes();
+                    continue;
+                case 8:
+                    if (tag !== 64) {
+                        break;
+                    }
+
+                    message.decimals = reader.uint32();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): TxHistoryPage {
+    fromJSON(object: any): GenesisInfo {
         return {
-            txs: Array.isArray(object?.txs)
-                ? object.txs.map((e: any) => Tx.fromJSON(e))
-                : [],
-            numPages: isSet(object.numPages) ? Number(object.numPages) : 0,
+            tokenTicker: isSet(object.tokenTicker)
+                ? bytesFromBase64(object.tokenTicker)
+                : new Uint8Array(0),
+            tokenName: isSet(object.tokenName)
+                ? bytesFromBase64(object.tokenName)
+                : new Uint8Array(0),
+            url: isSet(object.url)
+                ? bytesFromBase64(object.url)
+                : new Uint8Array(0),
+            hash: isSet(object.hash)
+                ? bytesFromBase64(object.hash)
+                : new Uint8Array(0),
+            mintVaultScripthash: isSet(object.mintVaultScripthash)
+                ? bytesFromBase64(object.mintVaultScripthash)
+                : new Uint8Array(0),
+            data: isSet(object.data)
+                ? bytesFromBase64(object.data)
+                : new Uint8Array(0),
+            authPubkey: isSet(object.authPubkey)
+                ? bytesFromBase64(object.authPubkey)
+                : new Uint8Array(0),
+            decimals: isSet(object.decimals)
+                ? globalThis.Number(object.decimals)
+                : 0,
         };
     },
 
-    toJSON(message: TxHistoryPage): unknown {
+    toJSON(message: GenesisInfo): unknown {
         const obj: any = {};
-        if (message.txs) {
-            obj.txs = message.txs.map(e => (e ? Tx.toJSON(e) : undefined));
-        } else {
-            obj.txs = [];
+        if (message.tokenTicker.length !== 0) {
+            obj.tokenTicker = base64FromBytes(message.tokenTicker);
+        }
+        if (message.tokenName.length !== 0) {
+            obj.tokenName = base64FromBytes(message.tokenName);
+        }
+        if (message.url.length !== 0) {
+            obj.url = base64FromBytes(message.url);
+        }
+        if (message.hash.length !== 0) {
+            obj.hash = base64FromBytes(message.hash);
+        }
+        if (message.mintVaultScripthash.length !== 0) {
+            obj.mintVaultScripthash = base64FromBytes(
+                message.mintVaultScripthash,
+            );
+        }
+        if (message.data.length !== 0) {
+            obj.data = base64FromBytes(message.data);
+        }
+        if (message.authPubkey.length !== 0) {
+            obj.authPubkey = base64FromBytes(message.authPubkey);
+        }
+        if (message.decimals !== 0) {
+            obj.decimals = Math.round(message.decimals);
         }
-        message.numPages !== undefined &&
-            (obj.numPages = Math.round(message.numPages));
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<TxHistoryPage>, I>>(
+    create<I extends Exact<DeepPartial<GenesisInfo>, I>>(
+        base?: I,
+    ): GenesisInfo {
+        return GenesisInfo.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<GenesisInfo>, I>>(
         object: I,
-    ): TxHistoryPage {
-        const message = createBaseTxHistoryPage();
-        message.txs = object.txs?.map(e => Tx.fromPartial(e)) || [];
-        message.numPages = object.numPages ?? 0;
+    ): GenesisInfo {
+        const message = createBaseGenesisInfo();
+        message.tokenTicker = object.tokenTicker ?? new Uint8Array(0);
+        message.tokenName = object.tokenName ?? new Uint8Array(0);
+        message.url = object.url ?? new Uint8Array(0);
+        message.hash = object.hash ?? new Uint8Array(0);
+        message.mintVaultScripthash =
+            object.mintVaultScripthash ?? new Uint8Array(0);
+        message.data = object.data ?? new Uint8Array(0);
+        message.authPubkey = object.authPubkey ?? new Uint8Array(0);
+        message.decimals = object.decimals ?? 0;
         return message;
     },
 };
 
-function createBaseUtxos(): Utxos {
-    return { scriptUtxos: [] };
+function createBaseToken(): Token {
+    return {
+        tokenId: '',
+        tokenType: undefined,
+        entryIdx: 0,
+        amount: '0',
+        isMintBaton: false,
+    };
 }
 
-export const Utxos = {
+export const Token = {
     encode(
-        message: Utxos,
+        message: Token,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        for (const v of message.scriptUtxos) {
-            ScriptUtxos.encode(v!, writer.uint32(10).fork()).ldelim();
+        if (message.tokenId !== '') {
+            writer.uint32(10).string(message.tokenId);
+        }
+        if (message.tokenType !== undefined) {
+            TokenType.encode(
+                message.tokenType,
+                writer.uint32(18).fork(),
+            ).ldelim();
+        }
+        if (message.entryIdx !== 0) {
+            writer.uint32(24).int32(message.entryIdx);
+        }
+        if (message.amount !== '0') {
+            writer.uint32(32).uint64(message.amount);
+        }
+        if (message.isMintBaton === true) {
+            writer.uint32(40).bool(message.isMintBaton);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): Utxos {
+    decode(input: _m0.Reader | Uint8Array, length?: number): Token {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseUtxos();
+        const message = createBaseToken();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.scriptUtxos.push(
-                        ScriptUtxos.decode(reader, reader.uint32()),
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.tokenId = reader.string();
+                    continue;
+                case 2:
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.tokenType = TokenType.decode(
+                        reader,
+                        reader.uint32(),
                     );
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    continue;
+                case 3:
+                    if (tag !== 24) {
+                        break;
+                    }
+
+                    message.entryIdx = reader.int32();
+                    continue;
+                case 4:
+                    if (tag !== 32) {
+                        break;
+                    }
+
+                    message.amount = longToString(reader.uint64() as Long);
+                    continue;
+                case 5:
+                    if (tag !== 40) {
+                        break;
+                    }
+
+                    message.isMintBaton = reader.bool();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): Utxos {
+    fromJSON(object: any): Token {
         return {
-            scriptUtxos: Array.isArray(object?.scriptUtxos)
-                ? object.scriptUtxos.map((e: any) => ScriptUtxos.fromJSON(e))
-                : [],
+            tokenId: isSet(object.tokenId)
+                ? globalThis.String(object.tokenId)
+                : '',
+            tokenType: isSet(object.tokenType)
+                ? TokenType.fromJSON(object.tokenType)
+                : undefined,
+            entryIdx: isSet(object.entryIdx)
+                ? globalThis.Number(object.entryIdx)
+                : 0,
+            amount: isSet(object.amount)
+                ? globalThis.String(object.amount)
+                : '0',
+            isMintBaton: isSet(object.isMintBaton)
+                ? globalThis.Boolean(object.isMintBaton)
+                : false,
         };
     },
 
-    toJSON(message: Utxos): unknown {
+    toJSON(message: Token): unknown {
         const obj: any = {};
-        if (message.scriptUtxos) {
-            obj.scriptUtxos = message.scriptUtxos.map(e =>
-                e ? ScriptUtxos.toJSON(e) : undefined,
-            );
-        } else {
-            obj.scriptUtxos = [];
+        if (message.tokenId !== '') {
+            obj.tokenId = message.tokenId;
+        }
+        if (message.tokenType !== undefined) {
+            obj.tokenType = TokenType.toJSON(message.tokenType);
+        }
+        if (message.entryIdx !== 0) {
+            obj.entryIdx = Math.round(message.entryIdx);
+        }
+        if (message.amount !== '0') {
+            obj.amount = message.amount;
+        }
+        if (message.isMintBaton === true) {
+            obj.isMintBaton = message.isMintBaton;
         }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<Utxos>, I>>(object: I): Utxos {
-        const message = createBaseUtxos();
-        message.scriptUtxos =
-            object.scriptUtxos?.map(e => ScriptUtxos.fromPartial(e)) || [];
+    create<I extends Exact<DeepPartial<Token>, I>>(base?: I): Token {
+        return Token.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<Token>, I>>(object: I): Token {
+        const message = createBaseToken();
+        message.tokenId = object.tokenId ?? '';
+        message.tokenType =
+            object.tokenType !== undefined && object.tokenType !== null
+                ? TokenType.fromPartial(object.tokenType)
+                : undefined;
+        message.entryIdx = object.entryIdx ?? 0;
+        message.amount = object.amount ?? '0';
+        message.isMintBaton = object.isMintBaton ?? false;
         return message;
     },
 };
 
-function createBaseBlocks(): Blocks {
-    return { blocks: [] };
+function createBaseTokenFailedParsing(): TokenFailedParsing {
+    return { pushdataIdx: 0, bytes: new Uint8Array(0), error: '' };
 }
 
-export const Blocks = {
+export const TokenFailedParsing = {
     encode(
-        message: Blocks,
+        message: TokenFailedParsing,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        for (const v of message.blocks) {
-            BlockInfo.encode(v!, writer.uint32(10).fork()).ldelim();
+        if (message.pushdataIdx !== 0) {
+            writer.uint32(8).int32(message.pushdataIdx);
+        }
+        if (message.bytes.length !== 0) {
+            writer.uint32(18).bytes(message.bytes);
+        }
+        if (message.error !== '') {
+            writer.uint32(26).string(message.error);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): Blocks {
+    decode(
+        input: _m0.Reader | Uint8Array,
+        length?: number,
+    ): TokenFailedParsing {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBlocks();
+        const message = createBaseTokenFailedParsing();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.blocks.push(
-                        BlockInfo.decode(reader, reader.uint32()),
-                    );
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 8) {
+                        break;
+                    }
+
+                    message.pushdataIdx = reader.int32();
+                    continue;
+                case 2:
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.bytes = reader.bytes();
+                    continue;
+                case 3:
+                    if (tag !== 26) {
+                        break;
+                    }
+
+                    message.error = reader.string();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): Blocks {
+    fromJSON(object: any): TokenFailedParsing {
         return {
-            blocks: Array.isArray(object?.blocks)
-                ? object.blocks.map((e: any) => BlockInfo.fromJSON(e))
-                : [],
+            pushdataIdx: isSet(object.pushdataIdx)
+                ? globalThis.Number(object.pushdataIdx)
+                : 0,
+            bytes: isSet(object.bytes)
+                ? bytesFromBase64(object.bytes)
+                : new Uint8Array(0),
+            error: isSet(object.error) ? globalThis.String(object.error) : '',
         };
     },
 
-    toJSON(message: Blocks): unknown {
+    toJSON(message: TokenFailedParsing): unknown {
         const obj: any = {};
-        if (message.blocks) {
-            obj.blocks = message.blocks.map(e =>
-                e ? BlockInfo.toJSON(e) : undefined,
-            );
-        } else {
-            obj.blocks = [];
+        if (message.pushdataIdx !== 0) {
+            obj.pushdataIdx = Math.round(message.pushdataIdx);
+        }
+        if (message.bytes.length !== 0) {
+            obj.bytes = base64FromBytes(message.bytes);
+        }
+        if (message.error !== '') {
+            obj.error = message.error;
         }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<Blocks>, I>>(object: I): Blocks {
-        const message = createBaseBlocks();
-        message.blocks =
-            object.blocks?.map(e => BlockInfo.fromPartial(e)) || [];
+    create<I extends Exact<DeepPartial<TokenFailedParsing>, I>>(
+        base?: I,
+    ): TokenFailedParsing {
+        return TokenFailedParsing.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<TokenFailedParsing>, I>>(
+        object: I,
+    ): TokenFailedParsing {
+        const message = createBaseTokenFailedParsing();
+        message.pushdataIdx = object.pushdataIdx ?? 0;
+        message.bytes = object.bytes ?? new Uint8Array(0);
+        message.error = object.error ?? '';
         return message;
     },
 };
 
-function createBaseSlpTxData(): SlpTxData {
-    return { slpMeta: undefined, genesisInfo: undefined };
+function createBaseTokenFailedColoring(): TokenFailedColoring {
+    return { pushdataIdx: 0, error: '' };
 }
 
-export const SlpTxData = {
+export const TokenFailedColoring = {
     encode(
-        message: SlpTxData,
+        message: TokenFailedColoring,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.slpMeta !== undefined) {
-            SlpMeta.encode(message.slpMeta, writer.uint32(10).fork()).ldelim();
+        if (message.pushdataIdx !== 0) {
+            writer.uint32(8).int32(message.pushdataIdx);
         }
-        if (message.genesisInfo !== undefined) {
-            SlpGenesisInfo.encode(
-                message.genesisInfo,
-                writer.uint32(18).fork(),
-            ).ldelim();
+        if (message.error !== '') {
+            writer.uint32(26).string(message.error);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): SlpTxData {
+    decode(
+        input: _m0.Reader | Uint8Array,
+        length?: number,
+    ): TokenFailedColoring {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseSlpTxData();
+        const message = createBaseTokenFailedColoring();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.slpMeta = SlpMeta.decode(reader, reader.uint32());
-                    break;
-                case 2:
-                    message.genesisInfo = SlpGenesisInfo.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 8) {
+                        break;
+                    }
+
+                    message.pushdataIdx = reader.int32();
+                    continue;
+                case 3:
+                    if (tag !== 26) {
+                        break;
+                    }
+
+                    message.error = reader.string();
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): SlpTxData {
+    fromJSON(object: any): TokenFailedColoring {
         return {
-            slpMeta: isSet(object.slpMeta)
-                ? SlpMeta.fromJSON(object.slpMeta)
-                : undefined,
-            genesisInfo: isSet(object.genesisInfo)
-                ? SlpGenesisInfo.fromJSON(object.genesisInfo)
-                : undefined,
+            pushdataIdx: isSet(object.pushdataIdx)
+                ? globalThis.Number(object.pushdataIdx)
+                : 0,
+            error: isSet(object.error) ? globalThis.String(object.error) : '',
         };
     },
 
-    toJSON(message: SlpTxData): unknown {
+    toJSON(message: TokenFailedColoring): unknown {
         const obj: any = {};
-        message.slpMeta !== undefined &&
-            (obj.slpMeta = message.slpMeta
-                ? SlpMeta.toJSON(message.slpMeta)
-                : undefined);
-        message.genesisInfo !== undefined &&
-            (obj.genesisInfo = message.genesisInfo
-                ? SlpGenesisInfo.toJSON(message.genesisInfo)
-                : undefined);
+        if (message.pushdataIdx !== 0) {
+            obj.pushdataIdx = Math.round(message.pushdataIdx);
+        }
+        if (message.error !== '') {
+            obj.error = message.error;
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<SlpTxData>, I>>(
+    create<I extends Exact<DeepPartial<TokenFailedColoring>, I>>(
+        base?: I,
+    ): TokenFailedColoring {
+        return TokenFailedColoring.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<TokenFailedColoring>, I>>(
         object: I,
-    ): SlpTxData {
-        const message = createBaseSlpTxData();
-        message.slpMeta =
-            object.slpMeta !== undefined && object.slpMeta !== null
-                ? SlpMeta.fromPartial(object.slpMeta)
-                : undefined;
-        message.genesisInfo =
-            object.genesisInfo !== undefined && object.genesisInfo !== null
-                ? SlpGenesisInfo.fromPartial(object.genesisInfo)
-                : undefined;
+    ): TokenFailedColoring {
+        const message = createBaseTokenFailedColoring();
+        message.pushdataIdx = object.pushdataIdx ?? 0;
+        message.error = object.error ?? '';
         return message;
     },
 };
 
-function createBaseSlpMeta(): SlpMeta {
-    return {
-        tokenType: 0,
-        txType: 0,
-        tokenId: new Uint8Array(),
-        groupTokenId: new Uint8Array(),
-    };
+function createBasePluginEntry(): PluginEntry {
+    return { groups: [], data: [] };
 }
 
-export const SlpMeta = {
+export const PluginEntry = {
     encode(
-        message: SlpMeta,
+        message: PluginEntry,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.tokenType !== 0) {
-            writer.uint32(8).int32(message.tokenType);
-        }
-        if (message.txType !== 0) {
-            writer.uint32(16).int32(message.txType);
-        }
-        if (message.tokenId.length !== 0) {
-            writer.uint32(26).bytes(message.tokenId);
+        for (const v of message.groups) {
+            writer.uint32(10).bytes(v!);
         }
-        if (message.groupTokenId.length !== 0) {
-            writer.uint32(34).bytes(message.groupTokenId);
+        for (const v of message.data) {
+            writer.uint32(18).bytes(v!);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): SlpMeta {
+    decode(input: _m0.Reader | Uint8Array, length?: number): PluginEntry {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseSlpMeta();
+        const message = createBasePluginEntry();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.tokenType = reader.int32() as any;
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.groups.push(reader.bytes());
+                    continue;
                 case 2:
-                    message.txType = reader.int32() as any;
-                    break;
-                case 3:
-                    message.tokenId = reader.bytes();
-                    break;
-                case 4:
-                    message.groupTokenId = reader.bytes();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.data.push(reader.bytes());
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): SlpMeta {
+    fromJSON(object: any): PluginEntry {
         return {
-            tokenType: isSet(object.tokenType)
-                ? slpTokenTypeFromJSON(object.tokenType)
-                : 0,
-            txType: isSet(object.txType) ? slpTxTypeFromJSON(object.txType) : 0,
-            tokenId: isSet(object.tokenId)
-                ? bytesFromBase64(object.tokenId)
-                : new Uint8Array(),
-            groupTokenId: isSet(object.groupTokenId)
-                ? bytesFromBase64(object.groupTokenId)
-                : new Uint8Array(),
+            groups: globalThis.Array.isArray(object?.groups)
+                ? object.groups.map((e: any) => bytesFromBase64(e))
+                : [],
+            data: globalThis.Array.isArray(object?.data)
+                ? object.data.map((e: any) => bytesFromBase64(e))
+                : [],
         };
     },
 
-    toJSON(message: SlpMeta): unknown {
+    toJSON(message: PluginEntry): unknown {
         const obj: any = {};
-        message.tokenType !== undefined &&
-            (obj.tokenType = slpTokenTypeToJSON(message.tokenType));
-        message.txType !== undefined &&
-            (obj.txType = slpTxTypeToJSON(message.txType));
-        message.tokenId !== undefined &&
-            (obj.tokenId = base64FromBytes(
-                message.tokenId !== undefined
-                    ? message.tokenId
-                    : new Uint8Array(),
-            ));
-        message.groupTokenId !== undefined &&
-            (obj.groupTokenId = base64FromBytes(
-                message.groupTokenId !== undefined
-                    ? message.groupTokenId
-                    : new Uint8Array(),
-            ));
+        if (message.groups?.length) {
+            obj.groups = message.groups.map(e => base64FromBytes(e));
+        }
+        if (message.data?.length) {
+            obj.data = message.data.map(e => base64FromBytes(e));
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<SlpMeta>, I>>(object: I): SlpMeta {
-        const message = createBaseSlpMeta();
-        message.tokenType = object.tokenType ?? 0;
-        message.txType = object.txType ?? 0;
-        message.tokenId = object.tokenId ?? new Uint8Array();
-        message.groupTokenId = object.groupTokenId ?? new Uint8Array();
+    create<I extends Exact<DeepPartial<PluginEntry>, I>>(
+        base?: I,
+    ): PluginEntry {
+        return PluginEntry.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<PluginEntry>, I>>(
+        object: I,
+    ): PluginEntry {
+        const message = createBasePluginEntry();
+        message.groups = object.groups?.map(e => e) || [];
+        message.data = object.data?.map(e => e) || [];
         return message;
     },
 };
 
-function createBaseTokenStats(): TokenStats {
-    return { totalMinted: '', totalBurned: '' };
+function createBasePluginGroup(): PluginGroup {
+    return { group: new Uint8Array(0) };
 }
 
-export const TokenStats = {
+export const PluginGroup = {
     encode(
-        message: TokenStats,
+        message: PluginGroup,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.totalMinted !== '') {
-            writer.uint32(10).string(message.totalMinted);
-        }
-        if (message.totalBurned !== '') {
-            writer.uint32(18).string(message.totalBurned);
+        if (message.group.length !== 0) {
+            writer.uint32(10).bytes(message.group);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): TokenStats {
+    decode(input: _m0.Reader | Uint8Array, length?: number): PluginGroup {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTokenStats();
+        const message = createBasePluginGroup();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.totalMinted = reader.string();
-                    break;
-                case 2:
-                    message.totalBurned = reader.string();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.group = reader.bytes();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): TokenStats {
+    fromJSON(object: any): PluginGroup {
         return {
-            totalMinted: isSet(object.totalMinted)
-                ? String(object.totalMinted)
-                : '',
-            totalBurned: isSet(object.totalBurned)
-                ? String(object.totalBurned)
-                : '',
+            group: isSet(object.group)
+                ? bytesFromBase64(object.group)
+                : new Uint8Array(0),
         };
     },
 
-    toJSON(message: TokenStats): unknown {
+    toJSON(message: PluginGroup): unknown {
         const obj: any = {};
-        message.totalMinted !== undefined &&
-            (obj.totalMinted = message.totalMinted);
-        message.totalBurned !== undefined &&
-            (obj.totalBurned = message.totalBurned);
+        if (message.group.length !== 0) {
+            obj.group = base64FromBytes(message.group);
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<TokenStats>, I>>(
+    create<I extends Exact<DeepPartial<PluginGroup>, I>>(
+        base?: I,
+    ): PluginGroup {
+        return PluginGroup.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<PluginGroup>, I>>(
         object: I,
-    ): TokenStats {
-        const message = createBaseTokenStats();
-        message.totalMinted = object.totalMinted ?? '';
-        message.totalBurned = object.totalBurned ?? '';
+    ): PluginGroup {
+        const message = createBasePluginGroup();
+        message.group = object.group ?? new Uint8Array(0);
         return message;
     },
 };
 
-function createBaseTxInput(): TxInput {
-    return {
-        prevOut: undefined,
-        inputScript: new Uint8Array(),
-        outputScript: new Uint8Array(),
-        value: '0',
-        sequenceNo: 0,
-        slpBurn: undefined,
-        slpToken: undefined,
-    };
+function createBasePluginGroups(): PluginGroups {
+    return { groups: [], nextStart: new Uint8Array(0) };
 }
 
-export const TxInput = {
+export const PluginGroups = {
     encode(
-        message: TxInput,
+        message: PluginGroups,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.prevOut !== undefined) {
-            OutPoint.encode(message.prevOut, writer.uint32(10).fork()).ldelim();
-        }
-        if (message.inputScript.length !== 0) {
-            writer.uint32(18).bytes(message.inputScript);
-        }
-        if (message.outputScript.length !== 0) {
-            writer.uint32(26).bytes(message.outputScript);
-        }
-        if (message.value !== '0') {
-            writer.uint32(32).int64(message.value);
-        }
-        if (message.sequenceNo !== 0) {
-            writer.uint32(40).uint32(message.sequenceNo);
+        for (const v of message.groups) {
+            PluginGroup.encode(v!, writer.uint32(10).fork()).ldelim();
         }
-        if (message.slpBurn !== undefined) {
-            SlpBurn.encode(message.slpBurn, writer.uint32(50).fork()).ldelim();
-        }
-        if (message.slpToken !== undefined) {
-            SlpToken.encode(
-                message.slpToken,
-                writer.uint32(58).fork(),
-            ).ldelim();
+        if (message.nextStart.length !== 0) {
+            writer.uint32(18).bytes(message.nextStart);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): TxInput {
+    decode(input: _m0.Reader | Uint8Array, length?: number): PluginGroups {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTxInput();
+        const message = createBasePluginGroups();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.prevOut = OutPoint.decode(reader, reader.uint32());
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.groups.push(
+                        PluginGroup.decode(reader, reader.uint32()),
+                    );
+                    continue;
                 case 2:
-                    message.inputScript = reader.bytes();
-                    break;
-                case 3:
-                    message.outputScript = reader.bytes();
-                    break;
-                case 4:
-                    message.value = longToString(reader.int64() as Long);
-                    break;
-                case 5:
-                    message.sequenceNo = reader.uint32();
-                    break;
-                case 6:
-                    message.slpBurn = SlpBurn.decode(reader, reader.uint32());
-                    break;
-                case 7:
-                    message.slpToken = SlpToken.decode(reader, reader.uint32());
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.nextStart = reader.bytes();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): TxInput {
+    fromJSON(object: any): PluginGroups {
         return {
-            prevOut: isSet(object.prevOut)
-                ? OutPoint.fromJSON(object.prevOut)
-                : undefined,
-            inputScript: isSet(object.inputScript)
-                ? bytesFromBase64(object.inputScript)
-                : new Uint8Array(),
-            outputScript: isSet(object.outputScript)
-                ? bytesFromBase64(object.outputScript)
-                : new Uint8Array(),
-            value: isSet(object.value) ? String(object.value) : '0',
-            sequenceNo: isSet(object.sequenceNo)
-                ? Number(object.sequenceNo)
-                : 0,
-            slpBurn: isSet(object.slpBurn)
-                ? SlpBurn.fromJSON(object.slpBurn)
-                : undefined,
-            slpToken: isSet(object.slpToken)
-                ? SlpToken.fromJSON(object.slpToken)
-                : undefined,
+            groups: globalThis.Array.isArray(object?.groups)
+                ? object.groups.map((e: any) => PluginGroup.fromJSON(e))
+                : [],
+            nextStart: isSet(object.nextStart)
+                ? bytesFromBase64(object.nextStart)
+                : new Uint8Array(0),
         };
     },
 
-    toJSON(message: TxInput): unknown {
+    toJSON(message: PluginGroups): unknown {
         const obj: any = {};
-        message.prevOut !== undefined &&
-            (obj.prevOut = message.prevOut
-                ? OutPoint.toJSON(message.prevOut)
-                : undefined);
-        message.inputScript !== undefined &&
-            (obj.inputScript = base64FromBytes(
-                message.inputScript !== undefined
-                    ? message.inputScript
-                    : new Uint8Array(),
-            ));
-        message.outputScript !== undefined &&
-            (obj.outputScript = base64FromBytes(
-                message.outputScript !== undefined
-                    ? message.outputScript
-                    : new Uint8Array(),
-            ));
-        message.value !== undefined && (obj.value = message.value);
-        message.sequenceNo !== undefined &&
-            (obj.sequenceNo = Math.round(message.sequenceNo));
-        message.slpBurn !== undefined &&
-            (obj.slpBurn = message.slpBurn
-                ? SlpBurn.toJSON(message.slpBurn)
-                : undefined);
-        message.slpToken !== undefined &&
-            (obj.slpToken = message.slpToken
-                ? SlpToken.toJSON(message.slpToken)
-                : undefined);
+        if (message.groups?.length) {
+            obj.groups = message.groups.map(e => PluginGroup.toJSON(e));
+        }
+        if (message.nextStart.length !== 0) {
+            obj.nextStart = base64FromBytes(message.nextStart);
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<TxInput>, I>>(object: I): TxInput {
-        const message = createBaseTxInput();
-        message.prevOut =
-            object.prevOut !== undefined && object.prevOut !== null
-                ? OutPoint.fromPartial(object.prevOut)
-                : undefined;
-        message.inputScript = object.inputScript ?? new Uint8Array();
-        message.outputScript = object.outputScript ?? new Uint8Array();
-        message.value = object.value ?? '0';
-        message.sequenceNo = object.sequenceNo ?? 0;
-        message.slpBurn =
-            object.slpBurn !== undefined && object.slpBurn !== null
-                ? SlpBurn.fromPartial(object.slpBurn)
-                : undefined;
-        message.slpToken =
-            object.slpToken !== undefined && object.slpToken !== null
-                ? SlpToken.fromPartial(object.slpToken)
-                : undefined;
+    create<I extends Exact<DeepPartial<PluginGroups>, I>>(
+        base?: I,
+    ): PluginGroups {
+        return PluginGroups.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<PluginGroups>, I>>(
+        object: I,
+    ): PluginGroups {
+        const message = createBasePluginGroups();
+        message.groups =
+            object.groups?.map(e => PluginGroup.fromPartial(e)) || [];
+        message.nextStart = object.nextStart ?? new Uint8Array(0);
         return message;
     },
 };
 
-function createBaseTxOutput(): TxOutput {
-    return {
-        value: '0',
-        outputScript: new Uint8Array(),
-        slpToken: undefined,
-        spentBy: undefined,
-    };
+function createBaseTxHistoryPage(): TxHistoryPage {
+    return { txs: [], numPages: 0, numTxs: 0 };
 }
 
-export const TxOutput = {
+export const TxHistoryPage = {
     encode(
-        message: TxOutput,
+        message: TxHistoryPage,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.value !== '0') {
-            writer.uint32(8).int64(message.value);
-        }
-        if (message.outputScript.length !== 0) {
-            writer.uint32(18).bytes(message.outputScript);
+        for (const v of message.txs) {
+            Tx.encode(v!, writer.uint32(10).fork()).ldelim();
         }
-        if (message.slpToken !== undefined) {
-            SlpToken.encode(
-                message.slpToken,
-                writer.uint32(26).fork(),
-            ).ldelim();
+        if (message.numPages !== 0) {
+            writer.uint32(16).uint32(message.numPages);
         }
-        if (message.spentBy !== undefined) {
-            OutPoint.encode(message.spentBy, writer.uint32(34).fork()).ldelim();
+        if (message.numTxs !== 0) {
+            writer.uint32(24).uint32(message.numTxs);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): TxOutput {
+    decode(input: _m0.Reader | Uint8Array, length?: number): TxHistoryPage {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTxOutput();
+        const message = createBaseTxHistoryPage();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.value = longToString(reader.int64() as Long);
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.txs.push(Tx.decode(reader, reader.uint32()));
+                    continue;
                 case 2:
-                    message.outputScript = reader.bytes();
-                    break;
+                    if (tag !== 16) {
+                        break;
+                    }
+
+                    message.numPages = reader.uint32();
+                    continue;
                 case 3:
-                    message.slpToken = SlpToken.decode(reader, reader.uint32());
-                    break;
-                case 4:
-                    message.spentBy = OutPoint.decode(reader, reader.uint32());
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 24) {
+                        break;
+                    }
+
+                    message.numTxs = reader.uint32();
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): TxOutput {
+    fromJSON(object: any): TxHistoryPage {
         return {
-            value: isSet(object.value) ? String(object.value) : '0',
-            outputScript: isSet(object.outputScript)
-                ? bytesFromBase64(object.outputScript)
-                : new Uint8Array(),
-            slpToken: isSet(object.slpToken)
-                ? SlpToken.fromJSON(object.slpToken)
-                : undefined,
-            spentBy: isSet(object.spentBy)
-                ? OutPoint.fromJSON(object.spentBy)
-                : undefined,
+            txs: globalThis.Array.isArray(object?.txs)
+                ? object.txs.map((e: any) => Tx.fromJSON(e))
+                : [],
+            numPages: isSet(object.numPages)
+                ? globalThis.Number(object.numPages)
+                : 0,
+            numTxs: isSet(object.numTxs) ? globalThis.Number(object.numTxs) : 0,
         };
     },
 
-    toJSON(message: TxOutput): unknown {
+    toJSON(message: TxHistoryPage): unknown {
         const obj: any = {};
-        message.value !== undefined && (obj.value = message.value);
-        message.outputScript !== undefined &&
-            (obj.outputScript = base64FromBytes(
-                message.outputScript !== undefined
-                    ? message.outputScript
-                    : new Uint8Array(),
-            ));
-        message.slpToken !== undefined &&
-            (obj.slpToken = message.slpToken
-                ? SlpToken.toJSON(message.slpToken)
-                : undefined);
-        message.spentBy !== undefined &&
-            (obj.spentBy = message.spentBy
-                ? OutPoint.toJSON(message.spentBy)
-                : undefined);
+        if (message.txs?.length) {
+            obj.txs = message.txs.map(e => Tx.toJSON(e));
+        }
+        if (message.numPages !== 0) {
+            obj.numPages = Math.round(message.numPages);
+        }
+        if (message.numTxs !== 0) {
+            obj.numTxs = Math.round(message.numTxs);
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<TxOutput>, I>>(
-        object: I,
-    ): TxOutput {
-        const message = createBaseTxOutput();
-        message.value = object.value ?? '0';
-        message.outputScript = object.outputScript ?? new Uint8Array();
-        message.slpToken =
-            object.slpToken !== undefined && object.slpToken !== null
-                ? SlpToken.fromPartial(object.slpToken)
-                : undefined;
-        message.spentBy =
-            object.spentBy !== undefined && object.spentBy !== null
-                ? OutPoint.fromPartial(object.spentBy)
-                : undefined;
+    create<I extends Exact<DeepPartial<TxHistoryPage>, I>>(
+        base?: I,
+    ): TxHistoryPage {
+        return TxHistoryPage.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<TxHistoryPage>, I>>(
+        object: I,
+    ): TxHistoryPage {
+        const message = createBaseTxHistoryPage();
+        message.txs = object.txs?.map(e => Tx.fromPartial(e)) || [];
+        message.numPages = object.numPages ?? 0;
+        message.numTxs = object.numTxs ?? 0;
         return message;
     },
 };
 
-function createBaseBlockMetadata(): BlockMetadata {
-    return { height: 0, hash: new Uint8Array(), timestamp: '0' };
+function createBaseScriptUtxos(): ScriptUtxos {
+    return { script: new Uint8Array(0), utxos: [] };
 }
 
-export const BlockMetadata = {
+export const ScriptUtxos = {
     encode(
-        message: BlockMetadata,
+        message: ScriptUtxos,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.height !== 0) {
-            writer.uint32(8).int32(message.height);
-        }
-        if (message.hash.length !== 0) {
-            writer.uint32(18).bytes(message.hash);
+        if (message.script.length !== 0) {
+            writer.uint32(10).bytes(message.script);
         }
-        if (message.timestamp !== '0') {
-            writer.uint32(24).int64(message.timestamp);
+        for (const v of message.utxos) {
+            ScriptUtxo.encode(v!, writer.uint32(18).fork()).ldelim();
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): BlockMetadata {
+    decode(input: _m0.Reader | Uint8Array, length?: number): ScriptUtxos {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBlockMetadata();
+        const message = createBaseScriptUtxos();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.height = reader.int32();
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.script = reader.bytes();
+                    continue;
                 case 2:
-                    message.hash = reader.bytes();
-                    break;
-                case 3:
-                    message.timestamp = longToString(reader.int64() as Long);
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.utxos.push(
+                        ScriptUtxo.decode(reader, reader.uint32()),
+                    );
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): BlockMetadata {
+    fromJSON(object: any): ScriptUtxos {
         return {
-            height: isSet(object.height) ? Number(object.height) : 0,
-            hash: isSet(object.hash)
-                ? bytesFromBase64(object.hash)
-                : new Uint8Array(),
-            timestamp: isSet(object.timestamp) ? String(object.timestamp) : '0',
+            script: isSet(object.script)
+                ? bytesFromBase64(object.script)
+                : new Uint8Array(0),
+            utxos: globalThis.Array.isArray(object?.utxos)
+                ? object.utxos.map((e: any) => ScriptUtxo.fromJSON(e))
+                : [],
         };
     },
 
-    toJSON(message: BlockMetadata): unknown {
+    toJSON(message: ScriptUtxos): unknown {
         const obj: any = {};
-        message.height !== undefined &&
-            (obj.height = Math.round(message.height));
-        message.hash !== undefined &&
-            (obj.hash = base64FromBytes(
-                message.hash !== undefined ? message.hash : new Uint8Array(),
-            ));
-        message.timestamp !== undefined && (obj.timestamp = message.timestamp);
+        if (message.script.length !== 0) {
+            obj.script = base64FromBytes(message.script);
+        }
+        if (message.utxos?.length) {
+            obj.utxos = message.utxos.map(e => ScriptUtxo.toJSON(e));
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<BlockMetadata>, I>>(
+    create<I extends Exact<DeepPartial<ScriptUtxos>, I>>(
+        base?: I,
+    ): ScriptUtxos {
+        return ScriptUtxos.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<ScriptUtxos>, I>>(
         object: I,
-    ): BlockMetadata {
-        const message = createBaseBlockMetadata();
-        message.height = object.height ?? 0;
-        message.hash = object.hash ?? new Uint8Array();
-        message.timestamp = object.timestamp ?? '0';
+    ): ScriptUtxos {
+        const message = createBaseScriptUtxos();
+        message.script = object.script ?? new Uint8Array(0);
+        message.utxos = object.utxos?.map(e => ScriptUtxo.fromPartial(e)) || [];
         return message;
     },
 };
 
-function createBaseOutPoint(): OutPoint {
-    return { txid: new Uint8Array(), outIdx: 0 };
+function createBaseUtxos(): Utxos {
+    return { utxos: [] };
 }
 
-export const OutPoint = {
+export const Utxos = {
     encode(
-        message: OutPoint,
+        message: Utxos,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.txid.length !== 0) {
-            writer.uint32(10).bytes(message.txid);
-        }
-        if (message.outIdx !== 0) {
-            writer.uint32(16).uint32(message.outIdx);
+        for (const v of message.utxos) {
+            Utxo.encode(v!, writer.uint32(10).fork()).ldelim();
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): OutPoint {
+    decode(input: _m0.Reader | Uint8Array, length?: number): Utxos {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseOutPoint();
+        const message = createBaseUtxos();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.txid = reader.bytes();
-                    break;
-                case 2:
-                    message.outIdx = reader.uint32();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.utxos.push(Utxo.decode(reader, reader.uint32()));
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): OutPoint {
+    fromJSON(object: any): Utxos {
         return {
-            txid: isSet(object.txid)
-                ? bytesFromBase64(object.txid)
-                : new Uint8Array(),
-            outIdx: isSet(object.outIdx) ? Number(object.outIdx) : 0,
+            utxos: globalThis.Array.isArray(object?.utxos)
+                ? object.utxos.map((e: any) => Utxo.fromJSON(e))
+                : [],
         };
     },
 
-    toJSON(message: OutPoint): unknown {
+    toJSON(message: Utxos): unknown {
         const obj: any = {};
-        message.txid !== undefined &&
-            (obj.txid = base64FromBytes(
-                message.txid !== undefined ? message.txid : new Uint8Array(),
-            ));
-        message.outIdx !== undefined &&
-            (obj.outIdx = Math.round(message.outIdx));
+        if (message.utxos?.length) {
+            obj.utxos = message.utxos.map(e => Utxo.toJSON(e));
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<OutPoint>, I>>(
-        object: I,
-    ): OutPoint {
-        const message = createBaseOutPoint();
-        message.txid = object.txid ?? new Uint8Array();
-        message.outIdx = object.outIdx ?? 0;
+    create<I extends Exact<DeepPartial<Utxos>, I>>(base?: I): Utxos {
+        return Utxos.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<Utxos>, I>>(object: I): Utxos {
+        const message = createBaseUtxos();
+        message.utxos = object.utxos?.map(e => Utxo.fromPartial(e)) || [];
         return message;
     },
 };
 
-function createBaseSlpToken(): SlpToken {
-    return { amount: '0', isMintBaton: false };
+function createBaseBroadcastTxRequest(): BroadcastTxRequest {
+    return { rawTx: new Uint8Array(0), skipTokenChecks: false };
 }
 
-export const SlpToken = {
+export const BroadcastTxRequest = {
     encode(
-        message: SlpToken,
+        message: BroadcastTxRequest,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.amount !== '0') {
-            writer.uint32(8).uint64(message.amount);
+        if (message.rawTx.length !== 0) {
+            writer.uint32(10).bytes(message.rawTx);
         }
-        if (message.isMintBaton === true) {
-            writer.uint32(16).bool(message.isMintBaton);
+        if (message.skipTokenChecks === true) {
+            writer.uint32(16).bool(message.skipTokenChecks);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): SlpToken {
+    decode(
+        input: _m0.Reader | Uint8Array,
+        length?: number,
+    ): BroadcastTxRequest {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseSlpToken();
+        const message = createBaseBroadcastTxRequest();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.amount = longToString(reader.uint64() as Long);
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.rawTx = reader.bytes();
+                    continue;
                 case 2:
-                    message.isMintBaton = reader.bool();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 16) {
+                        break;
+                    }
+
+                    message.skipTokenChecks = reader.bool();
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): SlpToken {
+    fromJSON(object: any): BroadcastTxRequest {
         return {
-            amount: isSet(object.amount) ? String(object.amount) : '0',
-            isMintBaton: isSet(object.isMintBaton)
-                ? Boolean(object.isMintBaton)
+            rawTx: isSet(object.rawTx)
+                ? bytesFromBase64(object.rawTx)
+                : new Uint8Array(0),
+            skipTokenChecks: isSet(object.skipTokenChecks)
+                ? globalThis.Boolean(object.skipTokenChecks)
                 : false,
         };
     },
 
-    toJSON(message: SlpToken): unknown {
+    toJSON(message: BroadcastTxRequest): unknown {
         const obj: any = {};
-        message.amount !== undefined && (obj.amount = message.amount);
-        message.isMintBaton !== undefined &&
-            (obj.isMintBaton = message.isMintBaton);
+        if (message.rawTx.length !== 0) {
+            obj.rawTx = base64FromBytes(message.rawTx);
+        }
+        if (message.skipTokenChecks === true) {
+            obj.skipTokenChecks = message.skipTokenChecks;
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<SlpToken>, I>>(
+    create<I extends Exact<DeepPartial<BroadcastTxRequest>, I>>(
+        base?: I,
+    ): BroadcastTxRequest {
+        return BroadcastTxRequest.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<BroadcastTxRequest>, I>>(
         object: I,
-    ): SlpToken {
-        const message = createBaseSlpToken();
-        message.amount = object.amount ?? '0';
-        message.isMintBaton = object.isMintBaton ?? false;
+    ): BroadcastTxRequest {
+        const message = createBaseBroadcastTxRequest();
+        message.rawTx = object.rawTx ?? new Uint8Array(0);
+        message.skipTokenChecks = object.skipTokenChecks ?? false;
         return message;
     },
 };
 
-function createBaseSlpBurn(): SlpBurn {
-    return { token: undefined, tokenId: new Uint8Array() };
+function createBaseBroadcastTxResponse(): BroadcastTxResponse {
+    return { txid: new Uint8Array(0) };
 }
 
-export const SlpBurn = {
+export const BroadcastTxResponse = {
     encode(
-        message: SlpBurn,
+        message: BroadcastTxResponse,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.token !== undefined) {
-            SlpToken.encode(message.token, writer.uint32(10).fork()).ldelim();
-        }
-        if (message.tokenId.length !== 0) {
-            writer.uint32(18).bytes(message.tokenId);
+        if (message.txid.length !== 0) {
+            writer.uint32(10).bytes(message.txid);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): SlpBurn {
+    decode(
+        input: _m0.Reader | Uint8Array,
+        length?: number,
+    ): BroadcastTxResponse {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseSlpBurn();
+        const message = createBaseBroadcastTxResponse();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.token = SlpToken.decode(reader, reader.uint32());
-                    break;
-                case 2:
-                    message.tokenId = reader.bytes();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.txid = reader.bytes();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): SlpBurn {
+    fromJSON(object: any): BroadcastTxResponse {
         return {
-            token: isSet(object.token)
-                ? SlpToken.fromJSON(object.token)
-                : undefined,
-            tokenId: isSet(object.tokenId)
-                ? bytesFromBase64(object.tokenId)
-                : new Uint8Array(),
+            txid: isSet(object.txid)
+                ? bytesFromBase64(object.txid)
+                : new Uint8Array(0),
         };
     },
 
-    toJSON(message: SlpBurn): unknown {
+    toJSON(message: BroadcastTxResponse): unknown {
         const obj: any = {};
-        message.token !== undefined &&
-            (obj.token = message.token
-                ? SlpToken.toJSON(message.token)
-                : undefined);
-        message.tokenId !== undefined &&
-            (obj.tokenId = base64FromBytes(
-                message.tokenId !== undefined
-                    ? message.tokenId
-                    : new Uint8Array(),
-            ));
+        if (message.txid.length !== 0) {
+            obj.txid = base64FromBytes(message.txid);
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<SlpBurn>, I>>(object: I): SlpBurn {
-        const message = createBaseSlpBurn();
-        message.token =
-            object.token !== undefined && object.token !== null
-                ? SlpToken.fromPartial(object.token)
-                : undefined;
-        message.tokenId = object.tokenId ?? new Uint8Array();
+    create<I extends Exact<DeepPartial<BroadcastTxResponse>, I>>(
+        base?: I,
+    ): BroadcastTxResponse {
+        return BroadcastTxResponse.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<BroadcastTxResponse>, I>>(
+        object: I,
+    ): BroadcastTxResponse {
+        const message = createBaseBroadcastTxResponse();
+        message.txid = object.txid ?? new Uint8Array(0);
         return message;
     },
 };
 
-function createBaseSlpGenesisInfo(): SlpGenesisInfo {
-    return {
-        tokenTicker: new Uint8Array(),
-        tokenName: new Uint8Array(),
-        tokenDocumentUrl: new Uint8Array(),
-        tokenDocumentHash: new Uint8Array(),
-        decimals: 0,
-    };
+function createBaseBroadcastTxsRequest(): BroadcastTxsRequest {
+    return { rawTxs: [], skipTokenChecks: false };
 }
 
-export const SlpGenesisInfo = {
+export const BroadcastTxsRequest = {
     encode(
-        message: SlpGenesisInfo,
+        message: BroadcastTxsRequest,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.tokenTicker.length !== 0) {
-            writer.uint32(10).bytes(message.tokenTicker);
-        }
-        if (message.tokenName.length !== 0) {
-            writer.uint32(18).bytes(message.tokenName);
-        }
-        if (message.tokenDocumentUrl.length !== 0) {
-            writer.uint32(26).bytes(message.tokenDocumentUrl);
-        }
-        if (message.tokenDocumentHash.length !== 0) {
-            writer.uint32(34).bytes(message.tokenDocumentHash);
+        for (const v of message.rawTxs) {
+            writer.uint32(10).bytes(v!);
         }
-        if (message.decimals !== 0) {
-            writer.uint32(40).uint32(message.decimals);
+        if (message.skipTokenChecks === true) {
+            writer.uint32(16).bool(message.skipTokenChecks);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): SlpGenesisInfo {
+    decode(
+        input: _m0.Reader | Uint8Array,
+        length?: number,
+    ): BroadcastTxsRequest {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseSlpGenesisInfo();
+        const message = createBaseBroadcastTxsRequest();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.tokenTicker = reader.bytes();
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.rawTxs.push(reader.bytes());
+                    continue;
                 case 2:
-                    message.tokenName = reader.bytes();
-                    break;
-                case 3:
-                    message.tokenDocumentUrl = reader.bytes();
-                    break;
-                case 4:
-                    message.tokenDocumentHash = reader.bytes();
-                    break;
-                case 5:
-                    message.decimals = reader.uint32();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 16) {
+                        break;
+                    }
+
+                    message.skipTokenChecks = reader.bool();
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): SlpGenesisInfo {
+    fromJSON(object: any): BroadcastTxsRequest {
         return {
-            tokenTicker: isSet(object.tokenTicker)
-                ? bytesFromBase64(object.tokenTicker)
-                : new Uint8Array(),
-            tokenName: isSet(object.tokenName)
-                ? bytesFromBase64(object.tokenName)
-                : new Uint8Array(),
-            tokenDocumentUrl: isSet(object.tokenDocumentUrl)
-                ? bytesFromBase64(object.tokenDocumentUrl)
-                : new Uint8Array(),
-            tokenDocumentHash: isSet(object.tokenDocumentHash)
-                ? bytesFromBase64(object.tokenDocumentHash)
-                : new Uint8Array(),
-            decimals: isSet(object.decimals) ? Number(object.decimals) : 0,
+            rawTxs: globalThis.Array.isArray(object?.rawTxs)
+                ? object.rawTxs.map((e: any) => bytesFromBase64(e))
+                : [],
+            skipTokenChecks: isSet(object.skipTokenChecks)
+                ? globalThis.Boolean(object.skipTokenChecks)
+                : false,
         };
     },
 
-    toJSON(message: SlpGenesisInfo): unknown {
+    toJSON(message: BroadcastTxsRequest): unknown {
         const obj: any = {};
-        message.tokenTicker !== undefined &&
-            (obj.tokenTicker = base64FromBytes(
-                message.tokenTicker !== undefined
-                    ? message.tokenTicker
-                    : new Uint8Array(),
-            ));
-        message.tokenName !== undefined &&
-            (obj.tokenName = base64FromBytes(
-                message.tokenName !== undefined
-                    ? message.tokenName
-                    : new Uint8Array(),
-            ));
-        message.tokenDocumentUrl !== undefined &&
-            (obj.tokenDocumentUrl = base64FromBytes(
-                message.tokenDocumentUrl !== undefined
-                    ? message.tokenDocumentUrl
-                    : new Uint8Array(),
-            ));
-        message.tokenDocumentHash !== undefined &&
-            (obj.tokenDocumentHash = base64FromBytes(
-                message.tokenDocumentHash !== undefined
-                    ? message.tokenDocumentHash
-                    : new Uint8Array(),
-            ));
-        message.decimals !== undefined &&
-            (obj.decimals = Math.round(message.decimals));
+        if (message.rawTxs?.length) {
+            obj.rawTxs = message.rawTxs.map(e => base64FromBytes(e));
+        }
+        if (message.skipTokenChecks === true) {
+            obj.skipTokenChecks = message.skipTokenChecks;
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<SlpGenesisInfo>, I>>(
+    create<I extends Exact<DeepPartial<BroadcastTxsRequest>, I>>(
+        base?: I,
+    ): BroadcastTxsRequest {
+        return BroadcastTxsRequest.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<BroadcastTxsRequest>, I>>(
         object: I,
-    ): SlpGenesisInfo {
-        const message = createBaseSlpGenesisInfo();
-        message.tokenTicker = object.tokenTicker ?? new Uint8Array();
-        message.tokenName = object.tokenName ?? new Uint8Array();
-        message.tokenDocumentUrl = object.tokenDocumentUrl ?? new Uint8Array();
-        message.tokenDocumentHash =
-            object.tokenDocumentHash ?? new Uint8Array();
-        message.decimals = object.decimals ?? 0;
+    ): BroadcastTxsRequest {
+        const message = createBaseBroadcastTxsRequest();
+        message.rawTxs = object.rawTxs?.map(e => e) || [];
+        message.skipTokenChecks = object.skipTokenChecks ?? false;
         return message;
     },
 };
 
-function createBaseUtxoState(): UtxoState {
-    return { height: 0, isConfirmed: false, state: 0 };
+function createBaseBroadcastTxsResponse(): BroadcastTxsResponse {
+    return { txids: [] };
 }
 
-export const UtxoState = {
+export const BroadcastTxsResponse = {
     encode(
-        message: UtxoState,
+        message: BroadcastTxsResponse,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.height !== 0) {
-            writer.uint32(8).int32(message.height);
-        }
-        if (message.isConfirmed === true) {
-            writer.uint32(16).bool(message.isConfirmed);
-        }
-        if (message.state !== 0) {
-            writer.uint32(24).int32(message.state);
+        for (const v of message.txids) {
+            writer.uint32(10).bytes(v!);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): UtxoState {
+    decode(
+        input: _m0.Reader | Uint8Array,
+        length?: number,
+    ): BroadcastTxsResponse {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseUtxoState();
+        const message = createBaseBroadcastTxsResponse();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.height = reader.int32();
-                    break;
-                case 2:
-                    message.isConfirmed = reader.bool();
-                    break;
-                case 3:
-                    message.state = reader.int32() as any;
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.txids.push(reader.bytes());
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): UtxoState {
+    fromJSON(object: any): BroadcastTxsResponse {
         return {
-            height: isSet(object.height) ? Number(object.height) : 0,
-            isConfirmed: isSet(object.isConfirmed)
-                ? Boolean(object.isConfirmed)
-                : false,
-            state: isSet(object.state)
-                ? utxoStateVariantFromJSON(object.state)
-                : 0,
+            txids: globalThis.Array.isArray(object?.txids)
+                ? object.txids.map((e: any) => bytesFromBase64(e))
+                : [],
         };
     },
 
-    toJSON(message: UtxoState): unknown {
+    toJSON(message: BroadcastTxsResponse): unknown {
         const obj: any = {};
-        message.height !== undefined &&
-            (obj.height = Math.round(message.height));
-        message.isConfirmed !== undefined &&
-            (obj.isConfirmed = message.isConfirmed);
-        message.state !== undefined &&
-            (obj.state = utxoStateVariantToJSON(message.state));
+        if (message.txids?.length) {
+            obj.txids = message.txids.map(e => base64FromBytes(e));
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<UtxoState>, I>>(
+    create<I extends Exact<DeepPartial<BroadcastTxsResponse>, I>>(
+        base?: I,
+    ): BroadcastTxsResponse {
+        return BroadcastTxsResponse.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<BroadcastTxsResponse>, I>>(
         object: I,
-    ): UtxoState {
-        const message = createBaseUtxoState();
-        message.height = object.height ?? 0;
-        message.isConfirmed = object.isConfirmed ?? false;
-        message.state = object.state ?? 0;
+    ): BroadcastTxsResponse {
+        const message = createBaseBroadcastTxsResponse();
+        message.txids = object.txids?.map(e => e) || [];
         return message;
     },
 };
 
-function createBaseSubscription(): Subscription {
-    return { scriptType: '', payload: new Uint8Array(), isSubscribe: false };
+function createBaseRawTx(): RawTx {
+    return { rawTx: new Uint8Array(0) };
 }
 
-export const Subscription = {
+export const RawTx = {
     encode(
-        message: Subscription,
+        message: RawTx,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.scriptType !== '') {
-            writer.uint32(10).string(message.scriptType);
-        }
-        if (message.payload.length !== 0) {
-            writer.uint32(18).bytes(message.payload);
-        }
-        if (message.isSubscribe === true) {
-            writer.uint32(24).bool(message.isSubscribe);
+        if (message.rawTx.length !== 0) {
+            writer.uint32(10).bytes(message.rawTx);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): Subscription {
+    decode(input: _m0.Reader | Uint8Array, length?: number): RawTx {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseSubscription();
+        const message = createBaseRawTx();
         while (reader.pos < end) {
             const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    message.scriptType = reader.string();
-                    break;
-                case 2:
-                    message.payload = reader.bytes();
-                    break;
-                case 3:
-                    message.isSubscribe = reader.bool();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+            switch (tag >>> 3) {
+                case 1:
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.rawTx = reader.bytes();
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): Subscription {
+    fromJSON(object: any): RawTx {
         return {
-            scriptType: isSet(object.scriptType)
-                ? String(object.scriptType)
-                : '',
-            payload: isSet(object.payload)
-                ? bytesFromBase64(object.payload)
-                : new Uint8Array(),
-            isSubscribe: isSet(object.isSubscribe)
-                ? Boolean(object.isSubscribe)
-                : false,
+            rawTx: isSet(object.rawTx)
+                ? bytesFromBase64(object.rawTx)
+                : new Uint8Array(0),
         };
     },
 
-    toJSON(message: Subscription): unknown {
+    toJSON(message: RawTx): unknown {
         const obj: any = {};
-        message.scriptType !== undefined &&
-            (obj.scriptType = message.scriptType);
-        message.payload !== undefined &&
-            (obj.payload = base64FromBytes(
-                message.payload !== undefined
-                    ? message.payload
-                    : new Uint8Array(),
-            ));
-        message.isSubscribe !== undefined &&
-            (obj.isSubscribe = message.isSubscribe);
+        if (message.rawTx.length !== 0) {
+            obj.rawTx = base64FromBytes(message.rawTx);
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<Subscription>, I>>(
-        object: I,
-    ): Subscription {
-        const message = createBaseSubscription();
-        message.scriptType = object.scriptType ?? '';
-        message.payload = object.payload ?? new Uint8Array();
-        message.isSubscribe = object.isSubscribe ?? false;
+    create<I extends Exact<DeepPartial<RawTx>, I>>(base?: I): RawTx {
+        return RawTx.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<RawTx>, I>>(object: I): RawTx {
+        const message = createBaseRawTx();
+        message.rawTx = object.rawTx ?? new Uint8Array(0);
         return message;
     },
 };
 
-function createBaseSubscribeMsg(): SubscribeMsg {
+function createBaseWsSub(): WsSub {
     return {
-        error: undefined,
-        AddedToMempool: undefined,
-        RemovedFromMempool: undefined,
-        Confirmed: undefined,
-        Reorg: undefined,
-        BlockConnected: undefined,
-        BlockDisconnected: undefined,
+        isUnsub: false,
+        blocks: undefined,
+        script: undefined,
+        tokenId: undefined,
+        lokadId: undefined,
     };
 }
 
-export const SubscribeMsg = {
+export const WsSub = {
     encode(
-        message: SubscribeMsg,
+        message: WsSub,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.error !== undefined) {
-            Error.encode(message.error, writer.uint32(10).fork()).ldelim();
+        if (message.isUnsub === true) {
+            writer.uint32(8).bool(message.isUnsub);
         }
-        if (message.AddedToMempool !== undefined) {
-            MsgAddedToMempool.encode(
-                message.AddedToMempool,
+        if (message.blocks !== undefined) {
+            WsSubBlocks.encode(
+                message.blocks,
                 writer.uint32(18).fork(),
             ).ldelim();
         }
-        if (message.RemovedFromMempool !== undefined) {
-            MsgRemovedFromMempool.encode(
-                message.RemovedFromMempool,
+        if (message.script !== undefined) {
+            WsSubScript.encode(
+                message.script,
                 writer.uint32(26).fork(),
             ).ldelim();
         }
-        if (message.Confirmed !== undefined) {
-            MsgConfirmed.encode(
-                message.Confirmed,
+        if (message.tokenId !== undefined) {
+            WsSubTokenId.encode(
+                message.tokenId,
                 writer.uint32(34).fork(),
             ).ldelim();
         }
-        if (message.Reorg !== undefined) {
-            MsgReorg.encode(message.Reorg, writer.uint32(42).fork()).ldelim();
-        }
-        if (message.BlockConnected !== undefined) {
-            MsgBlockConnected.encode(
-                message.BlockConnected,
-                writer.uint32(50).fork(),
-            ).ldelim();
-        }
-        if (message.BlockDisconnected !== undefined) {
-            MsgBlockDisconnected.encode(
-                message.BlockDisconnected,
-                writer.uint32(58).fork(),
+        if (message.lokadId !== undefined) {
+            WsSubLokadId.encode(
+                message.lokadId,
+                writer.uint32(42).fork(),
             ).ldelim();
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): SubscribeMsg {
+    decode(input: _m0.Reader | Uint8Array, length?: number): WsSub {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseSubscribeMsg();
+        const message = createBaseWsSub();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.error = Error.decode(reader, reader.uint32());
-                    break;
+                    if (tag !== 8) {
+                        break;
+                    }
+
+                    message.isUnsub = reader.bool();
+                    continue;
                 case 2:
-                    message.AddedToMempool = MsgAddedToMempool.decode(
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.blocks = WsSubBlocks.decode(
                         reader,
                         reader.uint32(),
                     );
-                    break;
+                    continue;
                 case 3:
-                    message.RemovedFromMempool = MsgRemovedFromMempool.decode(
+                    if (tag !== 26) {
+                        break;
+                    }
+
+                    message.script = WsSubScript.decode(
                         reader,
                         reader.uint32(),
                     );
-                    break;
+                    continue;
                 case 4:
-                    message.Confirmed = MsgConfirmed.decode(
+                    if (tag !== 34) {
+                        break;
+                    }
+
+                    message.tokenId = WsSubTokenId.decode(
                         reader,
                         reader.uint32(),
                     );
-                    break;
+                    continue;
                 case 5:
-                    message.Reorg = MsgReorg.decode(reader, reader.uint32());
-                    break;
-                case 6:
-                    message.BlockConnected = MsgBlockConnected.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    break;
-                case 7:
-                    message.BlockDisconnected = MsgBlockDisconnected.decode(
+                    if (tag !== 42) {
+                        break;
+                    }
+
+                    message.lokadId = WsSubLokadId.decode(
                         reader,
                         reader.uint32(),
                     );
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): SubscribeMsg {
+    fromJSON(object: any): WsSub {
         return {
-            error: isSet(object.error)
-                ? Error.fromJSON(object.error)
-                : undefined,
-            AddedToMempool: isSet(object.AddedToMempool)
-                ? MsgAddedToMempool.fromJSON(object.AddedToMempool)
-                : undefined,
-            RemovedFromMempool: isSet(object.RemovedFromMempool)
-                ? MsgRemovedFromMempool.fromJSON(object.RemovedFromMempool)
-                : undefined,
-            Confirmed: isSet(object.Confirmed)
-                ? MsgConfirmed.fromJSON(object.Confirmed)
+            isUnsub: isSet(object.isUnsub)
+                ? globalThis.Boolean(object.isUnsub)
+                : false,
+            blocks: isSet(object.blocks)
+                ? WsSubBlocks.fromJSON(object.blocks)
                 : undefined,
-            Reorg: isSet(object.Reorg)
-                ? MsgReorg.fromJSON(object.Reorg)
+            script: isSet(object.script)
+                ? WsSubScript.fromJSON(object.script)
                 : undefined,
-            BlockConnected: isSet(object.BlockConnected)
-                ? MsgBlockConnected.fromJSON(object.BlockConnected)
+            tokenId: isSet(object.tokenId)
+                ? WsSubTokenId.fromJSON(object.tokenId)
                 : undefined,
-            BlockDisconnected: isSet(object.BlockDisconnected)
-                ? MsgBlockDisconnected.fromJSON(object.BlockDisconnected)
+            lokadId: isSet(object.lokadId)
+                ? WsSubLokadId.fromJSON(object.lokadId)
                 : undefined,
         };
     },
 
-    toJSON(message: SubscribeMsg): unknown {
+    toJSON(message: WsSub): unknown {
         const obj: any = {};
-        message.error !== undefined &&
-            (obj.error = message.error
-                ? Error.toJSON(message.error)
-                : undefined);
-        message.AddedToMempool !== undefined &&
-            (obj.AddedToMempool = message.AddedToMempool
-                ? MsgAddedToMempool.toJSON(message.AddedToMempool)
-                : undefined);
-        message.RemovedFromMempool !== undefined &&
-            (obj.RemovedFromMempool = message.RemovedFromMempool
-                ? MsgRemovedFromMempool.toJSON(message.RemovedFromMempool)
-                : undefined);
-        message.Confirmed !== undefined &&
-            (obj.Confirmed = message.Confirmed
-                ? MsgConfirmed.toJSON(message.Confirmed)
-                : undefined);
-        message.Reorg !== undefined &&
-            (obj.Reorg = message.Reorg
-                ? MsgReorg.toJSON(message.Reorg)
-                : undefined);
-        message.BlockConnected !== undefined &&
-            (obj.BlockConnected = message.BlockConnected
-                ? MsgBlockConnected.toJSON(message.BlockConnected)
-                : undefined);
-        message.BlockDisconnected !== undefined &&
-            (obj.BlockDisconnected = message.BlockDisconnected
-                ? MsgBlockDisconnected.toJSON(message.BlockDisconnected)
-                : undefined);
+        if (message.isUnsub === true) {
+            obj.isUnsub = message.isUnsub;
+        }
+        if (message.blocks !== undefined) {
+            obj.blocks = WsSubBlocks.toJSON(message.blocks);
+        }
+        if (message.script !== undefined) {
+            obj.script = WsSubScript.toJSON(message.script);
+        }
+        if (message.tokenId !== undefined) {
+            obj.tokenId = WsSubTokenId.toJSON(message.tokenId);
+        }
+        if (message.lokadId !== undefined) {
+            obj.lokadId = WsSubLokadId.toJSON(message.lokadId);
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<SubscribeMsg>, I>>(
-        object: I,
-    ): SubscribeMsg {
-        const message = createBaseSubscribeMsg();
-        message.error =
-            object.error !== undefined && object.error !== null
-                ? Error.fromPartial(object.error)
-                : undefined;
-        message.AddedToMempool =
-            object.AddedToMempool !== undefined &&
-            object.AddedToMempool !== null
-                ? MsgAddedToMempool.fromPartial(object.AddedToMempool)
-                : undefined;
-        message.RemovedFromMempool =
-            object.RemovedFromMempool !== undefined &&
-            object.RemovedFromMempool !== null
-                ? MsgRemovedFromMempool.fromPartial(object.RemovedFromMempool)
-                : undefined;
-        message.Confirmed =
-            object.Confirmed !== undefined && object.Confirmed !== null
-                ? MsgConfirmed.fromPartial(object.Confirmed)
+    create<I extends Exact<DeepPartial<WsSub>, I>>(base?: I): WsSub {
+        return WsSub.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<WsSub>, I>>(object: I): WsSub {
+        const message = createBaseWsSub();
+        message.isUnsub = object.isUnsub ?? false;
+        message.blocks =
+            object.blocks !== undefined && object.blocks !== null
+                ? WsSubBlocks.fromPartial(object.blocks)
                 : undefined;
-        message.Reorg =
-            object.Reorg !== undefined && object.Reorg !== null
-                ? MsgReorg.fromPartial(object.Reorg)
+        message.script =
+            object.script !== undefined && object.script !== null
+                ? WsSubScript.fromPartial(object.script)
                 : undefined;
-        message.BlockConnected =
-            object.BlockConnected !== undefined &&
-            object.BlockConnected !== null
-                ? MsgBlockConnected.fromPartial(object.BlockConnected)
+        message.tokenId =
+            object.tokenId !== undefined && object.tokenId !== null
+                ? WsSubTokenId.fromPartial(object.tokenId)
                 : undefined;
-        message.BlockDisconnected =
-            object.BlockDisconnected !== undefined &&
-            object.BlockDisconnected !== null
-                ? MsgBlockDisconnected.fromPartial(object.BlockDisconnected)
+        message.lokadId =
+            object.lokadId !== undefined && object.lokadId !== null
+                ? WsSubLokadId.fromPartial(object.lokadId)
                 : undefined;
         return message;
     },
 };
 
-function createBaseMsgAddedToMempool(): MsgAddedToMempool {
-    return { txid: new Uint8Array() };
+function createBaseWsSubBlocks(): WsSubBlocks {
+    return {};
 }
 
-export const MsgAddedToMempool = {
+export const WsSubBlocks = {
     encode(
-        message: MsgAddedToMempool,
+        _: WsSubBlocks,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.txid.length !== 0) {
-            writer.uint32(10).bytes(message.txid);
+        return writer;
+    },
+
+    decode(input: _m0.Reader | Uint8Array, length?: number): WsSubBlocks {
+        const reader =
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
+        let end = length === undefined ? reader.len : reader.pos + length;
+        const message = createBaseWsSubBlocks();
+        while (reader.pos < end) {
+            const tag = reader.uint32();
+            switch (tag >>> 3) {
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
+        }
+        return message;
+    },
+
+    fromJSON(_: any): WsSubBlocks {
+        return {};
+    },
+
+    toJSON(_: WsSubBlocks): unknown {
+        const obj: any = {};
+        return obj;
+    },
+
+    create<I extends Exact<DeepPartial<WsSubBlocks>, I>>(
+        base?: I,
+    ): WsSubBlocks {
+        return WsSubBlocks.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<WsSubBlocks>, I>>(
+        _: I,
+    ): WsSubBlocks {
+        const message = createBaseWsSubBlocks();
+        return message;
+    },
+};
+
+function createBaseWsSubScript(): WsSubScript {
+    return { scriptType: '', payload: new Uint8Array(0) };
+}
+
+export const WsSubScript = {
+    encode(
+        message: WsSubScript,
+        writer: _m0.Writer = _m0.Writer.create(),
+    ): _m0.Writer {
+        if (message.scriptType !== '') {
+            writer.uint32(10).string(message.scriptType);
+        }
+        if (message.payload.length !== 0) {
+            writer.uint32(18).bytes(message.payload);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): MsgAddedToMempool {
+    decode(input: _m0.Reader | Uint8Array, length?: number): WsSubScript {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseMsgAddedToMempool();
+        const message = createBaseWsSubScript();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.txid = reader.bytes();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.scriptType = reader.string();
+                    continue;
+                case 2:
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.payload = reader.bytes();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): MsgAddedToMempool {
+    fromJSON(object: any): WsSubScript {
         return {
-            txid: isSet(object.txid)
-                ? bytesFromBase64(object.txid)
-                : new Uint8Array(),
+            scriptType: isSet(object.scriptType)
+                ? globalThis.String(object.scriptType)
+                : '',
+            payload: isSet(object.payload)
+                ? bytesFromBase64(object.payload)
+                : new Uint8Array(0),
         };
     },
 
-    toJSON(message: MsgAddedToMempool): unknown {
+    toJSON(message: WsSubScript): unknown {
         const obj: any = {};
-        message.txid !== undefined &&
-            (obj.txid = base64FromBytes(
-                message.txid !== undefined ? message.txid : new Uint8Array(),
-            ));
+        if (message.scriptType !== '') {
+            obj.scriptType = message.scriptType;
+        }
+        if (message.payload.length !== 0) {
+            obj.payload = base64FromBytes(message.payload);
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<MsgAddedToMempool>, I>>(
+    create<I extends Exact<DeepPartial<WsSubScript>, I>>(
+        base?: I,
+    ): WsSubScript {
+        return WsSubScript.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<WsSubScript>, I>>(
         object: I,
-    ): MsgAddedToMempool {
-        const message = createBaseMsgAddedToMempool();
-        message.txid = object.txid ?? new Uint8Array();
+    ): WsSubScript {
+        const message = createBaseWsSubScript();
+        message.scriptType = object.scriptType ?? '';
+        message.payload = object.payload ?? new Uint8Array(0);
         return message;
     },
 };
 
-function createBaseMsgRemovedFromMempool(): MsgRemovedFromMempool {
-    return { txid: new Uint8Array() };
+function createBaseWsSubTokenId(): WsSubTokenId {
+    return { tokenId: '' };
 }
 
-export const MsgRemovedFromMempool = {
+export const WsSubTokenId = {
     encode(
-        message: MsgRemovedFromMempool,
+        message: WsSubTokenId,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.txid.length !== 0) {
-            writer.uint32(10).bytes(message.txid);
+        if (message.tokenId !== '') {
+            writer.uint32(10).string(message.tokenId);
         }
         return writer;
     },
 
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): MsgRemovedFromMempool {
+    decode(input: _m0.Reader | Uint8Array, length?: number): WsSubTokenId {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseMsgRemovedFromMempool();
+        const message = createBaseWsSubTokenId();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.txid = reader.bytes();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.tokenId = reader.string();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): MsgRemovedFromMempool {
+    fromJSON(object: any): WsSubTokenId {
         return {
-            txid: isSet(object.txid)
-                ? bytesFromBase64(object.txid)
-                : new Uint8Array(),
+            tokenId: isSet(object.tokenId)
+                ? globalThis.String(object.tokenId)
+                : '',
         };
     },
 
-    toJSON(message: MsgRemovedFromMempool): unknown {
+    toJSON(message: WsSubTokenId): unknown {
         const obj: any = {};
-        message.txid !== undefined &&
-            (obj.txid = base64FromBytes(
-                message.txid !== undefined ? message.txid : new Uint8Array(),
-            ));
+        if (message.tokenId !== '') {
+            obj.tokenId = message.tokenId;
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<MsgRemovedFromMempool>, I>>(
+    create<I extends Exact<DeepPartial<WsSubTokenId>, I>>(
+        base?: I,
+    ): WsSubTokenId {
+        return WsSubTokenId.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<WsSubTokenId>, I>>(
         object: I,
-    ): MsgRemovedFromMempool {
-        const message = createBaseMsgRemovedFromMempool();
-        message.txid = object.txid ?? new Uint8Array();
+    ): WsSubTokenId {
+        const message = createBaseWsSubTokenId();
+        message.tokenId = object.tokenId ?? '';
         return message;
     },
 };
 
-function createBaseMsgConfirmed(): MsgConfirmed {
-    return { txid: new Uint8Array() };
+function createBaseWsSubLokadId(): WsSubLokadId {
+    return { lokadId: new Uint8Array(0) };
 }
 
-export const MsgConfirmed = {
+export const WsSubLokadId = {
     encode(
-        message: MsgConfirmed,
+        message: WsSubLokadId,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.txid.length !== 0) {
-            writer.uint32(10).bytes(message.txid);
+        if (message.lokadId.length !== 0) {
+            writer.uint32(10).bytes(message.lokadId);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): MsgConfirmed {
+    decode(input: _m0.Reader | Uint8Array, length?: number): WsSubLokadId {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseMsgConfirmed();
+        const message = createBaseWsSubLokadId();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.txid = reader.bytes();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.lokadId = reader.bytes();
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): MsgConfirmed {
+    fromJSON(object: any): WsSubLokadId {
         return {
-            txid: isSet(object.txid)
-                ? bytesFromBase64(object.txid)
-                : new Uint8Array(),
+            lokadId: isSet(object.lokadId)
+                ? bytesFromBase64(object.lokadId)
+                : new Uint8Array(0),
         };
     },
 
-    toJSON(message: MsgConfirmed): unknown {
+    toJSON(message: WsSubLokadId): unknown {
         const obj: any = {};
-        message.txid !== undefined &&
-            (obj.txid = base64FromBytes(
-                message.txid !== undefined ? message.txid : new Uint8Array(),
-            ));
+        if (message.lokadId.length !== 0) {
+            obj.lokadId = base64FromBytes(message.lokadId);
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<MsgConfirmed>, I>>(
+    create<I extends Exact<DeepPartial<WsSubLokadId>, I>>(
+        base?: I,
+    ): WsSubLokadId {
+        return WsSubLokadId.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<WsSubLokadId>, I>>(
         object: I,
-    ): MsgConfirmed {
-        const message = createBaseMsgConfirmed();
-        message.txid = object.txid ?? new Uint8Array();
+    ): WsSubLokadId {
+        const message = createBaseWsSubLokadId();
+        message.lokadId = object.lokadId ?? new Uint8Array(0);
         return message;
     },
 };
 
-function createBaseMsgReorg(): MsgReorg {
-    return { txid: new Uint8Array() };
+function createBaseWsMsg(): WsMsg {
+    return { error: undefined, block: undefined, tx: undefined };
 }
 
-export const MsgReorg = {
+export const WsMsg = {
     encode(
-        message: MsgReorg,
+        message: WsMsg,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.txid.length !== 0) {
-            writer.uint32(10).bytes(message.txid);
+        if (message.error !== undefined) {
+            Error.encode(message.error, writer.uint32(10).fork()).ldelim();
+        }
+        if (message.block !== undefined) {
+            MsgBlock.encode(message.block, writer.uint32(18).fork()).ldelim();
+        }
+        if (message.tx !== undefined) {
+            MsgTx.encode(message.tx, writer.uint32(26).fork()).ldelim();
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): MsgReorg {
+    decode(input: _m0.Reader | Uint8Array, length?: number): WsMsg {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseMsgReorg();
+        const message = createBaseWsMsg();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.txid = reader.bytes();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 10) {
+                        break;
+                    }
+
+                    message.error = Error.decode(reader, reader.uint32());
+                    continue;
+                case 2:
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.block = MsgBlock.decode(reader, reader.uint32());
+                    continue;
+                case 3:
+                    if (tag !== 26) {
+                        break;
+                    }
+
+                    message.tx = MsgTx.decode(reader, reader.uint32());
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): MsgReorg {
+    fromJSON(object: any): WsMsg {
         return {
-            txid: isSet(object.txid)
-                ? bytesFromBase64(object.txid)
-                : new Uint8Array(),
+            error: isSet(object.error)
+                ? Error.fromJSON(object.error)
+                : undefined,
+            block: isSet(object.block)
+                ? MsgBlock.fromJSON(object.block)
+                : undefined,
+            tx: isSet(object.tx) ? MsgTx.fromJSON(object.tx) : undefined,
         };
     },
 
-    toJSON(message: MsgReorg): unknown {
+    toJSON(message: WsMsg): unknown {
         const obj: any = {};
-        message.txid !== undefined &&
-            (obj.txid = base64FromBytes(
-                message.txid !== undefined ? message.txid : new Uint8Array(),
-            ));
+        if (message.error !== undefined) {
+            obj.error = Error.toJSON(message.error);
+        }
+        if (message.block !== undefined) {
+            obj.block = MsgBlock.toJSON(message.block);
+        }
+        if (message.tx !== undefined) {
+            obj.tx = MsgTx.toJSON(message.tx);
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<MsgReorg>, I>>(
-        object: I,
-    ): MsgReorg {
-        const message = createBaseMsgReorg();
-        message.txid = object.txid ?? new Uint8Array();
+    create<I extends Exact<DeepPartial<WsMsg>, I>>(base?: I): WsMsg {
+        return WsMsg.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<WsMsg>, I>>(object: I): WsMsg {
+        const message = createBaseWsMsg();
+        message.error =
+            object.error !== undefined && object.error !== null
+                ? Error.fromPartial(object.error)
+                : undefined;
+        message.block =
+            object.block !== undefined && object.block !== null
+                ? MsgBlock.fromPartial(object.block)
+                : undefined;
+        message.tx =
+            object.tx !== undefined && object.tx !== null
+                ? MsgTx.fromPartial(object.tx)
+                : undefined;
         return message;
     },
 };
 
-function createBaseMsgBlockConnected(): MsgBlockConnected {
-    return { blockHash: new Uint8Array() };
+function createBaseMsgBlock(): MsgBlock {
+    return { msgType: 0, blockHash: new Uint8Array(0), blockHeight: 0 };
 }
 
-export const MsgBlockConnected = {
+export const MsgBlock = {
     encode(
-        message: MsgBlockConnected,
+        message: MsgBlock,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
+        if (message.msgType !== 0) {
+            writer.uint32(8).int32(message.msgType);
+        }
         if (message.blockHash.length !== 0) {
-            writer.uint32(10).bytes(message.blockHash);
+            writer.uint32(18).bytes(message.blockHash);
+        }
+        if (message.blockHeight !== 0) {
+            writer.uint32(24).int32(message.blockHeight);
         }
         return writer;
     },
 
-    decode(input: _m0.Reader | Uint8Array, length?: number): MsgBlockConnected {
+    decode(input: _m0.Reader | Uint8Array, length?: number): MsgBlock {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseMsgBlockConnected();
+        const message = createBaseMsgBlock();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
+                    if (tag !== 8) {
+                        break;
+                    }
+
+                    message.msgType = reader.int32() as any;
+                    continue;
+                case 2:
+                    if (tag !== 18) {
+                        break;
+                    }
+
                     message.blockHash = reader.bytes();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    continue;
+                case 3:
+                    if (tag !== 24) {
+                        break;
+                    }
+
+                    message.blockHeight = reader.int32();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): MsgBlockConnected {
+    fromJSON(object: any): MsgBlock {
         return {
+            msgType: isSet(object.msgType)
+                ? blockMsgTypeFromJSON(object.msgType)
+                : 0,
             blockHash: isSet(object.blockHash)
                 ? bytesFromBase64(object.blockHash)
-                : new Uint8Array(),
+                : new Uint8Array(0),
+            blockHeight: isSet(object.blockHeight)
+                ? globalThis.Number(object.blockHeight)
+                : 0,
         };
     },
 
-    toJSON(message: MsgBlockConnected): unknown {
+    toJSON(message: MsgBlock): unknown {
         const obj: any = {};
-        message.blockHash !== undefined &&
-            (obj.blockHash = base64FromBytes(
-                message.blockHash !== undefined
-                    ? message.blockHash
-                    : new Uint8Array(),
-            ));
+        if (message.msgType !== 0) {
+            obj.msgType = blockMsgTypeToJSON(message.msgType);
+        }
+        if (message.blockHash.length !== 0) {
+            obj.blockHash = base64FromBytes(message.blockHash);
+        }
+        if (message.blockHeight !== 0) {
+            obj.blockHeight = Math.round(message.blockHeight);
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<MsgBlockConnected>, I>>(
+    create<I extends Exact<DeepPartial<MsgBlock>, I>>(base?: I): MsgBlock {
+        return MsgBlock.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<MsgBlock>, I>>(
         object: I,
-    ): MsgBlockConnected {
-        const message = createBaseMsgBlockConnected();
-        message.blockHash = object.blockHash ?? new Uint8Array();
+    ): MsgBlock {
+        const message = createBaseMsgBlock();
+        message.msgType = object.msgType ?? 0;
+        message.blockHash = object.blockHash ?? new Uint8Array(0);
+        message.blockHeight = object.blockHeight ?? 0;
         return message;
     },
 };
 
-function createBaseMsgBlockDisconnected(): MsgBlockDisconnected {
-    return { blockHash: new Uint8Array() };
+function createBaseMsgTx(): MsgTx {
+    return { msgType: 0, txid: new Uint8Array(0) };
 }
 
-export const MsgBlockDisconnected = {
+export const MsgTx = {
     encode(
-        message: MsgBlockDisconnected,
+        message: MsgTx,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.blockHash.length !== 0) {
-            writer.uint32(10).bytes(message.blockHash);
+        if (message.msgType !== 0) {
+            writer.uint32(8).int32(message.msgType);
+        }
+        if (message.txid.length !== 0) {
+            writer.uint32(18).bytes(message.txid);
         }
         return writer;
     },
 
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): MsgBlockDisconnected {
+    decode(input: _m0.Reader | Uint8Array, length?: number): MsgTx {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseMsgBlockDisconnected();
+        const message = createBaseMsgTx();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
                 case 1:
-                    message.blockHash = reader.bytes();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    if (tag !== 8) {
+                        break;
+                    }
+
+                    message.msgType = reader.int32() as any;
+                    continue;
+                case 2:
+                    if (tag !== 18) {
+                        break;
+                    }
+
+                    message.txid = reader.bytes();
+                    continue;
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
             }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
-    fromJSON(object: any): MsgBlockDisconnected {
+    fromJSON(object: any): MsgTx {
         return {
-            blockHash: isSet(object.blockHash)
-                ? bytesFromBase64(object.blockHash)
-                : new Uint8Array(),
+            msgType: isSet(object.msgType)
+                ? txMsgTypeFromJSON(object.msgType)
+                : 0,
+            txid: isSet(object.txid)
+                ? bytesFromBase64(object.txid)
+                : new Uint8Array(0),
         };
     },
 
-    toJSON(message: MsgBlockDisconnected): unknown {
+    toJSON(message: MsgTx): unknown {
         const obj: any = {};
-        message.blockHash !== undefined &&
-            (obj.blockHash = base64FromBytes(
-                message.blockHash !== undefined
-                    ? message.blockHash
-                    : new Uint8Array(),
-            ));
+        if (message.msgType !== 0) {
+            obj.msgType = txMsgTypeToJSON(message.msgType);
+        }
+        if (message.txid.length !== 0) {
+            obj.txid = base64FromBytes(message.txid);
+        }
         return obj;
     },
 
-    fromPartial<I extends Exact<DeepPartial<MsgBlockDisconnected>, I>>(
-        object: I,
-    ): MsgBlockDisconnected {
-        const message = createBaseMsgBlockDisconnected();
-        message.blockHash = object.blockHash ?? new Uint8Array();
+    create<I extends Exact<DeepPartial<MsgTx>, I>>(base?: I): MsgTx {
+        return MsgTx.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<MsgTx>, I>>(object: I): MsgTx {
+        const message = createBaseMsgTx();
+        message.msgType = object.msgType ?? 0;
+        message.txid = object.txid ?? new Uint8Array(0);
+        return message;
+    },
+};
+
+function createBaseEmpty(): Empty {
+    return {};
+}
+
+export const Empty = {
+    encode(_: Empty, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
+        return writer;
+    },
+
+    decode(input: _m0.Reader | Uint8Array, length?: number): Empty {
+        const reader =
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
+        let end = length === undefined ? reader.len : reader.pos + length;
+        const message = createBaseEmpty();
+        while (reader.pos < end) {
+            const tag = reader.uint32();
+            switch (tag >>> 3) {
+            }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
+        }
+        return message;
+    },
+
+    fromJSON(_: any): Empty {
+        return {};
+    },
+
+    toJSON(_: Empty): unknown {
+        const obj: any = {};
+        return obj;
+    },
+
+    create<I extends Exact<DeepPartial<Empty>, I>>(base?: I): Empty {
+        return Empty.fromPartial(base ?? ({} as any));
+    },
+    fromPartial<I extends Exact<DeepPartial<Empty>, I>>(_: I): Empty {
+        const message = createBaseEmpty();
         return message;
     },
 };
 
 function createBaseError(): Error {
-    return { errorCode: '', msg: '', isUserError: false };
+    return { msg: '' };
 }
 
 export const Error = {
@@ -3897,103 +6034,81 @@
         message: Error,
         writer: _m0.Writer = _m0.Writer.create(),
     ): _m0.Writer {
-        if (message.errorCode !== '') {
-            writer.uint32(10).string(message.errorCode);
-        }
         if (message.msg !== '') {
             writer.uint32(18).string(message.msg);
         }
-        if (message.isUserError === true) {
-            writer.uint32(24).bool(message.isUserError);
-        }
         return writer;
     },
 
     decode(input: _m0.Reader | Uint8Array, length?: number): Error {
         const reader =
-            input instanceof _m0.Reader ? input : new _m0.Reader(input);
+            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
         let end = length === undefined ? reader.len : reader.pos + length;
         const message = createBaseError();
         while (reader.pos < end) {
             const tag = reader.uint32();
             switch (tag >>> 3) {
-                case 1:
-                    message.errorCode = reader.string();
-                    break;
                 case 2:
+                    if (tag !== 18) {
+                        break;
+                    }
+
                     message.msg = reader.string();
-                    break;
-                case 3:
-                    message.isUserError = reader.bool();
-                    break;
-                default:
-                    reader.skipType(tag & 7);
-                    break;
+                    continue;
             }
+            if ((tag & 7) === 4 || tag === 0) {
+                break;
+            }
+            reader.skipType(tag & 7);
         }
         return message;
     },
 
     fromJSON(object: any): Error {
-        return {
-            errorCode: isSet(object.errorCode) ? String(object.errorCode) : '',
-            msg: isSet(object.msg) ? String(object.msg) : '',
-            isUserError: isSet(object.isUserError)
-                ? Boolean(object.isUserError)
-                : false,
-        };
+        return { msg: isSet(object.msg) ? globalThis.String(object.msg) : '' };
     },
 
     toJSON(message: Error): unknown {
         const obj: any = {};
-        message.errorCode !== undefined && (obj.errorCode = message.errorCode);
-        message.msg !== undefined && (obj.msg = message.msg);
-        message.isUserError !== undefined &&
-            (obj.isUserError = message.isUserError);
+        if (message.msg !== '') {
+            obj.msg = message.msg;
+        }
         return obj;
     },
 
+    create<I extends Exact<DeepPartial<Error>, I>>(base?: I): Error {
+        return Error.fromPartial(base ?? ({} as any));
+    },
     fromPartial<I extends Exact<DeepPartial<Error>, I>>(object: I): Error {
         const message = createBaseError();
-        message.errorCode = object.errorCode ?? '';
         message.msg = object.msg ?? '';
-        message.isUserError = object.isUserError ?? false;
         return message;
     },
 };
 
-declare var self: any | undefined;
-declare var window: any | undefined;
-declare var global: any | undefined;
-var globalThis: any = (() => {
-    if (typeof globalThis !== 'undefined') return globalThis;
-    if (typeof self !== 'undefined') return self;
-    if (typeof window !== 'undefined') return window;
-    if (typeof global !== 'undefined') return global;
-    throw 'Unable to locate global object';
-})();
-
-const atob: (b64: string) => string =
-    globalThis.atob ||
-    (b64 => globalThis.Buffer.from(b64, 'base64').toString('binary'));
 function bytesFromBase64(b64: string): Uint8Array {
-    const bin = atob(b64);
-    const arr = new Uint8Array(bin.length);
-    for (let i = 0; i < bin.length; ++i) {
-        arr[i] = bin.charCodeAt(i);
+    if (globalThis.Buffer) {
+        return Uint8Array.from(globalThis.Buffer.from(b64, 'base64'));
+    } else {
+        const bin = globalThis.atob(b64);
+        const arr = new Uint8Array(bin.length);
+        for (let i = 0; i < bin.length; ++i) {
+            arr[i] = bin.charCodeAt(i);
+        }
+        return arr;
     }
-    return arr;
 }
 
-const btoa: (bin: string) => string =
-    globalThis.btoa ||
-    (bin => globalThis.Buffer.from(bin, 'binary').toString('base64'));
 function base64FromBytes(arr: Uint8Array): string {
-    const bin: string[] = [];
-    arr.forEach(byte => {
-        bin.push(String.fromCharCode(byte));
-    });
-    return btoa(bin.join(''));
+    if (globalThis.Buffer) {
+        return globalThis.Buffer.from(arr).toString('base64');
+    } else {
+        const bin: string[] = [];
+        arr.forEach(byte => {
+            bin.push(globalThis.String.fromCharCode(byte));
+        });
+        return globalThis.btoa(bin.join(''));
+    }
 }
 
 type Builtin =
@@ -4007,8 +6122,8 @@
 
 export type DeepPartial<T> = T extends Builtin
     ? T
-    : T extends Array<infer U>
-    ? Array<DeepPartial<U>>
+    : T extends globalThis.Array<infer U>
+    ? globalThis.Array<DeepPartial<U>>
     : T extends ReadonlyArray<infer U>
     ? ReadonlyArray<DeepPartial<U>>
     : T extends {}
@@ -4018,10 +6133,9 @@
 type KeysOfUnion<T> = T extends T ? keyof T : never;
 export type Exact<P, I extends P> = P extends Builtin
     ? P
-    : P & { [K in keyof P]: Exact<P[K], I[K]> } & Record<
-              Exclude<keyof I, KeysOfUnion<P>>,
-              never
-          >;
+    : P & { [K in keyof P]: Exact<P[K], I[K]> } & {
+          [K in Exclude<keyof I, KeysOfUnion<P>>]: never;
+      };
 
 function longToString(long: Long) {
     return long.toString();
@@ -4032,6 +6146,10 @@
     _m0.configure();
 }
 
+function isObject(value: any): boolean {
+    return typeof value === 'object' && value !== null;
+}
+
 function isSet(value: any): boolean {
     return value !== null && value !== undefined;
 }
diff --git a/modules/chronik-client/proto/chronikNode.ts b/modules/chronik-client/proto/chronikNode.ts
deleted file mode 100644
--- a/modules/chronik-client/proto/chronikNode.ts
+++ /dev/null
@@ -1,6155 +0,0 @@
-/* eslint-disable */
-import Long from 'long';
-import _m0 from 'protobufjs/minimal';
-
-export const protobufPackage = 'chronik';
-
-/** Status of a token tx */
-export enum TokenStatus {
-    /**
-     * TOKEN_STATUS_NON_TOKEN - Tx involves no tokens whatsover, i.e. neither any burns nor any failed
-     * parsing/coloring or any tokens being created / moved.
-     */
-    TOKEN_STATUS_NON_TOKEN = 0,
-    /** TOKEN_STATUS_NORMAL - Tx involves tokens but no unintentional burns or failed parsings/colorings */
-    TOKEN_STATUS_NORMAL = 1,
-    /** TOKEN_STATUS_NOT_NORMAL - Tx involves tokens but contains unintentional burns or failed parsings/colorings */
-    TOKEN_STATUS_NOT_NORMAL = 2,
-    UNRECOGNIZED = -1,
-}
-
-export function tokenStatusFromJSON(object: any): TokenStatus {
-    switch (object) {
-        case 0:
-        case 'TOKEN_STATUS_NON_TOKEN':
-            return TokenStatus.TOKEN_STATUS_NON_TOKEN;
-        case 1:
-        case 'TOKEN_STATUS_NORMAL':
-            return TokenStatus.TOKEN_STATUS_NORMAL;
-        case 2:
-        case 'TOKEN_STATUS_NOT_NORMAL':
-            return TokenStatus.TOKEN_STATUS_NOT_NORMAL;
-        case -1:
-        case 'UNRECOGNIZED':
-        default:
-            return TokenStatus.UNRECOGNIZED;
-    }
-}
-
-export function tokenStatusToJSON(object: TokenStatus): string {
-    switch (object) {
-        case TokenStatus.TOKEN_STATUS_NON_TOKEN:
-            return 'TOKEN_STATUS_NON_TOKEN';
-        case TokenStatus.TOKEN_STATUS_NORMAL:
-            return 'TOKEN_STATUS_NORMAL';
-        case TokenStatus.TOKEN_STATUS_NOT_NORMAL:
-            return 'TOKEN_STATUS_NOT_NORMAL';
-        case TokenStatus.UNRECOGNIZED:
-        default:
-            return 'UNRECOGNIZED';
-    }
-}
-
-/** ALP token type */
-export enum AlpTokenType {
-    /** ALP_TOKEN_TYPE_STANDARD - Standard ALP token type */
-    ALP_TOKEN_TYPE_STANDARD = 0,
-    UNRECOGNIZED = -1,
-}
-
-export function alpTokenTypeFromJSON(object: any): AlpTokenType {
-    switch (object) {
-        case 0:
-        case 'ALP_TOKEN_TYPE_STANDARD':
-            return AlpTokenType.ALP_TOKEN_TYPE_STANDARD;
-        case -1:
-        case 'UNRECOGNIZED':
-        default:
-            return AlpTokenType.UNRECOGNIZED;
-    }
-}
-
-export function alpTokenTypeToJSON(object: AlpTokenType): string {
-    switch (object) {
-        case AlpTokenType.ALP_TOKEN_TYPE_STANDARD:
-            return 'ALP_TOKEN_TYPE_STANDARD';
-        case AlpTokenType.UNRECOGNIZED:
-        default:
-            return 'UNRECOGNIZED';
-    }
-}
-
-/** SLP token type */
-export enum SlpTokenType {
-    /** SLP_TOKEN_TYPE_NONE - Unknown "0" token type */
-    SLP_TOKEN_TYPE_NONE = 0,
-    /** SLP_TOKEN_TYPE_FUNGIBLE - SLP V1 token type */
-    SLP_TOKEN_TYPE_FUNGIBLE = 1,
-    /** SLP_TOKEN_TYPE_MINT_VAULT - SLP V2 mint vault token type */
-    SLP_TOKEN_TYPE_MINT_VAULT = 2,
-    /** SLP_TOKEN_TYPE_NFT1_GROUP - NFT1 group token type */
-    SLP_TOKEN_TYPE_NFT1_GROUP = 129,
-    /** SLP_TOKEN_TYPE_NFT1_CHILD - NFT1 child token type */
-    SLP_TOKEN_TYPE_NFT1_CHILD = 65,
-    UNRECOGNIZED = -1,
-}
-
-export function slpTokenTypeFromJSON(object: any): SlpTokenType {
-    switch (object) {
-        case 0:
-        case 'SLP_TOKEN_TYPE_NONE':
-            return SlpTokenType.SLP_TOKEN_TYPE_NONE;
-        case 1:
-        case 'SLP_TOKEN_TYPE_FUNGIBLE':
-            return SlpTokenType.SLP_TOKEN_TYPE_FUNGIBLE;
-        case 2:
-        case 'SLP_TOKEN_TYPE_MINT_VAULT':
-            return SlpTokenType.SLP_TOKEN_TYPE_MINT_VAULT;
-        case 129:
-        case 'SLP_TOKEN_TYPE_NFT1_GROUP':
-            return SlpTokenType.SLP_TOKEN_TYPE_NFT1_GROUP;
-        case 65:
-        case 'SLP_TOKEN_TYPE_NFT1_CHILD':
-            return SlpTokenType.SLP_TOKEN_TYPE_NFT1_CHILD;
-        case -1:
-        case 'UNRECOGNIZED':
-        default:
-            return SlpTokenType.UNRECOGNIZED;
-    }
-}
-
-export function slpTokenTypeToJSON(object: SlpTokenType): string {
-    switch (object) {
-        case SlpTokenType.SLP_TOKEN_TYPE_NONE:
-            return 'SLP_TOKEN_TYPE_NONE';
-        case SlpTokenType.SLP_TOKEN_TYPE_FUNGIBLE:
-            return 'SLP_TOKEN_TYPE_FUNGIBLE';
-        case SlpTokenType.SLP_TOKEN_TYPE_MINT_VAULT:
-            return 'SLP_TOKEN_TYPE_MINT_VAULT';
-        case SlpTokenType.SLP_TOKEN_TYPE_NFT1_GROUP:
-            return 'SLP_TOKEN_TYPE_NFT1_GROUP';
-        case SlpTokenType.SLP_TOKEN_TYPE_NFT1_CHILD:
-            return 'SLP_TOKEN_TYPE_NFT1_CHILD';
-        case SlpTokenType.UNRECOGNIZED:
-        default:
-            return 'UNRECOGNIZED';
-    }
-}
-
-/** SLP/ALP tx type */
-export enum TokenTxType {
-    /** NONE - No tx type, e.g. when input tokens are burned */
-    NONE = 0,
-    /** UNKNOWN - Unknown tx type, i.e. for unknown token types */
-    UNKNOWN = 1,
-    /** GENESIS - GENESIS tx */
-    GENESIS = 2,
-    /** SEND - SEND tx */
-    SEND = 3,
-    /** MINT - MINT tx */
-    MINT = 4,
-    /** BURN - BURN tx */
-    BURN = 5,
-    UNRECOGNIZED = -1,
-}
-
-export function tokenTxTypeFromJSON(object: any): TokenTxType {
-    switch (object) {
-        case 0:
-        case 'NONE':
-            return TokenTxType.NONE;
-        case 1:
-        case 'UNKNOWN':
-            return TokenTxType.UNKNOWN;
-        case 2:
-        case 'GENESIS':
-            return TokenTxType.GENESIS;
-        case 3:
-        case 'SEND':
-            return TokenTxType.SEND;
-        case 4:
-        case 'MINT':
-            return TokenTxType.MINT;
-        case 5:
-        case 'BURN':
-            return TokenTxType.BURN;
-        case -1:
-        case 'UNRECOGNIZED':
-        default:
-            return TokenTxType.UNRECOGNIZED;
-    }
-}
-
-export function tokenTxTypeToJSON(object: TokenTxType): string {
-    switch (object) {
-        case TokenTxType.NONE:
-            return 'NONE';
-        case TokenTxType.UNKNOWN:
-            return 'UNKNOWN';
-        case TokenTxType.GENESIS:
-            return 'GENESIS';
-        case TokenTxType.SEND:
-            return 'SEND';
-        case TokenTxType.MINT:
-            return 'MINT';
-        case TokenTxType.BURN:
-            return 'BURN';
-        case TokenTxType.UNRECOGNIZED:
-        default:
-            return 'UNRECOGNIZED';
-    }
-}
-
-/** Type of message for the block */
-export enum BlockMsgType {
-    /** BLK_CONNECTED - Block connected to the blockchain */
-    BLK_CONNECTED = 0,
-    /** BLK_DISCONNECTED - Block disconnected from the blockchain */
-    BLK_DISCONNECTED = 1,
-    /** BLK_FINALIZED - Block has been finalized by Avalanche */
-    BLK_FINALIZED = 2,
-    UNRECOGNIZED = -1,
-}
-
-export function blockMsgTypeFromJSON(object: any): BlockMsgType {
-    switch (object) {
-        case 0:
-        case 'BLK_CONNECTED':
-            return BlockMsgType.BLK_CONNECTED;
-        case 1:
-        case 'BLK_DISCONNECTED':
-            return BlockMsgType.BLK_DISCONNECTED;
-        case 2:
-        case 'BLK_FINALIZED':
-            return BlockMsgType.BLK_FINALIZED;
-        case -1:
-        case 'UNRECOGNIZED':
-        default:
-            return BlockMsgType.UNRECOGNIZED;
-    }
-}
-
-export function blockMsgTypeToJSON(object: BlockMsgType): string {
-    switch (object) {
-        case BlockMsgType.BLK_CONNECTED:
-            return 'BLK_CONNECTED';
-        case BlockMsgType.BLK_DISCONNECTED:
-            return 'BLK_DISCONNECTED';
-        case BlockMsgType.BLK_FINALIZED:
-            return 'BLK_FINALIZED';
-        case BlockMsgType.UNRECOGNIZED:
-        default:
-            return 'UNRECOGNIZED';
-    }
-}
-
-/** Type of message for a tx */
-export enum TxMsgType {
-    /** TX_ADDED_TO_MEMPOOL - Tx added to the mempool */
-    TX_ADDED_TO_MEMPOOL = 0,
-    /** TX_REMOVED_FROM_MEMPOOL - Tx removed from the mempool */
-    TX_REMOVED_FROM_MEMPOOL = 1,
-    /** TX_CONFIRMED - Tx confirmed in a block */
-    TX_CONFIRMED = 2,
-    /** TX_FINALIZED - Tx finalized by Avalanche */
-    TX_FINALIZED = 3,
-    UNRECOGNIZED = -1,
-}
-
-export function txMsgTypeFromJSON(object: any): TxMsgType {
-    switch (object) {
-        case 0:
-        case 'TX_ADDED_TO_MEMPOOL':
-            return TxMsgType.TX_ADDED_TO_MEMPOOL;
-        case 1:
-        case 'TX_REMOVED_FROM_MEMPOOL':
-            return TxMsgType.TX_REMOVED_FROM_MEMPOOL;
-        case 2:
-        case 'TX_CONFIRMED':
-            return TxMsgType.TX_CONFIRMED;
-        case 3:
-        case 'TX_FINALIZED':
-            return TxMsgType.TX_FINALIZED;
-        case -1:
-        case 'UNRECOGNIZED':
-        default:
-            return TxMsgType.UNRECOGNIZED;
-    }
-}
-
-export function txMsgTypeToJSON(object: TxMsgType): string {
-    switch (object) {
-        case TxMsgType.TX_ADDED_TO_MEMPOOL:
-            return 'TX_ADDED_TO_MEMPOOL';
-        case TxMsgType.TX_REMOVED_FROM_MEMPOOL:
-            return 'TX_REMOVED_FROM_MEMPOOL';
-        case TxMsgType.TX_CONFIRMED:
-            return 'TX_CONFIRMED';
-        case TxMsgType.TX_FINALIZED:
-            return 'TX_FINALIZED';
-        case TxMsgType.UNRECOGNIZED:
-        default:
-            return 'UNRECOGNIZED';
-    }
-}
-
-/** Block on the blockchain */
-export interface Block {
-    /** Info about the block */
-    blockInfo: BlockInfo | undefined;
-}
-
-/** Range of blocks */
-export interface Blocks {
-    /** Queried blocks */
-    blocks: BlockInfo[];
-}
-
-/** Header on the blockchain */
-export interface BlockHeader {
-    /** Raw data */
-    rawHeader: Uint8Array;
-}
-
-/** Range of headers */
-export interface BlockHeaders {
-    /** Queried headers */
-    headers: BlockHeader[];
-}
-
-/** Info about the state of the blockchain. */
-export interface BlockchainInfo {
-    /** Hash (little-endian) of the current tip */
-    tipHash: Uint8Array;
-    /** Height of the current tip (genesis has height = 0) */
-    tipHeight: number;
-}
-
-/** Info about the chronik software this server is running */
-export interface ChronikInfo {
-    /** chronik server version from chronik-http/Cargo.toml */
-    version: string;
-}
-
-/** Info about a block */
-export interface BlockInfo {
-    /** Hash (little-endian) */
-    hash: Uint8Array;
-    /** Hash of the previous block (little-endian) */
-    prevHash: Uint8Array;
-    /** Height in the chain */
-    height: number;
-    /** nBits field encoding the target */
-    nBits: number;
-    /** Timestamp field of the block */
-    timestamp: string;
-    /** Whether the block has been finalized by Avalanche */
-    isFinal: boolean;
-    /** Block size of this block in bytes (including headers etc.) */
-    blockSize: string;
-    /** Number of txs in this block */
-    numTxs: string;
-    /** Total number of tx inputs in block (including coinbase) */
-    numInputs: string;
-    /** Total number of tx output in block (including coinbase) */
-    numOutputs: string;
-    /** Total number of satoshis spent by tx inputs */
-    sumInputSats: string;
-    /** Block reward for this block */
-    sumCoinbaseOutputSats: string;
-    /** Total number of satoshis in non-coinbase tx outputs */
-    sumNormalOutputSats: string;
-    /** Total number of satoshis burned using OP_RETURN */
-    sumBurnedSats: string;
-}
-
-/** Details about a transaction */
-export interface Tx {
-    /** TxId (little-endian) of the tx */
-    txid: Uint8Array;
-    /** nVersion */
-    version: number;
-    /** Inputs of the tx (aka. `vin`) */
-    inputs: TxInput[];
-    /** Outputs of the tx (aka. `vout`) */
-    outputs: TxOutput[];
-    /** nLockTime */
-    lockTime: number;
-    /** Which block this tx is in, or None, if in the mempool */
-    block: BlockMetadata | undefined;
-    /** Time this tx has first been added to the mempool, or 0 if unknown */
-    timeFirstSeen: string;
-    /** Serialized size of the tx */
-    size: number;
-    /** Whether this tx is a coinbase tx */
-    isCoinbase: boolean;
-    /** Tokens involved in this txs */
-    tokenEntries: TokenEntry[];
-    /** Failed parsing attempts of this tx */
-    tokenFailedParsings: TokenFailedParsing[];
-    /**
-     * Token status, i.e. whether this tx has any tokens or unintentional token burns
-     * or something unexpected, like failed parsings etc.
-     */
-    tokenStatus: TokenStatus;
-}
-
-/** UTXO of a script. */
-export interface ScriptUtxo {
-    /** txid and out_idx of the unspent output. */
-    outpoint: OutPoint | undefined;
-    /** Block height of the UTXO, or -1 if in mempool. */
-    blockHeight: number;
-    /** Whether the UTXO has been created in a coinbase tx. */
-    isCoinbase: boolean;
-    /** Value of the output, in satoshis. */
-    value: string;
-    /** Whether the UTXO has been finalized by Avalanche. */
-    isFinal: boolean;
-    /** Token value attached to this UTXO */
-    token: Token | undefined;
-    /** Data attached to this output by plugins */
-    plugins: { [key: string]: PluginEntry };
-}
-
-export interface ScriptUtxo_PluginsEntry {
-    key: string;
-    value: PluginEntry | undefined;
-}
-
-/** UTXO, but with a script attached. */
-export interface Utxo {
-    /** txid and out_idx of the unspent output. */
-    outpoint: OutPoint | undefined;
-    /** Block height of the UTXO, or -1 if in mempool. */
-    blockHeight: number;
-    /** Whether the UTXO has been created in a coinbase tx. */
-    isCoinbase: boolean;
-    /** Value of the output, in satoshis. */
-    value: string;
-    /** Bytecode of the script of the output */
-    script: Uint8Array;
-    /** Whether the UTXO has been finalized by Avalanche. */
-    isFinal: boolean;
-    /** Token value attached to this UTXO */
-    token: Token | undefined;
-    /** Data attached to this output by plugins */
-    plugins: { [key: string]: PluginEntry };
-}
-
-export interface Utxo_PluginsEntry {
-    key: string;
-    value: PluginEntry | undefined;
-}
-
-/** COutPoint, points to a coin being spent by an input. */
-export interface OutPoint {
-    /** TxId of the tx of the output being spent. */
-    txid: Uint8Array;
-    /** Index of the output spent within the transaction. */
-    outIdx: number;
-}
-
-/** Points to an input spending a coin. */
-export interface SpentBy {
-    /** TxId of the tx with the input. */
-    txid: Uint8Array;
-    /** Index in the inputs of the tx. */
-    inputIdx: number;
-}
-
-/** CTxIn, spends a coin. */
-export interface TxInput {
-    /** Reference to the coin being spent. */
-    prevOut: OutPoint | undefined;
-    /** scriptSig, script unlocking the coin. */
-    inputScript: Uint8Array;
-    /** scriptPubKey, script of the output locking the coin. */
-    outputScript: Uint8Array;
-    /** value of the output being spent, in satoshis. */
-    value: string;
-    /** nSequence of the input. */
-    sequenceNo: number;
-    /** Token value attached to this input */
-    token: Token | undefined;
-    /** Data attached to this output by plugins */
-    plugins: { [key: string]: PluginEntry };
-}
-
-export interface TxInput_PluginsEntry {
-    key: string;
-    value: PluginEntry | undefined;
-}
-
-/** CTxOut, creates a new coin. */
-export interface TxOutput {
-    /** Value of the coin, in satoshis. */
-    value: string;
-    /** scriptPubKey, script locking the output. */
-    outputScript: Uint8Array;
-    /** Which tx and input spent this output, if any. */
-    spentBy: SpentBy | undefined;
-    /** Token value attached to this output */
-    token: Token | undefined;
-    /** Data attached to this output by plugins */
-    plugins: { [key: string]: PluginEntry };
-}
-
-export interface TxOutput_PluginsEntry {
-    key: string;
-    value: PluginEntry | undefined;
-}
-
-/** Data about a block which a Tx is in. */
-export interface BlockMetadata {
-    /** Height of the block the tx is in. */
-    height: number;
-    /** Hash of the block the tx is in. */
-    hash: Uint8Array;
-    /** nTime of the block the tx is in. */
-    timestamp: string;
-    /** Whether the block has been finalized by Avalanche. */
-    isFinal: boolean;
-}
-
-/** SLP/ALP token type */
-export interface TokenType {
-    /** SLP token type. Can have unknown values for unknown token types */
-    slp?: SlpTokenType | undefined;
-    /** ALP token type. Can have unknown values for unknown token types */
-    alp?: AlpTokenType | undefined;
-}
-
-/** Info about a token */
-export interface TokenInfo {
-    /**
-     * Hex token_id (in big-endian, like usually displayed to users) of the token.
-     * This is not `bytes` because SLP and ALP use different endiannnes, so to avoid this we use hex, which conventionally implies big-endian in a bitcoin context.
-     */
-    tokenId: string;
-    /** Token type of the token */
-    tokenType: TokenType | undefined;
-    /** Info found in the token's GENESIS tx */
-    genesisInfo: GenesisInfo | undefined;
-    /** Block of the GENESIS tx, if it's mined already */
-    block: BlockMetadata | undefined;
-    /** Time the GENESIS tx has first been seen by the indexer */
-    timeFirstSeen: string;
-}
-
-/** Token involved in a transaction */
-export interface TokenEntry {
-    /**
-     * Hex token_id (in big-endian, like usually displayed to users) of the token.
-     * This is not `bytes` because SLP and ALP use different endiannes, so to avoid
-     * this we use hex, which conventionally implies big-endian in a bitcoin context.
-     */
-    tokenId: string;
-    /** Token type of the token */
-    tokenType: TokenType | undefined;
-    /** Tx type of the token; NONE if there's no section that introduced it (e.g. in an accidental burn) */
-    txType: TokenTxType;
-    /** For NFT1 Child tokens: group ID */
-    groupTokenId: string;
-    /** Whether the validation rules have been violated for this section */
-    isInvalid: boolean;
-    /** Human-readable error message of why this entry burned tokens */
-    burnSummary: string;
-    /** Human-readable error messages of why colorings failed */
-    failedColorings: TokenFailedColoring[];
-    /**
-     * Number of actually burned tokens (as decimal integer string, e.g. "2000").
-     * This is because burns can exceed the 64-bit range of values and protobuf doesn't have a nice type to encode this.
-     */
-    actualBurnAmount: string;
-    /** Burn amount the user explicitly opted into */
-    intentionalBurn: string;
-    /** Whether any mint batons have been burned of this token */
-    burnsMintBatons: boolean;
-}
-
-/** Genesis info found in GENESIS txs of tokens */
-export interface GenesisInfo {
-    /** token_ticker of the token */
-    tokenTicker: Uint8Array;
-    /** token_name of the token */
-    tokenName: Uint8Array;
-    /** URL of the token */
-    url: Uint8Array;
-    /** token_document_hash of the token (only on SLP) */
-    hash: Uint8Array;
-    /** mint_vault_scripthash (only on SLP V2 Mint Vault) */
-    mintVaultScripthash: Uint8Array;
-    /** Arbitray payload data of the token (only on ALP) */
-    data: Uint8Array;
-    /** auth_pubkey of the token (only on ALP) */
-    authPubkey: Uint8Array;
-    /** decimals of the token, i.e. how many decimal places the token should be displayed with. */
-    decimals: number;
-}
-
-/** Token coloring an input or output */
-export interface Token {
-    /** Hex token_id of the token, see `TokenInfo` for details */
-    tokenId: string;
-    /** Token type of the token */
-    tokenType: TokenType | undefined;
-    /** Index into `token_entries` for `Tx`. -1 for UTXOs */
-    entryIdx: number;
-    /** Base token amount of the input/output */
-    amount: string;
-    /** Whether the token is a mint baton */
-    isMintBaton: boolean;
-}
-
-/**
- * A report of a failed parsing attempt of SLP/ALP.
- * This should always indicate something went wrong when building the tx.
- */
-export interface TokenFailedParsing {
-    /**
-     * For ALP, the index of the pushdata in the OP_RETURN that failed parsing.
-     * -1 if the whole OP_RETURN failed, e.g. for SLP or eMPP
-     */
-    pushdataIdx: number;
-    /** The bytes that failed parsing, useful for debugging */
-    bytes: Uint8Array;
-    /** Human-readable message of what went wrong */
-    error: string;
-}
-
-/**
- * A report of a failed coloring attempt of SLP/ALP.
- * This should always indicate something went wrong when building the tx.
- */
-export interface TokenFailedColoring {
-    /** For ALP, the index of the pushdata in the OP_RETURN that failed parsing. */
-    pushdataIdx: number;
-    /** Human-readable message of what went wrong */
-    error: string;
-}
-
-/** Data attached by a plugin to an output */
-export interface PluginEntry {
-    /** Groups assigned to this output */
-    groups: Uint8Array[];
-    /** Data assigned to the output */
-    data: Uint8Array[];
-}
-
-/** Data about a plugin group */
-export interface PluginGroup {
-    /** Group bytes */
-    group: Uint8Array;
-}
-
-/** List of plugin groups */
-export interface PluginGroups {
-    /** Groups */
-    groups: PluginGroup[];
-    /**
-     * Group that if specified as `start` will give us the next groups,
-     * or empty if groups have been exausted.
-     */
-    nextStart: Uint8Array;
-}
-
-/** Page with txs */
-export interface TxHistoryPage {
-    /** Txs of the page */
-    txs: Tx[];
-    /** How many pages there are total */
-    numPages: number;
-    /** How many txs there are total */
-    numTxs: number;
-}
-
-/** List of UTXOs of a script */
-export interface ScriptUtxos {
-    /** The serialized script of the UTXOs */
-    script: Uint8Array;
-    /** UTXOs of the script. */
-    utxos: ScriptUtxo[];
-}
-
-/** List of UTXOs */
-export interface Utxos {
-    /** UTXOs */
-    utxos: Utxo[];
-}
-
-/** Broadcast a single tx */
-export interface BroadcastTxRequest {
-    /** Serialized tx */
-    rawTx: Uint8Array;
-    /** Whether to skip token checks and broadcast even if tokens are unintentionally burned */
-    skipTokenChecks: boolean;
-}
-
-/** Response of broadcasting the tx */
-export interface BroadcastTxResponse {
-    /** TxId of the broadcast tx */
-    txid: Uint8Array;
-}
-
-/** Broadcast multiple txs. If one of the txs fails token validation, the entire batch will not be broadcast. */
-export interface BroadcastTxsRequest {
-    /** Serialized txs. */
-    rawTxs: Uint8Array[];
-    /** Whether to skip token checks and broadcast even if tokens are unintentionally burned */
-    skipTokenChecks: boolean;
-}
-
-/** Response of broadcasting txs */
-export interface BroadcastTxsResponse {
-    /** TxIds of the broadcast txs */
-    txids: Uint8Array[];
-}
-
-/** Raw serialized tx. */
-export interface RawTx {
-    /** Bytes of the serialized tx. */
-    rawTx: Uint8Array;
-}
-
-/** Subscription to WebSocket updates. */
-export interface WsSub {
-    /** Set this to `true` to unsubscribe from the event. */
-    isUnsub: boolean;
-    /** Subscription to block updates */
-    blocks?: WsSubBlocks | undefined;
-    /** Subscription to a script */
-    script?: WsSubScript | undefined;
-    /** Subscription to a token ID */
-    tokenId?: WsSubTokenId | undefined;
-    /** Subscription to a lokad ID */
-    lokadId?: WsSubLokadId | undefined;
-}
-
-/**
- * Subscription to blocks. They will be sent any time a block got connected,
- * disconnected or finalized.
- */
-export interface WsSubBlocks {}
-
-/**
- * Subscription to a script. They will be sent every time a tx spending the
- * given script or sending to the given script has been added to/removed from
- * the mempool, or confirmed in a block.
- */
-export interface WsSubScript {
-    /** Script type to subscribe to ("p2pkh", "p2sh", "p2pk", "other"). */
-    scriptType: string;
-    /**
-     * Payload for the given script type:
-     * - 20-byte hash for "p2pkh" and "p2sh"
-     * - 33-byte or 65-byte pubkey for "p2pk"
-     * - Serialized script for "other"
-     */
-    payload: Uint8Array;
-}
-
-/**
- * Subscription to a token ID. They will be sent every time a tx spending or
- * sending tokens with the token ID.
- */
-export interface WsSubTokenId {
-    /** Hex token ID to subscribe to. */
-    tokenId: string;
-}
-
-/**
- * Subscription to a LOKAD ID. They will be sent every time a tx matches the given LOKAD ID in one of the following ways:
- * - `OP_RETURN <LOKAD ID> ...`: The first output has an OP_RETURN with the given LOKAD ID as first pushop
- * - `OP_RETURN OP_RESERVED "<LOKAD_ID>..." "<LOKAD_ID>..." ...`: The first output has an eMPP encoded OP_RETURN, and one (or more) of the pushops has the LOKAD ID as prefix.
- * - `<LOKAD ID> ...`: An input's scriptSig has the given LOKAD ID as the first pushop
- */
-export interface WsSubLokadId {
-    /** 4-byte LOKAD ID. */
-    lokadId: Uint8Array;
-}
-
-/** Message coming from the WebSocket */
-export interface WsMsg {
-    /** Error, e.g. when a bad message has been sent into the WebSocket. */
-    error?: Error | undefined;
-    /** Block got connected, disconnected, finalized, etc. */
-    block?: MsgBlock | undefined;
-    /** Tx got added to/removed from the mempool, or confirmed in a block. */
-    tx?: MsgTx | undefined;
-}
-
-/** Block got connected, disconnected, finalized, etc. */
-export interface MsgBlock {
-    /** What happened to the block */
-    msgType: BlockMsgType;
-    /** Hash of the block (little-endian) */
-    blockHash: Uint8Array;
-    /** Height of the block */
-    blockHeight: number;
-}
-
-/** Tx got added to/removed from mempool, or confirmed in a block, etc. */
-export interface MsgTx {
-    /** What happened to the tx */
-    msgType: TxMsgType;
-    /** Txid of the tx (little-endian) */
-    txid: Uint8Array;
-}
-
-/** Empty msg without any data */
-export interface Empty {}
-
-/** Error message returned from our APIs. */
-export interface Error {
-    /** 2, as legacy chronik uses this for the message so we're still compatible. */
-    msg: string;
-}
-
-function createBaseBlock(): Block {
-    return { blockInfo: undefined };
-}
-
-export const Block = {
-    encode(
-        message: Block,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.blockInfo !== undefined) {
-            BlockInfo.encode(
-                message.blockInfo,
-                writer.uint32(10).fork(),
-            ).ldelim();
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): Block {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBlock();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.blockInfo = BlockInfo.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): Block {
-        return {
-            blockInfo: isSet(object.blockInfo)
-                ? BlockInfo.fromJSON(object.blockInfo)
-                : undefined,
-        };
-    },
-
-    toJSON(message: Block): unknown {
-        const obj: any = {};
-        if (message.blockInfo !== undefined) {
-            obj.blockInfo = BlockInfo.toJSON(message.blockInfo);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<Block>, I>>(base?: I): Block {
-        return Block.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<Block>, I>>(object: I): Block {
-        const message = createBaseBlock();
-        message.blockInfo =
-            object.blockInfo !== undefined && object.blockInfo !== null
-                ? BlockInfo.fromPartial(object.blockInfo)
-                : undefined;
-        return message;
-    },
-};
-
-function createBaseBlocks(): Blocks {
-    return { blocks: [] };
-}
-
-export const Blocks = {
-    encode(
-        message: Blocks,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        for (const v of message.blocks) {
-            BlockInfo.encode(v!, writer.uint32(10).fork()).ldelim();
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): Blocks {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBlocks();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.blocks.push(
-                        BlockInfo.decode(reader, reader.uint32()),
-                    );
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): Blocks {
-        return {
-            blocks: globalThis.Array.isArray(object?.blocks)
-                ? object.blocks.map((e: any) => BlockInfo.fromJSON(e))
-                : [],
-        };
-    },
-
-    toJSON(message: Blocks): unknown {
-        const obj: any = {};
-        if (message.blocks?.length) {
-            obj.blocks = message.blocks.map(e => BlockInfo.toJSON(e));
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<Blocks>, I>>(base?: I): Blocks {
-        return Blocks.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<Blocks>, I>>(object: I): Blocks {
-        const message = createBaseBlocks();
-        message.blocks =
-            object.blocks?.map(e => BlockInfo.fromPartial(e)) || [];
-        return message;
-    },
-};
-
-function createBaseBlockHeader(): BlockHeader {
-    return { rawHeader: new Uint8Array(0) };
-}
-
-export const BlockHeader = {
-    encode(
-        message: BlockHeader,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.rawHeader.length !== 0) {
-            writer.uint32(10).bytes(message.rawHeader);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): BlockHeader {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBlockHeader();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.rawHeader = reader.bytes();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): BlockHeader {
-        return {
-            rawHeader: isSet(object.rawHeader)
-                ? bytesFromBase64(object.rawHeader)
-                : new Uint8Array(0),
-        };
-    },
-
-    toJSON(message: BlockHeader): unknown {
-        const obj: any = {};
-        if (message.rawHeader.length !== 0) {
-            obj.rawHeader = base64FromBytes(message.rawHeader);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<BlockHeader>, I>>(
-        base?: I,
-    ): BlockHeader {
-        return BlockHeader.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<BlockHeader>, I>>(
-        object: I,
-    ): BlockHeader {
-        const message = createBaseBlockHeader();
-        message.rawHeader = object.rawHeader ?? new Uint8Array(0);
-        return message;
-    },
-};
-
-function createBaseBlockHeaders(): BlockHeaders {
-    return { headers: [] };
-}
-
-export const BlockHeaders = {
-    encode(
-        message: BlockHeaders,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        for (const v of message.headers) {
-            BlockHeader.encode(v!, writer.uint32(10).fork()).ldelim();
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): BlockHeaders {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBlockHeaders();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.headers.push(
-                        BlockHeader.decode(reader, reader.uint32()),
-                    );
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): BlockHeaders {
-        return {
-            headers: globalThis.Array.isArray(object?.headers)
-                ? object.headers.map((e: any) => BlockHeader.fromJSON(e))
-                : [],
-        };
-    },
-
-    toJSON(message: BlockHeaders): unknown {
-        const obj: any = {};
-        if (message.headers?.length) {
-            obj.headers = message.headers.map(e => BlockHeader.toJSON(e));
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<BlockHeaders>, I>>(
-        base?: I,
-    ): BlockHeaders {
-        return BlockHeaders.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<BlockHeaders>, I>>(
-        object: I,
-    ): BlockHeaders {
-        const message = createBaseBlockHeaders();
-        message.headers =
-            object.headers?.map(e => BlockHeader.fromPartial(e)) || [];
-        return message;
-    },
-};
-
-function createBaseBlockchainInfo(): BlockchainInfo {
-    return { tipHash: new Uint8Array(0), tipHeight: 0 };
-}
-
-export const BlockchainInfo = {
-    encode(
-        message: BlockchainInfo,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.tipHash.length !== 0) {
-            writer.uint32(10).bytes(message.tipHash);
-        }
-        if (message.tipHeight !== 0) {
-            writer.uint32(16).int32(message.tipHeight);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): BlockchainInfo {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBlockchainInfo();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.tipHash = reader.bytes();
-                    continue;
-                case 2:
-                    if (tag !== 16) {
-                        break;
-                    }
-
-                    message.tipHeight = reader.int32();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): BlockchainInfo {
-        return {
-            tipHash: isSet(object.tipHash)
-                ? bytesFromBase64(object.tipHash)
-                : new Uint8Array(0),
-            tipHeight: isSet(object.tipHeight)
-                ? globalThis.Number(object.tipHeight)
-                : 0,
-        };
-    },
-
-    toJSON(message: BlockchainInfo): unknown {
-        const obj: any = {};
-        if (message.tipHash.length !== 0) {
-            obj.tipHash = base64FromBytes(message.tipHash);
-        }
-        if (message.tipHeight !== 0) {
-            obj.tipHeight = Math.round(message.tipHeight);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<BlockchainInfo>, I>>(
-        base?: I,
-    ): BlockchainInfo {
-        return BlockchainInfo.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<BlockchainInfo>, I>>(
-        object: I,
-    ): BlockchainInfo {
-        const message = createBaseBlockchainInfo();
-        message.tipHash = object.tipHash ?? new Uint8Array(0);
-        message.tipHeight = object.tipHeight ?? 0;
-        return message;
-    },
-};
-
-function createBaseChronikInfo(): ChronikInfo {
-    return { version: '' };
-}
-
-export const ChronikInfo = {
-    encode(
-        message: ChronikInfo,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.version !== '') {
-            writer.uint32(10).string(message.version);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): ChronikInfo {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseChronikInfo();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.version = reader.string();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): ChronikInfo {
-        return {
-            version: isSet(object.version)
-                ? globalThis.String(object.version)
-                : '',
-        };
-    },
-
-    toJSON(message: ChronikInfo): unknown {
-        const obj: any = {};
-        if (message.version !== '') {
-            obj.version = message.version;
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<ChronikInfo>, I>>(
-        base?: I,
-    ): ChronikInfo {
-        return ChronikInfo.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<ChronikInfo>, I>>(
-        object: I,
-    ): ChronikInfo {
-        const message = createBaseChronikInfo();
-        message.version = object.version ?? '';
-        return message;
-    },
-};
-
-function createBaseBlockInfo(): BlockInfo {
-    return {
-        hash: new Uint8Array(0),
-        prevHash: new Uint8Array(0),
-        height: 0,
-        nBits: 0,
-        timestamp: '0',
-        isFinal: false,
-        blockSize: '0',
-        numTxs: '0',
-        numInputs: '0',
-        numOutputs: '0',
-        sumInputSats: '0',
-        sumCoinbaseOutputSats: '0',
-        sumNormalOutputSats: '0',
-        sumBurnedSats: '0',
-    };
-}
-
-export const BlockInfo = {
-    encode(
-        message: BlockInfo,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.hash.length !== 0) {
-            writer.uint32(10).bytes(message.hash);
-        }
-        if (message.prevHash.length !== 0) {
-            writer.uint32(18).bytes(message.prevHash);
-        }
-        if (message.height !== 0) {
-            writer.uint32(24).int32(message.height);
-        }
-        if (message.nBits !== 0) {
-            writer.uint32(32).uint32(message.nBits);
-        }
-        if (message.timestamp !== '0') {
-            writer.uint32(40).int64(message.timestamp);
-        }
-        if (message.isFinal === true) {
-            writer.uint32(112).bool(message.isFinal);
-        }
-        if (message.blockSize !== '0') {
-            writer.uint32(48).uint64(message.blockSize);
-        }
-        if (message.numTxs !== '0') {
-            writer.uint32(56).uint64(message.numTxs);
-        }
-        if (message.numInputs !== '0') {
-            writer.uint32(64).uint64(message.numInputs);
-        }
-        if (message.numOutputs !== '0') {
-            writer.uint32(72).uint64(message.numOutputs);
-        }
-        if (message.sumInputSats !== '0') {
-            writer.uint32(80).int64(message.sumInputSats);
-        }
-        if (message.sumCoinbaseOutputSats !== '0') {
-            writer.uint32(88).int64(message.sumCoinbaseOutputSats);
-        }
-        if (message.sumNormalOutputSats !== '0') {
-            writer.uint32(96).int64(message.sumNormalOutputSats);
-        }
-        if (message.sumBurnedSats !== '0') {
-            writer.uint32(104).int64(message.sumBurnedSats);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): BlockInfo {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBlockInfo();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.hash = reader.bytes();
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.prevHash = reader.bytes();
-                    continue;
-                case 3:
-                    if (tag !== 24) {
-                        break;
-                    }
-
-                    message.height = reader.int32();
-                    continue;
-                case 4:
-                    if (tag !== 32) {
-                        break;
-                    }
-
-                    message.nBits = reader.uint32();
-                    continue;
-                case 5:
-                    if (tag !== 40) {
-                        break;
-                    }
-
-                    message.timestamp = longToString(reader.int64() as Long);
-                    continue;
-                case 14:
-                    if (tag !== 112) {
-                        break;
-                    }
-
-                    message.isFinal = reader.bool();
-                    continue;
-                case 6:
-                    if (tag !== 48) {
-                        break;
-                    }
-
-                    message.blockSize = longToString(reader.uint64() as Long);
-                    continue;
-                case 7:
-                    if (tag !== 56) {
-                        break;
-                    }
-
-                    message.numTxs = longToString(reader.uint64() as Long);
-                    continue;
-                case 8:
-                    if (tag !== 64) {
-                        break;
-                    }
-
-                    message.numInputs = longToString(reader.uint64() as Long);
-                    continue;
-                case 9:
-                    if (tag !== 72) {
-                        break;
-                    }
-
-                    message.numOutputs = longToString(reader.uint64() as Long);
-                    continue;
-                case 10:
-                    if (tag !== 80) {
-                        break;
-                    }
-
-                    message.sumInputSats = longToString(reader.int64() as Long);
-                    continue;
-                case 11:
-                    if (tag !== 88) {
-                        break;
-                    }
-
-                    message.sumCoinbaseOutputSats = longToString(
-                        reader.int64() as Long,
-                    );
-                    continue;
-                case 12:
-                    if (tag !== 96) {
-                        break;
-                    }
-
-                    message.sumNormalOutputSats = longToString(
-                        reader.int64() as Long,
-                    );
-                    continue;
-                case 13:
-                    if (tag !== 104) {
-                        break;
-                    }
-
-                    message.sumBurnedSats = longToString(
-                        reader.int64() as Long,
-                    );
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): BlockInfo {
-        return {
-            hash: isSet(object.hash)
-                ? bytesFromBase64(object.hash)
-                : new Uint8Array(0),
-            prevHash: isSet(object.prevHash)
-                ? bytesFromBase64(object.prevHash)
-                : new Uint8Array(0),
-            height: isSet(object.height) ? globalThis.Number(object.height) : 0,
-            nBits: isSet(object.nBits) ? globalThis.Number(object.nBits) : 0,
-            timestamp: isSet(object.timestamp)
-                ? globalThis.String(object.timestamp)
-                : '0',
-            isFinal: isSet(object.isFinal)
-                ? globalThis.Boolean(object.isFinal)
-                : false,
-            blockSize: isSet(object.blockSize)
-                ? globalThis.String(object.blockSize)
-                : '0',
-            numTxs: isSet(object.numTxs)
-                ? globalThis.String(object.numTxs)
-                : '0',
-            numInputs: isSet(object.numInputs)
-                ? globalThis.String(object.numInputs)
-                : '0',
-            numOutputs: isSet(object.numOutputs)
-                ? globalThis.String(object.numOutputs)
-                : '0',
-            sumInputSats: isSet(object.sumInputSats)
-                ? globalThis.String(object.sumInputSats)
-                : '0',
-            sumCoinbaseOutputSats: isSet(object.sumCoinbaseOutputSats)
-                ? globalThis.String(object.sumCoinbaseOutputSats)
-                : '0',
-            sumNormalOutputSats: isSet(object.sumNormalOutputSats)
-                ? globalThis.String(object.sumNormalOutputSats)
-                : '0',
-            sumBurnedSats: isSet(object.sumBurnedSats)
-                ? globalThis.String(object.sumBurnedSats)
-                : '0',
-        };
-    },
-
-    toJSON(message: BlockInfo): unknown {
-        const obj: any = {};
-        if (message.hash.length !== 0) {
-            obj.hash = base64FromBytes(message.hash);
-        }
-        if (message.prevHash.length !== 0) {
-            obj.prevHash = base64FromBytes(message.prevHash);
-        }
-        if (message.height !== 0) {
-            obj.height = Math.round(message.height);
-        }
-        if (message.nBits !== 0) {
-            obj.nBits = Math.round(message.nBits);
-        }
-        if (message.timestamp !== '0') {
-            obj.timestamp = message.timestamp;
-        }
-        if (message.isFinal === true) {
-            obj.isFinal = message.isFinal;
-        }
-        if (message.blockSize !== '0') {
-            obj.blockSize = message.blockSize;
-        }
-        if (message.numTxs !== '0') {
-            obj.numTxs = message.numTxs;
-        }
-        if (message.numInputs !== '0') {
-            obj.numInputs = message.numInputs;
-        }
-        if (message.numOutputs !== '0') {
-            obj.numOutputs = message.numOutputs;
-        }
-        if (message.sumInputSats !== '0') {
-            obj.sumInputSats = message.sumInputSats;
-        }
-        if (message.sumCoinbaseOutputSats !== '0') {
-            obj.sumCoinbaseOutputSats = message.sumCoinbaseOutputSats;
-        }
-        if (message.sumNormalOutputSats !== '0') {
-            obj.sumNormalOutputSats = message.sumNormalOutputSats;
-        }
-        if (message.sumBurnedSats !== '0') {
-            obj.sumBurnedSats = message.sumBurnedSats;
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<BlockInfo>, I>>(base?: I): BlockInfo {
-        return BlockInfo.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<BlockInfo>, I>>(
-        object: I,
-    ): BlockInfo {
-        const message = createBaseBlockInfo();
-        message.hash = object.hash ?? new Uint8Array(0);
-        message.prevHash = object.prevHash ?? new Uint8Array(0);
-        message.height = object.height ?? 0;
-        message.nBits = object.nBits ?? 0;
-        message.timestamp = object.timestamp ?? '0';
-        message.isFinal = object.isFinal ?? false;
-        message.blockSize = object.blockSize ?? '0';
-        message.numTxs = object.numTxs ?? '0';
-        message.numInputs = object.numInputs ?? '0';
-        message.numOutputs = object.numOutputs ?? '0';
-        message.sumInputSats = object.sumInputSats ?? '0';
-        message.sumCoinbaseOutputSats = object.sumCoinbaseOutputSats ?? '0';
-        message.sumNormalOutputSats = object.sumNormalOutputSats ?? '0';
-        message.sumBurnedSats = object.sumBurnedSats ?? '0';
-        return message;
-    },
-};
-
-function createBaseTx(): Tx {
-    return {
-        txid: new Uint8Array(0),
-        version: 0,
-        inputs: [],
-        outputs: [],
-        lockTime: 0,
-        block: undefined,
-        timeFirstSeen: '0',
-        size: 0,
-        isCoinbase: false,
-        tokenEntries: [],
-        tokenFailedParsings: [],
-        tokenStatus: 0,
-    };
-}
-
-export const Tx = {
-    encode(message: Tx, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
-        if (message.txid.length !== 0) {
-            writer.uint32(10).bytes(message.txid);
-        }
-        if (message.version !== 0) {
-            writer.uint32(16).int32(message.version);
-        }
-        for (const v of message.inputs) {
-            TxInput.encode(v!, writer.uint32(26).fork()).ldelim();
-        }
-        for (const v of message.outputs) {
-            TxOutput.encode(v!, writer.uint32(34).fork()).ldelim();
-        }
-        if (message.lockTime !== 0) {
-            writer.uint32(40).uint32(message.lockTime);
-        }
-        if (message.block !== undefined) {
-            BlockMetadata.encode(
-                message.block,
-                writer.uint32(66).fork(),
-            ).ldelim();
-        }
-        if (message.timeFirstSeen !== '0') {
-            writer.uint32(72).int64(message.timeFirstSeen);
-        }
-        if (message.size !== 0) {
-            writer.uint32(88).uint32(message.size);
-        }
-        if (message.isCoinbase === true) {
-            writer.uint32(96).bool(message.isCoinbase);
-        }
-        for (const v of message.tokenEntries) {
-            TokenEntry.encode(v!, writer.uint32(106).fork()).ldelim();
-        }
-        for (const v of message.tokenFailedParsings) {
-            TokenFailedParsing.encode(v!, writer.uint32(114).fork()).ldelim();
-        }
-        if (message.tokenStatus !== 0) {
-            writer.uint32(120).int32(message.tokenStatus);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): Tx {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTx();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.txid = reader.bytes();
-                    continue;
-                case 2:
-                    if (tag !== 16) {
-                        break;
-                    }
-
-                    message.version = reader.int32();
-                    continue;
-                case 3:
-                    if (tag !== 26) {
-                        break;
-                    }
-
-                    message.inputs.push(
-                        TxInput.decode(reader, reader.uint32()),
-                    );
-                    continue;
-                case 4:
-                    if (tag !== 34) {
-                        break;
-                    }
-
-                    message.outputs.push(
-                        TxOutput.decode(reader, reader.uint32()),
-                    );
-                    continue;
-                case 5:
-                    if (tag !== 40) {
-                        break;
-                    }
-
-                    message.lockTime = reader.uint32();
-                    continue;
-                case 8:
-                    if (tag !== 66) {
-                        break;
-                    }
-
-                    message.block = BlockMetadata.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    continue;
-                case 9:
-                    if (tag !== 72) {
-                        break;
-                    }
-
-                    message.timeFirstSeen = longToString(
-                        reader.int64() as Long,
-                    );
-                    continue;
-                case 11:
-                    if (tag !== 88) {
-                        break;
-                    }
-
-                    message.size = reader.uint32();
-                    continue;
-                case 12:
-                    if (tag !== 96) {
-                        break;
-                    }
-
-                    message.isCoinbase = reader.bool();
-                    continue;
-                case 13:
-                    if (tag !== 106) {
-                        break;
-                    }
-
-                    message.tokenEntries.push(
-                        TokenEntry.decode(reader, reader.uint32()),
-                    );
-                    continue;
-                case 14:
-                    if (tag !== 114) {
-                        break;
-                    }
-
-                    message.tokenFailedParsings.push(
-                        TokenFailedParsing.decode(reader, reader.uint32()),
-                    );
-                    continue;
-                case 15:
-                    if (tag !== 120) {
-                        break;
-                    }
-
-                    message.tokenStatus = reader.int32() as any;
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): Tx {
-        return {
-            txid: isSet(object.txid)
-                ? bytesFromBase64(object.txid)
-                : new Uint8Array(0),
-            version: isSet(object.version)
-                ? globalThis.Number(object.version)
-                : 0,
-            inputs: globalThis.Array.isArray(object?.inputs)
-                ? object.inputs.map((e: any) => TxInput.fromJSON(e))
-                : [],
-            outputs: globalThis.Array.isArray(object?.outputs)
-                ? object.outputs.map((e: any) => TxOutput.fromJSON(e))
-                : [],
-            lockTime: isSet(object.lockTime)
-                ? globalThis.Number(object.lockTime)
-                : 0,
-            block: isSet(object.block)
-                ? BlockMetadata.fromJSON(object.block)
-                : undefined,
-            timeFirstSeen: isSet(object.timeFirstSeen)
-                ? globalThis.String(object.timeFirstSeen)
-                : '0',
-            size: isSet(object.size) ? globalThis.Number(object.size) : 0,
-            isCoinbase: isSet(object.isCoinbase)
-                ? globalThis.Boolean(object.isCoinbase)
-                : false,
-            tokenEntries: globalThis.Array.isArray(object?.tokenEntries)
-                ? object.tokenEntries.map((e: any) => TokenEntry.fromJSON(e))
-                : [],
-            tokenFailedParsings: globalThis.Array.isArray(
-                object?.tokenFailedParsings,
-            )
-                ? object.tokenFailedParsings.map((e: any) =>
-                      TokenFailedParsing.fromJSON(e),
-                  )
-                : [],
-            tokenStatus: isSet(object.tokenStatus)
-                ? tokenStatusFromJSON(object.tokenStatus)
-                : 0,
-        };
-    },
-
-    toJSON(message: Tx): unknown {
-        const obj: any = {};
-        if (message.txid.length !== 0) {
-            obj.txid = base64FromBytes(message.txid);
-        }
-        if (message.version !== 0) {
-            obj.version = Math.round(message.version);
-        }
-        if (message.inputs?.length) {
-            obj.inputs = message.inputs.map(e => TxInput.toJSON(e));
-        }
-        if (message.outputs?.length) {
-            obj.outputs = message.outputs.map(e => TxOutput.toJSON(e));
-        }
-        if (message.lockTime !== 0) {
-            obj.lockTime = Math.round(message.lockTime);
-        }
-        if (message.block !== undefined) {
-            obj.block = BlockMetadata.toJSON(message.block);
-        }
-        if (message.timeFirstSeen !== '0') {
-            obj.timeFirstSeen = message.timeFirstSeen;
-        }
-        if (message.size !== 0) {
-            obj.size = Math.round(message.size);
-        }
-        if (message.isCoinbase === true) {
-            obj.isCoinbase = message.isCoinbase;
-        }
-        if (message.tokenEntries?.length) {
-            obj.tokenEntries = message.tokenEntries.map(e =>
-                TokenEntry.toJSON(e),
-            );
-        }
-        if (message.tokenFailedParsings?.length) {
-            obj.tokenFailedParsings = message.tokenFailedParsings.map(e =>
-                TokenFailedParsing.toJSON(e),
-            );
-        }
-        if (message.tokenStatus !== 0) {
-            obj.tokenStatus = tokenStatusToJSON(message.tokenStatus);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<Tx>, I>>(base?: I): Tx {
-        return Tx.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<Tx>, I>>(object: I): Tx {
-        const message = createBaseTx();
-        message.txid = object.txid ?? new Uint8Array(0);
-        message.version = object.version ?? 0;
-        message.inputs = object.inputs?.map(e => TxInput.fromPartial(e)) || [];
-        message.outputs =
-            object.outputs?.map(e => TxOutput.fromPartial(e)) || [];
-        message.lockTime = object.lockTime ?? 0;
-        message.block =
-            object.block !== undefined && object.block !== null
-                ? BlockMetadata.fromPartial(object.block)
-                : undefined;
-        message.timeFirstSeen = object.timeFirstSeen ?? '0';
-        message.size = object.size ?? 0;
-        message.isCoinbase = object.isCoinbase ?? false;
-        message.tokenEntries =
-            object.tokenEntries?.map(e => TokenEntry.fromPartial(e)) || [];
-        message.tokenFailedParsings =
-            object.tokenFailedParsings?.map(e =>
-                TokenFailedParsing.fromPartial(e),
-            ) || [];
-        message.tokenStatus = object.tokenStatus ?? 0;
-        return message;
-    },
-};
-
-function createBaseScriptUtxo(): ScriptUtxo {
-    return {
-        outpoint: undefined,
-        blockHeight: 0,
-        isCoinbase: false,
-        value: '0',
-        isFinal: false,
-        token: undefined,
-        plugins: {},
-    };
-}
-
-export const ScriptUtxo = {
-    encode(
-        message: ScriptUtxo,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.outpoint !== undefined) {
-            OutPoint.encode(
-                message.outpoint,
-                writer.uint32(10).fork(),
-            ).ldelim();
-        }
-        if (message.blockHeight !== 0) {
-            writer.uint32(16).int32(message.blockHeight);
-        }
-        if (message.isCoinbase === true) {
-            writer.uint32(24).bool(message.isCoinbase);
-        }
-        if (message.value !== '0') {
-            writer.uint32(40).int64(message.value);
-        }
-        if (message.isFinal === true) {
-            writer.uint32(80).bool(message.isFinal);
-        }
-        if (message.token !== undefined) {
-            Token.encode(message.token, writer.uint32(90).fork()).ldelim();
-        }
-        Object.entries(message.plugins).forEach(([key, value]) => {
-            ScriptUtxo_PluginsEntry.encode(
-                { key: key as any, value },
-                writer.uint32(98).fork(),
-            ).ldelim();
-        });
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): ScriptUtxo {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseScriptUtxo();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.outpoint = OutPoint.decode(reader, reader.uint32());
-                    continue;
-                case 2:
-                    if (tag !== 16) {
-                        break;
-                    }
-
-                    message.blockHeight = reader.int32();
-                    continue;
-                case 3:
-                    if (tag !== 24) {
-                        break;
-                    }
-
-                    message.isCoinbase = reader.bool();
-                    continue;
-                case 5:
-                    if (tag !== 40) {
-                        break;
-                    }
-
-                    message.value = longToString(reader.int64() as Long);
-                    continue;
-                case 10:
-                    if (tag !== 80) {
-                        break;
-                    }
-
-                    message.isFinal = reader.bool();
-                    continue;
-                case 11:
-                    if (tag !== 90) {
-                        break;
-                    }
-
-                    message.token = Token.decode(reader, reader.uint32());
-                    continue;
-                case 12:
-                    if (tag !== 98) {
-                        break;
-                    }
-
-                    const entry12 = ScriptUtxo_PluginsEntry.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    if (entry12.value !== undefined) {
-                        message.plugins[entry12.key] = entry12.value;
-                    }
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): ScriptUtxo {
-        return {
-            outpoint: isSet(object.outpoint)
-                ? OutPoint.fromJSON(object.outpoint)
-                : undefined,
-            blockHeight: isSet(object.blockHeight)
-                ? globalThis.Number(object.blockHeight)
-                : 0,
-            isCoinbase: isSet(object.isCoinbase)
-                ? globalThis.Boolean(object.isCoinbase)
-                : false,
-            value: isSet(object.value) ? globalThis.String(object.value) : '0',
-            isFinal: isSet(object.isFinal)
-                ? globalThis.Boolean(object.isFinal)
-                : false,
-            token: isSet(object.token)
-                ? Token.fromJSON(object.token)
-                : undefined,
-            plugins: isObject(object.plugins)
-                ? Object.entries(object.plugins).reduce<{
-                      [key: string]: PluginEntry;
-                  }>((acc, [key, value]) => {
-                      acc[key] = PluginEntry.fromJSON(value);
-                      return acc;
-                  }, {})
-                : {},
-        };
-    },
-
-    toJSON(message: ScriptUtxo): unknown {
-        const obj: any = {};
-        if (message.outpoint !== undefined) {
-            obj.outpoint = OutPoint.toJSON(message.outpoint);
-        }
-        if (message.blockHeight !== 0) {
-            obj.blockHeight = Math.round(message.blockHeight);
-        }
-        if (message.isCoinbase === true) {
-            obj.isCoinbase = message.isCoinbase;
-        }
-        if (message.value !== '0') {
-            obj.value = message.value;
-        }
-        if (message.isFinal === true) {
-            obj.isFinal = message.isFinal;
-        }
-        if (message.token !== undefined) {
-            obj.token = Token.toJSON(message.token);
-        }
-        if (message.plugins) {
-            const entries = Object.entries(message.plugins);
-            if (entries.length > 0) {
-                obj.plugins = {};
-                entries.forEach(([k, v]) => {
-                    obj.plugins[k] = PluginEntry.toJSON(v);
-                });
-            }
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<ScriptUtxo>, I>>(base?: I): ScriptUtxo {
-        return ScriptUtxo.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<ScriptUtxo>, I>>(
-        object: I,
-    ): ScriptUtxo {
-        const message = createBaseScriptUtxo();
-        message.outpoint =
-            object.outpoint !== undefined && object.outpoint !== null
-                ? OutPoint.fromPartial(object.outpoint)
-                : undefined;
-        message.blockHeight = object.blockHeight ?? 0;
-        message.isCoinbase = object.isCoinbase ?? false;
-        message.value = object.value ?? '0';
-        message.isFinal = object.isFinal ?? false;
-        message.token =
-            object.token !== undefined && object.token !== null
-                ? Token.fromPartial(object.token)
-                : undefined;
-        message.plugins = Object.entries(object.plugins ?? {}).reduce<{
-            [key: string]: PluginEntry;
-        }>((acc, [key, value]) => {
-            if (value !== undefined) {
-                acc[key] = PluginEntry.fromPartial(value);
-            }
-            return acc;
-        }, {});
-        return message;
-    },
-};
-
-function createBaseScriptUtxo_PluginsEntry(): ScriptUtxo_PluginsEntry {
-    return { key: '', value: undefined };
-}
-
-export const ScriptUtxo_PluginsEntry = {
-    encode(
-        message: ScriptUtxo_PluginsEntry,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.key !== '') {
-            writer.uint32(10).string(message.key);
-        }
-        if (message.value !== undefined) {
-            PluginEntry.encode(
-                message.value,
-                writer.uint32(18).fork(),
-            ).ldelim();
-        }
-        return writer;
-    },
-
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): ScriptUtxo_PluginsEntry {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseScriptUtxo_PluginsEntry();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.key = reader.string();
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.value = PluginEntry.decode(reader, reader.uint32());
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): ScriptUtxo_PluginsEntry {
-        return {
-            key: isSet(object.key) ? globalThis.String(object.key) : '',
-            value: isSet(object.value)
-                ? PluginEntry.fromJSON(object.value)
-                : undefined,
-        };
-    },
-
-    toJSON(message: ScriptUtxo_PluginsEntry): unknown {
-        const obj: any = {};
-        if (message.key !== '') {
-            obj.key = message.key;
-        }
-        if (message.value !== undefined) {
-            obj.value = PluginEntry.toJSON(message.value);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<ScriptUtxo_PluginsEntry>, I>>(
-        base?: I,
-    ): ScriptUtxo_PluginsEntry {
-        return ScriptUtxo_PluginsEntry.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<ScriptUtxo_PluginsEntry>, I>>(
-        object: I,
-    ): ScriptUtxo_PluginsEntry {
-        const message = createBaseScriptUtxo_PluginsEntry();
-        message.key = object.key ?? '';
-        message.value =
-            object.value !== undefined && object.value !== null
-                ? PluginEntry.fromPartial(object.value)
-                : undefined;
-        return message;
-    },
-};
-
-function createBaseUtxo(): Utxo {
-    return {
-        outpoint: undefined,
-        blockHeight: 0,
-        isCoinbase: false,
-        value: '0',
-        script: new Uint8Array(0),
-        isFinal: false,
-        token: undefined,
-        plugins: {},
-    };
-}
-
-export const Utxo = {
-    encode(
-        message: Utxo,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.outpoint !== undefined) {
-            OutPoint.encode(
-                message.outpoint,
-                writer.uint32(10).fork(),
-            ).ldelim();
-        }
-        if (message.blockHeight !== 0) {
-            writer.uint32(16).int32(message.blockHeight);
-        }
-        if (message.isCoinbase === true) {
-            writer.uint32(24).bool(message.isCoinbase);
-        }
-        if (message.value !== '0') {
-            writer.uint32(32).int64(message.value);
-        }
-        if (message.script.length !== 0) {
-            writer.uint32(42).bytes(message.script);
-        }
-        if (message.isFinal === true) {
-            writer.uint32(48).bool(message.isFinal);
-        }
-        if (message.token !== undefined) {
-            Token.encode(message.token, writer.uint32(58).fork()).ldelim();
-        }
-        Object.entries(message.plugins).forEach(([key, value]) => {
-            Utxo_PluginsEntry.encode(
-                { key: key as any, value },
-                writer.uint32(66).fork(),
-            ).ldelim();
-        });
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): Utxo {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseUtxo();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.outpoint = OutPoint.decode(reader, reader.uint32());
-                    continue;
-                case 2:
-                    if (tag !== 16) {
-                        break;
-                    }
-
-                    message.blockHeight = reader.int32();
-                    continue;
-                case 3:
-                    if (tag !== 24) {
-                        break;
-                    }
-
-                    message.isCoinbase = reader.bool();
-                    continue;
-                case 4:
-                    if (tag !== 32) {
-                        break;
-                    }
-
-                    message.value = longToString(reader.int64() as Long);
-                    continue;
-                case 5:
-                    if (tag !== 42) {
-                        break;
-                    }
-
-                    message.script = reader.bytes();
-                    continue;
-                case 6:
-                    if (tag !== 48) {
-                        break;
-                    }
-
-                    message.isFinal = reader.bool();
-                    continue;
-                case 7:
-                    if (tag !== 58) {
-                        break;
-                    }
-
-                    message.token = Token.decode(reader, reader.uint32());
-                    continue;
-                case 8:
-                    if (tag !== 66) {
-                        break;
-                    }
-
-                    const entry8 = Utxo_PluginsEntry.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    if (entry8.value !== undefined) {
-                        message.plugins[entry8.key] = entry8.value;
-                    }
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): Utxo {
-        return {
-            outpoint: isSet(object.outpoint)
-                ? OutPoint.fromJSON(object.outpoint)
-                : undefined,
-            blockHeight: isSet(object.blockHeight)
-                ? globalThis.Number(object.blockHeight)
-                : 0,
-            isCoinbase: isSet(object.isCoinbase)
-                ? globalThis.Boolean(object.isCoinbase)
-                : false,
-            value: isSet(object.value) ? globalThis.String(object.value) : '0',
-            script: isSet(object.script)
-                ? bytesFromBase64(object.script)
-                : new Uint8Array(0),
-            isFinal: isSet(object.isFinal)
-                ? globalThis.Boolean(object.isFinal)
-                : false,
-            token: isSet(object.token)
-                ? Token.fromJSON(object.token)
-                : undefined,
-            plugins: isObject(object.plugins)
-                ? Object.entries(object.plugins).reduce<{
-                      [key: string]: PluginEntry;
-                  }>((acc, [key, value]) => {
-                      acc[key] = PluginEntry.fromJSON(value);
-                      return acc;
-                  }, {})
-                : {},
-        };
-    },
-
-    toJSON(message: Utxo): unknown {
-        const obj: any = {};
-        if (message.outpoint !== undefined) {
-            obj.outpoint = OutPoint.toJSON(message.outpoint);
-        }
-        if (message.blockHeight !== 0) {
-            obj.blockHeight = Math.round(message.blockHeight);
-        }
-        if (message.isCoinbase === true) {
-            obj.isCoinbase = message.isCoinbase;
-        }
-        if (message.value !== '0') {
-            obj.value = message.value;
-        }
-        if (message.script.length !== 0) {
-            obj.script = base64FromBytes(message.script);
-        }
-        if (message.isFinal === true) {
-            obj.isFinal = message.isFinal;
-        }
-        if (message.token !== undefined) {
-            obj.token = Token.toJSON(message.token);
-        }
-        if (message.plugins) {
-            const entries = Object.entries(message.plugins);
-            if (entries.length > 0) {
-                obj.plugins = {};
-                entries.forEach(([k, v]) => {
-                    obj.plugins[k] = PluginEntry.toJSON(v);
-                });
-            }
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<Utxo>, I>>(base?: I): Utxo {
-        return Utxo.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<Utxo>, I>>(object: I): Utxo {
-        const message = createBaseUtxo();
-        message.outpoint =
-            object.outpoint !== undefined && object.outpoint !== null
-                ? OutPoint.fromPartial(object.outpoint)
-                : undefined;
-        message.blockHeight = object.blockHeight ?? 0;
-        message.isCoinbase = object.isCoinbase ?? false;
-        message.value = object.value ?? '0';
-        message.script = object.script ?? new Uint8Array(0);
-        message.isFinal = object.isFinal ?? false;
-        message.token =
-            object.token !== undefined && object.token !== null
-                ? Token.fromPartial(object.token)
-                : undefined;
-        message.plugins = Object.entries(object.plugins ?? {}).reduce<{
-            [key: string]: PluginEntry;
-        }>((acc, [key, value]) => {
-            if (value !== undefined) {
-                acc[key] = PluginEntry.fromPartial(value);
-            }
-            return acc;
-        }, {});
-        return message;
-    },
-};
-
-function createBaseUtxo_PluginsEntry(): Utxo_PluginsEntry {
-    return { key: '', value: undefined };
-}
-
-export const Utxo_PluginsEntry = {
-    encode(
-        message: Utxo_PluginsEntry,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.key !== '') {
-            writer.uint32(10).string(message.key);
-        }
-        if (message.value !== undefined) {
-            PluginEntry.encode(
-                message.value,
-                writer.uint32(18).fork(),
-            ).ldelim();
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): Utxo_PluginsEntry {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseUtxo_PluginsEntry();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.key = reader.string();
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.value = PluginEntry.decode(reader, reader.uint32());
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): Utxo_PluginsEntry {
-        return {
-            key: isSet(object.key) ? globalThis.String(object.key) : '',
-            value: isSet(object.value)
-                ? PluginEntry.fromJSON(object.value)
-                : undefined,
-        };
-    },
-
-    toJSON(message: Utxo_PluginsEntry): unknown {
-        const obj: any = {};
-        if (message.key !== '') {
-            obj.key = message.key;
-        }
-        if (message.value !== undefined) {
-            obj.value = PluginEntry.toJSON(message.value);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<Utxo_PluginsEntry>, I>>(
-        base?: I,
-    ): Utxo_PluginsEntry {
-        return Utxo_PluginsEntry.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<Utxo_PluginsEntry>, I>>(
-        object: I,
-    ): Utxo_PluginsEntry {
-        const message = createBaseUtxo_PluginsEntry();
-        message.key = object.key ?? '';
-        message.value =
-            object.value !== undefined && object.value !== null
-                ? PluginEntry.fromPartial(object.value)
-                : undefined;
-        return message;
-    },
-};
-
-function createBaseOutPoint(): OutPoint {
-    return { txid: new Uint8Array(0), outIdx: 0 };
-}
-
-export const OutPoint = {
-    encode(
-        message: OutPoint,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.txid.length !== 0) {
-            writer.uint32(10).bytes(message.txid);
-        }
-        if (message.outIdx !== 0) {
-            writer.uint32(16).uint32(message.outIdx);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): OutPoint {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseOutPoint();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.txid = reader.bytes();
-                    continue;
-                case 2:
-                    if (tag !== 16) {
-                        break;
-                    }
-
-                    message.outIdx = reader.uint32();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): OutPoint {
-        return {
-            txid: isSet(object.txid)
-                ? bytesFromBase64(object.txid)
-                : new Uint8Array(0),
-            outIdx: isSet(object.outIdx) ? globalThis.Number(object.outIdx) : 0,
-        };
-    },
-
-    toJSON(message: OutPoint): unknown {
-        const obj: any = {};
-        if (message.txid.length !== 0) {
-            obj.txid = base64FromBytes(message.txid);
-        }
-        if (message.outIdx !== 0) {
-            obj.outIdx = Math.round(message.outIdx);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<OutPoint>, I>>(base?: I): OutPoint {
-        return OutPoint.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<OutPoint>, I>>(
-        object: I,
-    ): OutPoint {
-        const message = createBaseOutPoint();
-        message.txid = object.txid ?? new Uint8Array(0);
-        message.outIdx = object.outIdx ?? 0;
-        return message;
-    },
-};
-
-function createBaseSpentBy(): SpentBy {
-    return { txid: new Uint8Array(0), inputIdx: 0 };
-}
-
-export const SpentBy = {
-    encode(
-        message: SpentBy,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.txid.length !== 0) {
-            writer.uint32(10).bytes(message.txid);
-        }
-        if (message.inputIdx !== 0) {
-            writer.uint32(16).uint32(message.inputIdx);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): SpentBy {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseSpentBy();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.txid = reader.bytes();
-                    continue;
-                case 2:
-                    if (tag !== 16) {
-                        break;
-                    }
-
-                    message.inputIdx = reader.uint32();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): SpentBy {
-        return {
-            txid: isSet(object.txid)
-                ? bytesFromBase64(object.txid)
-                : new Uint8Array(0),
-            inputIdx: isSet(object.inputIdx)
-                ? globalThis.Number(object.inputIdx)
-                : 0,
-        };
-    },
-
-    toJSON(message: SpentBy): unknown {
-        const obj: any = {};
-        if (message.txid.length !== 0) {
-            obj.txid = base64FromBytes(message.txid);
-        }
-        if (message.inputIdx !== 0) {
-            obj.inputIdx = Math.round(message.inputIdx);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<SpentBy>, I>>(base?: I): SpentBy {
-        return SpentBy.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<SpentBy>, I>>(object: I): SpentBy {
-        const message = createBaseSpentBy();
-        message.txid = object.txid ?? new Uint8Array(0);
-        message.inputIdx = object.inputIdx ?? 0;
-        return message;
-    },
-};
-
-function createBaseTxInput(): TxInput {
-    return {
-        prevOut: undefined,
-        inputScript: new Uint8Array(0),
-        outputScript: new Uint8Array(0),
-        value: '0',
-        sequenceNo: 0,
-        token: undefined,
-        plugins: {},
-    };
-}
-
-export const TxInput = {
-    encode(
-        message: TxInput,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.prevOut !== undefined) {
-            OutPoint.encode(message.prevOut, writer.uint32(10).fork()).ldelim();
-        }
-        if (message.inputScript.length !== 0) {
-            writer.uint32(18).bytes(message.inputScript);
-        }
-        if (message.outputScript.length !== 0) {
-            writer.uint32(26).bytes(message.outputScript);
-        }
-        if (message.value !== '0') {
-            writer.uint32(32).int64(message.value);
-        }
-        if (message.sequenceNo !== 0) {
-            writer.uint32(40).uint32(message.sequenceNo);
-        }
-        if (message.token !== undefined) {
-            Token.encode(message.token, writer.uint32(66).fork()).ldelim();
-        }
-        Object.entries(message.plugins).forEach(([key, value]) => {
-            TxInput_PluginsEntry.encode(
-                { key: key as any, value },
-                writer.uint32(74).fork(),
-            ).ldelim();
-        });
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): TxInput {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTxInput();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.prevOut = OutPoint.decode(reader, reader.uint32());
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.inputScript = reader.bytes();
-                    continue;
-                case 3:
-                    if (tag !== 26) {
-                        break;
-                    }
-
-                    message.outputScript = reader.bytes();
-                    continue;
-                case 4:
-                    if (tag !== 32) {
-                        break;
-                    }
-
-                    message.value = longToString(reader.int64() as Long);
-                    continue;
-                case 5:
-                    if (tag !== 40) {
-                        break;
-                    }
-
-                    message.sequenceNo = reader.uint32();
-                    continue;
-                case 8:
-                    if (tag !== 66) {
-                        break;
-                    }
-
-                    message.token = Token.decode(reader, reader.uint32());
-                    continue;
-                case 9:
-                    if (tag !== 74) {
-                        break;
-                    }
-
-                    const entry9 = TxInput_PluginsEntry.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    if (entry9.value !== undefined) {
-                        message.plugins[entry9.key] = entry9.value;
-                    }
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): TxInput {
-        return {
-            prevOut: isSet(object.prevOut)
-                ? OutPoint.fromJSON(object.prevOut)
-                : undefined,
-            inputScript: isSet(object.inputScript)
-                ? bytesFromBase64(object.inputScript)
-                : new Uint8Array(0),
-            outputScript: isSet(object.outputScript)
-                ? bytesFromBase64(object.outputScript)
-                : new Uint8Array(0),
-            value: isSet(object.value) ? globalThis.String(object.value) : '0',
-            sequenceNo: isSet(object.sequenceNo)
-                ? globalThis.Number(object.sequenceNo)
-                : 0,
-            token: isSet(object.token)
-                ? Token.fromJSON(object.token)
-                : undefined,
-            plugins: isObject(object.plugins)
-                ? Object.entries(object.plugins).reduce<{
-                      [key: string]: PluginEntry;
-                  }>((acc, [key, value]) => {
-                      acc[key] = PluginEntry.fromJSON(value);
-                      return acc;
-                  }, {})
-                : {},
-        };
-    },
-
-    toJSON(message: TxInput): unknown {
-        const obj: any = {};
-        if (message.prevOut !== undefined) {
-            obj.prevOut = OutPoint.toJSON(message.prevOut);
-        }
-        if (message.inputScript.length !== 0) {
-            obj.inputScript = base64FromBytes(message.inputScript);
-        }
-        if (message.outputScript.length !== 0) {
-            obj.outputScript = base64FromBytes(message.outputScript);
-        }
-        if (message.value !== '0') {
-            obj.value = message.value;
-        }
-        if (message.sequenceNo !== 0) {
-            obj.sequenceNo = Math.round(message.sequenceNo);
-        }
-        if (message.token !== undefined) {
-            obj.token = Token.toJSON(message.token);
-        }
-        if (message.plugins) {
-            const entries = Object.entries(message.plugins);
-            if (entries.length > 0) {
-                obj.plugins = {};
-                entries.forEach(([k, v]) => {
-                    obj.plugins[k] = PluginEntry.toJSON(v);
-                });
-            }
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<TxInput>, I>>(base?: I): TxInput {
-        return TxInput.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<TxInput>, I>>(object: I): TxInput {
-        const message = createBaseTxInput();
-        message.prevOut =
-            object.prevOut !== undefined && object.prevOut !== null
-                ? OutPoint.fromPartial(object.prevOut)
-                : undefined;
-        message.inputScript = object.inputScript ?? new Uint8Array(0);
-        message.outputScript = object.outputScript ?? new Uint8Array(0);
-        message.value = object.value ?? '0';
-        message.sequenceNo = object.sequenceNo ?? 0;
-        message.token =
-            object.token !== undefined && object.token !== null
-                ? Token.fromPartial(object.token)
-                : undefined;
-        message.plugins = Object.entries(object.plugins ?? {}).reduce<{
-            [key: string]: PluginEntry;
-        }>((acc, [key, value]) => {
-            if (value !== undefined) {
-                acc[key] = PluginEntry.fromPartial(value);
-            }
-            return acc;
-        }, {});
-        return message;
-    },
-};
-
-function createBaseTxInput_PluginsEntry(): TxInput_PluginsEntry {
-    return { key: '', value: undefined };
-}
-
-export const TxInput_PluginsEntry = {
-    encode(
-        message: TxInput_PluginsEntry,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.key !== '') {
-            writer.uint32(10).string(message.key);
-        }
-        if (message.value !== undefined) {
-            PluginEntry.encode(
-                message.value,
-                writer.uint32(18).fork(),
-            ).ldelim();
-        }
-        return writer;
-    },
-
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): TxInput_PluginsEntry {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTxInput_PluginsEntry();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.key = reader.string();
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.value = PluginEntry.decode(reader, reader.uint32());
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): TxInput_PluginsEntry {
-        return {
-            key: isSet(object.key) ? globalThis.String(object.key) : '',
-            value: isSet(object.value)
-                ? PluginEntry.fromJSON(object.value)
-                : undefined,
-        };
-    },
-
-    toJSON(message: TxInput_PluginsEntry): unknown {
-        const obj: any = {};
-        if (message.key !== '') {
-            obj.key = message.key;
-        }
-        if (message.value !== undefined) {
-            obj.value = PluginEntry.toJSON(message.value);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<TxInput_PluginsEntry>, I>>(
-        base?: I,
-    ): TxInput_PluginsEntry {
-        return TxInput_PluginsEntry.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<TxInput_PluginsEntry>, I>>(
-        object: I,
-    ): TxInput_PluginsEntry {
-        const message = createBaseTxInput_PluginsEntry();
-        message.key = object.key ?? '';
-        message.value =
-            object.value !== undefined && object.value !== null
-                ? PluginEntry.fromPartial(object.value)
-                : undefined;
-        return message;
-    },
-};
-
-function createBaseTxOutput(): TxOutput {
-    return {
-        value: '0',
-        outputScript: new Uint8Array(0),
-        spentBy: undefined,
-        token: undefined,
-        plugins: {},
-    };
-}
-
-export const TxOutput = {
-    encode(
-        message: TxOutput,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.value !== '0') {
-            writer.uint32(8).int64(message.value);
-        }
-        if (message.outputScript.length !== 0) {
-            writer.uint32(18).bytes(message.outputScript);
-        }
-        if (message.spentBy !== undefined) {
-            SpentBy.encode(message.spentBy, writer.uint32(34).fork()).ldelim();
-        }
-        if (message.token !== undefined) {
-            Token.encode(message.token, writer.uint32(42).fork()).ldelim();
-        }
-        Object.entries(message.plugins).forEach(([key, value]) => {
-            TxOutput_PluginsEntry.encode(
-                { key: key as any, value },
-                writer.uint32(50).fork(),
-            ).ldelim();
-        });
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): TxOutput {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTxOutput();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 8) {
-                        break;
-                    }
-
-                    message.value = longToString(reader.int64() as Long);
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.outputScript = reader.bytes();
-                    continue;
-                case 4:
-                    if (tag !== 34) {
-                        break;
-                    }
-
-                    message.spentBy = SpentBy.decode(reader, reader.uint32());
-                    continue;
-                case 5:
-                    if (tag !== 42) {
-                        break;
-                    }
-
-                    message.token = Token.decode(reader, reader.uint32());
-                    continue;
-                case 6:
-                    if (tag !== 50) {
-                        break;
-                    }
-
-                    const entry6 = TxOutput_PluginsEntry.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    if (entry6.value !== undefined) {
-                        message.plugins[entry6.key] = entry6.value;
-                    }
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): TxOutput {
-        return {
-            value: isSet(object.value) ? globalThis.String(object.value) : '0',
-            outputScript: isSet(object.outputScript)
-                ? bytesFromBase64(object.outputScript)
-                : new Uint8Array(0),
-            spentBy: isSet(object.spentBy)
-                ? SpentBy.fromJSON(object.spentBy)
-                : undefined,
-            token: isSet(object.token)
-                ? Token.fromJSON(object.token)
-                : undefined,
-            plugins: isObject(object.plugins)
-                ? Object.entries(object.plugins).reduce<{
-                      [key: string]: PluginEntry;
-                  }>((acc, [key, value]) => {
-                      acc[key] = PluginEntry.fromJSON(value);
-                      return acc;
-                  }, {})
-                : {},
-        };
-    },
-
-    toJSON(message: TxOutput): unknown {
-        const obj: any = {};
-        if (message.value !== '0') {
-            obj.value = message.value;
-        }
-        if (message.outputScript.length !== 0) {
-            obj.outputScript = base64FromBytes(message.outputScript);
-        }
-        if (message.spentBy !== undefined) {
-            obj.spentBy = SpentBy.toJSON(message.spentBy);
-        }
-        if (message.token !== undefined) {
-            obj.token = Token.toJSON(message.token);
-        }
-        if (message.plugins) {
-            const entries = Object.entries(message.plugins);
-            if (entries.length > 0) {
-                obj.plugins = {};
-                entries.forEach(([k, v]) => {
-                    obj.plugins[k] = PluginEntry.toJSON(v);
-                });
-            }
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<TxOutput>, I>>(base?: I): TxOutput {
-        return TxOutput.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<TxOutput>, I>>(
-        object: I,
-    ): TxOutput {
-        const message = createBaseTxOutput();
-        message.value = object.value ?? '0';
-        message.outputScript = object.outputScript ?? new Uint8Array(0);
-        message.spentBy =
-            object.spentBy !== undefined && object.spentBy !== null
-                ? SpentBy.fromPartial(object.spentBy)
-                : undefined;
-        message.token =
-            object.token !== undefined && object.token !== null
-                ? Token.fromPartial(object.token)
-                : undefined;
-        message.plugins = Object.entries(object.plugins ?? {}).reduce<{
-            [key: string]: PluginEntry;
-        }>((acc, [key, value]) => {
-            if (value !== undefined) {
-                acc[key] = PluginEntry.fromPartial(value);
-            }
-            return acc;
-        }, {});
-        return message;
-    },
-};
-
-function createBaseTxOutput_PluginsEntry(): TxOutput_PluginsEntry {
-    return { key: '', value: undefined };
-}
-
-export const TxOutput_PluginsEntry = {
-    encode(
-        message: TxOutput_PluginsEntry,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.key !== '') {
-            writer.uint32(10).string(message.key);
-        }
-        if (message.value !== undefined) {
-            PluginEntry.encode(
-                message.value,
-                writer.uint32(18).fork(),
-            ).ldelim();
-        }
-        return writer;
-    },
-
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): TxOutput_PluginsEntry {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTxOutput_PluginsEntry();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.key = reader.string();
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.value = PluginEntry.decode(reader, reader.uint32());
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): TxOutput_PluginsEntry {
-        return {
-            key: isSet(object.key) ? globalThis.String(object.key) : '',
-            value: isSet(object.value)
-                ? PluginEntry.fromJSON(object.value)
-                : undefined,
-        };
-    },
-
-    toJSON(message: TxOutput_PluginsEntry): unknown {
-        const obj: any = {};
-        if (message.key !== '') {
-            obj.key = message.key;
-        }
-        if (message.value !== undefined) {
-            obj.value = PluginEntry.toJSON(message.value);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<TxOutput_PluginsEntry>, I>>(
-        base?: I,
-    ): TxOutput_PluginsEntry {
-        return TxOutput_PluginsEntry.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<TxOutput_PluginsEntry>, I>>(
-        object: I,
-    ): TxOutput_PluginsEntry {
-        const message = createBaseTxOutput_PluginsEntry();
-        message.key = object.key ?? '';
-        message.value =
-            object.value !== undefined && object.value !== null
-                ? PluginEntry.fromPartial(object.value)
-                : undefined;
-        return message;
-    },
-};
-
-function createBaseBlockMetadata(): BlockMetadata {
-    return {
-        height: 0,
-        hash: new Uint8Array(0),
-        timestamp: '0',
-        isFinal: false,
-    };
-}
-
-export const BlockMetadata = {
-    encode(
-        message: BlockMetadata,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.height !== 0) {
-            writer.uint32(8).int32(message.height);
-        }
-        if (message.hash.length !== 0) {
-            writer.uint32(18).bytes(message.hash);
-        }
-        if (message.timestamp !== '0') {
-            writer.uint32(24).int64(message.timestamp);
-        }
-        if (message.isFinal === true) {
-            writer.uint32(32).bool(message.isFinal);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): BlockMetadata {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBlockMetadata();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 8) {
-                        break;
-                    }
-
-                    message.height = reader.int32();
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.hash = reader.bytes();
-                    continue;
-                case 3:
-                    if (tag !== 24) {
-                        break;
-                    }
-
-                    message.timestamp = longToString(reader.int64() as Long);
-                    continue;
-                case 4:
-                    if (tag !== 32) {
-                        break;
-                    }
-
-                    message.isFinal = reader.bool();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): BlockMetadata {
-        return {
-            height: isSet(object.height) ? globalThis.Number(object.height) : 0,
-            hash: isSet(object.hash)
-                ? bytesFromBase64(object.hash)
-                : new Uint8Array(0),
-            timestamp: isSet(object.timestamp)
-                ? globalThis.String(object.timestamp)
-                : '0',
-            isFinal: isSet(object.isFinal)
-                ? globalThis.Boolean(object.isFinal)
-                : false,
-        };
-    },
-
-    toJSON(message: BlockMetadata): unknown {
-        const obj: any = {};
-        if (message.height !== 0) {
-            obj.height = Math.round(message.height);
-        }
-        if (message.hash.length !== 0) {
-            obj.hash = base64FromBytes(message.hash);
-        }
-        if (message.timestamp !== '0') {
-            obj.timestamp = message.timestamp;
-        }
-        if (message.isFinal === true) {
-            obj.isFinal = message.isFinal;
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<BlockMetadata>, I>>(
-        base?: I,
-    ): BlockMetadata {
-        return BlockMetadata.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<BlockMetadata>, I>>(
-        object: I,
-    ): BlockMetadata {
-        const message = createBaseBlockMetadata();
-        message.height = object.height ?? 0;
-        message.hash = object.hash ?? new Uint8Array(0);
-        message.timestamp = object.timestamp ?? '0';
-        message.isFinal = object.isFinal ?? false;
-        return message;
-    },
-};
-
-function createBaseTokenType(): TokenType {
-    return { slp: undefined, alp: undefined };
-}
-
-export const TokenType = {
-    encode(
-        message: TokenType,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.slp !== undefined) {
-            writer.uint32(8).int32(message.slp);
-        }
-        if (message.alp !== undefined) {
-            writer.uint32(16).int32(message.alp);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): TokenType {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTokenType();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 8) {
-                        break;
-                    }
-
-                    message.slp = reader.int32() as any;
-                    continue;
-                case 2:
-                    if (tag !== 16) {
-                        break;
-                    }
-
-                    message.alp = reader.int32() as any;
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): TokenType {
-        return {
-            slp: isSet(object.slp)
-                ? slpTokenTypeFromJSON(object.slp)
-                : undefined,
-            alp: isSet(object.alp)
-                ? alpTokenTypeFromJSON(object.alp)
-                : undefined,
-        };
-    },
-
-    toJSON(message: TokenType): unknown {
-        const obj: any = {};
-        if (message.slp !== undefined) {
-            obj.slp = slpTokenTypeToJSON(message.slp);
-        }
-        if (message.alp !== undefined) {
-            obj.alp = alpTokenTypeToJSON(message.alp);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<TokenType>, I>>(base?: I): TokenType {
-        return TokenType.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<TokenType>, I>>(
-        object: I,
-    ): TokenType {
-        const message = createBaseTokenType();
-        message.slp = object.slp ?? undefined;
-        message.alp = object.alp ?? undefined;
-        return message;
-    },
-};
-
-function createBaseTokenInfo(): TokenInfo {
-    return {
-        tokenId: '',
-        tokenType: undefined,
-        genesisInfo: undefined,
-        block: undefined,
-        timeFirstSeen: '0',
-    };
-}
-
-export const TokenInfo = {
-    encode(
-        message: TokenInfo,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.tokenId !== '') {
-            writer.uint32(10).string(message.tokenId);
-        }
-        if (message.tokenType !== undefined) {
-            TokenType.encode(
-                message.tokenType,
-                writer.uint32(18).fork(),
-            ).ldelim();
-        }
-        if (message.genesisInfo !== undefined) {
-            GenesisInfo.encode(
-                message.genesisInfo,
-                writer.uint32(26).fork(),
-            ).ldelim();
-        }
-        if (message.block !== undefined) {
-            BlockMetadata.encode(
-                message.block,
-                writer.uint32(34).fork(),
-            ).ldelim();
-        }
-        if (message.timeFirstSeen !== '0') {
-            writer.uint32(40).int64(message.timeFirstSeen);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): TokenInfo {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTokenInfo();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.tokenId = reader.string();
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.tokenType = TokenType.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    continue;
-                case 3:
-                    if (tag !== 26) {
-                        break;
-                    }
-
-                    message.genesisInfo = GenesisInfo.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    continue;
-                case 4:
-                    if (tag !== 34) {
-                        break;
-                    }
-
-                    message.block = BlockMetadata.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    continue;
-                case 5:
-                    if (tag !== 40) {
-                        break;
-                    }
-
-                    message.timeFirstSeen = longToString(
-                        reader.int64() as Long,
-                    );
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): TokenInfo {
-        return {
-            tokenId: isSet(object.tokenId)
-                ? globalThis.String(object.tokenId)
-                : '',
-            tokenType: isSet(object.tokenType)
-                ? TokenType.fromJSON(object.tokenType)
-                : undefined,
-            genesisInfo: isSet(object.genesisInfo)
-                ? GenesisInfo.fromJSON(object.genesisInfo)
-                : undefined,
-            block: isSet(object.block)
-                ? BlockMetadata.fromJSON(object.block)
-                : undefined,
-            timeFirstSeen: isSet(object.timeFirstSeen)
-                ? globalThis.String(object.timeFirstSeen)
-                : '0',
-        };
-    },
-
-    toJSON(message: TokenInfo): unknown {
-        const obj: any = {};
-        if (message.tokenId !== '') {
-            obj.tokenId = message.tokenId;
-        }
-        if (message.tokenType !== undefined) {
-            obj.tokenType = TokenType.toJSON(message.tokenType);
-        }
-        if (message.genesisInfo !== undefined) {
-            obj.genesisInfo = GenesisInfo.toJSON(message.genesisInfo);
-        }
-        if (message.block !== undefined) {
-            obj.block = BlockMetadata.toJSON(message.block);
-        }
-        if (message.timeFirstSeen !== '0') {
-            obj.timeFirstSeen = message.timeFirstSeen;
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<TokenInfo>, I>>(base?: I): TokenInfo {
-        return TokenInfo.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<TokenInfo>, I>>(
-        object: I,
-    ): TokenInfo {
-        const message = createBaseTokenInfo();
-        message.tokenId = object.tokenId ?? '';
-        message.tokenType =
-            object.tokenType !== undefined && object.tokenType !== null
-                ? TokenType.fromPartial(object.tokenType)
-                : undefined;
-        message.genesisInfo =
-            object.genesisInfo !== undefined && object.genesisInfo !== null
-                ? GenesisInfo.fromPartial(object.genesisInfo)
-                : undefined;
-        message.block =
-            object.block !== undefined && object.block !== null
-                ? BlockMetadata.fromPartial(object.block)
-                : undefined;
-        message.timeFirstSeen = object.timeFirstSeen ?? '0';
-        return message;
-    },
-};
-
-function createBaseTokenEntry(): TokenEntry {
-    return {
-        tokenId: '',
-        tokenType: undefined,
-        txType: 0,
-        groupTokenId: '',
-        isInvalid: false,
-        burnSummary: '',
-        failedColorings: [],
-        actualBurnAmount: '',
-        intentionalBurn: '0',
-        burnsMintBatons: false,
-    };
-}
-
-export const TokenEntry = {
-    encode(
-        message: TokenEntry,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.tokenId !== '') {
-            writer.uint32(10).string(message.tokenId);
-        }
-        if (message.tokenType !== undefined) {
-            TokenType.encode(
-                message.tokenType,
-                writer.uint32(18).fork(),
-            ).ldelim();
-        }
-        if (message.txType !== 0) {
-            writer.uint32(24).int32(message.txType);
-        }
-        if (message.groupTokenId !== '') {
-            writer.uint32(34).string(message.groupTokenId);
-        }
-        if (message.isInvalid === true) {
-            writer.uint32(40).bool(message.isInvalid);
-        }
-        if (message.burnSummary !== '') {
-            writer.uint32(50).string(message.burnSummary);
-        }
-        for (const v of message.failedColorings) {
-            TokenFailedColoring.encode(v!, writer.uint32(58).fork()).ldelim();
-        }
-        if (message.actualBurnAmount !== '') {
-            writer.uint32(66).string(message.actualBurnAmount);
-        }
-        if (message.intentionalBurn !== '0') {
-            writer.uint32(72).uint64(message.intentionalBurn);
-        }
-        if (message.burnsMintBatons === true) {
-            writer.uint32(80).bool(message.burnsMintBatons);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): TokenEntry {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTokenEntry();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.tokenId = reader.string();
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.tokenType = TokenType.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    continue;
-                case 3:
-                    if (tag !== 24) {
-                        break;
-                    }
-
-                    message.txType = reader.int32() as any;
-                    continue;
-                case 4:
-                    if (tag !== 34) {
-                        break;
-                    }
-
-                    message.groupTokenId = reader.string();
-                    continue;
-                case 5:
-                    if (tag !== 40) {
-                        break;
-                    }
-
-                    message.isInvalid = reader.bool();
-                    continue;
-                case 6:
-                    if (tag !== 50) {
-                        break;
-                    }
-
-                    message.burnSummary = reader.string();
-                    continue;
-                case 7:
-                    if (tag !== 58) {
-                        break;
-                    }
-
-                    message.failedColorings.push(
-                        TokenFailedColoring.decode(reader, reader.uint32()),
-                    );
-                    continue;
-                case 8:
-                    if (tag !== 66) {
-                        break;
-                    }
-
-                    message.actualBurnAmount = reader.string();
-                    continue;
-                case 9:
-                    if (tag !== 72) {
-                        break;
-                    }
-
-                    message.intentionalBurn = longToString(
-                        reader.uint64() as Long,
-                    );
-                    continue;
-                case 10:
-                    if (tag !== 80) {
-                        break;
-                    }
-
-                    message.burnsMintBatons = reader.bool();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): TokenEntry {
-        return {
-            tokenId: isSet(object.tokenId)
-                ? globalThis.String(object.tokenId)
-                : '',
-            tokenType: isSet(object.tokenType)
-                ? TokenType.fromJSON(object.tokenType)
-                : undefined,
-            txType: isSet(object.txType)
-                ? tokenTxTypeFromJSON(object.txType)
-                : 0,
-            groupTokenId: isSet(object.groupTokenId)
-                ? globalThis.String(object.groupTokenId)
-                : '',
-            isInvalid: isSet(object.isInvalid)
-                ? globalThis.Boolean(object.isInvalid)
-                : false,
-            burnSummary: isSet(object.burnSummary)
-                ? globalThis.String(object.burnSummary)
-                : '',
-            failedColorings: globalThis.Array.isArray(object?.failedColorings)
-                ? object.failedColorings.map((e: any) =>
-                      TokenFailedColoring.fromJSON(e),
-                  )
-                : [],
-            actualBurnAmount: isSet(object.actualBurnAmount)
-                ? globalThis.String(object.actualBurnAmount)
-                : '',
-            intentionalBurn: isSet(object.intentionalBurn)
-                ? globalThis.String(object.intentionalBurn)
-                : '0',
-            burnsMintBatons: isSet(object.burnsMintBatons)
-                ? globalThis.Boolean(object.burnsMintBatons)
-                : false,
-        };
-    },
-
-    toJSON(message: TokenEntry): unknown {
-        const obj: any = {};
-        if (message.tokenId !== '') {
-            obj.tokenId = message.tokenId;
-        }
-        if (message.tokenType !== undefined) {
-            obj.tokenType = TokenType.toJSON(message.tokenType);
-        }
-        if (message.txType !== 0) {
-            obj.txType = tokenTxTypeToJSON(message.txType);
-        }
-        if (message.groupTokenId !== '') {
-            obj.groupTokenId = message.groupTokenId;
-        }
-        if (message.isInvalid === true) {
-            obj.isInvalid = message.isInvalid;
-        }
-        if (message.burnSummary !== '') {
-            obj.burnSummary = message.burnSummary;
-        }
-        if (message.failedColorings?.length) {
-            obj.failedColorings = message.failedColorings.map(e =>
-                TokenFailedColoring.toJSON(e),
-            );
-        }
-        if (message.actualBurnAmount !== '') {
-            obj.actualBurnAmount = message.actualBurnAmount;
-        }
-        if (message.intentionalBurn !== '0') {
-            obj.intentionalBurn = message.intentionalBurn;
-        }
-        if (message.burnsMintBatons === true) {
-            obj.burnsMintBatons = message.burnsMintBatons;
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<TokenEntry>, I>>(base?: I): TokenEntry {
-        return TokenEntry.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<TokenEntry>, I>>(
-        object: I,
-    ): TokenEntry {
-        const message = createBaseTokenEntry();
-        message.tokenId = object.tokenId ?? '';
-        message.tokenType =
-            object.tokenType !== undefined && object.tokenType !== null
-                ? TokenType.fromPartial(object.tokenType)
-                : undefined;
-        message.txType = object.txType ?? 0;
-        message.groupTokenId = object.groupTokenId ?? '';
-        message.isInvalid = object.isInvalid ?? false;
-        message.burnSummary = object.burnSummary ?? '';
-        message.failedColorings =
-            object.failedColorings?.map(e =>
-                TokenFailedColoring.fromPartial(e),
-            ) || [];
-        message.actualBurnAmount = object.actualBurnAmount ?? '';
-        message.intentionalBurn = object.intentionalBurn ?? '0';
-        message.burnsMintBatons = object.burnsMintBatons ?? false;
-        return message;
-    },
-};
-
-function createBaseGenesisInfo(): GenesisInfo {
-    return {
-        tokenTicker: new Uint8Array(0),
-        tokenName: new Uint8Array(0),
-        url: new Uint8Array(0),
-        hash: new Uint8Array(0),
-        mintVaultScripthash: new Uint8Array(0),
-        data: new Uint8Array(0),
-        authPubkey: new Uint8Array(0),
-        decimals: 0,
-    };
-}
-
-export const GenesisInfo = {
-    encode(
-        message: GenesisInfo,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.tokenTicker.length !== 0) {
-            writer.uint32(10).bytes(message.tokenTicker);
-        }
-        if (message.tokenName.length !== 0) {
-            writer.uint32(18).bytes(message.tokenName);
-        }
-        if (message.url.length !== 0) {
-            writer.uint32(26).bytes(message.url);
-        }
-        if (message.hash.length !== 0) {
-            writer.uint32(34).bytes(message.hash);
-        }
-        if (message.mintVaultScripthash.length !== 0) {
-            writer.uint32(42).bytes(message.mintVaultScripthash);
-        }
-        if (message.data.length !== 0) {
-            writer.uint32(50).bytes(message.data);
-        }
-        if (message.authPubkey.length !== 0) {
-            writer.uint32(58).bytes(message.authPubkey);
-        }
-        if (message.decimals !== 0) {
-            writer.uint32(64).uint32(message.decimals);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): GenesisInfo {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseGenesisInfo();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.tokenTicker = reader.bytes();
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.tokenName = reader.bytes();
-                    continue;
-                case 3:
-                    if (tag !== 26) {
-                        break;
-                    }
-
-                    message.url = reader.bytes();
-                    continue;
-                case 4:
-                    if (tag !== 34) {
-                        break;
-                    }
-
-                    message.hash = reader.bytes();
-                    continue;
-                case 5:
-                    if (tag !== 42) {
-                        break;
-                    }
-
-                    message.mintVaultScripthash = reader.bytes();
-                    continue;
-                case 6:
-                    if (tag !== 50) {
-                        break;
-                    }
-
-                    message.data = reader.bytes();
-                    continue;
-                case 7:
-                    if (tag !== 58) {
-                        break;
-                    }
-
-                    message.authPubkey = reader.bytes();
-                    continue;
-                case 8:
-                    if (tag !== 64) {
-                        break;
-                    }
-
-                    message.decimals = reader.uint32();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): GenesisInfo {
-        return {
-            tokenTicker: isSet(object.tokenTicker)
-                ? bytesFromBase64(object.tokenTicker)
-                : new Uint8Array(0),
-            tokenName: isSet(object.tokenName)
-                ? bytesFromBase64(object.tokenName)
-                : new Uint8Array(0),
-            url: isSet(object.url)
-                ? bytesFromBase64(object.url)
-                : new Uint8Array(0),
-            hash: isSet(object.hash)
-                ? bytesFromBase64(object.hash)
-                : new Uint8Array(0),
-            mintVaultScripthash: isSet(object.mintVaultScripthash)
-                ? bytesFromBase64(object.mintVaultScripthash)
-                : new Uint8Array(0),
-            data: isSet(object.data)
-                ? bytesFromBase64(object.data)
-                : new Uint8Array(0),
-            authPubkey: isSet(object.authPubkey)
-                ? bytesFromBase64(object.authPubkey)
-                : new Uint8Array(0),
-            decimals: isSet(object.decimals)
-                ? globalThis.Number(object.decimals)
-                : 0,
-        };
-    },
-
-    toJSON(message: GenesisInfo): unknown {
-        const obj: any = {};
-        if (message.tokenTicker.length !== 0) {
-            obj.tokenTicker = base64FromBytes(message.tokenTicker);
-        }
-        if (message.tokenName.length !== 0) {
-            obj.tokenName = base64FromBytes(message.tokenName);
-        }
-        if (message.url.length !== 0) {
-            obj.url = base64FromBytes(message.url);
-        }
-        if (message.hash.length !== 0) {
-            obj.hash = base64FromBytes(message.hash);
-        }
-        if (message.mintVaultScripthash.length !== 0) {
-            obj.mintVaultScripthash = base64FromBytes(
-                message.mintVaultScripthash,
-            );
-        }
-        if (message.data.length !== 0) {
-            obj.data = base64FromBytes(message.data);
-        }
-        if (message.authPubkey.length !== 0) {
-            obj.authPubkey = base64FromBytes(message.authPubkey);
-        }
-        if (message.decimals !== 0) {
-            obj.decimals = Math.round(message.decimals);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<GenesisInfo>, I>>(
-        base?: I,
-    ): GenesisInfo {
-        return GenesisInfo.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<GenesisInfo>, I>>(
-        object: I,
-    ): GenesisInfo {
-        const message = createBaseGenesisInfo();
-        message.tokenTicker = object.tokenTicker ?? new Uint8Array(0);
-        message.tokenName = object.tokenName ?? new Uint8Array(0);
-        message.url = object.url ?? new Uint8Array(0);
-        message.hash = object.hash ?? new Uint8Array(0);
-        message.mintVaultScripthash =
-            object.mintVaultScripthash ?? new Uint8Array(0);
-        message.data = object.data ?? new Uint8Array(0);
-        message.authPubkey = object.authPubkey ?? new Uint8Array(0);
-        message.decimals = object.decimals ?? 0;
-        return message;
-    },
-};
-
-function createBaseToken(): Token {
-    return {
-        tokenId: '',
-        tokenType: undefined,
-        entryIdx: 0,
-        amount: '0',
-        isMintBaton: false,
-    };
-}
-
-export const Token = {
-    encode(
-        message: Token,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.tokenId !== '') {
-            writer.uint32(10).string(message.tokenId);
-        }
-        if (message.tokenType !== undefined) {
-            TokenType.encode(
-                message.tokenType,
-                writer.uint32(18).fork(),
-            ).ldelim();
-        }
-        if (message.entryIdx !== 0) {
-            writer.uint32(24).int32(message.entryIdx);
-        }
-        if (message.amount !== '0') {
-            writer.uint32(32).uint64(message.amount);
-        }
-        if (message.isMintBaton === true) {
-            writer.uint32(40).bool(message.isMintBaton);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): Token {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseToken();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.tokenId = reader.string();
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.tokenType = TokenType.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    continue;
-                case 3:
-                    if (tag !== 24) {
-                        break;
-                    }
-
-                    message.entryIdx = reader.int32();
-                    continue;
-                case 4:
-                    if (tag !== 32) {
-                        break;
-                    }
-
-                    message.amount = longToString(reader.uint64() as Long);
-                    continue;
-                case 5:
-                    if (tag !== 40) {
-                        break;
-                    }
-
-                    message.isMintBaton = reader.bool();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): Token {
-        return {
-            tokenId: isSet(object.tokenId)
-                ? globalThis.String(object.tokenId)
-                : '',
-            tokenType: isSet(object.tokenType)
-                ? TokenType.fromJSON(object.tokenType)
-                : undefined,
-            entryIdx: isSet(object.entryIdx)
-                ? globalThis.Number(object.entryIdx)
-                : 0,
-            amount: isSet(object.amount)
-                ? globalThis.String(object.amount)
-                : '0',
-            isMintBaton: isSet(object.isMintBaton)
-                ? globalThis.Boolean(object.isMintBaton)
-                : false,
-        };
-    },
-
-    toJSON(message: Token): unknown {
-        const obj: any = {};
-        if (message.tokenId !== '') {
-            obj.tokenId = message.tokenId;
-        }
-        if (message.tokenType !== undefined) {
-            obj.tokenType = TokenType.toJSON(message.tokenType);
-        }
-        if (message.entryIdx !== 0) {
-            obj.entryIdx = Math.round(message.entryIdx);
-        }
-        if (message.amount !== '0') {
-            obj.amount = message.amount;
-        }
-        if (message.isMintBaton === true) {
-            obj.isMintBaton = message.isMintBaton;
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<Token>, I>>(base?: I): Token {
-        return Token.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<Token>, I>>(object: I): Token {
-        const message = createBaseToken();
-        message.tokenId = object.tokenId ?? '';
-        message.tokenType =
-            object.tokenType !== undefined && object.tokenType !== null
-                ? TokenType.fromPartial(object.tokenType)
-                : undefined;
-        message.entryIdx = object.entryIdx ?? 0;
-        message.amount = object.amount ?? '0';
-        message.isMintBaton = object.isMintBaton ?? false;
-        return message;
-    },
-};
-
-function createBaseTokenFailedParsing(): TokenFailedParsing {
-    return { pushdataIdx: 0, bytes: new Uint8Array(0), error: '' };
-}
-
-export const TokenFailedParsing = {
-    encode(
-        message: TokenFailedParsing,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.pushdataIdx !== 0) {
-            writer.uint32(8).int32(message.pushdataIdx);
-        }
-        if (message.bytes.length !== 0) {
-            writer.uint32(18).bytes(message.bytes);
-        }
-        if (message.error !== '') {
-            writer.uint32(26).string(message.error);
-        }
-        return writer;
-    },
-
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): TokenFailedParsing {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTokenFailedParsing();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 8) {
-                        break;
-                    }
-
-                    message.pushdataIdx = reader.int32();
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.bytes = reader.bytes();
-                    continue;
-                case 3:
-                    if (tag !== 26) {
-                        break;
-                    }
-
-                    message.error = reader.string();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): TokenFailedParsing {
-        return {
-            pushdataIdx: isSet(object.pushdataIdx)
-                ? globalThis.Number(object.pushdataIdx)
-                : 0,
-            bytes: isSet(object.bytes)
-                ? bytesFromBase64(object.bytes)
-                : new Uint8Array(0),
-            error: isSet(object.error) ? globalThis.String(object.error) : '',
-        };
-    },
-
-    toJSON(message: TokenFailedParsing): unknown {
-        const obj: any = {};
-        if (message.pushdataIdx !== 0) {
-            obj.pushdataIdx = Math.round(message.pushdataIdx);
-        }
-        if (message.bytes.length !== 0) {
-            obj.bytes = base64FromBytes(message.bytes);
-        }
-        if (message.error !== '') {
-            obj.error = message.error;
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<TokenFailedParsing>, I>>(
-        base?: I,
-    ): TokenFailedParsing {
-        return TokenFailedParsing.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<TokenFailedParsing>, I>>(
-        object: I,
-    ): TokenFailedParsing {
-        const message = createBaseTokenFailedParsing();
-        message.pushdataIdx = object.pushdataIdx ?? 0;
-        message.bytes = object.bytes ?? new Uint8Array(0);
-        message.error = object.error ?? '';
-        return message;
-    },
-};
-
-function createBaseTokenFailedColoring(): TokenFailedColoring {
-    return { pushdataIdx: 0, error: '' };
-}
-
-export const TokenFailedColoring = {
-    encode(
-        message: TokenFailedColoring,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.pushdataIdx !== 0) {
-            writer.uint32(8).int32(message.pushdataIdx);
-        }
-        if (message.error !== '') {
-            writer.uint32(26).string(message.error);
-        }
-        return writer;
-    },
-
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): TokenFailedColoring {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTokenFailedColoring();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 8) {
-                        break;
-                    }
-
-                    message.pushdataIdx = reader.int32();
-                    continue;
-                case 3:
-                    if (tag !== 26) {
-                        break;
-                    }
-
-                    message.error = reader.string();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): TokenFailedColoring {
-        return {
-            pushdataIdx: isSet(object.pushdataIdx)
-                ? globalThis.Number(object.pushdataIdx)
-                : 0,
-            error: isSet(object.error) ? globalThis.String(object.error) : '',
-        };
-    },
-
-    toJSON(message: TokenFailedColoring): unknown {
-        const obj: any = {};
-        if (message.pushdataIdx !== 0) {
-            obj.pushdataIdx = Math.round(message.pushdataIdx);
-        }
-        if (message.error !== '') {
-            obj.error = message.error;
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<TokenFailedColoring>, I>>(
-        base?: I,
-    ): TokenFailedColoring {
-        return TokenFailedColoring.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<TokenFailedColoring>, I>>(
-        object: I,
-    ): TokenFailedColoring {
-        const message = createBaseTokenFailedColoring();
-        message.pushdataIdx = object.pushdataIdx ?? 0;
-        message.error = object.error ?? '';
-        return message;
-    },
-};
-
-function createBasePluginEntry(): PluginEntry {
-    return { groups: [], data: [] };
-}
-
-export const PluginEntry = {
-    encode(
-        message: PluginEntry,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        for (const v of message.groups) {
-            writer.uint32(10).bytes(v!);
-        }
-        for (const v of message.data) {
-            writer.uint32(18).bytes(v!);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): PluginEntry {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBasePluginEntry();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.groups.push(reader.bytes());
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.data.push(reader.bytes());
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): PluginEntry {
-        return {
-            groups: globalThis.Array.isArray(object?.groups)
-                ? object.groups.map((e: any) => bytesFromBase64(e))
-                : [],
-            data: globalThis.Array.isArray(object?.data)
-                ? object.data.map((e: any) => bytesFromBase64(e))
-                : [],
-        };
-    },
-
-    toJSON(message: PluginEntry): unknown {
-        const obj: any = {};
-        if (message.groups?.length) {
-            obj.groups = message.groups.map(e => base64FromBytes(e));
-        }
-        if (message.data?.length) {
-            obj.data = message.data.map(e => base64FromBytes(e));
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<PluginEntry>, I>>(
-        base?: I,
-    ): PluginEntry {
-        return PluginEntry.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<PluginEntry>, I>>(
-        object: I,
-    ): PluginEntry {
-        const message = createBasePluginEntry();
-        message.groups = object.groups?.map(e => e) || [];
-        message.data = object.data?.map(e => e) || [];
-        return message;
-    },
-};
-
-function createBasePluginGroup(): PluginGroup {
-    return { group: new Uint8Array(0) };
-}
-
-export const PluginGroup = {
-    encode(
-        message: PluginGroup,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.group.length !== 0) {
-            writer.uint32(10).bytes(message.group);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): PluginGroup {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBasePluginGroup();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.group = reader.bytes();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): PluginGroup {
-        return {
-            group: isSet(object.group)
-                ? bytesFromBase64(object.group)
-                : new Uint8Array(0),
-        };
-    },
-
-    toJSON(message: PluginGroup): unknown {
-        const obj: any = {};
-        if (message.group.length !== 0) {
-            obj.group = base64FromBytes(message.group);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<PluginGroup>, I>>(
-        base?: I,
-    ): PluginGroup {
-        return PluginGroup.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<PluginGroup>, I>>(
-        object: I,
-    ): PluginGroup {
-        const message = createBasePluginGroup();
-        message.group = object.group ?? new Uint8Array(0);
-        return message;
-    },
-};
-
-function createBasePluginGroups(): PluginGroups {
-    return { groups: [], nextStart: new Uint8Array(0) };
-}
-
-export const PluginGroups = {
-    encode(
-        message: PluginGroups,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        for (const v of message.groups) {
-            PluginGroup.encode(v!, writer.uint32(10).fork()).ldelim();
-        }
-        if (message.nextStart.length !== 0) {
-            writer.uint32(18).bytes(message.nextStart);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): PluginGroups {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBasePluginGroups();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.groups.push(
-                        PluginGroup.decode(reader, reader.uint32()),
-                    );
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.nextStart = reader.bytes();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): PluginGroups {
-        return {
-            groups: globalThis.Array.isArray(object?.groups)
-                ? object.groups.map((e: any) => PluginGroup.fromJSON(e))
-                : [],
-            nextStart: isSet(object.nextStart)
-                ? bytesFromBase64(object.nextStart)
-                : new Uint8Array(0),
-        };
-    },
-
-    toJSON(message: PluginGroups): unknown {
-        const obj: any = {};
-        if (message.groups?.length) {
-            obj.groups = message.groups.map(e => PluginGroup.toJSON(e));
-        }
-        if (message.nextStart.length !== 0) {
-            obj.nextStart = base64FromBytes(message.nextStart);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<PluginGroups>, I>>(
-        base?: I,
-    ): PluginGroups {
-        return PluginGroups.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<PluginGroups>, I>>(
-        object: I,
-    ): PluginGroups {
-        const message = createBasePluginGroups();
-        message.groups =
-            object.groups?.map(e => PluginGroup.fromPartial(e)) || [];
-        message.nextStart = object.nextStart ?? new Uint8Array(0);
-        return message;
-    },
-};
-
-function createBaseTxHistoryPage(): TxHistoryPage {
-    return { txs: [], numPages: 0, numTxs: 0 };
-}
-
-export const TxHistoryPage = {
-    encode(
-        message: TxHistoryPage,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        for (const v of message.txs) {
-            Tx.encode(v!, writer.uint32(10).fork()).ldelim();
-        }
-        if (message.numPages !== 0) {
-            writer.uint32(16).uint32(message.numPages);
-        }
-        if (message.numTxs !== 0) {
-            writer.uint32(24).uint32(message.numTxs);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): TxHistoryPage {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseTxHistoryPage();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.txs.push(Tx.decode(reader, reader.uint32()));
-                    continue;
-                case 2:
-                    if (tag !== 16) {
-                        break;
-                    }
-
-                    message.numPages = reader.uint32();
-                    continue;
-                case 3:
-                    if (tag !== 24) {
-                        break;
-                    }
-
-                    message.numTxs = reader.uint32();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): TxHistoryPage {
-        return {
-            txs: globalThis.Array.isArray(object?.txs)
-                ? object.txs.map((e: any) => Tx.fromJSON(e))
-                : [],
-            numPages: isSet(object.numPages)
-                ? globalThis.Number(object.numPages)
-                : 0,
-            numTxs: isSet(object.numTxs) ? globalThis.Number(object.numTxs) : 0,
-        };
-    },
-
-    toJSON(message: TxHistoryPage): unknown {
-        const obj: any = {};
-        if (message.txs?.length) {
-            obj.txs = message.txs.map(e => Tx.toJSON(e));
-        }
-        if (message.numPages !== 0) {
-            obj.numPages = Math.round(message.numPages);
-        }
-        if (message.numTxs !== 0) {
-            obj.numTxs = Math.round(message.numTxs);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<TxHistoryPage>, I>>(
-        base?: I,
-    ): TxHistoryPage {
-        return TxHistoryPage.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<TxHistoryPage>, I>>(
-        object: I,
-    ): TxHistoryPage {
-        const message = createBaseTxHistoryPage();
-        message.txs = object.txs?.map(e => Tx.fromPartial(e)) || [];
-        message.numPages = object.numPages ?? 0;
-        message.numTxs = object.numTxs ?? 0;
-        return message;
-    },
-};
-
-function createBaseScriptUtxos(): ScriptUtxos {
-    return { script: new Uint8Array(0), utxos: [] };
-}
-
-export const ScriptUtxos = {
-    encode(
-        message: ScriptUtxos,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.script.length !== 0) {
-            writer.uint32(10).bytes(message.script);
-        }
-        for (const v of message.utxos) {
-            ScriptUtxo.encode(v!, writer.uint32(18).fork()).ldelim();
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): ScriptUtxos {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseScriptUtxos();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.script = reader.bytes();
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.utxos.push(
-                        ScriptUtxo.decode(reader, reader.uint32()),
-                    );
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): ScriptUtxos {
-        return {
-            script: isSet(object.script)
-                ? bytesFromBase64(object.script)
-                : new Uint8Array(0),
-            utxos: globalThis.Array.isArray(object?.utxos)
-                ? object.utxos.map((e: any) => ScriptUtxo.fromJSON(e))
-                : [],
-        };
-    },
-
-    toJSON(message: ScriptUtxos): unknown {
-        const obj: any = {};
-        if (message.script.length !== 0) {
-            obj.script = base64FromBytes(message.script);
-        }
-        if (message.utxos?.length) {
-            obj.utxos = message.utxos.map(e => ScriptUtxo.toJSON(e));
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<ScriptUtxos>, I>>(
-        base?: I,
-    ): ScriptUtxos {
-        return ScriptUtxos.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<ScriptUtxos>, I>>(
-        object: I,
-    ): ScriptUtxos {
-        const message = createBaseScriptUtxos();
-        message.script = object.script ?? new Uint8Array(0);
-        message.utxos = object.utxos?.map(e => ScriptUtxo.fromPartial(e)) || [];
-        return message;
-    },
-};
-
-function createBaseUtxos(): Utxos {
-    return { utxos: [] };
-}
-
-export const Utxos = {
-    encode(
-        message: Utxos,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        for (const v of message.utxos) {
-            Utxo.encode(v!, writer.uint32(10).fork()).ldelim();
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): Utxos {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseUtxos();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.utxos.push(Utxo.decode(reader, reader.uint32()));
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): Utxos {
-        return {
-            utxos: globalThis.Array.isArray(object?.utxos)
-                ? object.utxos.map((e: any) => Utxo.fromJSON(e))
-                : [],
-        };
-    },
-
-    toJSON(message: Utxos): unknown {
-        const obj: any = {};
-        if (message.utxos?.length) {
-            obj.utxos = message.utxos.map(e => Utxo.toJSON(e));
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<Utxos>, I>>(base?: I): Utxos {
-        return Utxos.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<Utxos>, I>>(object: I): Utxos {
-        const message = createBaseUtxos();
-        message.utxos = object.utxos?.map(e => Utxo.fromPartial(e)) || [];
-        return message;
-    },
-};
-
-function createBaseBroadcastTxRequest(): BroadcastTxRequest {
-    return { rawTx: new Uint8Array(0), skipTokenChecks: false };
-}
-
-export const BroadcastTxRequest = {
-    encode(
-        message: BroadcastTxRequest,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.rawTx.length !== 0) {
-            writer.uint32(10).bytes(message.rawTx);
-        }
-        if (message.skipTokenChecks === true) {
-            writer.uint32(16).bool(message.skipTokenChecks);
-        }
-        return writer;
-    },
-
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): BroadcastTxRequest {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBroadcastTxRequest();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.rawTx = reader.bytes();
-                    continue;
-                case 2:
-                    if (tag !== 16) {
-                        break;
-                    }
-
-                    message.skipTokenChecks = reader.bool();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): BroadcastTxRequest {
-        return {
-            rawTx: isSet(object.rawTx)
-                ? bytesFromBase64(object.rawTx)
-                : new Uint8Array(0),
-            skipTokenChecks: isSet(object.skipTokenChecks)
-                ? globalThis.Boolean(object.skipTokenChecks)
-                : false,
-        };
-    },
-
-    toJSON(message: BroadcastTxRequest): unknown {
-        const obj: any = {};
-        if (message.rawTx.length !== 0) {
-            obj.rawTx = base64FromBytes(message.rawTx);
-        }
-        if (message.skipTokenChecks === true) {
-            obj.skipTokenChecks = message.skipTokenChecks;
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<BroadcastTxRequest>, I>>(
-        base?: I,
-    ): BroadcastTxRequest {
-        return BroadcastTxRequest.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<BroadcastTxRequest>, I>>(
-        object: I,
-    ): BroadcastTxRequest {
-        const message = createBaseBroadcastTxRequest();
-        message.rawTx = object.rawTx ?? new Uint8Array(0);
-        message.skipTokenChecks = object.skipTokenChecks ?? false;
-        return message;
-    },
-};
-
-function createBaseBroadcastTxResponse(): BroadcastTxResponse {
-    return { txid: new Uint8Array(0) };
-}
-
-export const BroadcastTxResponse = {
-    encode(
-        message: BroadcastTxResponse,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.txid.length !== 0) {
-            writer.uint32(10).bytes(message.txid);
-        }
-        return writer;
-    },
-
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): BroadcastTxResponse {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBroadcastTxResponse();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.txid = reader.bytes();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): BroadcastTxResponse {
-        return {
-            txid: isSet(object.txid)
-                ? bytesFromBase64(object.txid)
-                : new Uint8Array(0),
-        };
-    },
-
-    toJSON(message: BroadcastTxResponse): unknown {
-        const obj: any = {};
-        if (message.txid.length !== 0) {
-            obj.txid = base64FromBytes(message.txid);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<BroadcastTxResponse>, I>>(
-        base?: I,
-    ): BroadcastTxResponse {
-        return BroadcastTxResponse.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<BroadcastTxResponse>, I>>(
-        object: I,
-    ): BroadcastTxResponse {
-        const message = createBaseBroadcastTxResponse();
-        message.txid = object.txid ?? new Uint8Array(0);
-        return message;
-    },
-};
-
-function createBaseBroadcastTxsRequest(): BroadcastTxsRequest {
-    return { rawTxs: [], skipTokenChecks: false };
-}
-
-export const BroadcastTxsRequest = {
-    encode(
-        message: BroadcastTxsRequest,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        for (const v of message.rawTxs) {
-            writer.uint32(10).bytes(v!);
-        }
-        if (message.skipTokenChecks === true) {
-            writer.uint32(16).bool(message.skipTokenChecks);
-        }
-        return writer;
-    },
-
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): BroadcastTxsRequest {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBroadcastTxsRequest();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.rawTxs.push(reader.bytes());
-                    continue;
-                case 2:
-                    if (tag !== 16) {
-                        break;
-                    }
-
-                    message.skipTokenChecks = reader.bool();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): BroadcastTxsRequest {
-        return {
-            rawTxs: globalThis.Array.isArray(object?.rawTxs)
-                ? object.rawTxs.map((e: any) => bytesFromBase64(e))
-                : [],
-            skipTokenChecks: isSet(object.skipTokenChecks)
-                ? globalThis.Boolean(object.skipTokenChecks)
-                : false,
-        };
-    },
-
-    toJSON(message: BroadcastTxsRequest): unknown {
-        const obj: any = {};
-        if (message.rawTxs?.length) {
-            obj.rawTxs = message.rawTxs.map(e => base64FromBytes(e));
-        }
-        if (message.skipTokenChecks === true) {
-            obj.skipTokenChecks = message.skipTokenChecks;
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<BroadcastTxsRequest>, I>>(
-        base?: I,
-    ): BroadcastTxsRequest {
-        return BroadcastTxsRequest.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<BroadcastTxsRequest>, I>>(
-        object: I,
-    ): BroadcastTxsRequest {
-        const message = createBaseBroadcastTxsRequest();
-        message.rawTxs = object.rawTxs?.map(e => e) || [];
-        message.skipTokenChecks = object.skipTokenChecks ?? false;
-        return message;
-    },
-};
-
-function createBaseBroadcastTxsResponse(): BroadcastTxsResponse {
-    return { txids: [] };
-}
-
-export const BroadcastTxsResponse = {
-    encode(
-        message: BroadcastTxsResponse,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        for (const v of message.txids) {
-            writer.uint32(10).bytes(v!);
-        }
-        return writer;
-    },
-
-    decode(
-        input: _m0.Reader | Uint8Array,
-        length?: number,
-    ): BroadcastTxsResponse {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseBroadcastTxsResponse();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.txids.push(reader.bytes());
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): BroadcastTxsResponse {
-        return {
-            txids: globalThis.Array.isArray(object?.txids)
-                ? object.txids.map((e: any) => bytesFromBase64(e))
-                : [],
-        };
-    },
-
-    toJSON(message: BroadcastTxsResponse): unknown {
-        const obj: any = {};
-        if (message.txids?.length) {
-            obj.txids = message.txids.map(e => base64FromBytes(e));
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<BroadcastTxsResponse>, I>>(
-        base?: I,
-    ): BroadcastTxsResponse {
-        return BroadcastTxsResponse.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<BroadcastTxsResponse>, I>>(
-        object: I,
-    ): BroadcastTxsResponse {
-        const message = createBaseBroadcastTxsResponse();
-        message.txids = object.txids?.map(e => e) || [];
-        return message;
-    },
-};
-
-function createBaseRawTx(): RawTx {
-    return { rawTx: new Uint8Array(0) };
-}
-
-export const RawTx = {
-    encode(
-        message: RawTx,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.rawTx.length !== 0) {
-            writer.uint32(10).bytes(message.rawTx);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): RawTx {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseRawTx();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.rawTx = reader.bytes();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): RawTx {
-        return {
-            rawTx: isSet(object.rawTx)
-                ? bytesFromBase64(object.rawTx)
-                : new Uint8Array(0),
-        };
-    },
-
-    toJSON(message: RawTx): unknown {
-        const obj: any = {};
-        if (message.rawTx.length !== 0) {
-            obj.rawTx = base64FromBytes(message.rawTx);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<RawTx>, I>>(base?: I): RawTx {
-        return RawTx.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<RawTx>, I>>(object: I): RawTx {
-        const message = createBaseRawTx();
-        message.rawTx = object.rawTx ?? new Uint8Array(0);
-        return message;
-    },
-};
-
-function createBaseWsSub(): WsSub {
-    return {
-        isUnsub: false,
-        blocks: undefined,
-        script: undefined,
-        tokenId: undefined,
-        lokadId: undefined,
-    };
-}
-
-export const WsSub = {
-    encode(
-        message: WsSub,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.isUnsub === true) {
-            writer.uint32(8).bool(message.isUnsub);
-        }
-        if (message.blocks !== undefined) {
-            WsSubBlocks.encode(
-                message.blocks,
-                writer.uint32(18).fork(),
-            ).ldelim();
-        }
-        if (message.script !== undefined) {
-            WsSubScript.encode(
-                message.script,
-                writer.uint32(26).fork(),
-            ).ldelim();
-        }
-        if (message.tokenId !== undefined) {
-            WsSubTokenId.encode(
-                message.tokenId,
-                writer.uint32(34).fork(),
-            ).ldelim();
-        }
-        if (message.lokadId !== undefined) {
-            WsSubLokadId.encode(
-                message.lokadId,
-                writer.uint32(42).fork(),
-            ).ldelim();
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): WsSub {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseWsSub();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 8) {
-                        break;
-                    }
-
-                    message.isUnsub = reader.bool();
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.blocks = WsSubBlocks.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    continue;
-                case 3:
-                    if (tag !== 26) {
-                        break;
-                    }
-
-                    message.script = WsSubScript.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    continue;
-                case 4:
-                    if (tag !== 34) {
-                        break;
-                    }
-
-                    message.tokenId = WsSubTokenId.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    continue;
-                case 5:
-                    if (tag !== 42) {
-                        break;
-                    }
-
-                    message.lokadId = WsSubLokadId.decode(
-                        reader,
-                        reader.uint32(),
-                    );
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): WsSub {
-        return {
-            isUnsub: isSet(object.isUnsub)
-                ? globalThis.Boolean(object.isUnsub)
-                : false,
-            blocks: isSet(object.blocks)
-                ? WsSubBlocks.fromJSON(object.blocks)
-                : undefined,
-            script: isSet(object.script)
-                ? WsSubScript.fromJSON(object.script)
-                : undefined,
-            tokenId: isSet(object.tokenId)
-                ? WsSubTokenId.fromJSON(object.tokenId)
-                : undefined,
-            lokadId: isSet(object.lokadId)
-                ? WsSubLokadId.fromJSON(object.lokadId)
-                : undefined,
-        };
-    },
-
-    toJSON(message: WsSub): unknown {
-        const obj: any = {};
-        if (message.isUnsub === true) {
-            obj.isUnsub = message.isUnsub;
-        }
-        if (message.blocks !== undefined) {
-            obj.blocks = WsSubBlocks.toJSON(message.blocks);
-        }
-        if (message.script !== undefined) {
-            obj.script = WsSubScript.toJSON(message.script);
-        }
-        if (message.tokenId !== undefined) {
-            obj.tokenId = WsSubTokenId.toJSON(message.tokenId);
-        }
-        if (message.lokadId !== undefined) {
-            obj.lokadId = WsSubLokadId.toJSON(message.lokadId);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<WsSub>, I>>(base?: I): WsSub {
-        return WsSub.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<WsSub>, I>>(object: I): WsSub {
-        const message = createBaseWsSub();
-        message.isUnsub = object.isUnsub ?? false;
-        message.blocks =
-            object.blocks !== undefined && object.blocks !== null
-                ? WsSubBlocks.fromPartial(object.blocks)
-                : undefined;
-        message.script =
-            object.script !== undefined && object.script !== null
-                ? WsSubScript.fromPartial(object.script)
-                : undefined;
-        message.tokenId =
-            object.tokenId !== undefined && object.tokenId !== null
-                ? WsSubTokenId.fromPartial(object.tokenId)
-                : undefined;
-        message.lokadId =
-            object.lokadId !== undefined && object.lokadId !== null
-                ? WsSubLokadId.fromPartial(object.lokadId)
-                : undefined;
-        return message;
-    },
-};
-
-function createBaseWsSubBlocks(): WsSubBlocks {
-    return {};
-}
-
-export const WsSubBlocks = {
-    encode(
-        _: WsSubBlocks,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): WsSubBlocks {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseWsSubBlocks();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(_: any): WsSubBlocks {
-        return {};
-    },
-
-    toJSON(_: WsSubBlocks): unknown {
-        const obj: any = {};
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<WsSubBlocks>, I>>(
-        base?: I,
-    ): WsSubBlocks {
-        return WsSubBlocks.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<WsSubBlocks>, I>>(
-        _: I,
-    ): WsSubBlocks {
-        const message = createBaseWsSubBlocks();
-        return message;
-    },
-};
-
-function createBaseWsSubScript(): WsSubScript {
-    return { scriptType: '', payload: new Uint8Array(0) };
-}
-
-export const WsSubScript = {
-    encode(
-        message: WsSubScript,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.scriptType !== '') {
-            writer.uint32(10).string(message.scriptType);
-        }
-        if (message.payload.length !== 0) {
-            writer.uint32(18).bytes(message.payload);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): WsSubScript {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseWsSubScript();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.scriptType = reader.string();
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.payload = reader.bytes();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): WsSubScript {
-        return {
-            scriptType: isSet(object.scriptType)
-                ? globalThis.String(object.scriptType)
-                : '',
-            payload: isSet(object.payload)
-                ? bytesFromBase64(object.payload)
-                : new Uint8Array(0),
-        };
-    },
-
-    toJSON(message: WsSubScript): unknown {
-        const obj: any = {};
-        if (message.scriptType !== '') {
-            obj.scriptType = message.scriptType;
-        }
-        if (message.payload.length !== 0) {
-            obj.payload = base64FromBytes(message.payload);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<WsSubScript>, I>>(
-        base?: I,
-    ): WsSubScript {
-        return WsSubScript.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<WsSubScript>, I>>(
-        object: I,
-    ): WsSubScript {
-        const message = createBaseWsSubScript();
-        message.scriptType = object.scriptType ?? '';
-        message.payload = object.payload ?? new Uint8Array(0);
-        return message;
-    },
-};
-
-function createBaseWsSubTokenId(): WsSubTokenId {
-    return { tokenId: '' };
-}
-
-export const WsSubTokenId = {
-    encode(
-        message: WsSubTokenId,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.tokenId !== '') {
-            writer.uint32(10).string(message.tokenId);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): WsSubTokenId {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseWsSubTokenId();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.tokenId = reader.string();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): WsSubTokenId {
-        return {
-            tokenId: isSet(object.tokenId)
-                ? globalThis.String(object.tokenId)
-                : '',
-        };
-    },
-
-    toJSON(message: WsSubTokenId): unknown {
-        const obj: any = {};
-        if (message.tokenId !== '') {
-            obj.tokenId = message.tokenId;
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<WsSubTokenId>, I>>(
-        base?: I,
-    ): WsSubTokenId {
-        return WsSubTokenId.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<WsSubTokenId>, I>>(
-        object: I,
-    ): WsSubTokenId {
-        const message = createBaseWsSubTokenId();
-        message.tokenId = object.tokenId ?? '';
-        return message;
-    },
-};
-
-function createBaseWsSubLokadId(): WsSubLokadId {
-    return { lokadId: new Uint8Array(0) };
-}
-
-export const WsSubLokadId = {
-    encode(
-        message: WsSubLokadId,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.lokadId.length !== 0) {
-            writer.uint32(10).bytes(message.lokadId);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): WsSubLokadId {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseWsSubLokadId();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.lokadId = reader.bytes();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): WsSubLokadId {
-        return {
-            lokadId: isSet(object.lokadId)
-                ? bytesFromBase64(object.lokadId)
-                : new Uint8Array(0),
-        };
-    },
-
-    toJSON(message: WsSubLokadId): unknown {
-        const obj: any = {};
-        if (message.lokadId.length !== 0) {
-            obj.lokadId = base64FromBytes(message.lokadId);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<WsSubLokadId>, I>>(
-        base?: I,
-    ): WsSubLokadId {
-        return WsSubLokadId.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<WsSubLokadId>, I>>(
-        object: I,
-    ): WsSubLokadId {
-        const message = createBaseWsSubLokadId();
-        message.lokadId = object.lokadId ?? new Uint8Array(0);
-        return message;
-    },
-};
-
-function createBaseWsMsg(): WsMsg {
-    return { error: undefined, block: undefined, tx: undefined };
-}
-
-export const WsMsg = {
-    encode(
-        message: WsMsg,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.error !== undefined) {
-            Error.encode(message.error, writer.uint32(10).fork()).ldelim();
-        }
-        if (message.block !== undefined) {
-            MsgBlock.encode(message.block, writer.uint32(18).fork()).ldelim();
-        }
-        if (message.tx !== undefined) {
-            MsgTx.encode(message.tx, writer.uint32(26).fork()).ldelim();
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): WsMsg {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseWsMsg();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 10) {
-                        break;
-                    }
-
-                    message.error = Error.decode(reader, reader.uint32());
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.block = MsgBlock.decode(reader, reader.uint32());
-                    continue;
-                case 3:
-                    if (tag !== 26) {
-                        break;
-                    }
-
-                    message.tx = MsgTx.decode(reader, reader.uint32());
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): WsMsg {
-        return {
-            error: isSet(object.error)
-                ? Error.fromJSON(object.error)
-                : undefined,
-            block: isSet(object.block)
-                ? MsgBlock.fromJSON(object.block)
-                : undefined,
-            tx: isSet(object.tx) ? MsgTx.fromJSON(object.tx) : undefined,
-        };
-    },
-
-    toJSON(message: WsMsg): unknown {
-        const obj: any = {};
-        if (message.error !== undefined) {
-            obj.error = Error.toJSON(message.error);
-        }
-        if (message.block !== undefined) {
-            obj.block = MsgBlock.toJSON(message.block);
-        }
-        if (message.tx !== undefined) {
-            obj.tx = MsgTx.toJSON(message.tx);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<WsMsg>, I>>(base?: I): WsMsg {
-        return WsMsg.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<WsMsg>, I>>(object: I): WsMsg {
-        const message = createBaseWsMsg();
-        message.error =
-            object.error !== undefined && object.error !== null
-                ? Error.fromPartial(object.error)
-                : undefined;
-        message.block =
-            object.block !== undefined && object.block !== null
-                ? MsgBlock.fromPartial(object.block)
-                : undefined;
-        message.tx =
-            object.tx !== undefined && object.tx !== null
-                ? MsgTx.fromPartial(object.tx)
-                : undefined;
-        return message;
-    },
-};
-
-function createBaseMsgBlock(): MsgBlock {
-    return { msgType: 0, blockHash: new Uint8Array(0), blockHeight: 0 };
-}
-
-export const MsgBlock = {
-    encode(
-        message: MsgBlock,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.msgType !== 0) {
-            writer.uint32(8).int32(message.msgType);
-        }
-        if (message.blockHash.length !== 0) {
-            writer.uint32(18).bytes(message.blockHash);
-        }
-        if (message.blockHeight !== 0) {
-            writer.uint32(24).int32(message.blockHeight);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): MsgBlock {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseMsgBlock();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 8) {
-                        break;
-                    }
-
-                    message.msgType = reader.int32() as any;
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.blockHash = reader.bytes();
-                    continue;
-                case 3:
-                    if (tag !== 24) {
-                        break;
-                    }
-
-                    message.blockHeight = reader.int32();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): MsgBlock {
-        return {
-            msgType: isSet(object.msgType)
-                ? blockMsgTypeFromJSON(object.msgType)
-                : 0,
-            blockHash: isSet(object.blockHash)
-                ? bytesFromBase64(object.blockHash)
-                : new Uint8Array(0),
-            blockHeight: isSet(object.blockHeight)
-                ? globalThis.Number(object.blockHeight)
-                : 0,
-        };
-    },
-
-    toJSON(message: MsgBlock): unknown {
-        const obj: any = {};
-        if (message.msgType !== 0) {
-            obj.msgType = blockMsgTypeToJSON(message.msgType);
-        }
-        if (message.blockHash.length !== 0) {
-            obj.blockHash = base64FromBytes(message.blockHash);
-        }
-        if (message.blockHeight !== 0) {
-            obj.blockHeight = Math.round(message.blockHeight);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<MsgBlock>, I>>(base?: I): MsgBlock {
-        return MsgBlock.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<MsgBlock>, I>>(
-        object: I,
-    ): MsgBlock {
-        const message = createBaseMsgBlock();
-        message.msgType = object.msgType ?? 0;
-        message.blockHash = object.blockHash ?? new Uint8Array(0);
-        message.blockHeight = object.blockHeight ?? 0;
-        return message;
-    },
-};
-
-function createBaseMsgTx(): MsgTx {
-    return { msgType: 0, txid: new Uint8Array(0) };
-}
-
-export const MsgTx = {
-    encode(
-        message: MsgTx,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.msgType !== 0) {
-            writer.uint32(8).int32(message.msgType);
-        }
-        if (message.txid.length !== 0) {
-            writer.uint32(18).bytes(message.txid);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): MsgTx {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseMsgTx();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 1:
-                    if (tag !== 8) {
-                        break;
-                    }
-
-                    message.msgType = reader.int32() as any;
-                    continue;
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.txid = reader.bytes();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): MsgTx {
-        return {
-            msgType: isSet(object.msgType)
-                ? txMsgTypeFromJSON(object.msgType)
-                : 0,
-            txid: isSet(object.txid)
-                ? bytesFromBase64(object.txid)
-                : new Uint8Array(0),
-        };
-    },
-
-    toJSON(message: MsgTx): unknown {
-        const obj: any = {};
-        if (message.msgType !== 0) {
-            obj.msgType = txMsgTypeToJSON(message.msgType);
-        }
-        if (message.txid.length !== 0) {
-            obj.txid = base64FromBytes(message.txid);
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<MsgTx>, I>>(base?: I): MsgTx {
-        return MsgTx.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<MsgTx>, I>>(object: I): MsgTx {
-        const message = createBaseMsgTx();
-        message.msgType = object.msgType ?? 0;
-        message.txid = object.txid ?? new Uint8Array(0);
-        return message;
-    },
-};
-
-function createBaseEmpty(): Empty {
-    return {};
-}
-
-export const Empty = {
-    encode(_: Empty, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): Empty {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseEmpty();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(_: any): Empty {
-        return {};
-    },
-
-    toJSON(_: Empty): unknown {
-        const obj: any = {};
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<Empty>, I>>(base?: I): Empty {
-        return Empty.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<Empty>, I>>(_: I): Empty {
-        const message = createBaseEmpty();
-        return message;
-    },
-};
-
-function createBaseError(): Error {
-    return { msg: '' };
-}
-
-export const Error = {
-    encode(
-        message: Error,
-        writer: _m0.Writer = _m0.Writer.create(),
-    ): _m0.Writer {
-        if (message.msg !== '') {
-            writer.uint32(18).string(message.msg);
-        }
-        return writer;
-    },
-
-    decode(input: _m0.Reader | Uint8Array, length?: number): Error {
-        const reader =
-            input instanceof _m0.Reader ? input : _m0.Reader.create(input);
-        let end = length === undefined ? reader.len : reader.pos + length;
-        const message = createBaseError();
-        while (reader.pos < end) {
-            const tag = reader.uint32();
-            switch (tag >>> 3) {
-                case 2:
-                    if (tag !== 18) {
-                        break;
-                    }
-
-                    message.msg = reader.string();
-                    continue;
-            }
-            if ((tag & 7) === 4 || tag === 0) {
-                break;
-            }
-            reader.skipType(tag & 7);
-        }
-        return message;
-    },
-
-    fromJSON(object: any): Error {
-        return { msg: isSet(object.msg) ? globalThis.String(object.msg) : '' };
-    },
-
-    toJSON(message: Error): unknown {
-        const obj: any = {};
-        if (message.msg !== '') {
-            obj.msg = message.msg;
-        }
-        return obj;
-    },
-
-    create<I extends Exact<DeepPartial<Error>, I>>(base?: I): Error {
-        return Error.fromPartial(base ?? ({} as any));
-    },
-    fromPartial<I extends Exact<DeepPartial<Error>, I>>(object: I): Error {
-        const message = createBaseError();
-        message.msg = object.msg ?? '';
-        return message;
-    },
-};
-
-function bytesFromBase64(b64: string): Uint8Array {
-    if (globalThis.Buffer) {
-        return Uint8Array.from(globalThis.Buffer.from(b64, 'base64'));
-    } else {
-        const bin = globalThis.atob(b64);
-        const arr = new Uint8Array(bin.length);
-        for (let i = 0; i < bin.length; ++i) {
-            arr[i] = bin.charCodeAt(i);
-        }
-        return arr;
-    }
-}
-
-function base64FromBytes(arr: Uint8Array): string {
-    if (globalThis.Buffer) {
-        return globalThis.Buffer.from(arr).toString('base64');
-    } else {
-        const bin: string[] = [];
-        arr.forEach(byte => {
-            bin.push(globalThis.String.fromCharCode(byte));
-        });
-        return globalThis.btoa(bin.join(''));
-    }
-}
-
-type Builtin =
-    | Date
-    | Function
-    | Uint8Array
-    | string
-    | number
-    | boolean
-    | undefined;
-
-export type DeepPartial<T> = T extends Builtin
-    ? T
-    : T extends globalThis.Array<infer U>
-    ? globalThis.Array<DeepPartial<U>>
-    : T extends ReadonlyArray<infer U>
-    ? ReadonlyArray<DeepPartial<U>>
-    : T extends {}
-    ? { [K in keyof T]?: DeepPartial<T[K]> }
-    : Partial<T>;
-
-type KeysOfUnion<T> = T extends T ? keyof T : never;
-export type Exact<P, I extends P> = P extends Builtin
-    ? P
-    : P & { [K in keyof P]: Exact<P[K], I[K]> } & {
-          [K in Exclude<keyof I, KeysOfUnion<P>>]: never;
-      };
-
-function longToString(long: Long) {
-    return long.toString();
-}
-
-if (_m0.util.Long !== Long) {
-    _m0.util.Long = Long as any;
-    _m0.configure();
-}
-
-function isObject(value: any): boolean {
-    return typeof value === 'object' && value !== null;
-}
-
-function isSet(value: any): boolean {
-    return value !== null && value !== undefined;
-}
diff --git a/modules/chronik-client/src/ChronikClient.ts b/modules/chronik-client/src/ChronikClient.ts
--- a/modules/chronik-client/src/ChronikClient.ts
+++ b/modules/chronik-client/src/ChronikClient.ts
@@ -2,33 +2,36 @@
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
+import cashaddr from 'ecashaddrjs';
 import WebSocket from 'isomorphic-ws';
 import * as ws from 'ws';
 import * as proto from '../proto/chronik';
 import { FailoverProxy } from './failoverProxy';
-import { fromHex, fromHexRev, toHex, toHexRev } from './hex';
+import { fromHex, toHex, toHexRev } from './hex';
+import {
+    isValidWsSubscription,
+    verifyLokadId,
+    verifyTokenId,
+} from './validation';
 
 type MessageEvent = ws.MessageEvent | { data: Blob };
 
 /**
- * Client to access a Chronik instance.Plain object, without any
- * connections.
+ * Client to access an in-node Chronik instance.
+ * Plain object, without any connections.
  */
 export class ChronikClient {
     private _proxyInterface: FailoverProxy;
     /**
      * Create a new client. This just creates an object, without any connections.
      *
-     * @param {string | string[]} urls This param can be either an array of url strings or a singular
-     * url string. A valid url comes with schema and without a trailing slash.
-     * e.g. 'https://chronik.be.cash/xec'   or
-     * '['https://chronik.be.cash/xec', 'https://chronik.fabien.cash']
+     * @param {string[]} urls Array of valid urls. A valid url comes with schema and without a trailing slash.
+     * e.g. '['https://chronik.be.cash/xec2', 'https://chronik-native.fabien.cash']
      * The approach of accepting an array of urls as input is to ensure redundancy if the
-     * first url encounters downtime. The single url string input will eventually be deprecated
-     * for url arrays regardless of one or many urls being supplied.
+     * first url encounters downtime.
      * @throws {error} throws error on invalid constructor inputs
      */
-    constructor(urls: string | string[]) {
+    constructor(urls: string[]) {
         // Instantiate FailoverProxy with the urls array
         this._proxyInterface = new FailoverProxy(urls);
     }
@@ -40,16 +43,16 @@
 
     /**
      * Broadcasts the `rawTx` on the network.
-     * If `skipSlpCheck` is false, it will be checked that the tx doesn't burn
-     * any SLP tokens before broadcasting.
+     * If `skipTokenChecks` is false, it will be checked that the tx doesn't burn
+     * any tokens before broadcasting.
      */
     public async broadcastTx(
         rawTx: Uint8Array | string,
-        skipSlpCheck = false,
+        skipTokenChecks = false,
     ): Promise<{ txid: string }> {
         const request = proto.BroadcastTxRequest.encode({
             rawTx: typeof rawTx === 'string' ? fromHex(rawTx) : rawTx,
-            skipSlpCheck,
+            skipTokenChecks,
         }).finish();
         const data = await this._proxyInterface.post('/broadcast-tx', request);
         const broadcastResponse = proto.BroadcastTxResponse.decode(data);
@@ -60,18 +63,18 @@
 
     /**
      * Broadcasts the `rawTxs` on the network, only if all of them are valid.
-     * If `skipSlpCheck` is false, it will be checked that the txs don't burn
-     * any SLP tokens before broadcasting.
+     * If `skipTokenChecks` is false, it will be checked that the txs don't burn
+     * any tokens before broadcasting.
      */
     public async broadcastTxs(
         rawTxs: (Uint8Array | string)[],
-        skipSlpCheck = false,
+        skipTokenChecks = false,
     ): Promise<{ txids: string[] }> {
         const request = proto.BroadcastTxsRequest.encode({
             rawTxs: rawTxs.map(rawTx =>
                 typeof rawTx === 'string' ? fromHex(rawTx) : rawTx,
             ),
-            skipSlpCheck,
+            skipTokenChecks,
         }).finish();
         const data = await this._proxyInterface.post('/broadcast-txs', request);
         const broadcastResponse = proto.BroadcastTxsResponse.decode(data);
@@ -87,6 +90,13 @@
         return convertToBlockchainInfo(blockchainInfo);
     }
 
+    /** Fetch info about the current running chronik server */
+    public async chronikInfo(): Promise<ChronikInfo> {
+        const data = await this._proxyInterface.get(`/chronik-info`);
+        const chronikServerInfo = proto.ChronikInfo.decode(data);
+        return convertToChronikInfo(chronikServerInfo);
+    }
+
     /** Fetch the block given hash or height. */
     public async block(hashOrHeight: string | number): Promise<Block> {
         const data = await this._proxyInterface.get(`/block/${hashOrHeight}`);
@@ -94,9 +104,22 @@
         return convertToBlock(block);
     }
 
+    /** Fetch the tx history of a block given hash or height. */
+    public async blockTxs(
+        hashOrHeight: string | number,
+        page = 0, // Get the first page if unspecified
+        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
+    ): Promise<TxHistoryPage> {
+        const data = await this._proxyInterface.get(
+            `/block-txs/${hashOrHeight}?page=${page}&page_size=${pageSize}`,
+        );
+        const blockTxs = proto.TxHistoryPage.decode(data);
+        return convertToTxHistoryPage(blockTxs);
+    }
+
     /**
-     * Fetch block info of a range of blocks. `startHeight` and `endHeight` are
-     * inclusive ranges.
+     * Fetch block info of a range of blocks.
+     * `startHeight` and `endHeight` are inclusive ranges.
      */
     public async blocks(
         startHeight: number,
@@ -109,6 +132,13 @@
         return blocks.blocks.map(convertToBlockInfo);
     }
 
+    /** Fetch token info and stats given the tokenId. */
+    public async token(tokenId: string): Promise<TokenInfo> {
+        const data = await this._proxyInterface.get(`/token/${tokenId}`);
+        const tokenInfo = proto.TokenInfo.decode(data);
+        return convertToTokenInfo(tokenInfo);
+    }
+
     /** Fetch tx details given the txid. */
     public async tx(txid: string): Promise<Tx> {
         const data = await this._proxyInterface.get(`/tx/${txid}`);
@@ -116,34 +146,26 @@
         return convertToTx(tx);
     }
 
-    /** Fetch token info and stats given the tokenId. */
-    public async token(tokenId: string): Promise<Token> {
-        const data = await this._proxyInterface.get(`/token/${tokenId}`);
-        const token = proto.Token.decode(data);
-        return convertToToken(token);
+    /** Fetch tx details given the txid. */
+    public async rawTx(txid: string): Promise<RawTx> {
+        const data = await this._proxyInterface.get(`/raw-tx/${txid}`);
+        const rawTx = proto.RawTx.decode(data);
+        return convertToRawTx(rawTx);
     }
 
-    /**
-     * Validate the given outpoints: whether they are unspent, spent or
-     * never existed.
-     */
-    public async validateUtxos(outpoints: OutPoint[]): Promise<UtxoState[]> {
-        const request = proto.ValidateUtxoRequest.encode({
-            outpoints: outpoints.map(outpoint => ({
-                txid: fromHexRev(outpoint.txid),
-                outIdx: outpoint.outIdx,
-            })),
-        }).finish();
-        const data = await this._proxyInterface.post(
-            '/validate-utxos',
-            request,
-        );
-        const validationStates = proto.ValidateUtxoResponse.decode(data);
-        return validationStates.utxoStates.map(state => ({
-            height: state.height,
-            isConfirmed: state.isConfirmed,
-            state: convertToUtxoStateVariant(state.state),
-        }));
+    /** Create object that allows fetching info about a given token */
+    public tokenId(tokenId: string): TokenIdEndpoint {
+        return new TokenIdEndpoint(this._proxyInterface, tokenId);
+    }
+
+    /** Create object that allows fetching info about a given lokadId */
+    public lokadId(lokadId: string): LokadIdEndpoint {
+        return new LokadIdEndpoint(this._proxyInterface, lokadId);
+    }
+
+    /** Create object that allows fetching info about a given plugin */
+    public plugin(pluginName: string): PluginEndpoint {
+        return new PluginEndpoint(this._proxyInterface, pluginName);
     }
 
     /** Create object that allows fetching script history or UTXOs. */
@@ -158,12 +180,22 @@
         );
     }
 
+    /** Create object that allows fetching script history or UTXOs by p2pkh or p2sh address */
+    public address(address: string): ScriptEndpoint {
+        const { type, hash } = cashaddr.decode(address, true);
+
+        return new ScriptEndpoint(this._proxyInterface, type, hash as string);
+    }
+
     /** Open a WebSocket connection to listen for updates. */
     public ws(config: WsConfig): WsEndpoint {
         return new WsEndpoint(this._proxyInterface, config);
     }
 }
 
+// Do not break existing implementations
+export { ChronikClient as ChronikClientNode };
+
 /** Allows fetching script history and UTXOs. */
 export class ScriptEndpoint {
     private _proxyInterface: FailoverProxy;
@@ -182,30 +214,64 @@
 
     /**
      * Fetches the tx history of this script, in anti-chronological order.
-     * This means it's ordered by first-seen first. If the tx hasn't been seen
+     * This means it's ordered by first-seen first, i.e. TxHistoryPage.txs[0]
+     * will be the most recent tx. If the tx hasn't been seen
      * by the indexer before, it's ordered by the block timestamp.
      * @param page Page index of the tx history.
      * @param pageSize Number of txs per page.
      */
     public async history(
-        page?: number,
-        pageSize?: number,
+        page = 0, // Get the first page if unspecified
+        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
+    ): Promise<TxHistoryPage> {
+        const data = await this._proxyInterface.get(
+            `/script/${this._scriptType}/${this._scriptPayload}/history?page=${page}&page_size=${pageSize}`,
+        );
+        const historyPage = proto.TxHistoryPage.decode(data);
+        return {
+            txs: historyPage.txs.map(convertToTx),
+            numPages: historyPage.numPages,
+            numTxs: historyPage.numTxs,
+        };
+    }
+
+    /**
+     * Fetches the confirmed tx history of this script, in the order they appear on the blockchain.
+     * @param page Page index of the tx history.
+     * @param pageSize Number of txs per page.
+     */
+    public async confirmedTxs(
+        page = 0, // Get the first page if unspecified
+        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
+    ): Promise<TxHistoryPage> {
+        const data = await this._proxyInterface.get(
+            `/script/${this._scriptType}/${this._scriptPayload}/confirmed-txs?page=${page}&page_size=${pageSize}`,
+        );
+        const historyPage = proto.TxHistoryPage.decode(data);
+        return {
+            txs: historyPage.txs.map(convertToTx),
+            numPages: historyPage.numPages,
+            numTxs: historyPage.numTxs,
+        };
+    }
+
+    /**
+     * Fetches the unconfirmed tx history of this script, in chronological order.
+     * @param page Page index of the tx history.
+     * @param pageSize Number of txs per page.
+     */
+    public async unconfirmedTxs(
+        page = 0, // Get the first page if unspecified
+        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
     ): Promise<TxHistoryPage> {
-        const query =
-            page !== undefined && pageSize !== undefined
-                ? `?page=${page}&page_size=${pageSize}`
-                : page !== undefined
-                ? `?page=${page}`
-                : pageSize !== undefined
-                ? `?page_size=${pageSize}`
-                : '';
         const data = await this._proxyInterface.get(
-            `/script/${this._scriptType}/${this._scriptPayload}/history${query}`,
+            `/script/${this._scriptType}/${this._scriptPayload}/unconfirmed-txs?page=${page}&page_size=${pageSize}`,
         );
         const historyPage = proto.TxHistoryPage.decode(data);
         return {
             txs: historyPage.txs.map(convertToTx),
             numPages: historyPage.numPages,
+            numTxs: historyPage.numTxs,
         };
     }
 
@@ -214,22 +280,230 @@
      * It is grouped by output script, in case a script type can match multiple
      * different output scripts (e.g. Taproot on Lotus).
      */
-    public async utxos(): Promise<ScriptUtxos[]> {
+    public async utxos(): Promise<ScriptUtxos> {
         const data = await this._proxyInterface.get(
             `/script/${this._scriptType}/${this._scriptPayload}/utxos`,
         );
+        const scriptUtxos = proto.ScriptUtxos.decode(data);
+        return {
+            outputScript: toHex(scriptUtxos.script),
+            utxos: scriptUtxos.utxos.map(convertToScriptUtxo),
+        };
+    }
+}
+
+/** Allows fetching tokenId confirmedTxs, unconfirmedTxs, history, and UTXOs. */
+export class TokenIdEndpoint {
+    private _proxyInterface: FailoverProxy;
+    private _tokenId: string;
+
+    constructor(proxyInterface: FailoverProxy, tokenId: string) {
+        this._proxyInterface = proxyInterface;
+        this._tokenId = tokenId;
+    }
+
+    /**
+     * Fetches the tx history of this tokenId, in anti-chronological order.
+     * @param page Page index of the tx history.
+     * @param pageSize Number of txs per page.
+     */
+    public async history(
+        page = 0, // Get the first page if unspecified
+        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
+    ): Promise<TxHistoryPage> {
+        const data = await this._proxyInterface.get(
+            `/token-id/${this._tokenId}/history?page=${page}&page_size=${pageSize}`,
+        );
+        const historyPage = proto.TxHistoryPage.decode(data);
+        return {
+            txs: historyPage.txs.map(convertToTx),
+            numPages: historyPage.numPages,
+            numTxs: historyPage.numTxs,
+        };
+    }
+
+    /**
+     * Fetches the confirmed tx history of this tokenId, in the order they appear on the blockchain.
+     * @param page Page index of the tx history.
+     * @param pageSize Number of txs per page.
+     */
+    public async confirmedTxs(
+        page = 0, // Get the first page if unspecified
+        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
+    ): Promise<TxHistoryPage> {
+        const data = await this._proxyInterface.get(
+            `/token-id/${this._tokenId}/confirmed-txs?page=${page}&page_size=${pageSize}`,
+        );
+        const historyPage = proto.TxHistoryPage.decode(data);
+        return {
+            txs: historyPage.txs.map(convertToTx),
+            numPages: historyPage.numPages,
+            numTxs: historyPage.numTxs,
+        };
+    }
+
+    /**
+     * Fetches the unconfirmed tx history of this tokenId, in chronological order.
+     * @param page Page index of the tx history.
+     * @param pageSize Number of txs per page.
+     */
+    public async unconfirmedTxs(
+        page = 0, // Get the first page if unspecified
+        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
+    ): Promise<TxHistoryPage> {
+        const data = await this._proxyInterface.get(
+            `/token-id/${this._tokenId}/unconfirmed-txs?page=${page}&page_size=${pageSize}`,
+        );
+        const historyPage = proto.TxHistoryPage.decode(data);
+        return {
+            txs: historyPage.txs.map(convertToTx),
+            numPages: historyPage.numPages,
+            numTxs: historyPage.numTxs,
+        };
+    }
+
+    /**
+     * Fetches the current UTXO set for this tokenId.
+     */
+    public async utxos(): Promise<TokenIdUtxos> {
+        const data = await this._proxyInterface.get(
+            `/token-id/${this._tokenId}/utxos`,
+        );
+        const utxos = proto.Utxos.decode(data);
+        return {
+            tokenId: this._tokenId,
+            utxos: utxos.utxos.map(convertToUtxo),
+        };
+    }
+}
+
+/** Allows fetching lokadId confirmedTxs, unconfirmedTxs, and history. */
+export class LokadIdEndpoint {
+    private _proxyInterface: FailoverProxy;
+    private _lokadId: string;
+
+    constructor(proxyInterface: FailoverProxy, lokadId: string) {
+        this._proxyInterface = proxyInterface;
+        this._lokadId = lokadId;
+    }
+
+    /**
+     * Fetches the tx history of this tokenId, in anti-chronological order.
+     * @param page Page index of the tx history.
+     * @param pageSize Number of txs per page.
+     */
+    public async history(
+        page = 0, // Get the first page if unspecified
+        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
+    ): Promise<TxHistoryPage> {
+        const data = await this._proxyInterface.get(
+            `/lokad-id/${this._lokadId}/history?page=${page}&page_size=${pageSize}`,
+        );
+        const historyPage = proto.TxHistoryPage.decode(data);
+        return {
+            txs: historyPage.txs.map(convertToTx),
+            numPages: historyPage.numPages,
+            numTxs: historyPage.numTxs,
+        };
+    }
+
+    /**
+     * Fetches the confirmed tx history of this tokenId, in the order they appear on the blockchain.
+     * @param page Page index of the tx history.
+     * @param pageSize Number of txs per page.
+     */
+    public async confirmedTxs(
+        page = 0, // Get the first page if unspecified
+        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
+    ): Promise<TxHistoryPage> {
+        const data = await this._proxyInterface.get(
+            `/lokad-id/${this._lokadId}/confirmed-txs?page=${page}&page_size=${pageSize}`,
+        );
+        const historyPage = proto.TxHistoryPage.decode(data);
+        return {
+            txs: historyPage.txs.map(convertToTx),
+            numPages: historyPage.numPages,
+            numTxs: historyPage.numTxs,
+        };
+    }
+
+    /**
+     * Fetches the unconfirmed tx history of this tokenId, in chronological order.
+     * @param page Page index of the tx history.
+     * @param pageSize Number of txs per page.
+     */
+    public async unconfirmedTxs(
+        page = 0, // Get the first page if unspecified
+        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
+    ): Promise<TxHistoryPage> {
+        const data = await this._proxyInterface.get(
+            `/lokad-id/${this._lokadId}/unconfirmed-txs?page=${page}&page_size=${pageSize}`,
+        );
+        const historyPage = proto.TxHistoryPage.decode(data);
+        return {
+            txs: historyPage.txs.map(convertToTx),
+            numPages: historyPage.numPages,
+            numTxs: historyPage.numTxs,
+        };
+    }
+}
+
+/** Allows fetching plugin UTXOs. */
+export class PluginEndpoint {
+    private _proxyInterface: FailoverProxy;
+    private _pluginName: string;
+
+    constructor(proxyInterface: FailoverProxy, pluginName: string) {
+        this._proxyInterface = proxyInterface;
+        this._pluginName = pluginName;
+    }
+
+    /**
+     * Fetches the current UTXO set for this plugin group.
+     */
+    public async utxos(groupHex: string): Promise<PluginUtxos> {
+        const data = await this._proxyInterface.get(
+            `/plugin/${this._pluginName}/${groupHex}/utxos`,
+        );
         const utxos = proto.Utxos.decode(data);
-        return utxos.scriptUtxos.map(scriptUtxos => ({
-            outputScript: toHex(scriptUtxos.outputScript),
-            utxos: scriptUtxos.utxos.map(convertToUtxo),
-        }));
+        return {
+            pluginName: this._pluginName,
+            groupHex,
+            utxos: utxos.utxos.map(convertToUtxo),
+        };
+    }
+
+    /**
+     * Fetches groups of this plugin.
+     */
+    public async groups(
+        prefixHex?: string,
+        startHex?: string,
+        pageSize?: number,
+    ): Promise<PluginGroups> {
+        const query = new URLSearchParams();
+        if (prefixHex !== undefined) {
+            query.set('prefix', prefixHex);
+        }
+        if (startHex !== undefined) {
+            query.set('start', startHex);
+        }
+        if (pageSize !== undefined) {
+            query.set('page_size', pageSize.toString());
+        }
+        const data = await this._proxyInterface.get(
+            `/plugin/${this._pluginName}/groups?${query.toString()}`,
+        );
+        const groups = proto.PluginGroups.decode(data);
+
+        return convertToPluginGroups(groups);
     }
 }
 
 /** Config for a WebSocket connection to Chronik. */
 export interface WsConfig {
     /** Fired when a message is sent from the WebSocket. */
-    onMessage?: (msg: SubscribeMsg) => void;
+    onMessage?: (msg: WsMsgClient) => void;
 
     /** Fired when a connection has been (re)established. */
     onConnect?: (e: ws.Event) => void;
@@ -256,9 +530,8 @@
 /** WebSocket connection to Chronik. */
 export class WsEndpoint {
     private _proxyInterface: FailoverProxy;
-
     /** Fired when a message is sent from the WebSocket. */
-    public onMessage?: (msg: SubscribeMsg) => void;
+    public onMessage?: (msg: WsMsgClient) => void;
 
     /** Fired when a connection has been (re)established. */
     public onConnect?: (e: ws.Event) => void;
@@ -284,7 +557,7 @@
     public ws: ws.WebSocket | undefined;
     public connected: Promise<ws.Event> | undefined;
     public manuallyClosed: boolean;
-    public subs: { scriptType: ScriptType; scriptPayload: string }[];
+    public subs: WsSubscriptions;
 
     constructor(proxyInterface: FailoverProxy, config: WsConfig) {
         this.onMessage = config.onMessage;
@@ -294,7 +567,7 @@
         this.autoReconnect =
             config.autoReconnect !== undefined ? config.autoReconnect : true;
         this.manuallyClosed = false;
-        this.subs = [];
+        this.subs = { scripts: [], tokens: [], lokadIds: [], blocks: false };
         this._proxyInterface = proxyInterface;
     }
 
@@ -304,31 +577,169 @@
         await this.connected;
     }
 
+    /**
+     * Subscribe to block messages
+     */
+    public subscribeToBlocks() {
+        this.subs.blocks = true;
+        if (this.ws?.readyState === WebSocket.OPEN) {
+            this._subUnsubBlocks(false);
+        }
+    }
+
+    /**
+     * Unsubscribe from block messages
+     */
+    public unsubscribeFromBlocks() {
+        this.subs.blocks = false;
+        if (this.ws?.readyState === WebSocket.OPEN) {
+            this._subUnsubBlocks(true);
+        }
+    }
+
     /**
      * Subscribe to the given script type and payload.
      * For "p2pkh", `scriptPayload` is the 20 byte public key hash.
      */
-    public subscribe(scriptType: ScriptType, scriptPayload: string) {
-        this.subs.push({ scriptType, scriptPayload });
+    public subscribeToScript(type: ScriptType, payload: string) {
+        // Build sub according to chronik expected type
+        const subscription: WsSubScriptClient = {
+            scriptType: type,
+            payload,
+        };
+        // We do not want to add invalid subs to ws.subs
+        const scriptSubscriptionValidationCheck =
+            isValidWsSubscription(subscription);
+
+        if (scriptSubscriptionValidationCheck !== true) {
+            // isValidWsSubscription returns string error msg if the sub is invalid
+            throw new Error(scriptSubscriptionValidationCheck as string);
+        }
+
+        this.subs.scripts.push(subscription as WsSubScriptClient);
+
         if (this.ws?.readyState === WebSocket.OPEN) {
-            this.subUnsub(true, scriptType, scriptPayload);
+            this._subUnsubScript(false, subscription);
         }
     }
 
     /** Unsubscribe from the given script type and payload. */
-    public unsubscribe(scriptType: ScriptType, scriptPayload: string) {
-        this.subs = this.subs.filter(
-            sub =>
-                sub.scriptType !== scriptType ||
-                sub.scriptPayload !== scriptPayload,
+    public unsubscribeFromScript(type: ScriptType, payload: string) {
+        // Build sub according to chronik expected type
+        const subscription: WsSubScriptClient = {
+            scriptType: type,
+            payload,
+        };
+
+        // Find the requested unsub script and remove it
+        const unsubIndex = this.subs.scripts.findIndex(
+            sub => sub.scriptType === type && sub.payload === payload,
+        );
+        if (unsubIndex === -1) {
+            // If we cannot find this subscription in this.subs, throw an error
+            // We do not want an app developer thinking they have unsubscribed from something
+            throw new Error(`No existing sub at ${type}, ${payload}`);
+        }
+
+        // Remove the requested subscription from this.subs
+        this.subs.scripts.splice(unsubIndex, 1);
+
+        if (this.ws?.readyState === WebSocket.OPEN) {
+            this._subUnsubScript(true, subscription);
+        }
+    }
+
+    /**
+     * Subscribe to an address
+     * Method can be used for p2pkh or p2sh addresses
+     */
+    public subscribeToAddress(address: string) {
+        // Get type and hash
+        const { type, hash } = cashaddr.decode(address, true);
+
+        // Subscribe to script
+        this.subscribeToScript(type as 'p2pkh' | 'p2sh', hash as string);
+    }
+
+    /** Unsubscribe from the given address */
+    public unsubscribeFromAddress(address: string) {
+        // Get type and hash
+        const { type, hash } = cashaddr.decode(address, true);
+
+        // Unsubscribe from script
+        this.unsubscribeFromScript(type as 'p2pkh' | 'p2sh', hash as string);
+    }
+
+    /** Subscribe to a lokadId */
+    public subscribeToLokadId(lokadId: string) {
+        verifyLokadId(lokadId);
+
+        // Update ws.subs to include this lokadId
+        this.subs.lokadIds.push(lokadId);
+
+        if (this.ws?.readyState === WebSocket.OPEN) {
+            // Send subscribe msg to chronik server
+            this._subUnsubLokadId(false, lokadId);
+        }
+    }
+
+    /** Unsubscribe from the given lokadId */
+    public unsubscribeFromLokadId(lokadId: string) {
+        // Find the requested unsub lokadId and remove it
+        const unsubIndex = this.subs.lokadIds.findIndex(
+            thisLokadId => thisLokadId === lokadId,
+        );
+        if (unsubIndex === -1) {
+            // If we cannot find this subscription in this.subs.lokadIds, throw an error
+            // We do not want an app developer thinking they have unsubscribed from something if no action happened
+            throw new Error(`No existing sub at lokadId "${lokadId}"`);
+        }
+
+        // Remove the requested lokadId subscription from this.subs.lokadIds
+        this.subs.lokadIds.splice(unsubIndex, 1);
+
+        if (this.ws?.readyState === WebSocket.OPEN) {
+            // Send unsubscribe msg to chronik server
+            this._subUnsubLokadId(true, lokadId);
+        }
+    }
+
+    /** Subscribe to a tokenId */
+    public subscribeToTokenId(tokenId: string) {
+        verifyTokenId(tokenId);
+
+        // Update ws.subs to include this tokenId
+        this.subs.tokens.push(tokenId);
+
+        if (this.ws?.readyState === WebSocket.OPEN) {
+            // Send subscribe msg to chronik server
+            this._subUnsubToken(false, tokenId);
+        }
+    }
+
+    /** Unsubscribe from the given tokenId */
+    public unsubscribeFromTokenId(tokenId: string) {
+        // Find the requested unsub tokenId and remove it
+        const unsubIndex = this.subs.tokens.findIndex(
+            thisTokenId => thisTokenId === tokenId,
         );
+        if (unsubIndex === -1) {
+            // If we cannot find this subscription in this.subs.tokens, throw an error
+            // We do not want an app developer thinking they have unsubscribed from something if no action happened
+            throw new Error(`No existing sub at tokenId "${tokenId}"`);
+        }
+
+        // Remove the requested tokenId subscription from this.subs.tokens
+        this.subs.tokens.splice(unsubIndex, 1);
+
         if (this.ws?.readyState === WebSocket.OPEN) {
-            this.subUnsub(false, scriptType, scriptPayload);
+            // Send unsubscribe msg to chronik server
+            this._subUnsubToken(true, tokenId);
         }
     }
 
     /**
-     * Close the WebSocket connection and prevent future any reconnection
+     * Close the WebSocket connection and prevent any future reconnection
      * attempts.
      */
     public close() {
@@ -336,66 +747,93 @@
         this.ws?.close();
     }
 
-    public subUnsub(
-        isSubscribe: boolean,
-        scriptType: ScriptType,
-        scriptPayload: string,
-    ) {
-        const encodedSubscription = proto.Subscription.encode({
-            isSubscribe,
-            scriptType,
-            payload: fromHex(scriptPayload),
+    private _subUnsubBlocks(isUnsub: boolean) {
+        // Blocks subscription is empty object
+        const BLOCKS_SUBSCRIPTION: proto.WsSubBlocks = {};
+        const encodedSubscription = proto.WsSub.encode({
+            isUnsub,
+            blocks: BLOCKS_SUBSCRIPTION,
         }).finish();
-        if (this.ws === undefined)
-            throw new Error('Invalid state; ws is undefined');
+        if (this.ws === undefined) {
+            throw new Error('Invalid state; _ws is undefined');
+        }
         this.ws.send(encodedSubscription);
     }
 
-    public async handleMsg(wsMsg: MessageEvent) {
-        if (this.onMessage === undefined) {
-            return;
-        }
+    private _subUnsubScript(isUnsub: boolean, subscription: WsSubScriptClient) {
+        // If this subscription is to an address, leave the 'blocks' key undefined
+        const encodedSubscription = proto.WsSub.encode({
+            isUnsub,
+            script: {
+                scriptType: (subscription as WsSubScriptClient).scriptType,
+                payload: fromHex((subscription as WsSubScriptClient).payload),
+            },
+        }).finish();
+
+        if (this.ws === undefined) {
+            throw new Error('Invalid state; _ws is undefined');
+        }
+
+        this.ws.send(encodedSubscription);
+    }
+
+    private _subUnsubLokadId(isUnsub: boolean, lokadId: string) {
+        const encodedSubscription = proto.WsSub.encode({
+            isUnsub,
+            lokadId: {
+                // User input for lokadId is string
+                // Chronik expects bytes
+                lokadId: fromHex(lokadId),
+            },
+        }).finish();
+
+        if (this.ws === undefined) {
+            throw new Error('Invalid state; _ws is undefined');
+        }
+
+        this.ws.send(encodedSubscription);
+    }
+
+    private _subUnsubToken(isUnsub: boolean, tokenId: string) {
+        const encodedSubscription = proto.WsSub.encode({
+            isUnsub,
+            tokenId: {
+                tokenId: tokenId,
+            },
+        }).finish();
+
+        if (this.ws === undefined) {
+            throw new Error('Invalid state; _ws is undefined');
+        }
+
+        this.ws.send(encodedSubscription);
+    }
+
+    public async handleMsg(wsMsg: MessageEvent) {
+        if (typeof this.onMessage === 'undefined') {
+            return;
+        }
         const data =
             typeof window === 'undefined'
                 ? // NodeJS
                   (wsMsg.data as Uint8Array)
                 : // Browser
                   new Uint8Array(await (wsMsg.data as Blob).arrayBuffer());
-        const msg = proto.SubscribeMsg.decode(data);
-        if (msg.error) {
+        const msg = proto.WsMsg.decode(data);
+        if (typeof msg.error !== 'undefined') {
+            this.onMessage({ type: 'Error', ...msg.error });
+        } else if (typeof msg.block !== 'undefined') {
             this.onMessage({
-                type: 'Error',
-                ...msg.error,
+                type: 'Block',
+                msgType: convertToBlockMsgType(msg.block.msgType),
+                blockHash: toHexRev(msg.block.blockHash),
+                blockHeight: msg.block.blockHeight,
             });
-        } else if (msg.AddedToMempool) {
+        } else if (typeof msg.tx !== 'undefined') {
             this.onMessage({
-                type: 'AddedToMempool',
-                txid: toHexRev(msg.AddedToMempool.txid),
-            });
-        } else if (msg.RemovedFromMempool) {
-            this.onMessage({
-                type: 'RemovedFromMempool',
-                txid: toHexRev(msg.RemovedFromMempool.txid),
-            });
-        } else if (msg.Confirmed) {
-            this.onMessage({
-                type: 'Confirmed',
-                txid: toHexRev(msg.Confirmed.txid),
-            });
-        } else if (msg.Reorg) {
-            this.onMessage({
-                type: 'Reorg',
-                txid: toHexRev(msg.Reorg.txid),
-            });
-        } else if (msg.BlockConnected) {
-            this.onMessage({
-                type: 'BlockConnected',
-                blockHash: toHexRev(msg.BlockConnected.blockHash),
-            });
-        } else if (msg.BlockDisconnected) {
-            this.onMessage({
-                type: 'BlockDisconnected',
-                blockHash: toHexRev(msg.BlockDisconnected.blockHash),
+                type: 'Tx',
+                msgType: convertToTxMsgType(msg.tx.msgType),
+                txid: toHexRev(msg.tx.txid),
             });
         } else {
             console.log('Silently ignored unknown Chronik message:', msg);
@@ -412,212 +850,154 @@
     };
 }
 
+function convertToChronikInfo(chronikInfo: proto.ChronikInfo): ChronikInfo {
+    if (chronikInfo.version === undefined) {
+        throw new Error('chronikInfo has no version');
+    }
+    return {
+        version: chronikInfo.version.length !== 0 ? chronikInfo.version : '',
+    };
+}
+
 function convertToBlock(block: proto.Block): Block {
     if (block.blockInfo === undefined) {
         throw new Error('Block has no blockInfo');
     }
-    if (block.blockDetails === undefined) {
-        throw new Error('Block has no blockDetails');
-    }
     return {
         blockInfo: convertToBlockInfo(block.blockInfo),
-        blockDetails: convertToBlockDetails(block.blockDetails),
-        rawHeader: toHex(block.rawHeader),
-        txs: block.txs.map(convertToTx),
     };
 }
 
-function convertToTx(tx: proto.Tx): Tx {
+function convertToTxHistoryPage(blockTxs: proto.TxHistoryPage): TxHistoryPage {
+    const { txs, numPages, numTxs } = blockTxs;
+    const convertedTxs = txs.map(convertToTx);
     return {
+        txs: convertedTxs,
+        numPages,
+        numTxs,
+    };
+}
+
+function convertToBlockInfo(block: proto.BlockInfo): BlockInfo {
+    return {
+        ...block,
+        hash: toHexRev(block.hash),
+        prevHash: toHexRev(block.prevHash),
+        timestamp: parseInt(block.timestamp),
+        blockSize: parseInt(block.blockSize),
+        numTxs: parseInt(block.numTxs),
+        numInputs: parseInt(block.numInputs),
+        numOutputs: parseInt(block.numOutputs),
+        sumInputSats: parseInt(block.sumInputSats),
+        sumCoinbaseOutputSats: parseInt(block.sumCoinbaseOutputSats),
+        sumNormalOutputSats: parseInt(block.sumNormalOutputSats),
+        sumBurnedSats: parseInt(block.sumBurnedSats),
+    };
+}
+
+function convertToTx(tx: proto.Tx): Tx {
+    const convertedTx: Tx = {
         txid: toHexRev(tx.txid),
         version: tx.version,
         inputs: tx.inputs.map(convertToTxInput),
         outputs: tx.outputs.map(convertToTxOutput),
         lockTime: tx.lockTime,
-        slpTxData: tx.slpTxData ? convertToSlpTxData(tx.slpTxData) : undefined,
-        slpErrorMsg: tx.slpErrorMsg.length !== 0 ? tx.slpErrorMsg : undefined,
-        block:
-            tx.block !== undefined ? convertToBlockMeta(tx.block) : undefined,
-        timeFirstSeen: tx.timeFirstSeen,
+        timeFirstSeen: parseInt(tx.timeFirstSeen),
         size: tx.size,
         isCoinbase: tx.isCoinbase,
-        network: convertToNetwork(tx.network),
+        tokenEntries: tx.tokenEntries.map(convertToTokenEntry),
+        tokenFailedParsings: tx.tokenFailedParsings.map(
+            convertToTokenFailedParsing,
+        ),
+        tokenStatus: convertToTokenStatus(tx.tokenStatus),
     };
-}
-
-function convertToUtxo(utxo: proto.Utxo): Utxo {
-    if (utxo.outpoint === undefined) {
-        throw new Error('UTXO outpoint is undefined');
+    if (typeof tx.block !== 'undefined') {
+        // Only include block if the tx is in a block
+        convertedTx.block = convertToBlockMeta(tx.block);
     }
-    return {
-        outpoint: {
-            txid: toHexRev(utxo.outpoint.txid),
-            outIdx: utxo.outpoint.outIdx,
-        },
-        blockHeight: utxo.blockHeight,
-        isCoinbase: utxo.isCoinbase,
-        value: utxo.value,
-        slpMeta:
-            utxo.slpMeta !== undefined
-                ? convertToSlpMeta(utxo.slpMeta)
-                : undefined,
-        slpToken:
-            utxo.slpToken !== undefined
-                ? convertToSlpToken(utxo.slpToken)
-                : undefined,
-        network: convertToNetwork(utxo.network),
-    };
-}
-
-function convertToToken(token: proto.Token): Token {
-    if (token.slpTxData === undefined) {
-        throw new Error('Invalid proto, no slpTxData');
-    }
-    if (token.tokenStats === undefined) {
-        throw new Error('Invalid proto, no tokenStats');
-    }
-    return {
-        slpTxData: convertToSlpTokenTxData(token.slpTxData),
-        tokenStats: token.tokenStats,
-        block:
-            token.block !== undefined
-                ? convertToBlockMeta(token.block)
-                : undefined,
-        timeFirstSeen: token.timeFirstSeen,
-        initialTokenQuantity: token.initialTokenQuantity,
-        containsBaton: token.containsBaton,
-        network: convertToNetwork(token.network),
-    };
+    return convertedTx;
 }
 
 function convertToTxInput(input: proto.TxInput): TxInput {
     if (input.prevOut === undefined) {
         throw new Error('Invalid proto, no prevOut');
     }
-    return {
+    const txInput: TxInput = {
         prevOut: {
             txid: toHexRev(input.prevOut.txid),
             outIdx: input.prevOut.outIdx,
         },
         inputScript: toHex(input.inputScript),
-        outputScript:
-            input.outputScript.length > 0
-                ? toHex(input.outputScript)
-                : undefined,
-        value: input.value,
+        value: parseInt(input.value),
         sequenceNo: input.sequenceNo,
-        slpBurn:
-            input.slpBurn !== undefined
-                ? convertToSlpBurn(input.slpBurn)
-                : undefined,
-        slpToken:
-            input.slpToken !== undefined
-                ? convertToSlpToken(input.slpToken)
-                : undefined,
     };
+    if (typeof input.token !== 'undefined') {
+        // We only return a token key if we have token data for this input
+        txInput.token = convertToToken(input.token);
+    }
+    if (Object.keys(input.plugins).length > 0) {
+        // We only return a plugins key if we have plugins
+        txInput.plugins = convertToPluginEntries(input.plugins);
+    }
+    if (
+        typeof input.outputScript !== 'undefined' &&
+        input.outputScript.length > 0
+    ) {
+        // Coinbase tx inputs do not have an outputScript
+        txInput.outputScript = toHex(input.outputScript);
+    }
+    return txInput;
 }
 
 function convertToTxOutput(output: proto.TxOutput): TxOutput {
-    return {
-        value: output.value,
+    const txOutput: TxOutput = {
+        value: parseInt(output.value),
         outputScript: toHex(output.outputScript),
-        slpToken:
-            output.slpToken !== undefined
-                ? convertToSlpToken(output.slpToken)
-                : undefined,
-        spentBy:
-            output.spentBy !== undefined
-                ? {
-                      txid: toHexRev(output.spentBy.txid),
-                      outIdx: output.spentBy.outIdx,
-                  }
-                : undefined,
     };
-}
-
-function convertToSlpTxData(slpTxData: proto.SlpTxData): SlpTxData {
-    if (slpTxData.slpMeta === undefined) {
-        throw new Error('Invalid slpTxData: slpMeta is undefined');
+    if (Object.keys(output.plugins).length > 0) {
+        // We only return a plugins key if we have plugins
+        txOutput.plugins = convertToPluginEntries(output.plugins);
     }
-    return {
-        slpMeta: convertToSlpMeta(slpTxData.slpMeta),
-        genesisInfo:
-            slpTxData.genesisInfo !== undefined
-                ? convertToSlpGenesisInfo(slpTxData.genesisInfo)
-                : undefined,
-    };
-}
-
-function convertToSlpTokenTxData(slpTxData: proto.SlpTxData): SlpTokenTxData {
-    if (slpTxData.slpMeta === undefined) {
-        throw new Error('Invalid slpTxData: slpMeta is undefined');
+    if (typeof output.token !== 'undefined') {
+        // We only return a token key if we have token data for this input
+        txOutput.token = convertToToken(output.token);
     }
-    if (slpTxData.genesisInfo === undefined) {
-        throw new Error('Invalid slpTxData: genesisInfo is undefined');
+    if (typeof output.spentBy !== 'undefined') {
+        // We only return a spentBy key if this output has been spent
+        txOutput.spentBy = {
+            txid: toHexRev(output.spentBy.txid),
+            outIdx: output.spentBy.inputIdx,
+        };
     }
-    return {
-        slpMeta: convertToSlpMeta(slpTxData.slpMeta),
-        genesisInfo: convertToSlpGenesisInfo(slpTxData.genesisInfo),
-    };
+    return txOutput;
 }
 
-function convertToSlpMeta(slpMeta: proto.SlpMeta): SlpMeta {
-    let tokenType: SlpTokenType;
-    switch (slpMeta.tokenType) {
-        case proto.SlpTokenType.FUNGIBLE:
-            tokenType = 'FUNGIBLE';
-            break;
-        case proto.SlpTokenType.NFT1_GROUP:
-            tokenType = 'NFT1_GROUP';
-            break;
-        case proto.SlpTokenType.NFT1_CHILD:
-            tokenType = 'NFT1_CHILD';
-            break;
-        case proto.SlpTokenType.UNKNOWN_TOKEN_TYPE:
-            tokenType = 'UNKNOWN_TOKEN_TYPE';
-            break;
-        default:
-            throw new Error(`Invalid token type: ${slpMeta.tokenType}`);
-    }
-    let txType: SlpTxType;
-    switch (slpMeta.txType) {
-        case proto.SlpTxType.GENESIS:
-            txType = 'GENESIS';
-            break;
-        case proto.SlpTxType.SEND:
-            txType = 'SEND';
-            break;
-        case proto.SlpTxType.MINT:
-            txType = 'MINT';
-            break;
-        case proto.SlpTxType.BURN:
-            txType = 'BURN';
-            break;
-        case proto.SlpTxType.UNKNOWN_TX_TYPE:
-            txType = 'UNKNOWN_TX_TYPE';
-            break;
-        default:
-            throw new Error(`Invalid slp tx type: ${slpMeta.txType}`);
+function convertToPluginEntries(plugins: {
+    [key: string]: proto.PluginEntry;
+}): PluginEntries {
+    const pluginEntries: PluginEntries = {};
+    for (const [pluginName, plugin] of Object.entries(plugins)) {
+        if (typeof pluginName === 'undefined') {
+            continue;
+        }
+        const { groups, data } = plugin;
+
+        pluginEntries[pluginName] = {
+            groups: groups.map(toHex),
+            data: data.map(toHex),
+        };
     }
-    return {
-        tokenType,
-        txType,
-        tokenId: toHex(slpMeta.tokenId),
-        groupTokenId:
-            slpMeta.groupTokenId.length == 32
-                ? toHex(slpMeta.groupTokenId)
-                : undefined,
-    };
+
+    return pluginEntries;
 }
 
-function convertToSlpGenesisInfo(info: proto.SlpGenesisInfo): SlpGenesisInfo {
-    const decoder = new TextDecoder();
+function convertToPluginGroups(
+    protoPluginGroups: proto.PluginGroups,
+): PluginGroups {
+    const { groups } = protoPluginGroups;
     return {
-        tokenTicker: decoder.decode(info.tokenTicker),
-        tokenName: decoder.decode(info.tokenName),
-        tokenDocumentUrl: decoder.decode(info.tokenDocumentUrl),
-        tokenDocumentHash: toHex(info.tokenDocumentHash),
-        decimals: info.decimals,
+        groups: groups.map(group => ({ group: toHex(group.group) })),
+        nextStart: toHex(protoPluginGroups.nextStart),
     };
 }
 
@@ -625,289 +1005,396 @@
     return {
         height: block.height,
         hash: toHexRev(block.hash),
-        timestamp: block.timestamp,
+        timestamp: parseInt(block.timestamp),
     };
 }
 
-function convertToBlockInfo(block: proto.BlockInfo): BlockInfo {
+function convertToRawTx(rawTx: proto.RawTx): RawTx {
     return {
-        ...block,
-        hash: toHexRev(block.hash),
-        prevHash: toHexRev(block.prevHash),
+        rawTx: toHex(rawTx.rawTx),
     };
 }
 
-function convertToBlockDetails(blockDetails: proto.BlockDetails): BlockDetails {
-    return {
-        ...blockDetails,
-        merkleRoot: toHexRev(blockDetails.merkleRoot),
+function convertToScriptUtxo(utxo: proto.ScriptUtxo): ScriptUtxo {
+    if (utxo.outpoint === undefined) {
+        throw new Error('UTXO outpoint is undefined');
+    }
+    const convertedScriptUtxo: ScriptUtxo = {
+        outpoint: {
+            txid: toHexRev(utxo.outpoint.txid),
+            outIdx: utxo.outpoint.outIdx,
+        },
+        blockHeight: utxo.blockHeight,
+        isCoinbase: utxo.isCoinbase,
+        value: parseInt(utxo.value),
+        isFinal: utxo.isFinal,
     };
+    if (typeof utxo.token !== 'undefined') {
+        // We only return a token key if we have token data for this input
+        convertedScriptUtxo.token = convertToToken(utxo.token);
+    }
+    if (Object.keys(utxo.plugins).length > 0) {
+        // We only return a plugins key if we have plugins
+        convertedScriptUtxo.plugins = convertToPluginEntries(utxo.plugins);
+    }
+    return convertedScriptUtxo;
 }
 
-function convertToSlpBurn(burn: proto.SlpBurn): SlpBurn {
-    if (burn.token === undefined) {
-        throw new Error('Invalid burn: token is undefined');
+function convertToUtxo(utxo: proto.Utxo): Utxo {
+    if (utxo.outpoint === undefined) {
+        throw new Error('UTXO outpoint is undefined');
     }
-    return {
-        token: convertToSlpToken(burn.token),
-        tokenId: toHex(burn.tokenId),
+    const convertedUtxo: Utxo = {
+        outpoint: {
+            txid: toHexRev(utxo.outpoint.txid),
+            outIdx: utxo.outpoint.outIdx,
+        },
+        blockHeight: utxo.blockHeight,
+        isCoinbase: utxo.isCoinbase,
+        script: toHex(utxo.script),
+        value: parseInt(utxo.value),
+        isFinal: utxo.isFinal,
     };
+    if (typeof utxo.token !== 'undefined') {
+        // We only return a token key if we have token data for this input
+        convertedUtxo.token = convertToToken(utxo.token);
+    }
+    if (Object.keys(utxo.plugins).length > 0) {
+        // We only return a plugins key if we have plugins
+        convertedUtxo.plugins = convertToPluginEntries(utxo.plugins);
+    }
+    return convertedUtxo;
 }
 
-function convertToSlpToken(token: proto.SlpToken): SlpToken {
+function convertToTokenEntry(tokenEntry: proto.TokenEntry): TokenEntry {
+    if (typeof tokenEntry.tokenType === 'undefined') {
+        // Not expected to ever happen
+        throw new Error(
+            `chronik returned undefined tokenEntry.tokenType for tokenId "${tokenEntry.tokenId}"`,
+        );
+    }
+    const returnObj: TokenEntry = {
+        tokenId: tokenEntry.tokenId,
+        tokenType: convertToTokenType(tokenEntry.tokenType),
+        txType: convertToTokenTxType(tokenEntry.txType),
+        isInvalid: tokenEntry.isInvalid,
+        burnSummary: tokenEntry.burnSummary,
+        failedColorings: tokenEntry.failedColorings,
+        actualBurnAmount: tokenEntry.actualBurnAmount,
+        intentionalBurn: tokenEntry.intentionalBurn,
+        burnsMintBatons: tokenEntry.burnsMintBatons,
+    };
+    if (tokenEntry.groupTokenId !== '') {
+        // Only include groupTokenId if it is not empty
+        returnObj.groupTokenId = tokenEntry.groupTokenId;
+    }
+    return returnObj;
+}
+
+function convertToTokenFailedParsing(
+    tokenFailedParsing: proto.TokenFailedParsing,
+): TokenFailedParsing {
     return {
+        pushdataIdx: tokenFailedParsing.pushdataIdx,
+        bytes: toHex(tokenFailedParsing.bytes),
+        error: tokenFailedParsing.error,
+    };
+}
+
+function convertToTokenType(tokenType: proto.TokenType): TokenType {
+    if (typeof tokenType.alp !== 'undefined') {
+        return {
+            protocol: 'ALP',
+            type: convertToAlpTokenType(tokenType.alp),
+            number: tokenType.alp,
+        };
+    }
+    if (typeof tokenType.slp !== 'undefined') {
+        return {
+            protocol: 'SLP',
+            type: convertToSlpTokenType(tokenType.slp),
+            number: tokenType.slp,
+        };
+    }
+    // Should never happen
+    throw new Error('chronik did not return a token protocol for this token');
+}
+
+function convertToSlpTokenType(msgType: proto.SlpTokenType): SlpTokenType_Type {
+    const slpTokenType = proto.slpTokenTypeToJSON(msgType);
+    if (isSlpTokenType(slpTokenType)) {
+        return slpTokenType;
+    }
+    return 'SLP_TOKEN_TYPE_UNKNOWN';
+}
+
+function isSlpTokenType(msgType: any): msgType is SlpTokenType_Type {
+    return SLP_TOKEN_TYPES.includes(msgType);
+}
+
+function convertToAlpTokenType(msgType: proto.AlpTokenType): AlpTokenType_Type {
+    const alpTokenType = proto.alpTokenTypeToJSON(msgType);
+    if (isAlpTokenType(alpTokenType)) {
+        return alpTokenType;
+    }
+    return 'ALP_TOKEN_TYPE_UNKNOWN';
+}
+
+function isAlpTokenType(msgType: any): msgType is AlpTokenType_Type {
+    return ALP_TOKEN_TYPES.includes(msgType);
+}
+
+function convertToTokenStatus(msgType: proto.TokenStatus): TokenStatus {
+    const tokenStatus = proto.tokenStatusToJSON(msgType);
+    if (isTokenStatus(tokenStatus)) {
+        return tokenStatus;
+    }
+    return 'TOKEN_STATUS_UNKNOWN';
+}
+
+function isTokenStatus(msgType: any): msgType is TokenStatus {
+    return TOKEN_STATUS_TYPES.includes(msgType);
+}
+
+function convertToTokenTxType(msgType: proto.TokenTxType): TokenTxType {
+    const tokenTxType = proto.tokenTxTypeToJSON(msgType);
+    if (isTokenTxType(tokenTxType)) {
+        return tokenTxType;
+    }
+    return 'UNKNOWN';
+}
+
+function isTokenTxType(msgType: any): msgType is TokenTxType {
+    return TOKEN_TX_TYPE_TYPES.includes(msgType);
+}
+
+function convertToToken(token: proto.Token): Token {
+    if (typeof token.tokenType === 'undefined') {
+        // Not expected to ever happen
+        throw new Error(
+            `chronik returned undefined token.tokenType for tokenId "${token.tokenId}"`,
+        );
+    }
+
+    const convertedToken: Token = {
+        tokenId: token.tokenId,
+        tokenType: convertToTokenType(token.tokenType),
         amount: token.amount,
         isMintBaton: token.isMintBaton,
     };
+
+    // We do not bother including entryIdx for utxos, where it is always -1
+    if (token.entryIdx !== -1) {
+        convertedToken.entryIdx = token.entryIdx;
+    }
+
+    return convertedToken;
 }
 
-function convertToNetwork(network: proto.Network): Network {
-    switch (network) {
-        case proto.Network.BCH:
-            return 'BCH';
-        case proto.Network.XEC:
-            return 'XEC';
-        case proto.Network.XPI:
-            return 'XPI';
-        case proto.Network.XRG:
-            return 'XRG';
-        default:
-            throw new Error(`Unknown network: ${network}`);
+function convertToBlockMsgType(msgType: proto.BlockMsgType): BlockMsgType {
+    const blockMsgType = proto.blockMsgTypeToJSON(msgType);
+    if (isBlockMsgType(blockMsgType)) {
+        return blockMsgType;
     }
+    return 'UNRECOGNIZED';
+}
+
+function isBlockMsgType(msgType: any): msgType is BlockMsgType {
+    return BLK_MSG_TYPES.includes(msgType);
 }
 
-function convertToUtxoStateVariant(
-    variant: proto.UtxoStateVariant,
-): UtxoStateVariant {
-    switch (variant) {
-        case proto.UtxoStateVariant.UNSPENT:
-            return 'UNSPENT';
-        case proto.UtxoStateVariant.SPENT:
-            return 'SPENT';
-        case proto.UtxoStateVariant.NO_SUCH_TX:
-            return 'NO_SUCH_TX';
-        case proto.UtxoStateVariant.NO_SUCH_OUTPUT:
-            return 'NO_SUCH_OUTPUT';
-        default:
-            throw new Error(`Unknown UtxoStateVariant: ${variant}`);
+function convertToTxMsgType(msgType: proto.TxMsgType): TxMsgType {
+    const txMsgType = proto.txMsgTypeToJSON(msgType);
+    if (isTxMsgType(txMsgType)) {
+        return txMsgType;
     }
+    return 'UNRECOGNIZED';
 }
 
-/** Current state of the blockchain. */
-export interface BlockchainInfo {
-    /** Block hash of the current blockchain tip */
-    tipHash: string;
-    /** Current height of the blockchain */
-    tipHeight: number;
+function convertToTokenInfo(tokenInfo: proto.TokenInfo): TokenInfo {
+    if (typeof tokenInfo.tokenType === 'undefined') {
+        // Not expected to ever happen
+        throw new Error(
+            `chronik returned undefined tokenInfo.tokenType for tokenId "${tokenInfo.tokenId}"`,
+        );
+    }
+    if (typeof tokenInfo.genesisInfo === 'undefined') {
+        // Not expected to ever happen
+        throw new Error(
+            `chronik returned undefined tokenInfo.genesisInfo for tokenId "${tokenInfo.tokenId}"`,
+        );
+    }
+
+    // We use tokenType to get the correct shape of genesisInfo
+    const tokenType = convertToTokenType(tokenInfo.tokenType);
+
+    const returnedTokenInfo: TokenInfo = {
+        tokenId: tokenInfo.tokenId,
+        tokenType,
+        timeFirstSeen: parseInt(tokenInfo.timeFirstSeen),
+        genesisInfo: convertToGenesisInfo(tokenInfo.genesisInfo, tokenType),
+    };
+
+    if (typeof tokenInfo.block !== 'undefined') {
+        // Only include block if the tx is in a block
+        returnedTokenInfo.block = convertToBlockMeta(tokenInfo.block);
+    }
+
+    return returnedTokenInfo;
 }
 
-/** A transaction on the blockchain or in the mempool. */
-export interface Tx {
-    /**
-     * Transaction ID.
-     * - On BCH, eCash and Ergon, this is the hash of the tx.
-     * - On Lotus, this is a special serialization, omitting the input scripts.
-     */
-    txid: string;
-    /** `version` field of the transaction. */
-    version: number;
-    /** Inputs of this transaction. */
-    inputs: TxInput[];
-    /** Outputs of this transaction. */
-    outputs: TxOutput[];
-    /** `locktime` field of the transaction, tx is not valid before this time. */
-    lockTime: number;
-    /** SLP data about this transaction, if valid. */
-    slpTxData: SlpTxData | undefined;
-    /** A human-readable message as to why this tx is not an SLP transaction,
-     * unless trivially so. */
-    slpErrorMsg: string | undefined;
-    /** Block data for this tx, or undefined if not mined yet. */
-    block: BlockMetadata | undefined;
-    /**
-     * UNIX timestamp when this tx has first been seen in the mempool.
-     * 0 if unknown -> make sure to check.
-     */
-    timeFirstSeen: string;
-    /** Serialized size of the tx. */
-    size: number;
-    /** Whether this tx is a coinbase tx. */
-    isCoinbase: boolean;
-    /** Which network this tx is on. */
-    network: Network;
+function convertToGenesisInfo(
+    genesisInfo: proto.GenesisInfo,
+    tokenType: TokenType,
+): GenesisInfo {
+    const decoder = new TextDecoder();
+    const returnedGenesisInfo: GenesisInfo = {
+        tokenTicker: decoder.decode(genesisInfo.tokenTicker),
+        tokenName: decoder.decode(genesisInfo.tokenName),
+        url: decoder.decode(genesisInfo.url),
+        decimals: genesisInfo.decimals,
+    };
+
+    // Add ALP fields for ALP types only
+    if (tokenType.protocol === 'ALP') {
+        returnedGenesisInfo.data = genesisInfo.data;
+        returnedGenesisInfo.authPubkey = toHex(genesisInfo.authPubkey);
+    }
+
+    // Add mintVaultHash for SLP Mint Vault only
+    if (tokenType.type === 'SLP_TOKEN_TYPE_MINT_VAULT') {
+        returnedGenesisInfo.mintVaultScripthash = toHex(
+            genesisInfo.mintVaultScripthash,
+        );
+    }
+
+    // Add url for SLP only
+    if (tokenType.protocol === 'SLP') {
+        returnedGenesisInfo.hash = toHex(genesisInfo.hash);
+    }
+
+    return returnedGenesisInfo;
 }
 
-/** An unspent transaction output (aka. UTXO, aka. "Coin") of a script. */
-export interface Utxo {
-    /** Outpoint of the UTXO. */
-    outpoint: OutPoint;
-    /** Which block this UTXO is in, or -1 if in the mempool. */
-    blockHeight: number;
-    /**
-     * Whether this UTXO is a coinbase UTXO
-     * (make sure it's buried 100 blocks before spending!)
-     */
-    isCoinbase: boolean;
-    /** Value of the UTXO in satoshis. */
-    value: string;
-    /** SLP data in this UTXO. */
-    slpMeta: SlpMeta | undefined;
-    /** SLP token of this UTXO (i.e. SLP amount + whether it's a mint baton). */
-    slpToken: SlpToken | undefined;
-    /** Which network this UTXO is on. */
-    network: Network;
+function isTxMsgType(msgType: any): msgType is TxMsgType {
+    return TX_MSG_TYPES.includes(msgType);
 }
 
-/** Data and stats about an SLP token. */
-export interface Token {
-    /** SLP data of the GENESIS transaction. */
-    slpTxData: SlpTokenTxData;
-    /** Current stats about this token, e.g. minted and burned amount. */
-    tokenStats: TokenStats;
-    /** Block the GENESIS transaction has been mined in, or undefined if not mined yet. */
-    block: BlockMetadata | undefined;
-    /**
-     * UNIX timestamp when the GENESIS transaction has first been seen in the mempool.
-     * 0 if unknown.
-     */
-    timeFirstSeen: string;
-    /** How many tokens have been mined in the GENESIS transaction. */
-    initialTokenQuantity: string;
-    /**
-     * Whether the GENESIS transaction created a mint baton.
-     * Note: This doesn't indicate whether the mint baton is still alive.
-     */
-    containsBaton: boolean;
-    /** Which network this token is on. */
-    network: Network;
+/** Info about connected chronik server */
+export interface ChronikInfo {
+    version: string;
 }
 
-/** Block info about a block */
+/**  BlockInfo interface for in-node chronik */
 export interface BlockInfo {
     /** Block hash of the block, in 'human-readable' (big-endian) hex encoding. */
     hash: string;
-    /**
-     * Block hash of the previous block, in 'human-readable' (big-endian) hex
-     * encoding.
-     */
+    /** Block hash of the prev block, in 'human-readable' (big-endian) hex encoding. */
     prevHash: string;
     /** Height of the block; Genesis block has height 0. */
     height: number;
     /** nBits field of the block, encodes the target compactly. */
     nBits: number;
     /**
-     * Timestamp of the block. Filled in by the miner, so might not be 100%
-     * precise.
+     * Timestamp of the block. Filled in by the miner,
+     * so might not be 100 % precise.
      */
-    timestamp: string;
+    timestamp: number;
+    /** Is this block avalanche finalized? */
+    isFinal: boolean;
     /** Block size of this block in bytes (including headers etc.). */
-    blockSize: string;
+    blockSize: number;
     /** Number of txs in this block. */
-    numTxs: string;
+    numTxs: number;
     /** Total number of tx inputs in block (including coinbase). */
-    numInputs: string;
+    numInputs: number;
     /** Total number of tx output in block (including coinbase). */
-    numOutputs: string;
+    numOutputs: number;
     /** Total number of satoshis spent by tx inputs. */
-    sumInputSats: string;
+    sumInputSats: number;
     /** Total block reward for this block. */
-    sumCoinbaseOutputSats: string;
+    sumCoinbaseOutputSats: number;
     /** Total number of satoshis in non-coinbase tx outputs. */
-    sumNormalOutputSats: string;
+    sumNormalOutputSats: number;
     /** Total number of satoshis burned using OP_RETURN. */
-    sumBurnedSats: string;
-}
-
-/** Additional details about a block. */
-export interface BlockDetails {
-    /** nVersion field of the block. */
-    version: number;
-    /** Merkle root of the block. */
-    merkleRoot: string;
-    /** Nonce of the block (32-bit on XEC, 64-bit on XPI). */
-    nonce: string;
-    /** Median-time-past (MTP) of the last 11 blocks. */
-    medianTimestamp: string;
+    sumBurnedSats: number;
 }
 
-/** Block on the blockchain. */
+/** Block interface for in-node chronik */
 export interface Block {
-    /** Info about the block. */
+    /** Contains the blockInfo object defined above */
     blockInfo: BlockInfo;
-    /** Details about the block. */
-    blockDetails: BlockDetails;
-    /** Header encoded as hex. */
-    rawHeader: string;
-    /**
-     * Txs in this block, in canonical order
-     * (at least on all supported chains).
-     */
-    txs: Tx[];
 }
 
-/** Group of UTXOs by output script. */
-export interface ScriptUtxos {
-    /** Output script in hex. */
-    outputScript: string;
-    /** UTXOs of the output script. */
-    utxos: Utxo[];
-}
-
-/** Page of the transaction history. */
+/** A page of in-node chronik tx history */
 export interface TxHistoryPage {
-    /** Txs of this page. */
+    /** Txs of the page */
     txs: Tx[];
-    /**
-     * Number of pages of the entire transaction history.
-     * This changes based on the `pageSize` provided.
-     */
+    /** How many pages there are total */
     numPages: number;
+    /** How many txs there are total */
+    numTxs: number;
 }
 
-/** SLP data about an SLP transaction. */
-export interface SlpTxData {
-    /** SLP metadata. */
-    slpMeta: SlpMeta;
-    /** Genesis info, only present for GENESIS txs. */
-    genesisInfo: SlpGenesisInfo | undefined;
+/** The hex bytes of a raw tx */
+export interface RawTx {
+    rawTx: string;
 }
 
-/** SLP data about an SLP transaction. */
-export interface SlpTokenTxData {
-    /** SLP metadata. */
-    slpMeta: SlpMeta;
-    /** Genesis info of the token. */
-    genesisInfo: SlpGenesisInfo;
+/** Current state of the blockchain. */
+export interface BlockchainInfo {
+    /** Block hash of the current blockchain tip */
+    tipHash: string;
+    /** Current height of the blockchain */
+    tipHeight: number;
 }
 
-/** Metadata about an SLP tx or UTXO. */
-export interface SlpMeta {
-    /** Whether this token is a normal fungible token, or an NFT or unknown. */
-    tokenType: SlpTokenType;
-    /** Whether this tx is a GENESIS, MINT, SEND or UNKNOWN transaction. */
-    txType: SlpTxType;
-    /** Token ID of this tx/UTXO, in human-readable (big-endian) hex encoding. */
-    tokenId: string;
+/**
+ * Outpoint referencing an output on the blockchain (or input for field
+ * `spentBy`).
+ */
+export interface OutPoint {
+    /** Transaction referenced by this outpoint. */
+    txid: string;
     /**
-     * Group token ID of this tx/UTXO, NFT only, in human-readable
-     * (big-endian) hex encoding.
-     * This is the token ID of the token that went into the GENESIS of this token
-     * as first input.
+     * Index of the output in the tx referenced by this outpoint
+     * (or input index if used in field `spentBy`).
      */
-    groupTokenId: string | undefined;
+    outIdx: number;
 }
 
-/**
- * Stats about a token.
- *
- * `totalMinted` and `totalBurned` don't fit in a 64-bit integer, therefore we
- * use a string with the decimal representation.
- */
-export interface TokenStats {
-    /** Total number of tokens minted (including GENESIS). */
-    totalMinted: string;
-    /** Total number of tokens burned. */
-    totalBurned: string;
+/** A transaction on the blockchain or in the mempool. */
+export interface Tx {
+    /** Transaction ID. */
+    txid: string;
+    /** `version` field of the transaction. */
+    version: number;
+    /** Inputs of this transaction. */
+    inputs: TxInput[];
+    /** Outputs of this transaction. */
+    outputs: TxOutput[];
+    /** `locktime` field of the transaction, tx is not valid before this time. */
+    lockTime: number;
+    /** Block data for this tx, if it is in a block. */
+    block?: BlockMetadata;
+    /**
+     * UNIX timestamp when this tx has first been seen in the mempool.
+     * 0 if unknown -> make sure to check.
+     */
+    timeFirstSeen: number;
+    /** Serialized size of the tx. */
+    size: number;
+    /** Whether this tx is a coinbase tx. */
+    isCoinbase: boolean;
+    /** Tokens involved in this txs */
+    tokenEntries: TokenEntry[];
+    /** Failed parsing attempts of this tx */
+    tokenFailedParsings: TokenFailedParsing[];
+    /**
+     * Token status, i.e. whether this tx has any tokens or unintentional token burns
+     * or something unexpected, like failed parsings etc.
+     */
+    tokenStatus: TokenStatus;
 }
 
 /** Input of a tx, spends an output of a previous tx. */
@@ -922,40 +1409,37 @@
     /**
      * Script of the output, in hex encoding.
      * Aka. `scriptPubKey` in bitcoind parlance.
+     * Not present for coinbase txs
      */
-    outputScript: string | undefined;
+    outputScript?: string;
     /** Value of the output spent by this input, in satoshis. */
-    value: string;
+    value: number;
     /** `sequence` field of the input; can be used for relative time locking. */
     sequenceNo: number;
-    /** SLP tokens burned by this input, or `undefined` if no burn occured. */
-    slpBurn: SlpBurn | undefined;
-    /**
-     * SLP tokens spent by this input, or `undefined` if the tokens were burned
-     * or if there were no tokens in the output spent by this input.
-     */
-    slpToken: SlpToken | undefined;
+    /** Token value attached to this input */
+    token?: Token;
+    /** Plugin data attached to this input */
+    plugins?: PluginEntries;
 }
 
 /** Output of a tx, creates new UTXOs. */
 export interface TxOutput {
     /** Value of the output, in satoshis. */
-    value: string;
+    value: number;
     /**
      * Script of this output, locking the coins.
      * Aka. `scriptPubKey` in bitcoind parlance.
      */
     outputScript: string;
     /**
-     * SLP tokens locked up in this output, or `undefined` if no tokens were sent
-     * to this output.
-     */
-    slpToken: SlpToken | undefined;
-    /**
-     * Transaction & input index spending this output, or undefined if
-     * unspent.
+     * Transaction & input index spending this output, if
+     * spent.
      */
-    spentBy: OutPoint | undefined;
+    spentBy?: OutPoint;
+    /** Token value attached to this output */
+    token?: Token;
+    /** Plugin data attached to this output */
+    plugins?: PluginEntries;
 }
 
 /** Metadata of a block, used in transaction data. */
@@ -968,182 +1452,237 @@
      * Timestamp of the block; useful if `timeFirstSeen` of a transaction is
      * unknown.
      */
-    timestamp: string;
-}
-
-/**
- * Outpoint referencing an output on the blockchain (or input for field
- * `spentBy`).
- */
-export interface OutPoint {
-    /** Transaction referenced by this outpoint. */
-    txid: string;
-    /**
-     * Index of the output in the tx referenced by this outpoint
-     * (or input index if used in field `spentBy`).
-     */
-    outIdx: number;
+    timestamp: number;
 }
 
-/** SLP amount or whether this is a mint baton, for inputs and outputs. */
-export interface SlpToken {
-    /** SLP amount of the input or output, in base units. */
-    amount: string;
-    /** Whether this input/output is a mint baton. */
-    isMintBaton: boolean;
-}
-
-/** SLP burn; indicates burn of some tokens. */
-export interface SlpBurn {
-    /** SLP amount/mint baton burned by this burn. */
-    token: SlpToken;
+/** Token involved in a transaction */
+interface TokenEntry {
     /**
-     * Token ID of the burned SLP tokens, in human-readable (big-endian) hex
-     * encoding.
+     * Hex token_id (in big-endian, like usually displayed to users) of the token.
+     * This is not `bytes` because SLP and ALP use different endiannes, so to avoid
+     * this we use hex, which conventionally implies big-endian in a bitcoin context.
      */
     tokenId: string;
-}
-
-/** SLP info about a GENESIS transaction. */
-export interface SlpGenesisInfo {
-    /** Ticker of the token, decoded as UTF-8. */
-    tokenTicker: string;
-    /** Name of the token, decoded as UTF-8. */
-    tokenName: string;
-    /** URL of the token, decoded as UTF-8. */
-    tokenDocumentUrl: string;
+    /** Token type of the token */
+    tokenType: TokenType;
+    /** Tx type of the token; NONE if there's no section that introduced it (e.g. in an accidental burn) */
+    txType: TokenTxType;
     /**
-     * Document hash of the token, encoded in hex (byte order as occuring in the
-     * OP_RETURN).
+     *  For NFT1 Child tokens: group ID
+     *  Unset if the token is not an NFT1 Child token
      */
-    tokenDocumentHash: string;
-    /** Number of decimals of the GENESIS transaction. */
-    decimals: number;
-}
-
-/** State of a UTXO (from `validateUtxos`). */
-export interface UtxoState {
+    groupTokenId?: string;
+    /** Whether the validation rules have been violated for this section */
+    isInvalid: boolean;
+    /** Human-readable error message of why this entry burned tokens */
+    burnSummary: string;
+    /** Human-readable error messages of why colorings failed */
+    failedColorings: TokenFailedColoring[];
     /**
-     * Height of the UTXO. -1 if the tx doesn't exist or is unconfirmed.
-     * If it's confirmed (or if the output doesn't exist but the tx does),
-     * it's the height of the block confirming the tx.
+     * Number of actually burned tokens (as decimal integer string, e.g. "2000").
+     * This is because burns can exceed the 64-bit range of values and protobuf doesn't have a nice type to encode this.
      */
-    height: number;
-    /** Whether the UTXO or the transaction queried is confirmed. */
-    isConfirmed: boolean;
-    /**
-     * State of the UTXO, can be unconfirmed, confirmed, tx doesn't exist or
-     * output doesn't exist.
-     */
-    state: UtxoStateVariant;
-}
-
-/** Message returned from the WebSocket. */
-export type SubscribeMsg =
-    | Error
-    | MsgAddedToMempool
-    | MsgRemovedFromMempool
-    | MsgConfirmed
-    | MsgReorg
-    | MsgBlockConnected
-    | MsgBlockDisconnected;
-
-/** A transaction has been added to the mempool. */
-export interface MsgAddedToMempool {
-    type: 'AddedToMempool';
-    /** txid of the transaction, in 'human-readable' (big-endian) hex encoding. */
-    txid: string;
+    actualBurnAmount: string;
+    /** Burn amount the user explicitly opted into (as decimal integer string) */
+    intentionalBurn: string;
+    /** Whether any mint batons have been burned of this token */
+    burnsMintBatons: boolean;
 }
 
 /**
- * A transaction has been removed from the mempool,
- * but not because of a confirmation (e.g. expiry, conflict, etc.).
+ * SLP/ALP token type
  */
-export interface MsgRemovedFromMempool {
-    type: 'RemovedFromMempool';
-    /** txid of the transaction, in 'human-readable' (big-endian) hex encoding. */
-    txid: string;
+export type TokenType = SlpTokenType | AlpTokenType;
+
+export interface SlpTokenType {
+    protocol: 'SLP';
+    type: SlpTokenType_Type;
+    number: number;
 }
 
-/** A transaction has been confirmed in a block. */
-export interface MsgConfirmed {
-    type: 'Confirmed';
-    /** txid of the transaction, in 'human-readable' (big-endian) hex encoding. */
-    txid: string;
+export interface AlpTokenType {
+    protocol: 'ALP';
+    type: AlpTokenType_Type;
+    number: number;
 }
 
+/** Possible ALP token types returned by chronik */
+export type AlpTokenType_Type =
+    | 'ALP_TOKEN_TYPE_STANDARD'
+    | 'ALP_TOKEN_TYPE_UNKNOWN';
+
+export const ALP_TOKEN_TYPES: AlpTokenType_Type[] = [
+    'ALP_TOKEN_TYPE_STANDARD',
+    'ALP_TOKEN_TYPE_UNKNOWN',
+];
+
+/** Possible SLP token types returned by chronik */
+export type SlpTokenType_Type =
+    | 'SLP_TOKEN_TYPE_FUNGIBLE'
+    | 'SLP_TOKEN_TYPE_MINT_VAULT'
+    | 'SLP_TOKEN_TYPE_NFT1_GROUP'
+    | 'SLP_TOKEN_TYPE_NFT1_CHILD'
+    | 'SLP_TOKEN_TYPE_UNKNOWN';
+
+const SLP_TOKEN_TYPES: SlpTokenType_Type[] = [
+    'SLP_TOKEN_TYPE_FUNGIBLE',
+    'SLP_TOKEN_TYPE_MINT_VAULT',
+    'SLP_TOKEN_TYPE_NFT1_GROUP',
+    'SLP_TOKEN_TYPE_NFT1_CHILD',
+    'SLP_TOKEN_TYPE_UNKNOWN',
+];
+
 /**
- * A transaction used to be part of a block but now got re-orged.
- * Usually, unless something malicious occurs, a "Confirmed" message is sent
- * immediately afterwards.
+ * TokenStatus
+ * TOKEN_STATUS_NON_TOKEN - Tx involves no tokens whatsover, i.e. neither any burns nor any failed
+ * parsing/coloring or any tokens being created / moved.
+ * TOKEN_STATUS_NORMAL - Tx involves tokens but no unintentional burns or failed parsings/colorings
+ * TOKEN_STATUS_NOT_NORMAL - Tx involves tokens but contains unintentional burns or failed parsings/colorings
+ * TOKEN_STATUS_UNKNOWN - Token tx of unknown status
  */
-export interface MsgReorg {
-    type: 'Reorg';
-    /** txid of the transaction, in 'human-readable' (big-endian) hex encoding. */
-    txid: string;
-}
-
-/** A new block has been added to the chain. Sent regardless of subscriptions. */
-export interface MsgBlockConnected {
-    type: 'BlockConnected';
-    /** block hash of the block, in 'human-readable' (big-endian) hex encoding. */
-    blockHash: string;
-}
+export type TokenStatus =
+    | 'TOKEN_STATUS_NON_TOKEN'
+    | 'TOKEN_STATUS_NORMAL'
+    | 'TOKEN_STATUS_NOT_NORMAL'
+    | 'TOKEN_STATUS_UNKNOWN';
+
+const TOKEN_STATUS_TYPES: TokenStatus[] = [
+    'TOKEN_STATUS_NON_TOKEN',
+    'TOKEN_STATUS_NORMAL',
+    'TOKEN_STATUS_NOT_NORMAL',
+    'TOKEN_STATUS_UNKNOWN',
+];
+
+/** SLP/ALP tx type */
+export type TokenTxType =
+    /** NONE - No tx type, e.g. when input tokens are burned */
+    | 'NONE'
+    /** UNKNOWN - Unknown tx type, i.e. for unknown token types */
+    | 'UNKNOWN'
+    /** GENESIS - GENESIS tx */
+    | 'GENESIS'
+    /** SEND - SEND tx */
+    | 'SEND'
+    /** MINT - MINT tx */
+    | 'MINT'
+    /** BURN - BURN tx */
+    | 'BURN';
+
+const TOKEN_TX_TYPE_TYPES: TokenTxType[] = [
+    'NONE',
+    'UNKNOWN',
+    'GENESIS',
+    'SEND',
+    'MINT',
+    'BURN',
+];
 
-/** A block has been removed from the chain. Sent regardless of subscriptions. */
-export interface MsgBlockDisconnected {
-    type: 'BlockDisconnected';
-    /** block hash of the block, in 'human-readable' (big-endian) hex encoding. */
-    blockHash: string;
+/**
+ * A report of a failed coloring attempt of SLP/ALP.
+ * This should always indicate something went wrong when building the tx.
+ */
+export interface TokenFailedColoring {
+    /** For ALP, the index of the pushdata in the OP_RETURN that failed parsing. */
+    pushdataIdx: number;
+    /** Human-readable message of what went wrong */
+    error: string;
 }
 
-/** Reports an error, e.g. when a subscription is malformed. */
-export interface Error {
-    type: 'Error';
-    /** Code for this error, e.g. "tx-not-found". */
-    errorCode: string;
-    /** Human-readable message for this error. */
-    msg: string;
+/**
+ * TokenFailedParsing
+ * A report of a failed parsing attempt of SLP/ALP.
+ * This should always indicate something went wrong when building the tx.
+ */
+export interface TokenFailedParsing {
     /**
-     * Whether this error is presentable to an end-user.
-     * This is somewhat subjective, but can be used as a good heuristic.
+     * For ALP, the index of the pushdata in the OP_RETURN that failed parsing.
+     * -1 if the whole OP_RETURN failed, e.g. for SLP or eMPP
      */
-    isUserError: boolean;
+    pushdataIdx: number;
+    /** The bytes that failed parsing, useful for debugging */
+    bytes: string;
+    /** Human-readable message of what went wrong */
+    error: string;
 }
 
-/**
- * Different networks of txs/blocks/UTXOs.
- * Supported are BCH, eCash, Lotus and Ergon.
- */
-export type Network = 'BCH' | 'XEC' | 'XPI' | 'XRG';
+/** Data attached by a plugin to an output */
+export interface PluginEntry {
+    /** Groups assigned to this output */
+    groups: string[];
+    /** Data assigned to the output */
+    data: string[];
+}
 
-/** Which SLP tx type. */
-export type SlpTxType =
-    | 'GENESIS'
-    | 'SEND'
-    | 'MINT'
-    | 'BURN'
-    | 'UNKNOWN_TX_TYPE';
+export type PluginEntries = { [key: string]: PluginEntry };
 
-/** Which SLP token type (normal fungible, NFT, unknown). */
-export type SlpTokenType =
-    | 'FUNGIBLE'
-    | 'NFT1_GROUP'
-    | 'NFT1_CHILD'
-    | 'UNKNOWN_TOKEN_TYPE';
+/** Group of UTXOs by output script. */
+export interface ScriptUtxos {
+    /** Output script in hex. */
+    outputScript: string;
+    /** UTXOs of the output script. */
+    utxos: ScriptUtxo[];
+}
+
+/** An unspent transaction output (aka. UTXO, aka. "Coin") of a script. */
+export interface ScriptUtxo {
+    /** Outpoint of the UTXO. */
+    outpoint: OutPoint;
+    /** Which block this UTXO is in, or -1 if in the mempool. */
+    blockHeight: number;
+    /** Whether this UTXO is a coinbase UTXO
+     * (make sure it's buried 100 blocks before spending!) */
+    isCoinbase: boolean;
+    /** Value of the UTXO in satoshis. */
+    value: number;
+    /** Is this utxo avalanche finalized */
+    isFinal: boolean;
+    /** Token value attached to this utxo */
+    token?: Token;
+    /** Plugin data attached to this output */
+    plugins?: PluginEntries;
+}
 
 /**
- * State of a transaction output.
- * - `UNSPENT`: The UTXO is unspent.
- * - `SPENT`: The output is spent and no longer part of the UTXO set.
- * - `NO_SUCH_TX`: The tx queried does not exist.
- * - `NO_SUCH_OUTPUT`: The output queried does not exist, but the tx does exist.
+ * An unspent transaction output (aka. UTXO, aka. "Coin") with script attached
+ * Useful when getting utxos by something other than script, e.g. tokenId
  */
-export type UtxoStateVariant =
-    | 'UNSPENT'
-    | 'SPENT'
-    | 'NO_SUCH_TX'
-    | 'NO_SUCH_OUTPUT';
+export interface Utxo {
+    /** Outpoint of the UTXO. */
+    outpoint: OutPoint;
+    /** Which block this UTXO is in, or -1 if in the mempool. */
+    blockHeight: number;
+    /** Whether this UTXO is a coinbase UTXO
+     * (make sure it's buried 100 blocks before spending!) */
+    isCoinbase: boolean;
+    /** Value of the UTXO in satoshis. */
+    value: number;
+    /** Bytecode of the script of the output */
+    script: string;
+    /** Is this utxo avalanche finalized */
+    isFinal: boolean;
+    /** Token value attached to this utxo */
+    token?: Token;
+    /** Plugin data attached to this output */
+    plugins?: PluginEntries;
+}
+
+/** Token coloring an input or output */
+export interface Token {
+    /** Hex token_id of the token, see `TokenInfo` for details */
+    tokenId: string;
+    /** Token type of the token */
+    tokenType: TokenType;
+    /**
+     * Index into `token_entries` for `Tx`
+     * chronik returns -1 for UTXOs, chronik-client
+     * passes no entryIdx key for UTXOS
+     */
+    entryIdx?: number;
+    /** Base token amount of the input/output */
+    amount: string;
+    /** Whether the token is a mint baton */
+    isMintBaton: boolean;
+}
 
 /**
  * Script type queried in the `script` method.
@@ -1156,16 +1695,157 @@
  *   Payload is the 20 byte public key hash.
  * - `p2sh`: Pay-to-Script-Hash (`OP_HASH160 <sh> OP_EQUAL`).
  *   Payload is the 20 byte script hash.
- * - `p2tr-commitment`: Pay-to-Taproot
- *   (`OP_SCRIPTTYPE OP_1 <commitment> <state>?`), only on Lotus.
- *   Queries by the commitment. Payload is the 33 byte commitment.
- * - `p2tr-state`: Pay-to-Taproot (`OP_SCRIPTTYPE OP_1 <commitment> <state>`),
- *   only on Lotus. Queries by the state. Payload is the 32 byte state.
  */
-export type ScriptType =
-    | 'other'
-    | 'p2pk'
-    | 'p2pkh'
-    | 'p2sh'
-    | 'p2tr-commitment'
-    | 'p2tr-state';
+export type ScriptType = 'other' | 'p2pk' | 'p2pkh' | 'p2sh';
+
+/** Message returned from the WebSocket, translated to be more human-readable for client */
+export type WsMsgClient = Error | MsgBlockClient | MsgTxClient;
+
+/** Block got connected, disconnected, finalized, etc.*/
+export interface MsgBlockClient {
+    type: 'Block';
+    /** What happened to the block */
+    msgType: BlockMsgType;
+    /** Hash of the block (human-readable big-endian) */
+    blockHash: string;
+    /** Height of the block */
+    blockHeight: number;
+}
+
+/** Block message types that can come from chronik */
+export type BlockMsgType =
+    | 'BLK_CONNECTED'
+    | 'BLK_DISCONNECTED'
+    | 'BLK_FINALIZED'
+    | 'UNRECOGNIZED';
+
+const BLK_MSG_TYPES: BlockMsgType[] = [
+    'BLK_CONNECTED',
+    'BLK_DISCONNECTED',
+    'BLK_FINALIZED',
+    'UNRECOGNIZED',
+];
+
+/** Tx got added to/removed from mempool, or confirmed in a block, etc.*/
+export interface MsgTxClient {
+    type: 'Tx';
+    /** What happened to the tx */
+    msgType: TxMsgType;
+    /** Txid of the tx (human-readable big-endian) */
+    txid: string;
+}
+
+/** Tx message types that can come from chronik */
+export type TxMsgType =
+    | 'TX_ADDED_TO_MEMPOOL'
+    | 'TX_REMOVED_FROM_MEMPOOL'
+    | 'TX_CONFIRMED'
+    | 'TX_FINALIZED'
+    | 'UNRECOGNIZED';
+
+const TX_MSG_TYPES: TxMsgType[] = [
+    'TX_ADDED_TO_MEMPOOL',
+    'TX_REMOVED_FROM_MEMPOOL',
+    'TX_CONFIRMED',
+    'TX_FINALIZED',
+    'UNRECOGNIZED',
+];
+
+/* The script type and its associated payload for a chronik-client subscribeToScript subscription */
+export interface WsSubScriptClient {
+    /** Script type to subscribe to ("p2pkh", "p2sh", "p2pk", "other"). */
+    scriptType: ScriptType;
+    /**
+     * Payload for the given script type:
+     * - 20-byte hash for "p2pkh" and "p2sh"
+     * - 33-byte or 65-byte pubkey for "p2pk"
+     * - Serialized script for "other"
+     */
+    payload: string;
+}
+
+export interface Error {
+    type: 'Error';
+    msg: string;
+}
+
+/** List of UTXOs */
+export interface TokenIdUtxos {
+    /** TokenId used to fetch these utxos */
+    tokenId: string;
+    /** UTXOs */
+    utxos: Utxo[];
+}
+
+/** List of UTXOs */
+export interface PluginUtxos {
+    /** Plugin used to fetch these utxos */
+    pluginName: string;
+    /** Group hex */
+    groupHex: string;
+    /** UTXOs */
+    utxos: Utxo[];
+}
+
+/**
+ * Information about a given plugin group
+ * For now, we just include the group
+ */
+export interface PluginGroup {
+    group: string;
+}
+
+/** List of plugin groups */
+export interface PluginGroups {
+    groups: PluginGroup[];
+    nextStart: string;
+}
+
+/** Info about a token */
+export interface TokenInfo {
+    /**
+     * Hex token_id (in big-endian, like usually displayed to users) of the token.
+     * This is not `bytes` because SLP and ALP use different endiannnes,
+     * so to avoid this we use hex, which conventionally implies big-endian in a bitcoin context.
+     */
+    tokenId: string;
+    /** Token type of the token */
+    tokenType: TokenType;
+    /** Info found in the token's GENESIS tx */
+    genesisInfo: GenesisInfo;
+    /** Block of the GENESIS tx, if it's mined already */
+    block?: BlockMetadata;
+    /** Time the GENESIS tx has first been seen by the indexer */
+    timeFirstSeen: number;
+}
+
+/** Genesis info found in GENESIS txs of tokens */
+export interface GenesisInfo {
+    /** token_ticker of the token */
+    tokenTicker: string;
+    /** token_name of the token */
+    tokenName: string;
+    /** URL of the token */
+    url: string;
+    /** token_document_hash of the token (only on SLP) */
+    hash?: string;
+    /** mint_vault_scripthash (only on SLP V2 Mint Vault) */
+    mintVaultScripthash?: string;
+    /** Arbitray payload data of the token (only on ALP) */
+    data?: Uint8Array;
+    /** auth_pubkey of the token (only on ALP) */
+    authPubkey?: string;
+    /** decimals of the token, i.e. how many decimal places the token should be displayed with. */
+    decimals: number;
+}
+
+interface WsSubscriptions {
+    /** Subscriptions to scripts */
+    scripts: WsSubScriptClient[];
+    /** Subscriptions to tokens by tokenId */
+    tokens: string[];
+    /** Subscriptions to lokadIds */
+    lokadIds: string[];
+    /** Subscription to blocks */
+    blocks: boolean;
+}
diff --git a/modules/chronik-client/src/ChronikClientNode.ts b/modules/chronik-client/src/ChronikClientNode.ts
deleted file mode 100644
--- a/modules/chronik-client/src/ChronikClientNode.ts
+++ /dev/null
@@ -1,1835 +0,0 @@
-// Copyright (c) 2023-2024 The Bitcoin developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-import cashaddr from 'ecashaddrjs';
-import WebSocket from 'isomorphic-ws';
-import * as ws from 'ws';
-import * as proto from '../proto/chronikNode';
-import { BlockchainInfo, OutPoint } from './ChronikClient';
-import { FailoverProxy } from './failoverProxy';
-import { fromHex, toHex, toHexRev } from './hex';
-import {
-    isValidWsSubscription,
-    verifyLokadId,
-    verifyTokenId,
-} from './validation';
-
-type MessageEvent = ws.MessageEvent | { data: Blob };
-
-/**
- * Client to access an in-node Chronik instance.
- * Plain object, without any connections.
- */
-export class ChronikClientNode {
-    private _proxyInterface: FailoverProxy;
-    /**
-     * Create a new client. This just creates an object, without any connections.
-     *
-     * @param {string[]} urls Array of valid urls. A valid url comes with schema and without a trailing slash.
-     * e.g. '['https://chronik.be.cash/xec2', 'https://chronik-native.fabien.cash']
-     * The approach of accepting an array of urls as input is to ensure redundancy if the
-     * first url encounters downtime.
-     * @throws {error} throws error on invalid constructor inputs
-     */
-    constructor(urls: string[]) {
-        // Instantiate FailoverProxy with the urls array
-        this._proxyInterface = new FailoverProxy(urls);
-    }
-
-    // For unit test verification
-    public proxyInterface(): FailoverProxy {
-        return this._proxyInterface;
-    }
-
-    /**
-     * Broadcasts the `rawTx` on the network.
-     * If `skipTokenChecks` is false, it will be checked that the tx doesn't burn
-     * any tokens before broadcasting.
-     */
-    public async broadcastTx(
-        rawTx: Uint8Array | string,
-        skipTokenChecks = false,
-    ): Promise<{ txid: string }> {
-        const request = proto.BroadcastTxRequest.encode({
-            rawTx: typeof rawTx === 'string' ? fromHex(rawTx) : rawTx,
-            skipTokenChecks,
-        }).finish();
-        const data = await this._proxyInterface.post('/broadcast-tx', request);
-        const broadcastResponse = proto.BroadcastTxResponse.decode(data);
-        return {
-            txid: toHexRev(broadcastResponse.txid),
-        };
-    }
-
-    /**
-     * Broadcasts the `rawTxs` on the network, only if all of them are valid.
-     * If `skipTokenChecks` is false, it will be checked that the txs don't burn
-     * any tokens before broadcasting.
-     */
-    public async broadcastTxs(
-        rawTxs: (Uint8Array | string)[],
-        skipTokenChecks = false,
-    ): Promise<{ txids: string[] }> {
-        const request = proto.BroadcastTxsRequest.encode({
-            rawTxs: rawTxs.map(rawTx =>
-                typeof rawTx === 'string' ? fromHex(rawTx) : rawTx,
-            ),
-            skipTokenChecks,
-        }).finish();
-        const data = await this._proxyInterface.post('/broadcast-txs', request);
-        const broadcastResponse = proto.BroadcastTxsResponse.decode(data);
-        return {
-            txids: broadcastResponse.txids.map(toHexRev),
-        };
-    }
-
-    /** Fetch current info of the blockchain, such as tip hash and height. */
-    public async blockchainInfo(): Promise<BlockchainInfo> {
-        const data = await this._proxyInterface.get(`/blockchain-info`);
-        const blockchainInfo = proto.BlockchainInfo.decode(data);
-        return convertToBlockchainInfo(blockchainInfo);
-    }
-
-    /** Fetch info about the current running chronik server */
-    public async chronikInfo(): Promise<ChronikInfo> {
-        const data = await this._proxyInterface.get(`/chronik-info`);
-        const chronikServerInfo = proto.ChronikInfo.decode(data);
-        return convertToChronikInfo(chronikServerInfo);
-    }
-
-    /** Fetch the block given hash or height. */
-    public async block(hashOrHeight: string | number): Promise<Block_InNode> {
-        const data = await this._proxyInterface.get(`/block/${hashOrHeight}`);
-        const block = proto.Block.decode(data);
-        return convertToBlock(block);
-    }
-
-    /** Fetch the tx history of a block given hash or height. */
-    public async blockTxs(
-        hashOrHeight: string | number,
-        page = 0, // Get the first page if unspecified
-        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
-    ): Promise<TxHistoryPage_InNode> {
-        const data = await this._proxyInterface.get(
-            `/block-txs/${hashOrHeight}?page=${page}&page_size=${pageSize}`,
-        );
-        const blockTxs = proto.TxHistoryPage.decode(data);
-        return convertToTxHistoryPage(blockTxs);
-    }
-
-    /**
-     * Fetch block info of a range of blocks.
-     * `startHeight` and `endHeight` are inclusive ranges.
-     */
-    public async blocks(
-        startHeight: number,
-        endHeight: number,
-    ): Promise<BlockInfo_InNode[]> {
-        const data = await this._proxyInterface.get(
-            `/blocks/${startHeight}/${endHeight}`,
-        );
-        const blocks = proto.Blocks.decode(data);
-        return blocks.blocks.map(convertToBlockInfo);
-    }
-
-    /** Fetch token info and stats given the tokenId. */
-    public async token(tokenId: string): Promise<TokenInfo> {
-        const data = await this._proxyInterface.get(`/token/${tokenId}`);
-        const tokenInfo = proto.TokenInfo.decode(data);
-        return convertToTokenInfo(tokenInfo);
-    }
-
-    /** Fetch tx details given the txid. */
-    public async tx(txid: string): Promise<Tx_InNode> {
-        const data = await this._proxyInterface.get(`/tx/${txid}`);
-        const tx = proto.Tx.decode(data);
-        return convertToTx(tx);
-    }
-
-    /** Fetch tx details given the txid. */
-    public async rawTx(txid: string): Promise<RawTx> {
-        const data = await this._proxyInterface.get(`/raw-tx/${txid}`);
-        const rawTx = proto.RawTx.decode(data);
-        return convertToRawTx(rawTx);
-    }
-
-    /** Create object that allows fetching info about a given token */
-    public tokenId(tokenId: string): TokenIdEndpoint {
-        return new TokenIdEndpoint(this._proxyInterface, tokenId);
-    }
-
-    /** Create object that allows fetching info about a given lokadId */
-    public lokadId(lokadId: string): LokadIdEndpoint {
-        return new LokadIdEndpoint(this._proxyInterface, lokadId);
-    }
-
-    /** Create object that allows fetching info about a given plugin */
-    public plugin(pluginName: string): PluginEndpoint {
-        return new PluginEndpoint(this._proxyInterface, pluginName);
-    }
-
-    /** Create object that allows fetching script history or UTXOs. */
-    public script(
-        scriptType: ScriptType_InNode,
-        scriptPayload: string,
-    ): ScriptEndpointInNode {
-        return new ScriptEndpointInNode(
-            this._proxyInterface,
-            scriptType,
-            scriptPayload,
-        );
-    }
-
-    /** Create object that allows fetching script history or UTXOs by p2pkh or p2sh address */
-    public address(address: string): ScriptEndpointInNode {
-        const { type, hash } = cashaddr.decode(address, true);
-
-        return new ScriptEndpointInNode(
-            this._proxyInterface,
-            type,
-            hash as string,
-        );
-    }
-
-    /** Open a WebSocket connection to listen for updates. */
-    public ws(config: WsConfig_InNode): WsEndpoint_InNode {
-        return new WsEndpoint_InNode(this._proxyInterface, config);
-    }
-}
-
-/** Allows fetching script history and UTXOs. */
-export class ScriptEndpointInNode {
-    private _proxyInterface: FailoverProxy;
-    private _scriptType: string;
-    private _scriptPayload: string;
-
-    constructor(
-        proxyInterface: FailoverProxy,
-        scriptType: string,
-        scriptPayload: string,
-    ) {
-        this._proxyInterface = proxyInterface;
-        this._scriptType = scriptType;
-        this._scriptPayload = scriptPayload;
-    }
-
-    /**
-     * Fetches the tx history of this script, in anti-chronological order.
-     * This means it's ordered by first-seen first, i.e. TxHistoryPage_InNode.txs[0]
-     * will be the most recent tx. If the tx hasn't been seen
-     * by the indexer before, it's ordered by the block timestamp.
-     * @param page Page index of the tx history.
-     * @param pageSize Number of txs per page.
-     */
-    public async history(
-        page = 0, // Get the first page if unspecified
-        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
-    ): Promise<TxHistoryPage_InNode> {
-        const data = await this._proxyInterface.get(
-            `/script/${this._scriptType}/${this._scriptPayload}/history?page=${page}&page_size=${pageSize}`,
-        );
-        const historyPage = proto.TxHistoryPage.decode(data);
-        return {
-            txs: historyPage.txs.map(convertToTx),
-            numPages: historyPage.numPages,
-            numTxs: historyPage.numTxs,
-        };
-    }
-
-    /**
-     * Fetches the confirmed tx history of this script, in the order they appear on the blockchain.
-     * @param page Page index of the tx history.
-     * @param pageSize Number of txs per page.
-     */
-    public async confirmedTxs(
-        page = 0, // Get the first page if unspecified
-        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
-    ): Promise<TxHistoryPage_InNode> {
-        const data = await this._proxyInterface.get(
-            `/script/${this._scriptType}/${this._scriptPayload}/confirmed-txs?page=${page}&page_size=${pageSize}`,
-        );
-        const historyPage = proto.TxHistoryPage.decode(data);
-        return {
-            txs: historyPage.txs.map(convertToTx),
-            numPages: historyPage.numPages,
-            numTxs: historyPage.numTxs,
-        };
-    }
-
-    /**
-     * Fetches the unconfirmed tx history of this script, in chronological order.
-     * @param page Page index of the tx history.
-     * @param pageSize Number of txs per page.
-     */
-    public async unconfirmedTxs(
-        page = 0, // Get the first page if unspecified
-        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
-    ): Promise<TxHistoryPage_InNode> {
-        const data = await this._proxyInterface.get(
-            `/script/${this._scriptType}/${this._scriptPayload}/unconfirmed-txs?page=${page}&page_size=${pageSize}`,
-        );
-        const historyPage = proto.TxHistoryPage.decode(data);
-        return {
-            txs: historyPage.txs.map(convertToTx),
-            numPages: historyPage.numPages,
-            numTxs: historyPage.numTxs,
-        };
-    }
-
-    /**
-     * Fetches the current UTXO set for this script.
-     * It is grouped by output script, in case a script type can match multiple
-     * different output scripts (e.g. Taproot on Lotus).
-     */
-    public async utxos(): Promise<ScriptUtxos_InNode> {
-        const data = await this._proxyInterface.get(
-            `/script/${this._scriptType}/${this._scriptPayload}/utxos`,
-        );
-        const scriptUtxos = proto.ScriptUtxos.decode(data);
-        return {
-            outputScript: toHex(scriptUtxos.script),
-            utxos: scriptUtxos.utxos.map(convertToScriptUtxo),
-        };
-    }
-}
-
-/** Allows fetching tokenId confirmedTxs, unconfirmedTxs, history, and UTXOs. */
-export class TokenIdEndpoint {
-    private _proxyInterface: FailoverProxy;
-    private _tokenId: string;
-
-    constructor(proxyInterface: FailoverProxy, tokenId: string) {
-        this._proxyInterface = proxyInterface;
-        this._tokenId = tokenId;
-    }
-
-    /**
-     * Fetches the tx history of this tokenId, in anti-chronological order.
-     * @param page Page index of the tx history.
-     * @param pageSize Number of txs per page.
-     */
-    public async history(
-        page = 0, // Get the first page if unspecified
-        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
-    ): Promise<TxHistoryPage_InNode> {
-        const data = await this._proxyInterface.get(
-            `/token-id/${this._tokenId}/history?page=${page}&page_size=${pageSize}`,
-        );
-        const historyPage = proto.TxHistoryPage.decode(data);
-        return {
-            txs: historyPage.txs.map(convertToTx),
-            numPages: historyPage.numPages,
-            numTxs: historyPage.numTxs,
-        };
-    }
-
-    /**
-     * Fetches the confirmed tx history of this tokenId, in the order they appear on the blockchain.
-     * @param page Page index of the tx history.
-     * @param pageSize Number of txs per page.
-     */
-    public async confirmedTxs(
-        page = 0, // Get the first page if unspecified
-        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
-    ): Promise<TxHistoryPage_InNode> {
-        const data = await this._proxyInterface.get(
-            `/token-id/${this._tokenId}/confirmed-txs?page=${page}&page_size=${pageSize}`,
-        );
-        const historyPage = proto.TxHistoryPage.decode(data);
-        return {
-            txs: historyPage.txs.map(convertToTx),
-            numPages: historyPage.numPages,
-            numTxs: historyPage.numTxs,
-        };
-    }
-
-    /**
-     * Fetches the unconfirmed tx history of this tokenId, in chronological order.
-     * @param page Page index of the tx history.
-     * @param pageSize Number of txs per page.
-     */
-    public async unconfirmedTxs(
-        page = 0, // Get the first page if unspecified
-        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
-    ): Promise<TxHistoryPage_InNode> {
-        const data = await this._proxyInterface.get(
-            `/token-id/${this._tokenId}/unconfirmed-txs?page=${page}&page_size=${pageSize}`,
-        );
-        const historyPage = proto.TxHistoryPage.decode(data);
-        return {
-            txs: historyPage.txs.map(convertToTx),
-            numPages: historyPage.numPages,
-            numTxs: historyPage.numTxs,
-        };
-    }
-
-    /**
-     * Fetches the current UTXO set for this tokenId.
-     */
-    public async utxos(): Promise<TokenIdUtxos> {
-        const data = await this._proxyInterface.get(
-            `/token-id/${this._tokenId}/utxos`,
-        );
-        const utxos = proto.Utxos.decode(data);
-        return {
-            tokenId: this._tokenId,
-            utxos: utxos.utxos.map(convertToUtxo),
-        };
-    }
-}
-
-/** Allows fetching lokadId confirmedTxs, unconfirmedTxs, and history. */
-export class LokadIdEndpoint {
-    private _proxyInterface: FailoverProxy;
-    private _lokadId: string;
-
-    constructor(proxyInterface: FailoverProxy, lokadId: string) {
-        this._proxyInterface = proxyInterface;
-        this._lokadId = lokadId;
-    }
-
-    /**
-     * Fetches the tx history of this tokenId, in anti-chronological order.
-     * @param page Page index of the tx history.
-     * @param pageSize Number of txs per page.
-     */
-    public async history(
-        page = 0, // Get the first page if unspecified
-        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
-    ): Promise<TxHistoryPage_InNode> {
-        const data = await this._proxyInterface.get(
-            `/lokad-id/${this._lokadId}/history?page=${page}&page_size=${pageSize}`,
-        );
-        const historyPage = proto.TxHistoryPage.decode(data);
-        return {
-            txs: historyPage.txs.map(convertToTx),
-            numPages: historyPage.numPages,
-            numTxs: historyPage.numTxs,
-        };
-    }
-
-    /**
-     * Fetches the confirmed tx history of this tokenId, in the order they appear on the blockchain.
-     * @param page Page index of the tx history.
-     * @param pageSize Number of txs per page.
-     */
-    public async confirmedTxs(
-        page = 0, // Get the first page if unspecified
-        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
-    ): Promise<TxHistoryPage_InNode> {
-        const data = await this._proxyInterface.get(
-            `/lokad-id/${this._lokadId}/confirmed-txs?page=${page}&page_size=${pageSize}`,
-        );
-        const historyPage = proto.TxHistoryPage.decode(data);
-        return {
-            txs: historyPage.txs.map(convertToTx),
-            numPages: historyPage.numPages,
-            numTxs: historyPage.numTxs,
-        };
-    }
-
-    /**
-     * Fetches the unconfirmed tx history of this tokenId, in chronological order.
-     * @param page Page index of the tx history.
-     * @param pageSize Number of txs per page.
-     */
-    public async unconfirmedTxs(
-        page = 0, // Get the first page if unspecified
-        pageSize = 25, // Must be less than 200, let server handle error as server setting could change
-    ): Promise<TxHistoryPage_InNode> {
-        const data = await this._proxyInterface.get(
-            `/lokad-id/${this._lokadId}/unconfirmed-txs?page=${page}&page_size=${pageSize}`,
-        );
-        const historyPage = proto.TxHistoryPage.decode(data);
-        return {
-            txs: historyPage.txs.map(convertToTx),
-            numPages: historyPage.numPages,
-            numTxs: historyPage.numTxs,
-        };
-    }
-}
-
-/** Allows fetching plugin UTXOs. */
-export class PluginEndpoint {
-    private _proxyInterface: FailoverProxy;
-    private _pluginName: string;
-
-    constructor(proxyInterface: FailoverProxy, pluginName: string) {
-        this._proxyInterface = proxyInterface;
-        this._pluginName = pluginName;
-    }
-
-    /**
-     * Fetches the current UTXO set for this plugin group.
-     */
-    public async utxos(groupHex: string): Promise<PluginUtxos> {
-        const data = await this._proxyInterface.get(
-            `/plugin/${this._pluginName}/${groupHex}/utxos`,
-        );
-        const utxos = proto.Utxos.decode(data);
-        return {
-            pluginName: this._pluginName,
-            groupHex,
-            utxos: utxos.utxos.map(convertToUtxo),
-        };
-    }
-
-    /**
-     * Fetches groups of this plugin.
-     */
-    public async groups(
-        prefixHex?: string,
-        startHex?: string,
-        pageSize?: number,
-    ): Promise<PluginGroups> {
-        const query = new URLSearchParams();
-        if (prefixHex !== undefined) {
-            query.set('prefix', prefixHex);
-        }
-        if (startHex !== undefined) {
-            query.set('start', startHex);
-        }
-        if (pageSize !== undefined) {
-            query.set('page_size', pageSize.toString());
-        }
-        const data = await this._proxyInterface.get(
-            `/plugin/${this._pluginName}/groups?${query.toString()}`,
-        );
-        const groups = proto.PluginGroups.decode(data);
-
-        return convertToPluginGroups(groups);
-    }
-}
-
-/** Config for a WebSocket connection to Chronik. */
-export interface WsConfig_InNode {
-    /** Fired when a message is sent from the WebSocket. */
-    onMessage?: (msg: WsMsgClient) => void;
-
-    /** Fired when a connection has been (re)established. */
-    onConnect?: (e: ws.Event) => void;
-
-    /**
-     * Fired after a connection has been unexpectedly closed, and before a
-     * reconnection attempt is made. Only fired if `autoReconnect` is true.
-     */
-    onReconnect?: (e: ws.Event) => void;
-
-    /** Fired when an error with the WebSocket occurs. */
-    onError?: (e: ws.ErrorEvent) => void;
-
-    /**
-     * Fired after a connection has been manually closed, or if `autoReconnect`
-     * is false, if the WebSocket disconnects for any reason.
-     */
-    onEnd?: (e: ws.Event) => void;
-
-    /** Whether to automatically reconnect on disconnect, default true. */
-    autoReconnect?: boolean;
-}
-
-/** WebSocket connection to Chronik. */
-export class WsEndpoint_InNode {
-    private _proxyInterface: FailoverProxy;
-    /** Fired when a message is sent from the WebSocket. */
-    public onMessage?: (msg: WsMsgClient) => void;
-
-    /** Fired when a connection has been (re)established. */
-    public onConnect?: (e: ws.Event) => void;
-
-    /**
-     * Fired after a connection has been unexpectedly closed, and before a
-     * reconnection attempt is made. Only fired if `autoReconnect` is true.
-     */
-    public onReconnect?: (e: ws.Event) => void;
-
-    /** Fired when an error with the WebSocket occurs. */
-    public onError?: (e: ws.ErrorEvent) => void;
-
-    /**
-     * Fired after a connection has been manually closed, or if `autoReconnect`
-     * is false, if the WebSocket disconnects for any reason.
-     */
-    public onEnd?: (e: ws.Event) => void;
-
-    /** Whether to automatically reconnect on disconnect, default true. */
-    public autoReconnect: boolean;
-
-    public ws: ws.WebSocket | undefined;
-    public connected: Promise<ws.Event> | undefined;
-    public manuallyClosed: boolean;
-    public subs: WsSubscriptions;
-
-    constructor(proxyInterface: FailoverProxy, config: WsConfig_InNode) {
-        this.onMessage = config.onMessage;
-        this.onConnect = config.onConnect;
-        this.onReconnect = config.onReconnect;
-        this.onEnd = config.onEnd;
-        this.autoReconnect =
-            config.autoReconnect !== undefined ? config.autoReconnect : true;
-        this.manuallyClosed = false;
-        this.subs = { scripts: [], tokens: [], lokadIds: [], blocks: false };
-        this._proxyInterface = proxyInterface;
-    }
-
-    /** Wait for the WebSocket to be connected. */
-    public async waitForOpen() {
-        await this._proxyInterface.connectWs(this);
-        await this.connected;
-    }
-
-    /**
-     * Subscribe to block messages
-     */
-    public subscribeToBlocks() {
-        this.subs.blocks = true;
-        if (this.ws?.readyState === WebSocket.OPEN) {
-            this._subUnsubBlocks(false);
-        }
-    }
-
-    /**
-     * Unsubscribe from block messages
-     */
-    public unsubscribeFromBlocks() {
-        this.subs.blocks = false;
-        if (this.ws?.readyState === WebSocket.OPEN) {
-            this._subUnsubBlocks(true);
-        }
-    }
-
-    /**
-     * Subscribe to the given script type and payload.
-     * For "p2pkh", `scriptPayload` is the 20 byte public key hash.
-     */
-    public subscribeToScript(type: ScriptType_InNode, payload: string) {
-        // Build sub according to chronik expected type
-        const subscription: WsSubScriptClient = {
-            scriptType: type,
-            payload,
-        };
-        // We do not want to add invalid subs to ws.subs
-        const scriptSubscriptionValidationCheck =
-            isValidWsSubscription(subscription);
-
-        if (scriptSubscriptionValidationCheck !== true) {
-            // isValidWsSubscription returns string error msg if the sub is invalid
-            throw new Error(scriptSubscriptionValidationCheck as string);
-        }
-
-        this.subs.scripts.push(subscription as WsSubScriptClient);
-
-        if (this.ws?.readyState === WebSocket.OPEN) {
-            this._subUnsubScript(false, subscription);
-        }
-    }
-
-    /** Unsubscribe from the given script type and payload. */
-    public unsubscribeFromScript(type: ScriptType_InNode, payload: string) {
-        // Build sub according to chronik expected type
-        const subscription: WsSubScriptClient = {
-            scriptType: type,
-            payload,
-        };
-
-        // Find the requested unsub script and remove it
-        const unsubIndex = this.subs.scripts.findIndex(
-            sub => sub.scriptType === type && sub.payload === payload,
-        );
-        if (unsubIndex === -1) {
-            // If we cannot find this subscription in this.subs, throw an error
-            // We do not want an app developer thinking they have unsubscribed from something
-            throw new Error(`No existing sub at ${type}, ${payload}`);
-        }
-
-        // Remove the requested subscription from this.subs
-        this.subs.scripts.splice(unsubIndex, 1);
-
-        if (this.ws?.readyState === WebSocket.OPEN) {
-            this._subUnsubScript(true, subscription);
-        }
-    }
-
-    /**
-     * Subscribe to an address
-     * Method can be used for p2pkh or p2sh addresses
-     */
-    public subscribeToAddress(address: string) {
-        // Get type and hash
-        const { type, hash } = cashaddr.decode(address, true);
-
-        // Subscribe to script
-        this.subscribeToScript(type as 'p2pkh' | 'p2sh', hash as string);
-    }
-
-    /** Unsubscribe from the given address */
-    public unsubscribeFromAddress(address: string) {
-        // Get type and hash
-        const { type, hash } = cashaddr.decode(address, true);
-
-        // Unsubscribe from script
-        this.unsubscribeFromScript(type as 'p2pkh' | 'p2sh', hash as string);
-    }
-
-    /** Subscribe to a lokadId */
-    public subscribeToLokadId(lokadId: string) {
-        verifyLokadId(lokadId);
-
-        // Update ws.subs to include this lokadId
-        this.subs.lokadIds.push(lokadId);
-
-        if (this.ws?.readyState === WebSocket.OPEN) {
-            // Send subscribe msg to chronik server
-            this._subUnsubLokadId(false, lokadId);
-        }
-    }
-
-    /** Unsubscribe from the given lokadId */
-    public unsubscribeFromLokadId(lokadId: string) {
-        // Find the requested unsub lokadId and remove it
-        const unsubIndex = this.subs.lokadIds.findIndex(
-            thisLokadId => thisLokadId === lokadId,
-        );
-        if (unsubIndex === -1) {
-            // If we cannot find this subscription in this.subs.lokadIds, throw an error
-            // We do not want an app developer thinking they have unsubscribed from something if no action happened
-            throw new Error(`No existing sub at lokadId "${lokadId}"`);
-        }
-
-        // Remove the requested lokadId subscription from this.subs.lokadIds
-        this.subs.lokadIds.splice(unsubIndex, 1);
-
-        if (this.ws?.readyState === WebSocket.OPEN) {
-            // Send unsubscribe msg to chronik server
-            this._subUnsubLokadId(true, lokadId);
-        }
-    }
-
-    /** Subscribe to a tokenId */
-    public subscribeToTokenId(tokenId: string) {
-        verifyTokenId(tokenId);
-
-        // Update ws.subs to include this tokenId
-        this.subs.tokens.push(tokenId);
-
-        if (this.ws?.readyState === WebSocket.OPEN) {
-            // Send subscribe msg to chronik server
-            this._subUnsubToken(false, tokenId);
-        }
-    }
-
-    /** Unsubscribe from the given tokenId */
-    public unsubscribeFromTokenId(tokenId: string) {
-        // Find the requested unsub tokenId and remove it
-        const unsubIndex = this.subs.tokens.findIndex(
-            thisTokenId => thisTokenId === tokenId,
-        );
-        if (unsubIndex === -1) {
-            // If we cannot find this subscription in this.subs.tokens, throw an error
-            // We do not want an app developer thinking they have unsubscribed from something if no action happened
-            throw new Error(`No existing sub at tokenId "${tokenId}"`);
-        }
-
-        // Remove the requested tokenId subscription from this.subs.tokens
-        this.subs.tokens.splice(unsubIndex, 1);
-
-        if (this.ws?.readyState === WebSocket.OPEN) {
-            // Send unsubscribe msg to chronik server
-            this._subUnsubToken(true, tokenId);
-        }
-    }
-
-    /**
-     * Close the WebSocket connection and prevent any future reconnection
-     * attempts.
-     */
-    public close() {
-        this.manuallyClosed = true;
-        this.ws?.close();
-    }
-
-    private _subUnsubBlocks(isUnsub: boolean) {
-        // Blocks subscription is empty object
-        const BLOCKS_SUBSCRIPTION: proto.WsSubBlocks = {};
-        const encodedSubscription = proto.WsSub.encode({
-            isUnsub,
-            blocks: BLOCKS_SUBSCRIPTION,
-        }).finish();
-        if (this.ws === undefined) {
-            throw new Error('Invalid state; _ws is undefined');
-        }
-        this.ws.send(encodedSubscription);
-    }
-
-    private _subUnsubScript(isUnsub: boolean, subscription: WsSubScriptClient) {
-        // If this subscription is to an address, leave the 'blocks' key undefined
-        const encodedSubscription = proto.WsSub.encode({
-            isUnsub,
-            script: {
-                scriptType: (subscription as WsSubScriptClient).scriptType,
-                payload: fromHex((subscription as WsSubScriptClient).payload),
-            },
-        }).finish();
-
-        if (this.ws === undefined) {
-            throw new Error('Invalid state; _ws is undefined');
-        }
-
-        this.ws.send(encodedSubscription);
-    }
-
-    private _subUnsubLokadId(isUnsub: boolean, lokadId: string) {
-        const encodedSubscription = proto.WsSub.encode({
-            isUnsub,
-            lokadId: {
-                // User input for lokadId is string
-                // Chronik expects bytes
-                lokadId: fromHex(lokadId),
-            },
-        }).finish();
-
-        if (this.ws === undefined) {
-            throw new Error('Invalid state; _ws is undefined');
-        }
-
-        this.ws.send(encodedSubscription);
-    }
-
-    private _subUnsubToken(isUnsub: boolean, tokenId: string) {
-        const encodedSubscription = proto.WsSub.encode({
-            isUnsub,
-            tokenId: {
-                tokenId: tokenId,
-            },
-        }).finish();
-
-        if (this.ws === undefined) {
-            throw new Error('Invalid state; _ws is undefined');
-        }
-
-        this.ws.send(encodedSubscription);
-    }
-
-    public async handleMsg(wsMsg: MessageEvent) {
-        if (typeof this.onMessage === 'undefined') {
-            return;
-        }
-        const data =
-            typeof window === 'undefined'
-                ? // NodeJS
-                  (wsMsg.data as Uint8Array)
-                : // Browser
-                  new Uint8Array(await (wsMsg.data as Blob).arrayBuffer());
-        const msg = proto.WsMsg.decode(data);
-        if (typeof msg.error !== 'undefined') {
-            this.onMessage({ type: 'Error', ...msg.error });
-        } else if (typeof msg.block !== 'undefined') {
-            this.onMessage({
-                type: 'Block',
-                msgType: convertToBlockMsgType(msg.block.msgType),
-                blockHash: toHexRev(msg.block.blockHash),
-                blockHeight: msg.block.blockHeight,
-            });
-        } else if (typeof msg.tx !== 'undefined') {
-            this.onMessage({
-                type: 'Tx',
-                msgType: convertToTxMsgType(msg.tx.msgType),
-                txid: toHexRev(msg.tx.txid),
-            });
-        } else {
-            console.log('Silently ignored unknown Chronik message:', msg);
-        }
-    }
-}
-
-function convertToBlockchainInfo(
-    blockchainInfo: proto.BlockchainInfo,
-): BlockchainInfo {
-    return {
-        tipHash: toHexRev(blockchainInfo.tipHash),
-        tipHeight: blockchainInfo.tipHeight,
-    };
-}
-
-function convertToChronikInfo(chronikInfo: proto.ChronikInfo): ChronikInfo {
-    if (chronikInfo.version === undefined) {
-        throw new Error('chronikInfo has no version');
-    }
-    return {
-        version: chronikInfo.version.length !== 0 ? chronikInfo.version : '',
-    };
-}
-
-function convertToBlock(block: proto.Block): Block_InNode {
-    if (block.blockInfo === undefined) {
-        throw new Error('Block has no blockInfo');
-    }
-    return {
-        blockInfo: convertToBlockInfo(block.blockInfo),
-    };
-}
-
-function convertToTxHistoryPage(
-    blockTxs: proto.TxHistoryPage,
-): TxHistoryPage_InNode {
-    const { txs, numPages, numTxs } = blockTxs;
-    const convertedTxs = txs.map(convertToTx);
-    return {
-        txs: convertedTxs,
-        numPages,
-        numTxs,
-    };
-}
-
-function convertToBlockInfo(block: proto.BlockInfo): BlockInfo_InNode {
-    return {
-        ...block,
-        hash: toHexRev(block.hash),
-        prevHash: toHexRev(block.prevHash),
-        timestamp: parseInt(block.timestamp),
-        blockSize: parseInt(block.blockSize),
-        numTxs: parseInt(block.numTxs),
-        numInputs: parseInt(block.numInputs),
-        numOutputs: parseInt(block.numOutputs),
-        sumInputSats: parseInt(block.sumInputSats),
-        sumCoinbaseOutputSats: parseInt(block.sumCoinbaseOutputSats),
-        sumNormalOutputSats: parseInt(block.sumNormalOutputSats),
-        sumBurnedSats: parseInt(block.sumBurnedSats),
-    };
-}
-
-function convertToTx(tx: proto.Tx): Tx_InNode {
-    const convertedTx: Tx_InNode = {
-        txid: toHexRev(tx.txid),
-        version: tx.version,
-        inputs: tx.inputs.map(convertToTxInput),
-        outputs: tx.outputs.map(convertToTxOutput),
-        lockTime: tx.lockTime,
-        timeFirstSeen: parseInt(tx.timeFirstSeen),
-        size: tx.size,
-        isCoinbase: tx.isCoinbase,
-        tokenEntries: tx.tokenEntries.map(convertToTokenEntry),
-        tokenFailedParsings: tx.tokenFailedParsings.map(
-            convertToTokenFailedParsing,
-        ),
-        tokenStatus: convertToTokenStatus(tx.tokenStatus),
-    };
-    if (typeof tx.block !== 'undefined') {
-        // Only include block if the tx is in a block
-        convertedTx.block = convertToBlockMeta(tx.block);
-    }
-    return convertedTx;
-}
-
-function convertToTxInput(input: proto.TxInput): TxInput_InNode {
-    if (input.prevOut === undefined) {
-        throw new Error('Invalid proto, no prevOut');
-    }
-    const txInput: TxInput_InNode = {
-        prevOut: {
-            txid: toHexRev(input.prevOut.txid),
-            outIdx: input.prevOut.outIdx,
-        },
-        inputScript: toHex(input.inputScript),
-        value: parseInt(input.value),
-        sequenceNo: input.sequenceNo,
-    };
-    if (typeof input.token !== 'undefined') {
-        // We only return a token key if we have token data for this input
-        txInput.token = convertToTokenInNode(input.token);
-    }
-    if (Object.keys(input.plugins).length > 0) {
-        // We only return a plugins key if we have plugins
-        txInput.plugins = convertToPluginEntries(input.plugins);
-    }
-    if (
-        typeof input.outputScript !== 'undefined' &&
-        input.outputScript.length > 0
-    ) {
-        // Coinbase tx inputs do not have an outputScript
-        txInput.outputScript = toHex(input.outputScript);
-    }
-    return txInput;
-}
-
-function convertToTxOutput(output: proto.TxOutput): TxOutput_InNode {
-    const txOutput: TxOutput_InNode = {
-        value: parseInt(output.value),
-        outputScript: toHex(output.outputScript),
-    };
-    if (Object.keys(output.plugins).length > 0) {
-        // We only return a plugins key if we have plugins
-        txOutput.plugins = convertToPluginEntries(output.plugins);
-    }
-    if (typeof output.token !== 'undefined') {
-        // We only return a token key if we have token data for this input
-        txOutput.token = convertToTokenInNode(output.token);
-    }
-    if (typeof output.spentBy !== 'undefined') {
-        // We only return a spentBy key if this output has been spent
-        txOutput.spentBy = {
-            txid: toHexRev(output.spentBy.txid),
-            outIdx: output.spentBy.inputIdx,
-        };
-    }
-    return txOutput;
-}
-
-function convertToPluginEntries(plugins: {
-    [key: string]: proto.PluginEntry;
-}): PluginEntries {
-    const pluginEntries: PluginEntries = {};
-    for (const [pluginName, plugin] of Object.entries(plugins)) {
-        if (typeof pluginName === 'undefined') {
-            continue;
-        }
-        const { groups, data } = plugin;
-
-        pluginEntries[pluginName] = {
-            groups: groups.map(toHex),
-            data: data.map(toHex),
-        };
-    }
-
-    return pluginEntries;
-}
-
-function convertToPluginGroups(
-    protoPluginGroups: proto.PluginGroups,
-): PluginGroups {
-    const { groups } = protoPluginGroups;
-    return {
-        groups: groups.map(group => ({ group: toHex(group.group) })),
-        nextStart: toHex(protoPluginGroups.nextStart),
-    };
-}
-
-function convertToBlockMeta(block: proto.BlockMetadata): BlockMetadata_InNode {
-    return {
-        height: block.height,
-        hash: toHexRev(block.hash),
-        timestamp: parseInt(block.timestamp),
-    };
-}
-
-function convertToRawTx(rawTx: proto.RawTx): RawTx {
-    return {
-        rawTx: toHex(rawTx.rawTx),
-    };
-}
-
-function convertToScriptUtxo(utxo: proto.ScriptUtxo): ScriptUtxo_InNode {
-    if (utxo.outpoint === undefined) {
-        throw new Error('UTXO outpoint is undefined');
-    }
-    const utxoInNode: ScriptUtxo_InNode = {
-        outpoint: {
-            txid: toHexRev(utxo.outpoint.txid),
-            outIdx: utxo.outpoint.outIdx,
-        },
-        blockHeight: utxo.blockHeight,
-        isCoinbase: utxo.isCoinbase,
-        value: parseInt(utxo.value),
-        isFinal: utxo.isFinal,
-    };
-    if (typeof utxo.token !== 'undefined') {
-        // We only return a token key if we have token data for this input
-        utxoInNode.token = convertToTokenInNode(utxo.token);
-    }
-    if (Object.keys(utxo.plugins).length > 0) {
-        // We only return a plugins key if we have plugins
-        utxoInNode.plugins = convertToPluginEntries(utxo.plugins);
-    }
-    return utxoInNode;
-}
-
-function convertToUtxo(utxo: proto.Utxo): Utxo_InNode {
-    if (utxo.outpoint === undefined) {
-        throw new Error('UTXO outpoint is undefined');
-    }
-    const utxoInNode: Utxo_InNode = {
-        outpoint: {
-            txid: toHexRev(utxo.outpoint.txid),
-            outIdx: utxo.outpoint.outIdx,
-        },
-        blockHeight: utxo.blockHeight,
-        isCoinbase: utxo.isCoinbase,
-        script: toHex(utxo.script),
-        value: parseInt(utxo.value),
-        isFinal: utxo.isFinal,
-    };
-    if (typeof utxo.token !== 'undefined') {
-        // We only return a token key if we have token data for this input
-        utxoInNode.token = convertToTokenInNode(utxo.token);
-    }
-    if (Object.keys(utxo.plugins).length > 0) {
-        // We only return a plugins key if we have plugins
-        utxoInNode.plugins = convertToPluginEntries(utxo.plugins);
-    }
-    return utxoInNode;
-}
-
-function convertToTokenEntry(tokenEntry: proto.TokenEntry): TokenEntry {
-    if (typeof tokenEntry.tokenType === 'undefined') {
-        // Not expected to ever happen
-        throw new Error(
-            `chronik returned undefined tokenEntry.tokenType for tokenId "${tokenEntry.tokenId}"`,
-        );
-    }
-    const returnObj: TokenEntry = {
-        tokenId: tokenEntry.tokenId,
-        tokenType: convertToTokenType(tokenEntry.tokenType),
-        txType: convertToTokenTxType(tokenEntry.txType),
-        isInvalid: tokenEntry.isInvalid,
-        burnSummary: tokenEntry.burnSummary,
-        failedColorings: tokenEntry.failedColorings,
-        actualBurnAmount: tokenEntry.actualBurnAmount,
-        intentionalBurn: tokenEntry.intentionalBurn,
-        burnsMintBatons: tokenEntry.burnsMintBatons,
-    };
-    if (tokenEntry.groupTokenId !== '') {
-        // Only include groupTokenId if it is not empty
-        returnObj.groupTokenId = tokenEntry.groupTokenId;
-    }
-    return returnObj;
-}
-
-function convertToTokenFailedParsing(
-    tokenFailedParsing: proto.TokenFailedParsing,
-): TokenFailedParsing {
-    return {
-        pushdataIdx: tokenFailedParsing.pushdataIdx,
-        bytes: toHex(tokenFailedParsing.bytes),
-        error: tokenFailedParsing.error,
-    };
-}
-
-function convertToTokenType(tokenType: proto.TokenType): TokenType {
-    if (typeof tokenType.alp !== 'undefined') {
-        return {
-            protocol: 'ALP',
-            type: convertToAlpTokenType(tokenType.alp),
-            number: tokenType.alp,
-        };
-    }
-    if (typeof tokenType.slp !== 'undefined') {
-        return {
-            protocol: 'SLP',
-            type: convertToSlpTokenType(tokenType.slp),
-            number: tokenType.slp,
-        };
-    }
-    // Should never happen
-    throw new Error('chronik did not return a token protocol for this token');
-}
-
-function convertToSlpTokenType(
-    msgType: proto.SlpTokenType,
-): SlpTokenType_InNode_Type {
-    const slpTokenType = proto.slpTokenTypeToJSON(msgType);
-    if (isSlpTokenType(slpTokenType)) {
-        return slpTokenType;
-    }
-    return 'SLP_TOKEN_TYPE_UNKNOWN';
-}
-
-function isSlpTokenType(msgType: any): msgType is SlpTokenType_InNode_Type {
-    return SLP_TOKEN_TYPES.includes(msgType);
-}
-
-function convertToAlpTokenType(msgType: proto.AlpTokenType): AlpTokenType_Type {
-    const alpTokenType = proto.alpTokenTypeToJSON(msgType);
-    if (isAlpTokenType(alpTokenType)) {
-        return alpTokenType;
-    }
-    return 'ALP_TOKEN_TYPE_UNKNOWN';
-}
-
-function isAlpTokenType(msgType: any): msgType is AlpTokenType_Type {
-    return ALP_TOKEN_TYPES.includes(msgType);
-}
-
-function convertToTokenStatus(msgType: proto.TokenStatus): TokenStatus {
-    const tokenStatus = proto.tokenStatusToJSON(msgType);
-    if (isTokenStatus(tokenStatus)) {
-        return tokenStatus;
-    }
-    return 'TOKEN_STATUS_UNKNOWN';
-}
-
-function isTokenStatus(msgType: any): msgType is TokenStatus {
-    return TOKEN_STATUS_TYPES.includes(msgType);
-}
-
-function convertToTokenTxType(msgType: proto.TokenTxType): TokenTxType {
-    const tokenTxType = proto.tokenTxTypeToJSON(msgType);
-    if (isTokenTxType(tokenTxType)) {
-        return tokenTxType;
-    }
-    return 'UNKNOWN';
-}
-
-function isTokenTxType(msgType: any): msgType is TokenTxType {
-    return TOKEN_TX_TYPE_TYPES.includes(msgType);
-}
-
-function convertToTokenInNode(token: proto.Token): Token_InNode {
-    if (typeof token.tokenType === 'undefined') {
-        // Not expected to ever happen
-        throw new Error(
-            `chronik returned undefined token.tokenType for tokenId "${token.tokenId}"`,
-        );
-    }
-
-    const tokenInNode: Token_InNode = {
-        tokenId: token.tokenId,
-        tokenType: convertToTokenType(token.tokenType),
-        amount: token.amount,
-        isMintBaton: token.isMintBaton,
-    };
-
-    // We do not bother including entryIdx for utxos, where it is always -1
-    if (token.entryIdx !== -1) {
-        tokenInNode.entryIdx = token.entryIdx;
-    }
-
-    return tokenInNode;
-}
-
-function convertToBlockMsgType(msgType: proto.BlockMsgType): BlockMsgType {
-    const blockMsgType = proto.blockMsgTypeToJSON(msgType);
-    if (isBlockMsgType(blockMsgType)) {
-        return blockMsgType;
-    }
-    return 'UNRECOGNIZED';
-}
-
-function isBlockMsgType(msgType: any): msgType is BlockMsgType {
-    return BLK_MSG_TYPES.includes(msgType);
-}
-
-function convertToTxMsgType(msgType: proto.TxMsgType): TxMsgType {
-    const txMsgType = proto.txMsgTypeToJSON(msgType);
-    if (isTxMsgType(txMsgType)) {
-        return txMsgType;
-    }
-    return 'UNRECOGNIZED';
-}
-
-function convertToTokenInfo(tokenInfo: proto.TokenInfo): TokenInfo {
-    if (typeof tokenInfo.tokenType === 'undefined') {
-        // Not expected to ever happen
-        throw new Error(
-            `chronik returned undefined tokenInfo.tokenType for tokenId "${tokenInfo.tokenId}"`,
-        );
-    }
-    if (typeof tokenInfo.genesisInfo === 'undefined') {
-        // Not expected to ever happen
-        throw new Error(
-            `chronik returned undefined tokenInfo.genesisInfo for tokenId "${tokenInfo.tokenId}"`,
-        );
-    }
-
-    // We use tokenType to get the correct shape of genesisInfo
-    const tokenType = convertToTokenType(tokenInfo.tokenType);
-
-    const returnedTokenInfo: TokenInfo = {
-        tokenId: tokenInfo.tokenId,
-        tokenType,
-        timeFirstSeen: parseInt(tokenInfo.timeFirstSeen),
-        genesisInfo: convertToGenesisInfo(tokenInfo.genesisInfo, tokenType),
-    };
-
-    if (typeof tokenInfo.block !== 'undefined') {
-        // Only include block if the tx is in a block
-        returnedTokenInfo.block = convertToBlockMeta(tokenInfo.block);
-    }
-
-    return returnedTokenInfo;
-}
-
-function convertToGenesisInfo(
-    genesisInfo: proto.GenesisInfo,
-    tokenType: TokenType,
-): GenesisInfo {
-    const decoder = new TextDecoder();
-    const returnedGenesisInfo: GenesisInfo = {
-        tokenTicker: decoder.decode(genesisInfo.tokenTicker),
-        tokenName: decoder.decode(genesisInfo.tokenName),
-        url: decoder.decode(genesisInfo.url),
-        decimals: genesisInfo.decimals,
-    };
-
-    // Add ALP fields for ALP types only
-    if (tokenType.protocol === 'ALP') {
-        returnedGenesisInfo.data = genesisInfo.data;
-        returnedGenesisInfo.authPubkey = toHex(genesisInfo.authPubkey);
-    }
-
-    // Add mintVaultHash for SLP Mint Vault only
-    if (tokenType.type === 'SLP_TOKEN_TYPE_MINT_VAULT') {
-        returnedGenesisInfo.mintVaultScripthash = toHex(
-            genesisInfo.mintVaultScripthash,
-        );
-    }
-
-    // Add url for SLP only
-    if (tokenType.protocol === 'SLP') {
-        returnedGenesisInfo.hash = toHex(genesisInfo.hash);
-    }
-
-    return returnedGenesisInfo;
-}
-
-function isTxMsgType(msgType: any): msgType is TxMsgType {
-    return TX_MSG_TYPES.includes(msgType);
-}
-
-/** Info about connected chronik server */
-export interface ChronikInfo {
-    version: string;
-}
-
-/**  BlockInfo interface for in-node chronik */
-export interface BlockInfo_InNode {
-    /** Block hash of the block, in 'human-readable' (big-endian) hex encoding. */
-    hash: string;
-    /** Block hash of the prev block, in 'human-readable' (big-endian) hex encoding. */
-    prevHash: string;
-    /** Height of the block; Genesis block has height 0. */
-    height: number;
-    /** nBits field of the block, encodes the target compactly. */
-    nBits: number;
-    /**
-     * Timestamp of the block. Filled in by the miner,
-     * so might not be 100 % precise.
-     */
-    timestamp: number;
-    /** Is this block avalanche finalized? */
-    isFinal: boolean;
-    /** Block size of this block in bytes (including headers etc.). */
-    blockSize: number;
-    /** Number of txs in this block. */
-    numTxs: number;
-    /** Total number of tx inputs in block (including coinbase). */
-    numInputs: number;
-    /** Total number of tx output in block (including coinbase). */
-    numOutputs: number;
-    /** Total number of satoshis spent by tx inputs. */
-    sumInputSats: number;
-    /** Total block reward for this block. */
-    sumCoinbaseOutputSats: number;
-    /** Total number of satoshis in non-coinbase tx outputs. */
-    sumNormalOutputSats: number;
-    /** Total number of satoshis burned using OP_RETURN. */
-    sumBurnedSats: number;
-}
-
-/** Block interface for in-node chronik */
-export interface Block_InNode {
-    /** Contains the blockInfo object defined above */
-    blockInfo: BlockInfo_InNode;
-}
-
-/** A page of in-node chronik tx history */
-export interface TxHistoryPage_InNode {
-    /** Txs of the page */
-    txs: Tx_InNode[];
-    /** How many pages there are total */
-    numPages: number;
-    /** How many txs there are total */
-    numTxs: number;
-}
-
-/** The hex bytes of a raw tx */
-export interface RawTx {
-    rawTx: string;
-}
-
-/** A transaction on the blockchain or in the mempool. */
-export interface Tx_InNode {
-    /** Transaction ID. */
-    txid: string;
-    /** `version` field of the transaction. */
-    version: number;
-    /** Inputs of this transaction. */
-    inputs: TxInput_InNode[];
-    /** Outputs of this transaction. */
-    outputs: TxOutput_InNode[];
-    /** `locktime` field of the transaction, tx is not valid before this time. */
-    lockTime: number;
-    /** Block data for this tx, if it is in a block. */
-    block?: BlockMetadata_InNode;
-    /**
-     * UNIX timestamp when this tx has first been seen in the mempool.
-     * 0 if unknown -> make sure to check.
-     */
-    timeFirstSeen: number;
-    /** Serialized size of the tx. */
-    size: number;
-    /** Whether this tx is a coinbase tx. */
-    isCoinbase: boolean;
-    /** Tokens involved in this txs */
-    tokenEntries: TokenEntry[];
-    /** Failed parsing attempts of this tx */
-    tokenFailedParsings: TokenFailedParsing[];
-    /**
-     * Token status, i.e. whether this tx has any tokens or unintentional token burns
-     * or something unexpected, like failed parsings etc.
-     */
-    tokenStatus: TokenStatus;
-}
-
-/** Input of a tx, spends an output of a previous tx. */
-export interface TxInput_InNode {
-    /** Points to an output spent by this input. */
-    prevOut: OutPoint;
-    /**
-     * Script unlocking the output, in hex encoding.
-     * Aka. `scriptSig` in bitcoind parlance.
-     */
-    inputScript: string;
-    /**
-     * Script of the output, in hex encoding.
-     * Aka. `scriptPubKey` in bitcoind parlance.
-     * Not present for coinbase txs
-     */
-    outputScript?: string;
-    /** Value of the output spent by this input, in satoshis. */
-    value: number;
-    /** `sequence` field of the input; can be used for relative time locking. */
-    sequenceNo: number;
-    /** Token value attached to this input */
-    token?: Token_InNode;
-    /** Plugin data attached to this input */
-    plugins?: PluginEntries;
-}
-
-/** Output of a tx, creates new UTXOs. */
-export interface TxOutput_InNode {
-    /** Value of the output, in satoshis. */
-    value: number;
-    /**
-     * Script of this output, locking the coins.
-     * Aka. `scriptPubKey` in bitcoind parlance.
-     */
-    outputScript: string;
-    /**
-     * Transaction & input index spending this output, if
-     * spent.
-     */
-    spentBy?: OutPoint;
-    /** Token value attached to this output */
-    token?: Token_InNode;
-    /** Plugin data attached to this output */
-    plugins?: PluginEntries;
-}
-
-/** Metadata of a block, used in transaction data. */
-export interface BlockMetadata_InNode {
-    /** Height of the block. */
-    height: number;
-    /** Hash of the block. */
-    hash: string;
-    /**
-     * Timestamp of the block; useful if `timeFirstSeen` of a transaction is
-     * unknown.
-     */
-    timestamp: number;
-}
-
-/** Token involved in a transaction */
-interface TokenEntry {
-    /**
-     * Hex token_id (in big-endian, like usually displayed to users) of the token.
-     * This is not `bytes` because SLP and ALP use different endiannes, so to avoid
-     * this we use hex, which conventionally implies big-endian in a bitcoin context.
-     */
-    tokenId: string;
-    /** Token type of the token */
-    tokenType: TokenType;
-    /** Tx type of the token; NONE if there's no section that introduced it (e.g. in an accidental burn) */
-    txType: TokenTxType;
-    /**
-     *  For NFT1 Child tokens: group ID
-     *  Unset if the token is not an NFT1 Child token
-     */
-    groupTokenId?: string;
-    /** Whether the validation rules have been violated for this section */
-    isInvalid: boolean;
-    /** Human-readable error message of why this entry burned tokens */
-    burnSummary: string;
-    /** Human-readable error messages of why colorings failed */
-    failedColorings: TokenFailedColoring[];
-    /**
-     * Number of actually burned tokens (as decimal integer string, e.g. "2000").
-     * This is because burns can exceed the 64-bit range of values and protobuf doesn't have a nice type to encode this.
-     */
-    actualBurnAmount: string;
-    /** Burn amount the user explicitly opted into (as decimal integer string) */
-    intentionalBurn: string;
-    /** Whether any mint batons have been burned of this token */
-    burnsMintBatons: boolean;
-}
-
-/**
- * SLP/ALP token type
- */
-export type TokenType = SlpTokenType_InNode | AlpTokenType;
-
-export interface SlpTokenType_InNode {
-    protocol: 'SLP';
-    type: SlpTokenType_InNode_Type;
-    number: number;
-}
-
-export interface AlpTokenType {
-    protocol: 'ALP';
-    type: AlpTokenType_Type;
-    number: number;
-}
-
-/** Possible ALP token types returned by chronik */
-export type AlpTokenType_Type =
-    | 'ALP_TOKEN_TYPE_STANDARD'
-    | 'ALP_TOKEN_TYPE_UNKNOWN';
-
-export const ALP_TOKEN_TYPES: AlpTokenType_Type[] = [
-    'ALP_TOKEN_TYPE_STANDARD',
-    'ALP_TOKEN_TYPE_UNKNOWN',
-];
-
-/** Possible SLP token types returned by chronik */
-export type SlpTokenType_InNode_Type =
-    | 'SLP_TOKEN_TYPE_FUNGIBLE'
-    | 'SLP_TOKEN_TYPE_MINT_VAULT'
-    | 'SLP_TOKEN_TYPE_NFT1_GROUP'
-    | 'SLP_TOKEN_TYPE_NFT1_CHILD'
-    | 'SLP_TOKEN_TYPE_UNKNOWN';
-
-const SLP_TOKEN_TYPES: SlpTokenType_InNode_Type[] = [
-    'SLP_TOKEN_TYPE_FUNGIBLE',
-    'SLP_TOKEN_TYPE_MINT_VAULT',
-    'SLP_TOKEN_TYPE_NFT1_GROUP',
-    'SLP_TOKEN_TYPE_NFT1_CHILD',
-    'SLP_TOKEN_TYPE_UNKNOWN',
-];
-
-/**
- * TokenStatus
- * TOKEN_STATUS_NON_TOKEN - Tx involves no tokens whatsover, i.e. neither any burns nor any failed
- * parsing/coloring or any tokens being created / moved.
- * TOKEN_STATUS_NORMAL - Tx involves tokens but no unintentional burns or failed parsings/colorings
- * TOKEN_STATUS_NOT_NORMAL - Tx involves tokens but contains unintentional burns or failed parsings/colorings
- * TOKEN_STATUS_UNKNOWN - Token tx of unknown status
- */
-export type TokenStatus =
-    | 'TOKEN_STATUS_NON_TOKEN'
-    | 'TOKEN_STATUS_NORMAL'
-    | 'TOKEN_STATUS_NOT_NORMAL'
-    | 'TOKEN_STATUS_UNKNOWN';
-
-const TOKEN_STATUS_TYPES: TokenStatus[] = [
-    'TOKEN_STATUS_NON_TOKEN',
-    'TOKEN_STATUS_NORMAL',
-    'TOKEN_STATUS_NOT_NORMAL',
-    'TOKEN_STATUS_UNKNOWN',
-];
-
-/** SLP/ALP tx type */
-export type TokenTxType =
-    /** NONE - No tx type, e.g. when input tokens are burned */
-    | 'NONE'
-    /** UNKNOWN - Unknown tx type, i.e. for unknown token types */
-    | 'UNKNOWN'
-    /** GENESIS - GENESIS tx */
-    | 'GENESIS'
-    /** SEND - SEND tx */
-    | 'SEND'
-    /** MINT - MINT tx */
-    | 'MINT'
-    /** BURN - BURN tx */
-    | 'BURN';
-
-const TOKEN_TX_TYPE_TYPES: TokenTxType[] = [
-    'NONE',
-    'UNKNOWN',
-    'GENESIS',
-    'SEND',
-    'MINT',
-    'BURN',
-];
-
-/**
- * A report of a failed coloring attempt of SLP/ALP.
- * This should always indicate something went wrong when building the tx.
- */
-export interface TokenFailedColoring {
-    /** For ALP, the index of the pushdata in the OP_RETURN that failed parsing. */
-    pushdataIdx: number;
-    /** Human-readable message of what went wrong */
-    error: string;
-}
-
-/**
- * TokenFailedParsing
- * A report of a failed parsing attempt of SLP/ALP.
- * This should always indicate something went wrong when building the tx.
- */
-export interface TokenFailedParsing {
-    /**
-     * For ALP, the index of the pushdata in the OP_RETURN that failed parsing.
-     * -1 if the whole OP_RETURN failed, e.g. for SLP or eMPP
-     */
-    pushdataIdx: number;
-    /** The bytes that failed parsing, useful for debugging */
-    bytes: string;
-    /** Human-readable message of what went wrong */
-    error: string;
-}
-
-/** Data attached by a plugin to an output */
-export interface PluginEntry {
-    /** Groups assigned to this output */
-    groups: string[];
-    /** Data assigned to the output */
-    data: string[];
-}
-
-export type PluginEntries = { [key: string]: PluginEntry };
-
-/** Group of UTXOs by output script. */
-export interface ScriptUtxos_InNode {
-    /** Output script in hex. */
-    outputScript: string;
-    /** UTXOs of the output script. */
-    utxos: ScriptUtxo_InNode[];
-}
-
-/** An unspent transaction output (aka. UTXO, aka. "Coin") of a script. */
-export interface ScriptUtxo_InNode {
-    /** Outpoint of the UTXO. */
-    outpoint: OutPoint;
-    /** Which block this UTXO is in, or -1 if in the mempool. */
-    blockHeight: number;
-    /** Whether this UTXO is a coinbase UTXO
-     * (make sure it's buried 100 blocks before spending!) */
-    isCoinbase: boolean;
-    /** Value of the UTXO in satoshis. */
-    value: number;
-    /** Is this utxo avalanche finalized */
-    isFinal: boolean;
-    /** Token value attached to this utxo */
-    token?: Token_InNode;
-    /** Plugin data attached to this output */
-    plugins?: PluginEntries;
-}
-
-/**
- * An unspent transaction output (aka. UTXO, aka. "Coin") with script attached
- * Useful when getting utxos by something other than script, e.g. tokenId
- */
-export interface Utxo_InNode {
-    /** Outpoint of the UTXO. */
-    outpoint: OutPoint;
-    /** Which block this UTXO is in, or -1 if in the mempool. */
-    blockHeight: number;
-    /** Whether this UTXO is a coinbase UTXO
-     * (make sure it's buried 100 blocks before spending!) */
-    isCoinbase: boolean;
-    /** Value of the UTXO in satoshis. */
-    value: number;
-    /** Bytecode of the script of the output */
-    script: string;
-    /** Is this utxo avalanche finalized */
-    isFinal: boolean;
-    /** Token value attached to this utxo */
-    token?: Token_InNode;
-    /** Plugin data attached to this output */
-    plugins?: PluginEntries;
-}
-
-/** Token coloring an input or output */
-export interface Token_InNode {
-    /** Hex token_id of the token, see `TokenInfo` for details */
-    tokenId: string;
-    /** Token type of the token */
-    tokenType: TokenType;
-    /**
-     * Index into `token_entries` for `Tx`
-     * chronik returns -1 for UTXOs, chronik-client
-     * passes no entryIdx key for UTXOS
-     */
-    entryIdx?: number;
-    /** Base token amount of the input/output */
-    amount: string;
-    /** Whether the token is a mint baton */
-    isMintBaton: boolean;
-}
-
-/**
- * Script type queried in the `script` method.
- * - `other`: Script type not covered by the standard script types; payload is
- *   the raw hex.
- * - `p2pk`: Pay-to-Public-Key (`<pk> OP_CHECKSIG`), payload is the hex of the
- *   pubkey (compressed (33 bytes) or uncompressed (65 bytes)).
- * - `p2pkh`: Pay-to-Public-Key-Hash
- *   (`OP_DUP OP_HASH160 <pkh> OP_EQUALVERIFY OP_CHECKSIG`).
- *   Payload is the 20 byte public key hash.
- * - `p2sh`: Pay-to-Script-Hash (`OP_HASH160 <sh> OP_EQUAL`).
- *   Payload is the 20 byte script hash.
- */
-export type ScriptType_InNode = 'other' | 'p2pk' | 'p2pkh' | 'p2sh';
-
-/** Message returned from the WebSocket, translated to be more human-readable for client */
-export type WsMsgClient = Error_InNode | MsgBlockClient | MsgTxClient;
-
-/** Block got connected, disconnected, finalized, etc.*/
-export interface MsgBlockClient {
-    type: 'Block';
-    /** What happened to the block */
-    msgType: BlockMsgType;
-    /** Hash of the block (human-readable big-endian) */
-    blockHash: string;
-    /** Height of the block */
-    blockHeight: number;
-}
-
-/** Block message types that can come from chronik */
-export type BlockMsgType =
-    | 'BLK_CONNECTED'
-    | 'BLK_DISCONNECTED'
-    | 'BLK_FINALIZED'
-    | 'UNRECOGNIZED';
-
-const BLK_MSG_TYPES: BlockMsgType[] = [
-    'BLK_CONNECTED',
-    'BLK_DISCONNECTED',
-    'BLK_FINALIZED',
-    'UNRECOGNIZED',
-];
-
-/** Tx got added to/removed from mempool, or confirmed in a block, etc.*/
-export interface MsgTxClient {
-    type: 'Tx';
-    /** What happened to the tx */
-    msgType: TxMsgType;
-    /** Txid of the tx (human-readable big-endian) */
-    txid: string;
-}
-
-/** Tx message types that can come from chronik */
-export type TxMsgType =
-    | 'TX_ADDED_TO_MEMPOOL'
-    | 'TX_REMOVED_FROM_MEMPOOL'
-    | 'TX_CONFIRMED'
-    | 'TX_FINALIZED'
-    | 'UNRECOGNIZED';
-
-const TX_MSG_TYPES: TxMsgType[] = [
-    'TX_ADDED_TO_MEMPOOL',
-    'TX_REMOVED_FROM_MEMPOOL',
-    'TX_CONFIRMED',
-    'TX_FINALIZED',
-    'UNRECOGNIZED',
-];
-
-/* The script type and its associated payload for a chronik-client subscribeToScript subscription */
-export interface WsSubScriptClient {
-    /** Script type to subscribe to ("p2pkh", "p2sh", "p2pk", "other"). */
-    scriptType: ScriptType_InNode;
-    /**
-     * Payload for the given script type:
-     * - 20-byte hash for "p2pkh" and "p2sh"
-     * - 33-byte or 65-byte pubkey for "p2pk"
-     * - Serialized script for "other"
-     */
-    payload: string;
-}
-
-export interface Error_InNode {
-    type: 'Error';
-    msg: string;
-}
-
-/** List of UTXOs */
-export interface TokenIdUtxos {
-    /** TokenId used to fetch these utxos */
-    tokenId: string;
-    /** UTXOs */
-    utxos: Utxo_InNode[];
-}
-
-/** List of UTXOs */
-export interface PluginUtxos {
-    /** Plugin used to fetch these utxos */
-    pluginName: string;
-    /** Group hex */
-    groupHex: string;
-    /** UTXOs */
-    utxos: Utxo_InNode[];
-}
-
-/**
- * Information about a given plugin group
- * For now, we just include the group
- */
-export interface PluginGroup {
-    group: string;
-}
-
-/** List of plugin groups */
-export interface PluginGroups {
-    groups: PluginGroup[];
-    nextStart: string;
-}
-
-/** Info about a token */
-export interface TokenInfo {
-    /**
-     * Hex token_id (in big-endian, like usually displayed to users) of the token.
-     * This is not `bytes` because SLP and ALP use different endiannnes,
-     * so to avoid this we use hex, which conventionally implies big-endian in a bitcoin context.
-     */
-    tokenId: string;
-    /** Token type of the token */
-    tokenType: TokenType;
-    /** Info found in the token's GENESIS tx */
-    genesisInfo: GenesisInfo;
-    /** Block of the GENESIS tx, if it's mined already */
-    block?: BlockMetadata_InNode;
-    /** Time the GENESIS tx has first been seen by the indexer */
-    timeFirstSeen: number;
-}
-
-/** Genesis info found in GENESIS txs of tokens */
-export interface GenesisInfo {
-    /** token_ticker of the token */
-    tokenTicker: string;
-    /** token_name of the token */
-    tokenName: string;
-    /** URL of the token */
-    url: string;
-    /** token_document_hash of the token (only on SLP) */
-    hash?: string;
-    /** mint_vault_scripthash (only on SLP V2 Mint Vault) */
-    mintVaultScripthash?: string;
-    /** Arbitray payload data of the token (only on ALP) */
-    data?: Uint8Array;
-    /** auth_pubkey of the token (only on ALP) */
-    authPubkey?: string;
-    /** decimals of the token, i.e. how many decimal places the token should be displayed with. */
-    decimals: number;
-}
-
-interface WsSubscriptions {
-    /** Subscriptions to scripts */
-    scripts: WsSubScriptClient[];
-    /** Subscriptions to tokens by tokenId */
-    tokens: string[];
-    /** Subscriptions to lokadIds */
-    lokadIds: string[];
-    /** Subscription to blocks */
-    blocks: boolean;
-}
diff --git a/modules/chronik-client/src/failoverProxy.ts b/modules/chronik-client/src/failoverProxy.ts
--- a/modules/chronik-client/src/failoverProxy.ts
+++ b/modules/chronik-client/src/failoverProxy.ts
@@ -7,7 +7,6 @@
 import * as ws from 'ws';
 import * as proto from '../proto/chronik';
 import { WsEndpoint } from './ChronikClient';
-import { WsEndpoint_InNode } from './ChronikClientNode';
 
 type MessageEvent = ws.MessageEvent | { data: Blob };
 
@@ -216,9 +215,7 @@
                 );
             }
             if (errorCanBeDecoded) {
-                throw new Error(
-                    `Failed getting ${path} (${error.errorCode}): ${error.msg}`,
-                );
+                throw new Error(`Failed getting ${path}: ${error.msg}`);
             }
         }
     }
@@ -258,7 +255,7 @@
     // Iterates through available websocket urls and attempts connection.
     // Upon a successful connection it handles the various websocket callbacks.
     // Upon an unsuccessful connection it iterates to the next websocket url in the array.
-    public async connectWs(wsEndpoint: WsEndpoint | WsEndpoint_InNode) {
+    public async connectWs(wsEndpoint: WsEndpoint) {
         for (let i = 0; i < this._endpointArray.length; i += 1) {
             const index = this.deriveEndpointIndex(i);
             const thisProxyWsUrl = this._endpointArray[index].wsUrl;
@@ -293,54 +290,37 @@
                     this.connectWs(wsEndpoint);
                 };
                 wsEndpoint.ws = ws;
-                wsEndpoint.connected =
-                    wsEndpoint instanceof WsEndpoint
-                        ? new Promise(resolve => {
-                              ws.onopen = msg => {
-                                  wsEndpoint.subs.forEach(sub =>
-                                      wsEndpoint.subUnsub(
-                                          true,
-                                          sub.scriptType,
-                                          sub.scriptPayload,
-                                      ),
-                                  );
-                                  resolve(msg);
-                                  if (wsEndpoint.onConnect !== undefined) {
-                                      wsEndpoint.onConnect(msg);
-                                  }
-                              };
-                          })
-                        : new Promise(resolve => {
-                              // WsEndpoint_InNode has a slightly different API vs NNG
-                              ws.onopen = msg => {
-                                  // Subscribe to all previously-subscribed scripts
-                                  wsEndpoint.subs.scripts.forEach(sub =>
-                                      wsEndpoint.subscribeToScript(
-                                          sub.scriptType,
-                                          sub.payload,
-                                      ),
-                                  );
-                                  // Subscribe to all previously-subscribed lokadIds
-                                  wsEndpoint.subs.lokadIds.forEach(lokadId =>
-                                      wsEndpoint.subscribeToLokadId(lokadId),
-                                  );
-                                  // Subscribe to all previously-subscribed tokenIds
-                                  wsEndpoint.subs.tokens.forEach(tokenId =>
-                                      wsEndpoint.subscribeToTokenId(tokenId),
-                                  );
+                wsEndpoint.connected = new Promise(resolve => {
+                    // WsEndpoint has a slightly different API vs NNG
+                    ws.onopen = msg => {
+                        // Subscribe to all previously-subscribed scripts
+                        wsEndpoint.subs.scripts.forEach(sub =>
+                            wsEndpoint.subscribeToScript(
+                                sub.scriptType,
+                                sub.payload,
+                            ),
+                        );
+                        // Subscribe to all previously-subscribed lokadIds
+                        wsEndpoint.subs.lokadIds.forEach(lokadId =>
+                            wsEndpoint.subscribeToLokadId(lokadId),
+                        );
+                        // Subscribe to all previously-subscribed tokenIds
+                        wsEndpoint.subs.tokens.forEach(tokenId =>
+                            wsEndpoint.subscribeToTokenId(tokenId),
+                        );
 
-                                  // Subscribe to blocks method, if previously subscribed
-                                  if (wsEndpoint.subs.blocks === true) {
-                                      wsEndpoint.subscribeToBlocks();
-                                  }
-                                  resolve(msg);
-                                  if (wsEndpoint.onConnect !== undefined) {
-                                      wsEndpoint.onConnect(msg);
-                                  }
-                                  // If no errors thrown from above call then set this index to state
-                                  this._workingIndex = index;
-                              };
-                          });
+                        // Subscribe to blocks method, if previously subscribed
+                        if (wsEndpoint.subs.blocks === true) {
+                            wsEndpoint.subscribeToBlocks();
+                        }
+                        resolve(msg);
+                        if (wsEndpoint.onConnect !== undefined) {
+                            wsEndpoint.onConnect(msg);
+                        }
+                        // If no errors thrown from above call then set this index to state
+                        this._workingIndex = index;
+                    };
+                });
                 return;
             }
         }
diff --git a/modules/chronik-client/src/validation.ts b/modules/chronik-client/src/validation.ts
--- a/modules/chronik-client/src/validation.ts
+++ b/modules/chronik-client/src/validation.ts
@@ -2,7 +2,7 @@
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
-import { WsSubScriptClient } from './ChronikClientNode';
+import { WsSubScriptClient } from './ChronikClient';
 
 const VALID_HEX_REGEX = new RegExp(/^[a-f0-9]+$/);
 const VALID_LOKADID_REGEX = new RegExp(/^[a-f0-9]{8}$/);
diff --git a/modules/chronik-client/test/integration/block_and_blocks.ts b/modules/chronik-client/test/integration/block_and_blocks.ts
--- a/modules/chronik-client/test/integration/block_and_blocks.ts
+++ b/modules/chronik-client/test/integration/block_and_blocks.ts
@@ -7,7 +7,7 @@
 import { ChildProcess } from 'node:child_process';
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
-import { ChronikClientNode } from '../../index';
+import { ChronikClient } from '../../index';
 import initializeTestRunner, {
     cleanupMochaRegtest,
     setMochaTimeout,
@@ -76,7 +76,7 @@
     const REGTEST_CHAIN_INIT_HEIGHT = 200;
 
     it('gives us the block and blocks', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
         const blockFromHeight = await chronik.block(REGTEST_CHAIN_INIT_HEIGHT);
         expect(blockFromHeight.blockInfo.height).to.eql(
             REGTEST_CHAIN_INIT_HEIGHT,
@@ -118,11 +118,11 @@
             ),
         ).to.be.rejectedWith(
             Error,
-            'Failed getting /blocks/200/198 (): 400: Invalid block end height: 198',
+            'Failed getting /blocks/200/198: 400: Invalid block end height: 198',
         );
     });
     it('gives us the block at 10 higher', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
         const blockFromHeight = await chronik.block(
             REGTEST_CHAIN_INIT_HEIGHT + 10,
         );
@@ -159,7 +159,7 @@
         }
     });
     it('gives us the block after parking the last block and throws expected error attempting to get parked block', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
         const blockFromHeight = await chronik.block(
             REGTEST_CHAIN_INIT_HEIGHT + 9,
         );
@@ -180,7 +180,7 @@
             chronik.block(REGTEST_CHAIN_INIT_HEIGHT + 10),
         ).to.be.rejectedWith(
             Error,
-            'Failed getting /block/210 (): 404: Block not found: 210',
+            'Failed getting /block/210: 404: Block not found: 210',
         );
 
         // blocks does not throw error if asked for parked block, but also does not return it
@@ -211,7 +211,7 @@
         expect(latestBlockAvailableByBlocks).to.deep.equal([]);
     });
     it('gives us the block and blocks after unparking the last block', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
         const blockFromHeight = await chronik.block(
             REGTEST_CHAIN_INIT_HEIGHT + 10,
         );
@@ -258,7 +258,7 @@
         );
     });
     it('gives us the block and blocks after invalidating the last block and throws expected error attempting to get invalidated block', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
         const blockFromHeight = await chronik.block(
             REGTEST_CHAIN_INIT_HEIGHT + 9,
         );
@@ -279,7 +279,7 @@
             chronik.block(REGTEST_CHAIN_INIT_HEIGHT + 10),
         ).to.be.rejectedWith(
             Error,
-            'Failed getting /block/210 (): 404: Block not found: 210',
+            'Failed getting /block/210: 404: Block not found: 210',
         );
 
         // blocks does not throw error if asked for invalidated block, but also does not return it
@@ -310,7 +310,7 @@
         expect(latestBlockAvailableByBlocks).to.deep.equal([]);
     });
     it('gives us the block and blocks after reconsiderblock called on the last block', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
         const blockFromHeight = await chronik.block(
             REGTEST_CHAIN_INIT_HEIGHT + 10,
         );
diff --git a/modules/chronik-client/test/integration/blockchain_info.ts b/modules/chronik-client/test/integration/blockchain_info.ts
--- a/modules/chronik-client/test/integration/blockchain_info.ts
+++ b/modules/chronik-client/test/integration/blockchain_info.ts
@@ -7,7 +7,7 @@
 import { ChildProcess } from 'node:child_process';
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
-import { ChronikClientNode } from '../../index';
+import { ChronikClient } from '../../index';
 import initializeTestRunner, {
     cleanupMochaRegtest,
     setMochaTimeout,
@@ -76,40 +76,40 @@
     const REGTEST_CHAIN_INIT_HEIGHT = 200;
 
     it('gives us the blockchain info + throws expected error on bad connection', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
         const blockchainInfo = await chronik.blockchainInfo();
         expect(blockchainInfo.tipHash.length).to.eql(64);
         expect(blockchainInfo.tipHeight).to.eql(REGTEST_CHAIN_INIT_HEIGHT);
 
         // Throws expected error if called on bad server
 
-        // Create a ChronikClientNode instance with a bad server URL
-        const badChronik = new ChronikClientNode([`${chronikUrl}5`]);
+        // Create a ChronikClient instance with a bad server URL
+        const badChronik = new ChronikClient([`${chronikUrl}5`]);
         await expect(badChronik.blockchainInfo()).to.be.rejectedWith(
             Error,
             'Error connecting to known Chronik instances',
         );
     });
     it('gives us the blockchain info with 10 more blocks', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
         const blockchainInfo = await chronik.blockchainInfo();
         expect(blockchainInfo.tipHash.length).to.eql(64);
         expect(blockchainInfo.tipHeight).to.eql(REGTEST_CHAIN_INIT_HEIGHT + 10);
     });
     it('gives us the blockchain info with again 10 more blocks', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
         const blockchainInfo = await chronik.blockchainInfo();
         expect(blockchainInfo.tipHash.length).to.eql(64);
         expect(blockchainInfo.tipHeight).to.eql(REGTEST_CHAIN_INIT_HEIGHT + 20);
     });
     it('gives us the blockchain info after parking the last block', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
         const blockchainInfo = await chronik.blockchainInfo();
         expect(blockchainInfo.tipHash.length).to.eql(64);
         expect(blockchainInfo.tipHeight).to.eql(REGTEST_CHAIN_INIT_HEIGHT + 19);
     });
     it('gives us the blockchain info after unparking the last block', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
         const blockchainInfo = await chronik.blockchainInfo();
         expect(blockchainInfo.tipHash.length).to.eql(64);
         expect(blockchainInfo.tipHeight).to.eql(REGTEST_CHAIN_INIT_HEIGHT + 20);
diff --git a/modules/chronik-client/test/integration/blocktxs_and_tx_and_rawtx.ts b/modules/chronik-client/test/integration/blocktxs_and_tx_and_rawtx.ts
--- a/modules/chronik-client/test/integration/blocktxs_and_tx_and_rawtx.ts
+++ b/modules/chronik-client/test/integration/blocktxs_and_tx_and_rawtx.ts
@@ -7,7 +7,7 @@
 import { ChildProcess } from 'node:child_process';
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
-import { ChronikClientNode } from '../../index';
+import { ChronikClient } from '../../index';
 import initializeTestRunner, {
     cleanupMochaRegtest,
     setMochaTimeout,
@@ -86,7 +86,7 @@
     let broadcastTxids: string[] = [];
 
     it('New regtest chain', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         // Gets the block by height (need the block hash)
         const blockFromHeight = await chronik.block(REGTEST_CHAIN_INIT_HEIGHT);
@@ -131,13 +131,13 @@
         const notTxid = 'thisIsNotATxid';
         await expect(chronik.tx(notTxid)).to.be.rejectedWith(
             Error,
-            `Failed getting /tx/${notTxid} (): 400: Not a txid: ${notTxid}`,
+            `Failed getting /tx/${notTxid}: 400: Not a txid: ${notTxid}`,
         );
 
         // Calling for a rawTx with an invalid txid throws expected error
         await expect(chronik.rawTx(notTxid)).to.be.rejectedWith(
             Error,
-            `Failed getting /raw-tx/${notTxid} (): 400: Not a txid: ${notTxid}`,
+            `Failed getting /raw-tx/${notTxid}: 400: Not a txid: ${notTxid}`,
         );
 
         // Calling for a tx with a txid that does not exist throws expected error
@@ -145,17 +145,17 @@
             'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd';
         await expect(chronik.tx(nonExistentTxid)).to.be.rejectedWith(
             Error,
-            `Failed getting /tx/${nonExistentTxid} (): 404: Transaction ${nonExistentTxid} not found in the index`,
+            `Failed getting /tx/${nonExistentTxid}: 404: Transaction ${nonExistentTxid} not found in the index`,
         );
 
         // Calling for a rawTx with a txid that does not exist throws expected error
         await expect(chronik.rawTx(nonExistentTxid)).to.be.rejectedWith(
             Error,
-            `Failed getting /raw-tx/${nonExistentTxid} (): 404: Transaction ${nonExistentTxid} not found in the index`,
+            `Failed getting /raw-tx/${nonExistentTxid}: 404: Transaction ${nonExistentTxid} not found in the index`,
         );
     });
     it('After some txs have been broadcast', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
         txsAndRawTxsBroadcastInTest = await chronik_txs_and_rawtxs;
         broadcastTxids = Object.keys(txsAndRawTxsBroadcastInTest);
 
@@ -172,7 +172,7 @@
         }
     });
     it('After these txs are mined', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         // We have another block
         const blockFromHeight = await chronik.block(
@@ -245,14 +245,14 @@
         expect(emptyPage.txs.length).to.eql(0);
     });
     it('After this mined block has been parked', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         // We can't get blockTxs for the now-parked block
         await expect(
             chronik.blockTxs(REGTEST_CHAIN_INIT_HEIGHT + 1),
         ).to.be.rejectedWith(
             Error,
-            'Failed getting /block-txs/201?page=0&page_size=25 (): 404: Block not found: 201',
+            'Failed getting /block-txs/201?page=0&page_size=25: 404: Block not found: 201',
         );
 
         // Gives us a tx by txid
diff --git a/modules/chronik-client/test/integration/broadcast_txs.ts b/modules/chronik-client/test/integration/broadcast_txs.ts
--- a/modules/chronik-client/test/integration/broadcast_txs.ts
+++ b/modules/chronik-client/test/integration/broadcast_txs.ts
@@ -7,7 +7,7 @@
 import { ChildProcess } from 'node:child_process';
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
-import { ChronikClientNode } from '../../index';
+import { ChronikClient } from '../../index';
 import initializeTestRunner, {
     cleanupMochaRegtest,
     setMochaTimeout,
@@ -17,7 +17,7 @@
 const expect = chai.expect;
 chai.use(chaiAsPromised);
 
-describe('Test broadcastTx and broadcastTxs methods from ChronikClientNode', () => {
+describe('Test broadcastTx and broadcastTxs methods from ChronikClient', () => {
     // Define variables used in scope of this test
     const testName = path.basename(__filename);
     let testRunner: ChildProcess;
@@ -130,15 +130,15 @@
     });
 
     it('New regtest chain', async () => {
-        // Initialize new ChronikClientNode
-        const chronik = new ChronikClientNode(chronikUrl);
+        // Initialize new ChronikClient
+        const chronik = new ChronikClient(chronikUrl);
 
         // We can't broadcast an invalid tx
         const BAD_RAW_TX =
             '0100000001fa5b8f14f5b63ae42f7624a416214bdfffd1de438e9db843a4ddf4d392302e2100000000020151000000000800000000000000003c6a5039534c5032000747454e4553495300000000000006e80300000000d00700000000b80b00000000a00f0000000088130000000070170000000000102700000000000017a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87102700000000000017a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87102700000000000017a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87102700000000000017a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87102700000000000017a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87102700000000000017a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b8760c937278c04000017a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b8700000000';
         await expect(chronik.broadcastTx(BAD_RAW_TX)).to.be.rejectedWith(
             Error,
-            `Failed getting /broadcast-tx (): 400: Broadcast failed: Transaction rejected by mempool: bad-txns-in-belowout, value in (25000000.00) < value out (49999999600.00)`,
+            `Failed getting /broadcast-tx: 400: Broadcast failed: Transaction rejected by mempool: bad-txns-in-belowout, value in (25000000.00) < value out (49999999600.00)`,
         );
 
         // We can broadcast an ALP genesis tx
@@ -155,7 +155,7 @@
 
         await expect(chronik.broadcastTx(alpBurnRawTx)).to.be.rejectedWith(
             Error,
-            `Failed getting /broadcast-tx (): 400: Tx ${alpBurnTxid} failed token checks: Unexpected burn: Burns 1 base tokens.`,
+            `Failed getting /broadcast-tx: 400: Tx ${alpBurnTxid} failed token checks: Unexpected burn: Burns 1 base tokens.`,
         );
 
         // We also can't broadcast an array of txs if one tx is a burn
@@ -166,7 +166,7 @@
             chronik.broadcastTxs([okRawTx, alpBurnRawTx]),
         ).to.be.rejectedWith(
             Error,
-            `Failed getting /broadcast-txs (): 400: Tx ${alpBurnTxid} failed token checks: Unexpected burn: Burns 1 base tokens.`,
+            `Failed getting /broadcast-txs: 400: Tx ${alpBurnTxid} failed token checks: Unexpected burn: Burns 1 base tokens.`,
         );
 
         // We can't broadcast an array of txs if one tx is invalid
@@ -176,7 +176,7 @@
             chronik.broadcastTxs([okRawTx, BAD_RAW_TX]),
         ).to.be.rejectedWith(
             Error,
-            `Failed getting /broadcast-txs (): 400: Broadcast failed: Transaction rejected by mempool: txn-mempool-conflict`,
+            `Failed getting /broadcast-txs: 400: Broadcast failed: Transaction rejected by mempool: txn-mempool-conflict`,
         );
 
         // We can broadcast multiple txs including a burn if we set skipTokenChecks
@@ -211,7 +211,7 @@
         // We can't broadcast a rawtx that conflicts with the mempool
         await expect(chronik.broadcastTx(BAD_RAW_TX)).to.be.rejectedWith(
             Error,
-            `Failed getting /broadcast-tx (): 400: Broadcast failed: Transaction rejected by mempool: txn-mempool-conflict`,
+            `Failed getting /broadcast-tx: 400: Broadcast failed: Transaction rejected by mempool: txn-mempool-conflict`,
         );
 
         // If we broadcast a tx already in the mempool, we get a normal response
@@ -229,19 +229,19 @@
             chronik.broadcastTx(INPUTS_DO_NOT_EXIST_RAWTX),
         ).to.be.rejectedWith(
             Error,
-            `Failed getting /broadcast-tx (): 400: Failed indexing mempool token tx: Tx is spending 1a3fa6b5a219a75bc287c382280ae36f3ff118757330f5670d463e10ec949154 which is found neither in the mempool nor DB`,
+            `Failed getting /broadcast-tx: 400: Failed indexing mempool token tx: Tx is spending 1a3fa6b5a219a75bc287c382280ae36f3ff118757330f5670d463e10ec949154 which is found neither in the mempool nor DB`,
         );
     });
     it('After broadcastTxs are mined', async () => {
-        // Initialize new ChronikClientNode
-        const chronik = new ChronikClientNode(chronikUrl);
+        // Initialize new ChronikClient
+        const chronik = new ChronikClient(chronikUrl);
 
         const alpGenesisRawTx = await get_alp_genesis_rawtx;
         // If we broadcast a tx already in the mempool, we get a normal response
 
         await expect(chronik.broadcastTx(alpGenesisRawTx)).to.be.rejectedWith(
             Error,
-            `Failed getting /broadcast-tx (): 400: Broadcast failed: Transaction already in block chain`,
+            `Failed getting /broadcast-tx: 400: Broadcast failed: Transaction already in block chain`,
         );
     });
 });
diff --git a/modules/chronik-client/test/integration/chronik_info.ts b/modules/chronik-client/test/integration/chronik_info.ts
--- a/modules/chronik-client/test/integration/chronik_info.ts
+++ b/modules/chronik-client/test/integration/chronik_info.ts
@@ -7,7 +7,7 @@
 import { ChildProcess } from 'node:child_process';
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
-import { ChronikClientNode } from '../../index';
+import { ChronikClient } from '../../index';
 import initializeTestRunner, {
     cleanupMochaRegtest,
     setMochaTimeout,
@@ -71,14 +71,14 @@
 
     it('gives us the chronik info and throws expected error on bad server connection', async () => {
         const EXPECTED_CHRONIK_VERSION = '0.1.0';
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
         const chronikInfo = await chronik.chronikInfo();
         expect(chronikInfo.version).to.eql(EXPECTED_CHRONIK_VERSION);
 
         // Throws expected error if called on bad server
 
-        // Create a ChronikClientNode instance with a bad server URL
-        const badChronik = new ChronikClientNode([`${chronikUrl}5`]);
+        // Create a ChronikClient instance with a bad server URL
+        const badChronik = new ChronikClient([`${chronikUrl}5`]);
         await expect(badChronik.chronikInfo()).to.be.rejectedWith(
             Error,
             'Error connecting to known Chronik instances',
diff --git a/modules/chronik-client/test/integration/lokad_id.ts b/modules/chronik-client/test/integration/lokad_id.ts
--- a/modules/chronik-client/test/integration/lokad_id.ts
+++ b/modules/chronik-client/test/integration/lokad_id.ts
@@ -7,7 +7,7 @@
 import { ChildProcess } from 'node:child_process';
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
-import { ChronikClientNode, WsEndpoint_InNode, WsMsgClient } from '../../index';
+import { ChronikClient, WsEndpoint, WsMsgClient } from '../../index';
 import initializeTestRunner, {
     cleanupMochaRegtest,
     expectWsMsgs,
@@ -30,7 +30,7 @@
     const statusEvent = new EventEmitter();
     let get_test_info: Promise<TestInfo>;
     let chronikUrl: string[];
-    let chronik: ChronikClientNode;
+    let chronik: ChronikClient;
     let setupScriptTermination: ReturnType<typeof setTimeout>;
 
     before(async function () {
@@ -51,7 +51,7 @@
         const testInfo = await get_test_info;
 
         chronikUrl = [testInfo.chronik];
-        chronik = new ChronikClientNode(chronikUrl);
+        chronik = new ChronikClient(chronikUrl);
         console.info(`chronikUrl set to ${JSON.stringify(chronikUrl)}`);
 
         setupScriptTermination = setMochaTimeout(
@@ -90,8 +90,8 @@
     const LOKAD2 = Buffer.from('lok2').toString('hex');
     const LOKAD3 = Buffer.from('lok3').toString('hex');
     const LOKAD4 = Buffer.from('lok4').toString('hex');
-    let ws: WsEndpoint_InNode;
-    let ws2: WsEndpoint_InNode;
+    let ws: WsEndpoint;
+    let ws2: WsEndpoint;
 
     const BASE_ADDEDTOMEMPOOL_WSMSG: WsMsgClient = {
         type: 'Tx',
@@ -144,7 +144,7 @@
             chronik.lokadId('somestring').history(),
         ).to.be.rejectedWith(
             Error,
-            `Failed getting /lokad-id/somestring/history?page=0&page_size=25 (): 400: Invalid hex: Invalid character 's' at position 0`,
+            `Failed getting /lokad-id/somestring/history?page=0&page_size=25: 400: Invalid hex: Invalid character 's' at position 0`,
         );
 
         // Connect to the websocket with a testable onMessage handler
diff --git a/modules/chronik-client/test/integration/mempool_conflicts.ts b/modules/chronik-client/test/integration/mempool_conflicts.ts
--- a/modules/chronik-client/test/integration/mempool_conflicts.ts
+++ b/modules/chronik-client/test/integration/mempool_conflicts.ts
@@ -9,10 +9,10 @@
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
 import {
-    ChronikClientNode,
+    ChronikClient,
     MsgTxClient,
-    ScriptType_InNode,
-    WsEndpoint_InNode,
+    ScriptType,
+    WsEndpoint,
     WsMsgClient,
     WsSubScriptClient,
 } from '../../index';
@@ -121,7 +121,7 @@
     let tx2Txid = '';
     let tx3Txid = '';
 
-    let ws: WsEndpoint_InNode;
+    let ws: WsEndpoint;
 
     let subscriptions: Array<WsSubScriptClient> = [];
 
@@ -129,8 +129,8 @@
         const { type, hash } =
             cashaddr.getTypeAndHashFromOutputScript(P2SH_OP_TRUE);
 
-        // Initialize a new instance of ChronikClientNode
-        const chronik = new ChronikClientNode(chronikUrl);
+        // Initialize a new instance of ChronikClient
+        const chronik = new ChronikClient(chronikUrl);
 
         // Connect to the websocket with a testable onMessage handler
         ws = chronik.ws({
@@ -143,7 +143,7 @@
         // Subscribe to addresses and scripts
         subscriptions = [
             {
-                scriptType: type as ScriptType_InNode,
+                scriptType: type as ScriptType,
                 payload: hash,
             },
         ];
diff --git a/modules/chronik-client/test/integration/plugin_groups.ts b/modules/chronik-client/test/integration/plugin_groups.ts
--- a/modules/chronik-client/test/integration/plugin_groups.ts
+++ b/modules/chronik-client/test/integration/plugin_groups.ts
@@ -7,7 +7,7 @@
 import { ChildProcess } from 'node:child_process';
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
-import { ChronikClientNode } from '../../index';
+import { ChronikClient } from '../../index';
 import initializeTestRunner, {
     cleanupMochaRegtest,
     setMochaTimeout,
@@ -25,7 +25,7 @@
     const statusEvent = new EventEmitter();
     let get_test_info: Promise<TestInfo>;
     let chronikUrl: string[];
-    let chronik: ChronikClientNode;
+    let chronik: ChronikClient;
     let setupScriptTermination: ReturnType<typeof setTimeout>;
 
     before(async function () {
@@ -46,7 +46,7 @@
         const testInfo = await get_test_info;
 
         chronikUrl = [testInfo.chronik];
-        chronik = new ChronikClientNode(chronikUrl);
+        chronik = new ChronikClient(chronikUrl);
         console.info(`chronikUrl set to ${JSON.stringify(chronikUrl)}`);
 
         setupScriptTermination = setMochaTimeout(
@@ -112,7 +112,7 @@
             chronik.plugin('doesnotexist').groups(),
         ).to.be.rejectedWith(
             Error,
-            `Failed getting /plugin/doesnotexist/groups? (): 404: Plugin "doesnotexist" not loaded`,
+            `Failed getting /plugin/doesnotexist/groups?: 404: Plugin "doesnotexist" not loaded`,
         );
 
         // We throw an error if the endpoint is called with an invalid prefix or start hex
@@ -122,13 +122,13 @@
             chronik.plugin(PLUGIN_NAME).groups(badPrefixHex, 'deadbeef'),
         ).to.be.rejectedWith(
             Error,
-            `Failed getting /plugin/${PLUGIN_NAME}/groups?prefix=not+hex&start=deadbeef (): 400: Invalid hex: Odd number of digits`,
+            `Failed getting /plugin/${PLUGIN_NAME}/groups?prefix=not+hex&start=deadbeef: 400: Invalid hex: Odd number of digits`,
         );
         await expect(
             chronik.plugin(PLUGIN_NAME).groups('deadbeef', badStartHex),
         ).to.be.rejectedWith(
             Error,
-            `Failed getting /plugin/${PLUGIN_NAME}/groups?prefix=deadbeef&start=nothex (): 400: Invalid hex: Invalid character 'n' at position 0`,
+            `Failed getting /plugin/${PLUGIN_NAME}/groups?prefix=deadbeef&start=nothex: 400: Invalid hex: Invalid character 'n' at position 0`,
         );
 
         // We cannot request pageSize greater than 50
@@ -136,21 +136,21 @@
             chronik.plugin(PLUGIN_NAME).groups('deadbeef', 'deadbeef', 51),
         ).to.be.rejectedWith(
             Error,
-            `Failed getting /plugin/${PLUGIN_NAME}/groups?prefix=deadbeef&start=deadbeef&page_size=51 (): 400: Requested page size 51 is too big, maximum is 50`,
+            `Failed getting /plugin/${PLUGIN_NAME}/groups?prefix=deadbeef&start=deadbeef&page_size=51: 400: Requested page size 51 is too big, maximum is 50`,
         );
         // We cannot request pageSize less than 1
         await expect(
             chronik.plugin(PLUGIN_NAME).groups('deadbeef', 'deadbeef', 0),
         ).to.be.rejectedWith(
             Error,
-            `Failed getting /plugin/${PLUGIN_NAME}/groups?prefix=deadbeef&start=deadbeef&page_size=0 (): 400: Requested page size 0 is too small, minimum is 1`,
+            `Failed getting /plugin/${PLUGIN_NAME}/groups?prefix=deadbeef&start=deadbeef&page_size=0: 400: Requested page size 0 is too small, minimum is 1`,
         );
         // We cannot request pageSize of way more than 50
         await expect(
             chronik.plugin(PLUGIN_NAME).groups('deadbeef', 'deadbeef', 2 ** 32),
         ).to.be.rejectedWith(
             Error,
-            `Failed getting /plugin/${PLUGIN_NAME}/groups?prefix=deadbeef&start=deadbeef&page_size=4294967296 (): 400: Invalid param page_size: 4294967296, number too large to fit in target type`,
+            `Failed getting /plugin/${PLUGIN_NAME}/groups?prefix=deadbeef&start=deadbeef&page_size=4294967296: 400: Invalid param page_size: 4294967296, number too large to fit in target type`,
         );
     });
     it('After sending a tx to create plugin utxos in multiple groups', async () => {
diff --git a/modules/chronik-client/test/integration/plugins.ts b/modules/chronik-client/test/integration/plugins.ts
--- a/modules/chronik-client/test/integration/plugins.ts
+++ b/modules/chronik-client/test/integration/plugins.ts
@@ -7,7 +7,7 @@
 import { ChildProcess } from 'node:child_process';
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
-import { ChronikClientNode } from '../../index';
+import { ChronikClient } from '../../index';
 import initializeTestRunner, {
     cleanupMochaRegtest,
     setMochaTimeout,
@@ -25,7 +25,7 @@
     const statusEvent = new EventEmitter();
     let get_test_info: Promise<TestInfo>;
     let chronikUrl: string[];
-    let chronik: ChronikClientNode;
+    let chronik: ChronikClient;
     let setupScriptTermination: ReturnType<typeof setTimeout>;
 
     before(async function () {
@@ -46,7 +46,7 @@
         const testInfo = await get_test_info;
 
         chronikUrl = [testInfo.chronik];
-        chronik = new ChronikClientNode(chronikUrl);
+        chronik = new ChronikClient(chronikUrl);
         console.info(`chronikUrl set to ${JSON.stringify(chronikUrl)}`);
 
         setupScriptTermination = setMochaTimeout(
@@ -135,7 +135,7 @@
             chronik.plugin('doesnotexist').utxos(BYTES_a),
         ).to.be.rejectedWith(
             Error,
-            `Failed getting /plugin/doesnotexist/${BYTES_a}/utxos (): 404: Plugin "doesnotexist" not loaded`,
+            `Failed getting /plugin/doesnotexist/${BYTES_a}/utxos: 404: Plugin "doesnotexist" not loaded`,
         );
 
         // We throw an error if the endpoint is called with an invalid plugin group hex
@@ -143,7 +143,7 @@
             chronik.plugin(PLUGIN_NAME).utxos('not a hex string'),
         ).to.be.rejectedWith(
             Error,
-            `Failed getting /plugin/${PLUGIN_NAME}/not a hex string/utxos (): 400: Invalid hex: Invalid character 'n' at position 0`,
+            `Failed getting /plugin/${PLUGIN_NAME}/not a hex string/utxos: 400: Invalid hex: Invalid character 'n' at position 0`,
         );
     });
     it('After broadcasting a tx with plugin utxos in group "a"', async () => {
diff --git a/modules/chronik-client/test/integration/script_endpoints.ts b/modules/chronik-client/test/integration/script_endpoints.ts
--- a/modules/chronik-client/test/integration/script_endpoints.ts
+++ b/modules/chronik-client/test/integration/script_endpoints.ts
@@ -8,7 +8,7 @@
 import { ChildProcess } from 'node:child_process';
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
-import { ChronikClientNode, ScriptType_InNode, Tx_InNode } from '../../index';
+import { ChronikClient, ScriptType, Tx } from '../../index';
 import initializeTestRunner, {
     cleanupMochaRegtest,
     setMochaTimeout,
@@ -170,7 +170,7 @@
     let otherTxids: string[] = [];
 
     it('New regtest chain', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         // Get addresses / scripts (used in all tests)
         p2pkhAddress = await get_p2pkh_address;
@@ -201,8 +201,8 @@
         );
 
         const checkEmptyScriptMethods = async (
-            chronik: ChronikClientNode,
-            type: ScriptType_InNode,
+            chronik: ChronikClient,
+            type: ScriptType,
             payload: string,
             expectedOutputScript: string,
         ) => {
@@ -273,8 +273,8 @@
 
         // Expected errors
         const checkExpectedErrors = async (
-            chronik: ChronikClientNode,
-            type: ScriptType_InNode,
+            chronik: ChronikClient,
+            type: ScriptType,
         ) => {
             const nonHexPayload = 'justsomestring';
             const chronikScriptNonHexPayload = chronik.script(
@@ -285,23 +285,23 @@
                 chronikScriptNonHexPayload.history(),
             ).to.be.rejectedWith(
                 Error,
-                `Failed getting /script/${type}/${nonHexPayload}/history?page=0&page_size=25 (): 400: Invalid hex: Invalid character '${nonHexPayload[0]}' at position 0`,
+                `Failed getting /script/${type}/${nonHexPayload}/history?page=0&page_size=25: 400: Invalid hex: Invalid character '${nonHexPayload[0]}' at position 0`,
             );
             await expect(
                 chronikScriptNonHexPayload.confirmedTxs(),
             ).to.be.rejectedWith(
                 Error,
-                `Failed getting /script/${type}/${nonHexPayload}/confirmed-txs?page=0&page_size=25 (): 400: Invalid hex: Invalid character '${nonHexPayload[0]}' at position 0`,
+                `Failed getting /script/${type}/${nonHexPayload}/confirmed-txs?page=0&page_size=25: 400: Invalid hex: Invalid character '${nonHexPayload[0]}' at position 0`,
             );
             await expect(
                 chronikScriptNonHexPayload.unconfirmedTxs(),
             ).to.be.rejectedWith(
                 Error,
-                `Failed getting /script/${type}/${nonHexPayload}/unconfirmed-txs?page=0&page_size=25 (): 400: Invalid hex: Invalid character '${nonHexPayload[0]}' at position 0`,
+                `Failed getting /script/${type}/${nonHexPayload}/unconfirmed-txs?page=0&page_size=25: 400: Invalid hex: Invalid character '${nonHexPayload[0]}' at position 0`,
             );
             await expect(chronikScriptNonHexPayload.utxos()).to.be.rejectedWith(
                 Error,
-                `Failed getting /script/${type}/${nonHexPayload}/utxos (): 400: Invalid hex: Invalid character '${nonHexPayload[0]}' at position 0`,
+                `Failed getting /script/${type}/${nonHexPayload}/utxos: 400: Invalid hex: Invalid character '${nonHexPayload[0]}' at position 0`,
             );
 
             const hexPayload = 'deadbeef';
@@ -312,25 +312,25 @@
                     chronikScriptHexPayload.history(),
                 ).to.be.rejectedWith(
                     Error,
-                    `Failed getting /script/${type}/${hexPayload}/history?page=0&page_size=25 (): 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected 20 bytes but got 4 bytes`,
+                    `Failed getting /script/${type}/${hexPayload}/history?page=0&page_size=25: 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected 20 bytes but got 4 bytes`,
                 );
                 await expect(
                     chronikScriptHexPayload.confirmedTxs(),
                 ).to.be.rejectedWith(
                     Error,
-                    `Failed getting /script/${type}/${hexPayload}/confirmed-txs?page=0&page_size=25 (): 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected 20 bytes but got 4 bytes`,
+                    `Failed getting /script/${type}/${hexPayload}/confirmed-txs?page=0&page_size=25: 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected 20 bytes but got 4 bytes`,
                 );
                 await expect(
                     chronikScriptHexPayload.unconfirmedTxs(),
                 ).to.be.rejectedWith(
                     Error,
-                    `Failed getting /script/${type}/${hexPayload}/unconfirmed-txs?page=0&page_size=25 (): 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected 20 bytes but got 4 bytes`,
+                    `Failed getting /script/${type}/${hexPayload}/unconfirmed-txs?page=0&page_size=25: 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected 20 bytes but got 4 bytes`,
                 );
                 await expect(
                     chronikScriptHexPayload.utxos(),
                 ).to.be.rejectedWith(
                     Error,
-                    `Failed getting /script/${type}/${hexPayload}/utxos (): 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected 20 bytes but got 4 bytes`,
+                    `Failed getting /script/${type}/${hexPayload}/utxos: 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected 20 bytes but got 4 bytes`,
                 );
             }
             if (type === 'p2pk') {
@@ -338,25 +338,25 @@
                     chronikScriptHexPayload.history(),
                 ).to.be.rejectedWith(
                     Error,
-                    `Failed getting /script/${type}/${hexPayload}/history?page=0&page_size=25 (): 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected one of [33, 65] but got 4 bytes`,
+                    `Failed getting /script/${type}/${hexPayload}/history?page=0&page_size=25: 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected one of [33, 65] but got 4 bytes`,
                 );
                 await expect(
                     chronikScriptHexPayload.confirmedTxs(),
                 ).to.be.rejectedWith(
                     Error,
-                    `Failed getting /script/${type}/${hexPayload}/confirmed-txs?page=0&page_size=25 (): 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected one of [33, 65] but got 4 bytes`,
+                    `Failed getting /script/${type}/${hexPayload}/confirmed-txs?page=0&page_size=25: 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected one of [33, 65] but got 4 bytes`,
                 );
                 await expect(
                     chronikScriptHexPayload.unconfirmedTxs(),
                 ).to.be.rejectedWith(
                     Error,
-                    `Failed getting /script/${type}/${hexPayload}/unconfirmed-txs?page=0&page_size=25 (): 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected one of [33, 65] but got 4 bytes`,
+                    `Failed getting /script/${type}/${hexPayload}/unconfirmed-txs?page=0&page_size=25: 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected one of [33, 65] but got 4 bytes`,
                 );
                 await expect(
                     chronikScriptHexPayload.utxos(),
                 ).to.be.rejectedWith(
                     Error,
-                    `Failed getting /script/${type}/${hexPayload}/utxos (): 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected one of [33, 65] but got 4 bytes`,
+                    `Failed getting /script/${type}/${hexPayload}/utxos: 400: Invalid payload for ${type.toUpperCase()}: Invalid length, expected one of [33, 65] but got 4 bytes`,
                 );
             }
 
@@ -385,11 +385,11 @@
     it('After some txs have been broadcast', async () => {
         txsBroadcast = parseInt(await get_txs_broadcast);
 
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         const checkScriptMethodsInMempool = async (
-            chronik: ChronikClientNode,
-            type: ScriptType_InNode,
+            chronik: ChronikClient,
+            type: ScriptType,
             payload: string,
             expectedOutputScript: string,
             broadcastTxids: string[],
@@ -404,9 +404,7 @@
             // within history txs, confirmed txs are sorted in block order, unconfirmed txs are sorted by timeFirstSeen
             // i.e., history.txs[0] will have the highest timeFirstSeen
             // For txs with the same timeFirstSeen, the alphabetically-last txs appears first
-            const historyClone: Tx_InNode[] = JSON.parse(
-                JSON.stringify(history.txs),
-            );
+            const historyClone: Tx[] = JSON.parse(JSON.stringify(history.txs));
 
             // Sort historyClone by timeFirstSeen and then by txid
             historyClone.sort(
@@ -524,8 +522,8 @@
         );
 
         const checkPagination = async (
-            chronik: ChronikClientNode,
-            type: ScriptType_InNode,
+            chronik: ChronikClient,
+            type: ScriptType,
             payload: string,
             txsBroadcast: number,
             customPageSize: number,
@@ -570,7 +568,7 @@
             // We cannot use pageSize of 0
             await expect(chronikScript.history(0, 0)).to.be.rejectedWith(
                 Error,
-                `Failed getting /script/${type}/${payload}/history?page=0&page_size=0 (): 400: Requested page size 0 is too small, minimum is 1`,
+                `Failed getting /script/${type}/${payload}/history?page=0&page_size=0: 400: Requested page size 0 is too small, minimum is 1`,
             );
 
             console.log('\x1b[32m%s\x1b[0m', `✔ ${type} pagination`);
@@ -598,11 +596,11 @@
         await checkPagination(chronik, 'other', otherScript, txsBroadcast, 50);
     });
     it('After these txs are mined', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         const checkScriptMethodsAfterConfirmation = async (
-            chronik: ChronikClientNode,
-            type: ScriptType_InNode,
+            chronik: ChronikClient,
+            type: ScriptType,
             payload: string,
             expectedOutputScript: string,
             broadcastTxids: string[],
@@ -615,9 +613,7 @@
                 broadcastTxids.length,
             );
             // Clone history.txs to test sorting
-            const historyClone: Tx_InNode[] = JSON.parse(
-                JSON.stringify(history.txs),
-            );
+            const historyClone: Tx[] = JSON.parse(JSON.stringify(history.txs));
 
             // history txs within blocks sorting
             // The history endpoint returns confirmed txs sorted by timeFirstSeen (high to low) and then by txid (alphabetical last to first)
@@ -732,11 +728,11 @@
         // as 'isFinal' is present only on utxos
         // Potential TODO, add isFinal key to tx proto in chronik
 
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         const checkAvalancheFinalized = async (
-            chronik: ChronikClientNode,
-            type: ScriptType_InNode,
+            chronik: ChronikClient,
+            type: ScriptType,
             payload: string,
             expectedOutputScript: string,
             broadcastTxids: string[],
@@ -802,12 +798,12 @@
         );
     });
     it('After a tx is broadcast with outputs of each type', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
         const mixedTxid = await get_mixed_output_txid;
 
         const checkMixedTxInHistory = async (
-            chronik: ChronikClientNode,
-            type: ScriptType_InNode,
+            chronik: ChronikClient,
+            type: ScriptType,
             payload: string,
             mixedTxid: string,
             txsBroadcast: number,
diff --git a/modules/chronik-client/test/integration/token_alp.ts b/modules/chronik-client/test/integration/token_alp.ts
--- a/modules/chronik-client/test/integration/token_alp.ts
+++ b/modules/chronik-client/test/integration/token_alp.ts
@@ -8,12 +8,12 @@
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
 import {
-    ChronikClientNode,
+    ChronikClient,
     TokenInfo,
-    Token_InNode,
-    TxHistoryPage_InNode,
-    Tx_InNode,
-    WsEndpoint_InNode,
+    Token,
+    TxHistoryPage,
+    Tx,
+    WsEndpoint,
     WsMsgClient,
 } from '../../index';
 import initializeTestRunner, {
@@ -183,14 +183,14 @@
     let alpMintTwoTxid = '';
     let alpNonUtf8GenesisTxid = '';
 
-    let alpGenesis: Tx_InNode;
-    let alpMint: Tx_InNode;
-    let alpSend: Tx_InNode;
-    let alpNextGenesis: Tx_InNode;
-    let alpMulti: Tx_InNode;
-    let alpMega: Tx_InNode;
-    let alpMintTwo: Tx_InNode;
-    let alpSendTwo: Tx_InNode;
+    let alpGenesis: Tx;
+    let alpMint: Tx;
+    let alpSend: Tx;
+    let alpNextGenesis: Tx;
+    let alpMulti: Tx;
+    let alpMega: Tx;
+    let alpMintTwo: Tx;
+    let alpSendTwo: Tx;
 
     const alpTokenInfo: TokenInfo = {
         tokenId:
@@ -214,9 +214,9 @@
         },
     };
 
-    let confirmedTxsForAlpGenesisTxid: TxHistoryPage_InNode;
+    let confirmedTxsForAlpGenesisTxid: TxHistoryPage;
 
-    let ws: WsEndpoint_InNode;
+    let ws: WsEndpoint;
 
     const BASE_ADDEDTOMEMPOOL_WSMSG: WsMsgClient = {
         type: 'Tx',
@@ -230,7 +230,7 @@
     };
 
     it('Gets an ALP genesis tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         alpGenesisTxid = await get_alp_genesis_txid;
 
@@ -377,13 +377,13 @@
             output => 'token' in output,
         );
 
-        const utxoTokenKeysFromOutputs: Token_InNode[] = [];
+        const utxoTokenKeysFromOutputs: Token[] = [];
         for (const output of outputsWithTokenKey) {
             if ('token' in output) {
                 const { token } = output;
                 // Remove the entryIdx key from these outputs, as we do not expect to see it in tokenId.utxos() output
-                delete (token as Token_InNode).entryIdx;
-                utxoTokenKeysFromOutputs.push(output.token as Token_InNode);
+                delete (token as Token).entryIdx;
+                utxoTokenKeysFromOutputs.push(output.token as Token);
             }
         }
 
@@ -433,7 +433,7 @@
         // Invalid tokenId is rejected
         await expect(chronik.token('somestring')).to.be.rejectedWith(
             Error,
-            `Failed getting /token/somestring (): 400: Not a txid: somestring`,
+            `Failed getting /token/somestring: 400: Not a txid: somestring`,
         );
         // We get expected error for a txid that is not in the mempool
         await expect(
@@ -442,11 +442,11 @@
             ),
         ).to.be.rejectedWith(
             Error,
-            `Failed getting /token/0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f (): 404: Token 0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f not found in the index`,
+            `Failed getting /token/0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f: 404: Token 0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f not found in the index`,
         );
     });
     it('Gets an ALP mint tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         // We can get an alp mint tx from the mempool
         alpMintTxid = await get_alp_mint_txid;
@@ -530,11 +530,11 @@
         // Error is thrown for a txid that is in the mempool but is not a tokenId
         await expect(chronik.token(alpMintTxid)).to.be.rejectedWith(
             Error,
-            `Failed getting /token/0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f (): 404: Token 0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f not found in the index`,
+            `Failed getting /token/0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f: 404: Token 0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f not found in the index`,
         );
     });
     it('Gets an ALP send tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         // We can get an alp send tx from the mempool
         alpSendTxid = await get_alp_send_txid;
@@ -625,7 +625,7 @@
         expect(alpSend.tokenStatus).to.eql('TOKEN_STATUS_NORMAL');
     });
     it('Gets another ALP genesis tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         // We can get another alp genesis tx from the mempool
         alpNextGenesisTxid = await get_alp_genesis2_txid;
@@ -709,7 +709,7 @@
         expect(alpNextGenesis.tokenStatus).to.eql('TOKEN_STATUS_NORMAL');
     });
     it('Gets an ALP genesis, mint, and send (also a burn) combo tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         // We can get an ALP GENESIS + MINT + SEND all in one tx from the mempool
         alpMultiTxid = await get_alp_multi_txid;
@@ -885,7 +885,7 @@
         }
     });
     it('Can get all of the above txs, and a wild mega-tx, from the blockTxs endpoint after they are mined in a block', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         // Now that we have a block, we get a block key from token info
         const alpGenesisConfirmedInfo = await chronik.token(alpGenesisTxid);
@@ -1191,7 +1191,7 @@
             alpMega,
         ].sort((a, b) => a.txid.localeCompare(b.txid));
 
-        // The token fields of Tx_InNode(s) from blockTxs match the Tx_InNode(s) from tx
+        // The token fields of Tx(s) from blockTxs match the Tx(s) from tx
         // Note the txs are not expected to fully match bc now we have block key and spentBy,
         // expected after confirmation
         // This type of functionality is tested in blocktxs_and_tx_and_rawtx.ts
@@ -1282,7 +1282,7 @@
         ]);
     });
     it('Can get confirmed and unconfirmed txs from tokenId.history()', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         alpNonUtf8GenesisTxid = await get_alp_nonutf8_genesis_txid;
         alpMintTwoTxid = await get_alp_mint_two_txid;
@@ -1455,7 +1455,7 @@
         );
     });
     it('We get tx history in expected order from both tokenId().history() and tokenId.confirmedTxs()', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         // Can get all confirmed token txs for alpGenesisTxid
         const confirmedTxs = await chronik
diff --git a/modules/chronik-client/test/integration/token_slp_fungible.ts b/modules/chronik-client/test/integration/token_slp_fungible.ts
--- a/modules/chronik-client/test/integration/token_slp_fungible.ts
+++ b/modules/chronik-client/test/integration/token_slp_fungible.ts
@@ -7,12 +7,7 @@
 import { ChildProcess } from 'node:child_process';
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
-import {
-    ChronikClientNode,
-    Tx_InNode,
-    WsEndpoint_InNode,
-    WsMsgClient,
-} from '../../index';
+import { ChronikClient, Tx, WsEndpoint, WsMsgClient } from '../../index';
 import initializeTestRunner, {
     cleanupMochaRegtest,
     expectWsMsgs,
@@ -148,12 +143,12 @@
     let slpSendTxid = '';
     let slpEmptyGenesisTxid = '';
 
-    let slpGenesis: Tx_InNode;
-    let slpMint: Tx_InNode;
-    let slpSend: Tx_InNode;
-    let slpEmptyGenesis: Tx_InNode;
+    let slpGenesis: Tx;
+    let slpMint: Tx;
+    let slpSend: Tx;
+    let slpEmptyGenesis: Tx;
 
-    let ws: WsEndpoint_InNode;
+    let ws: WsEndpoint;
 
     const BASE_ADDEDTOMEMPOOL_WSMSG: WsMsgClient = {
         type: 'Tx',
@@ -167,7 +162,7 @@
     };
 
     it('Gets an SLP genesis tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         slpGenesisTxid = await get_slp_fungible_genesis_txid;
 
@@ -273,7 +268,7 @@
         // Note: ws subs and unsubs tested in token_alp.ts
     });
     it('Gets an SLP fungible mint tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         slpMintTxid = await get_slp_fungible_mint_txid;
 
@@ -353,7 +348,7 @@
         expect(slpMint.tokenStatus).to.eql('TOKEN_STATUS_NORMAL');
     });
     it('Gets an SLP fungible send tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         slpSendTxid = await get_slp_fungible_send_txid;
 
@@ -432,7 +427,7 @@
         expect(slpSend.tokenStatus).to.eql('TOKEN_STATUS_NORMAL');
     });
     it('Gets an SLP fungible empty genesis tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         slpEmptyGenesisTxid = await get_slp_fungible_genesis_empty_txid;
 
@@ -490,7 +485,7 @@
         expect(slpEmptyGenesis.tokenStatus).to.eql('TOKEN_STATUS_NORMAL');
     });
     it('Can get all of the above txs from the blockTxs endpoint after they are mined in a block', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         // Now that we have a block, we get a block key from token info
         const slpGenesisConfirmedInfo = await chronik.token(slpGenesisTxid);
@@ -518,7 +513,7 @@
             slpEmptyGenesis,
         ].sort((a, b) => a.txid.localeCompare(b.txid));
 
-        // The token fields of Tx_InNode(s) from blockTxs match the Tx_InNode(s) from tx
+        // The token fields of Tx(s) from blockTxs match the Tx(s) from tx
         // Note the txs are not expected to fully match bc now we have block and spentBy keys,
         // which are expected after confirmation
         // Full endpoint output is tested in blocktxs_and_tx_and_rawtx.ts
diff --git a/modules/chronik-client/test/integration/token_slp_mint_vault.ts b/modules/chronik-client/test/integration/token_slp_mint_vault.ts
--- a/modules/chronik-client/test/integration/token_slp_mint_vault.ts
+++ b/modules/chronik-client/test/integration/token_slp_mint_vault.ts
@@ -7,12 +7,7 @@
 import { ChildProcess } from 'node:child_process';
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
-import {
-    ChronikClientNode,
-    Tx_InNode,
-    WsEndpoint_InNode,
-    WsMsgClient,
-} from '../../index';
+import { ChronikClient, Tx, WsEndpoint, WsMsgClient } from '../../index';
 import initializeTestRunner, {
     cleanupMochaRegtest,
     expectWsMsgs,
@@ -152,11 +147,11 @@
     let slpVaultMintTxid = '';
     let validSlpVaultMintTxid = '';
 
-    let vaultSetup: Tx_InNode;
-    let slpVaultGenesis: Tx_InNode;
-    let slpVaultMint: Tx_InNode;
+    let vaultSetup: Tx;
+    let slpVaultGenesis: Tx;
+    let slpVaultMint: Tx;
 
-    let ws: WsEndpoint_InNode;
+    let ws: WsEndpoint;
 
     const BASE_CONFIRMED_WSMSG: WsMsgClient = {
         type: 'Tx',
@@ -170,7 +165,7 @@
     };
 
     it('Gets an SLP vault setup tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         vaultSetupTxid = await get_vault_setup_txid;
 
@@ -212,7 +207,7 @@
         expect(vaultSetup.tokenStatus).to.eql('TOKEN_STATUS_NON_TOKEN');
     });
     it('Gets this tx from a block', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         const blockTxs = await chronik.blockTxs(CHAIN_INIT_HEIGHT + 2);
         const confirmedVaultSetup = blockTxs.txs.find(
@@ -233,7 +228,7 @@
         expect(history.txs[0]).to.deep.equal(confirmedVaultSetup);
     });
     it('Gets an SLP vault genesis tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         slpVaultGenesisTxid = await get_slp_vault_genesis_txid;
 
@@ -328,7 +323,7 @@
         });
     });
     it('Gets a badly constructed SLP v2 Vault Mint tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         slpVaultMintTxid = await get_slp_vault_mint_txid;
 
diff --git a/modules/chronik-client/test/integration/token_slp_nft1.ts b/modules/chronik-client/test/integration/token_slp_nft1.ts
--- a/modules/chronik-client/test/integration/token_slp_nft1.ts
+++ b/modules/chronik-client/test/integration/token_slp_nft1.ts
@@ -7,12 +7,7 @@
 import { ChildProcess } from 'node:child_process';
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
-import {
-    ChronikClientNode,
-    Tx_InNode,
-    WsEndpoint_InNode,
-    WsMsgClient,
-} from '../../index';
+import { ChronikClient, Tx, WsEndpoint, WsMsgClient } from '../../index';
 import initializeTestRunner, {
     cleanupMochaRegtest,
     expectWsMsgs,
@@ -152,12 +147,12 @@
     let slpSendTxid = '';
     let slpChildGenesisTxid = '';
 
-    let slpGenesis: Tx_InNode;
-    let slpMint: Tx_InNode;
-    let slpSend: Tx_InNode;
-    let slpChildGenesis: Tx_InNode;
+    let slpGenesis: Tx;
+    let slpMint: Tx;
+    let slpSend: Tx;
+    let slpChildGenesis: Tx;
 
-    let ws: WsEndpoint_InNode;
+    let ws: WsEndpoint;
 
     const BASE_ADDEDTOMEMPOOL_WSMSG: WsMsgClient = {
         type: 'Tx',
@@ -171,7 +166,7 @@
     };
 
     it('Gets an SLP NFT1 genesis tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         slpGenesisTxid = await get_slp_nft1_genesis_txid;
 
@@ -269,7 +264,7 @@
         ws.subscribeToTokenId(slpGenesisTxid);
     });
     it('Gets an SLP NFT1 mint tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         slpMintTxid = await get_slp_nft1_mint_txid;
 
@@ -348,7 +343,7 @@
         expect(slpMint.tokenStatus).to.eql('TOKEN_STATUS_NORMAL');
     });
     it('Gets an SLP NFT1 send tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         slpSendTxid = await get_slp_nft1_send_txid;
 
@@ -446,7 +441,7 @@
         expect(slpSend.tokenStatus).to.eql('TOKEN_STATUS_NORMAL');
     });
     it('Gets an SLP NFT1 child genesis tx from the mempool', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         slpChildGenesisTxid = await get_slp_nft1_child_genesis1_txid;
 
@@ -559,7 +554,7 @@
         expect(slpChildGenesis.tokenStatus).to.eql('TOKEN_STATUS_NORMAL');
     });
     it('Can get all of the above txs from the blockTxs endpoint after they are mined in a block', async () => {
-        const chronik = new ChronikClientNode(chronikUrl);
+        const chronik = new ChronikClient(chronikUrl);
 
         const blockTxs = await chronik.blockTxs(CHAIN_INIT_HEIGHT + 2);
 
@@ -593,7 +588,7 @@
             slpChildGenesis,
         ].sort((a, b) => a.txid.localeCompare(b.txid));
 
-        // The token fields of Tx_InNode(s) from blockTxs match the Tx_InNode(s) from tx
+        // The token fields of Tx(s) from blockTxs match the Tx(s) from tx
         // Note the txs are not expected to fully match bc now we have block and spentBy keys,
         // which are expected after confirmation
         // Full endpoint output is tested in blocktxs_and_tx_and_rawtx.ts
diff --git a/modules/chronik-client/test/integration/websocket.ts b/modules/chronik-client/test/integration/websocket.ts
--- a/modules/chronik-client/test/integration/websocket.ts
+++ b/modules/chronik-client/test/integration/websocket.ts
@@ -9,8 +9,8 @@
 import { EventEmitter, once } from 'node:events';
 import path from 'path';
 import {
-    ChronikClientNode,
-    WsEndpoint_InNode,
+    ChronikClient,
+    WsEndpoint,
     WsMsgClient,
     WsSubScriptClient,
 } from '../../index';
@@ -190,7 +190,7 @@
 
     let mixedOutputTxid = '';
 
-    let ws: WsEndpoint_InNode;
+    let ws: WsEndpoint;
 
     let subscriptions: Array<WsSubScriptClient> = [];
 
@@ -203,8 +203,8 @@
         p2pkScript = await get_p2pk_script;
         otherScript = await get_other_script;
 
-        // Initialize a new instance of ChronikClientNode
-        const chronik = new ChronikClientNode(chronikUrl);
+        // Initialize a new instance of ChronikClient
+        const chronik = new ChronikClient(chronikUrl);
 
         // Connect to the websocket with a testable onMessage handler
         ws = chronik.ws({
diff --git a/modules/ecash-agora/src/ad.ts b/modules/ecash-agora/src/ad.ts
--- a/modules/ecash-agora/src/ad.ts
+++ b/modules/ecash-agora/src/ad.ts
@@ -29,7 +29,7 @@
     spentBy: OutPoint | undefined;
 }
 
-export function parseAgoraTx(tx: chronik.Tx_InNode): ParsedAd | undefined {
+export function parseAgoraTx(tx: chronik.Tx): ParsedAd | undefined {
     if (tx.inputs.length === 0) {
         return undefined;
     }
diff --git a/modules/ecash-agora/tests/oneshot.test.ts b/modules/ecash-agora/tests/oneshot.test.ts
--- a/modules/ecash-agora/tests/oneshot.test.ts
+++ b/modules/ecash-agora/tests/oneshot.test.ts
@@ -4,7 +4,7 @@
 
 import { assert, expect, use } from 'chai';
 import chaiAsPromised from 'chai-as-promised';
-import { ChronikClientNode } from 'chronik-client';
+import { ChronikClient } from 'chronik-client';
 import {
     ALL_BIP143,
     Ecc,
@@ -50,7 +50,7 @@
 
 describe('SLP', () => {
     let runner: TestRunner;
-    let chronik: ChronikClientNode;
+    let chronik: ChronikClient;
     let ecc: Ecc;
 
     before(async () => {
diff --git a/modules/ecash-lib/src/test/testRunner.ts b/modules/ecash-lib/src/test/testRunner.ts
--- a/modules/ecash-lib/src/test/testRunner.ts
+++ b/modules/ecash-lib/src/test/testRunner.ts
@@ -2,7 +2,7 @@
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
-import type { ChronikClientNode } from 'chronik-client';
+import type { ChronikClient } from 'chronik-client';
 import type { ChildProcess } from 'node:child_process';
 
 import { Ecc } from '../ecc.js';
@@ -24,14 +24,14 @@
 export class TestRunner {
     public ecc: Ecc;
     public runner: ChildProcess;
-    public chronik: ChronikClientNode;
+    public chronik: ChronikClient;
     private coinsTxid: string | undefined;
     private lastUsedOutIdx: number;
 
     private constructor(
         ecc: Ecc,
         runner: ChildProcess,
-        chronik: ChronikClientNode,
+        chronik: ChronikClient,
     ) {
         this.ecc = ecc;
         this.runner = runner;
@@ -41,7 +41,7 @@
     }
 
     public static async setup(): Promise<TestRunner> {
-        const { ChronikClientNode } = await import('chronik-client');
+        const { ChronikClient } = await import('chronik-client');
         const { spawn } = await import('node:child_process');
         const events = await import('node:events');
         const statusEvent = new events.EventEmitter();
@@ -93,14 +93,14 @@
             console.log('Test runner started');
         });
 
-        let chronik: ChronikClientNode | undefined = undefined;
+        let chronik: ChronikClient | undefined = undefined;
         runner.on('message', async function (message: any) {
             if (message && message.test_info && message.test_info.chronik) {
                 console.log(
                     'Setting chronik url to ',
                     message.test_info.chronik,
                 );
-                chronik = new ChronikClientNode(message.test_info.chronik);
+                chronik = new ChronikClient(message.test_info.chronik);
             }
 
             if (message && message.status) {
diff --git a/modules/ecash-lib/tests/alp.test.ts b/modules/ecash-lib/tests/alp.test.ts
--- a/modules/ecash-lib/tests/alp.test.ts
+++ b/modules/ecash-lib/tests/alp.test.ts
@@ -4,7 +4,7 @@
 
 import { expect } from 'chai';
 
-import { ChronikClientNode } from 'chronik-client';
+import { ChronikClient } from 'chronik-client';
 
 import { Ecc } from '../src/ecc.js';
 import { shaRmd160 } from '../src/hash.js';
@@ -33,7 +33,7 @@
 
 describe('ALP', () => {
     let runner: TestRunner;
-    let chronik: ChronikClientNode;
+    let chronik: ChronikClient;
     let ecc: Ecc;
 
     before(async () => {
diff --git a/modules/ecash-lib/tests/slp.test.ts b/modules/ecash-lib/tests/slp.test.ts
--- a/modules/ecash-lib/tests/slp.test.ts
+++ b/modules/ecash-lib/tests/slp.test.ts
@@ -3,7 +3,7 @@
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 import { expect } from 'chai';
-import { ChronikClientNode } from 'chronik-client';
+import { ChronikClient } from 'chronik-client';
 import { EventEmitter, once } from 'node:events';
 
 import { Ecc } from '../src/ecc.js';
@@ -57,7 +57,7 @@
 
 describe('SLP Integration Test', () => {
     let runner: TestRunner;
-    let chronik: ChronikClientNode;
+    let chronik: ChronikClient;
     let ecc: Ecc;
 
     before(async () => {
diff --git a/modules/ecash-lib/tests/txBuilder.test.ts b/modules/ecash-lib/tests/txBuilder.test.ts
--- a/modules/ecash-lib/tests/txBuilder.test.ts
+++ b/modules/ecash-lib/tests/txBuilder.test.ts
@@ -4,7 +4,7 @@
 
 import { expect } from 'chai';
 
-import { ChronikClientNode } from 'chronik-client';
+import { ChronikClient } from 'chronik-client';
 
 import { Ecc } from '../src/ecc.js';
 import { sha256d, shaRmd160 } from '../src/hash.js';
@@ -50,7 +50,7 @@
 
 describe('TxBuilder', () => {
     let runner: TestRunner;
-    let chronik: ChronikClientNode;
+    let chronik: ChronikClient;
     let ecc: Ecc;
 
     before(async () => {