diff --git a/apps/ecash-herald/config.ts b/apps/ecash-herald/config.ts
index f536899cf..ed989f5ec 100644
--- a/apps/ecash-herald/config.ts
+++ b/apps/ecash-herald/config.ts
@@ -1,190 +1,191 @@
-// Copyright (c) 2023 The Bitcoin developers
+// Copyright (c) 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 { SendMessageOptions } from 'node-telegram-bot-api';
 
 interface CryptoSlug {
     coingeckoSlug: string;
     ticker: string;
 }
 export type FiatCode = 'usd' | 'eur' | 'gbp' | 'jpy';
 export interface HeraldPriceApi {
     apiBase: string;
     cryptos: CryptoSlug[];
     fiat: FiatCode;
     precision: number;
 }
 export interface HeraldConfig {
     cacheTtlMsecs: number;
     xecSendDisplayCount: number;
     chronik: string[];
     blockExplorer: string;
     priceApi: HeraldPriceApi;
     fiatReference: { usd: string; jpy: string; eur: string; gbp: string };
     stakingRewardApiUrl: string;
     ifpAddress: string;
     tgMsgOptions: SendMessageOptions;
     whaleSats: {
         bigWhale: number;
         // 10 billion xec
         modestWhale: number;
         // 5 billion xec
         shark: number;
         // 1 billion xec
         swordfish: number;
         // 700 million xec
         barracuda: number;
         // 500 million xec
         octopus: number;
         // 250 million xec
         piranha: number;
         // 100 million xec
         crab: number;
         // anything under 100 million xec
         shrimp: number;
     };
     emojis: {
         agora: string;
         agoraBuy: string;
         agoraList: string;
         agoraCancel: string;
         alias: string;
         alp: string;
         invalid: string;
         nft: string;
         mintvault: string;
         block: string;
         miner: string;
         staker: string;
         xecSend: string;
         arrowRight: string;
         tokenBurn: string;
         tokenGenesis: string;
         tokenSend: string;
         tokenMint: string;
         tokenFixed: string;
         gift: string;
         bank: string;
         app: string;
         token: string;
         fusion: string;
         cashtabMsg: string;
         cashtabEncrypted: string;
         payButton: string;
         swap: string;
         airdrop: string;
         paywall: string;
         authentication: string;
         unknown: string;
         memo: string;
         bigWhale: string;
         modestWhale: string;
         shark: string;
         swordfish: string;
         barracuda: string;
         octopus: string;
         piranha: string;
         crab: string;
         shrimp: string;
         priceUp: string;
         priceDown: string;
     };
 }
 const config: HeraldConfig = {
     cacheTtlMsecs: 1000 * 60 * 60 * 4, // 4 hours
     xecSendDisplayCount: 12,
     chronik: [
         'https://chronik-native1.fabien.cash',
         'https://chronik-native2.fabien.cash',
         'https://chronik-native.fabien.cash',
         'https://chronik.pay2stay.com/xec',
         'https://chronik.be.cash/xec2',
     ],
     blockExplorer: 'https://explorer.e.cash',
     priceApi: {
         apiBase: 'https://api.coingecko.com/api/v3/simple/price',
         cryptos: [
             { coingeckoSlug: 'ecash', ticker: 'XEC' },
             { coingeckoSlug: 'bitcoin', ticker: 'BTC' },
             { coingeckoSlug: 'ethereum', ticker: 'ETH' },
         ],
         fiat: 'usd',
         precision: 8,
     },
     fiatReference: { usd: '$', jpy: 'Β₯', eur: '€', gbp: 'Β£' },
     stakingRewardApiUrl: 'https://avalanche.cash/api/nextstakingreward',
     ifpAddress: 'ecash:prfhcnyqnl5cgrnmlfmms675w93ld7mvvqd0y8lz07',
     tgMsgOptions: {
         parse_mode: 'HTML',
         disable_web_page_preview: true,
     },
     whaleSats: {
         // 20 billion xec
         bigWhale: 2000000000000,
         // 10 billion xec
         modestWhale: 1000000000000,
         // 5 billion xec
         shark: 500000000000,
         // 1 billion xec
         swordfish: 100000000000,
         // 700 million xec
         barracuda: 70000000000,
         // 500 million xec
         octopus: 50000000000,
         // 250 million xec
         piranha: 25000000000,
         // 100 million xec
         crab: 10000000000,
         // anything under 100 million xec
         shrimp: 0,
     },
     emojis: {
         agora: 'πŸ›',
         agoraBuy: 'πŸ’°',
         agoraList: '🏷',
         agoraCancel: '❌',
         alias: 'πŸ‘Ύ',
         alp: 'πŸ—»',
         invalid: '❌',
         nft: 'πŸ–Ό',
         mintvault: '🧩',
         block: 'πŸ“¦',
         miner: '⛏️',
         staker: 'πŸ’°',
         xecSend: 'πŸ’Έ',
         arrowRight: '➑️',
         tokenBurn: 'πŸ”₯',
         tokenGenesis: 'πŸ§ͺ',
         tokenSend: '🎟',
         tokenMint: 'πŸ”¨',
         tokenFixed: 'πŸ”’',
         gift: '🎁',
         bank: '🏦',
         app: 'πŸ“±',
         token: 'πŸͺ™',
         fusion: 'βš›οΈ',
         cashtabMsg: 'πŸ–‹',
         cashtabEncrypted: 'πŸ”',
         payButton: 'πŸ›’',
         swap: '🀳',
         airdrop: 'πŸͺ‚',
         paywall: 'πŸ’Έ',
         authentication: 'πŸ”“',
         unknown: '❓',
         memo: 'πŸ—ž',
         bigWhale: 'πŸ‹',
         modestWhale: '🐳',
         shark: '🦈',
         swordfish: '🐬',
         barracuda: '🐠',
         octopus: 'πŸ™',
         piranha: '🐑',
         crab: 'πŸ¦€',
         // Most addresses seen by the app are shrimp, so use empty string
         shrimp: '',
         priceUp: 'πŸ“ˆ',
         priceDown: 'πŸ“‰',
     },
 };
 
 export default config;
diff --git a/apps/ecash-herald/scripts/generateMock.ts b/apps/ecash-herald/scripts/generateMock.ts
index ca8d5fb94..c34920c42 100644
--- a/apps/ecash-herald/scripts/generateMock.ts
+++ b/apps/ecash-herald/scripts/generateMock.ts
@@ -1,278 +1,278 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 import config from '../config';
 import fs from 'fs';
 import path from 'path';
 import { ChronikClient, Tx } from 'chronik-client';
 import { MockChronikClient } from '../../../modules/mock-chronik-client';
 import { jsonReplacer, getCoingeckoApiUrl } from '../src/utils';
 import unrevivedBlockMocks from '../test/mocks/block';
 import { jsonReviver } from '../src/utils';
 import { handleBlockFinalized, StoredMock } from '../src/events';
 import { parseBlockTxs } from '../src/parse';
 import { sendBlockSummary } from '../src/telegram';
 import cashaddr from 'ecashaddrjs';
 import axios from 'axios';
 import MockAdapter from 'axios-mock-adapter';
 import { caching } from 'cache-manager';
 import { MockTelegramBot } from '../test/mocks/telegramBotMock';
 import secrets from '../secrets';
 import TelegramBot from 'node-telegram-bot-api';
 
 const mockedChronik = new MockChronikClient();
 const chronik = new ChronikClient(config.chronik);
 const mockedTelegramBot = new MockTelegramBot();
 const { dev } = secrets;
 const { botId, channelId } = dev.telegram;
 
 const blockMocks = JSON.parse(JSON.stringify(unrevivedBlockMocks), jsonReviver);
 
 // Initialize telegram bot to send msgs to dev channel
 const telegramBotDev = new TelegramBot(botId, { polling: true });
 
 /**
  * generateMock
  *
  * This script takes an array of txids and builds a fake block with them
  * In this way we can still use ecash-herald's block-parsing functionality
  * while showcasing all of its features, without needing to duplicate txids
  * that are already tested
  */
 
 const MOCK_HASH =
     '0000000000000000000000000000000000000000000000000000000000000000';
 const MOCK_HEIGHT = 819346;
 
 // Test vectors
 // Add txids to this array related to new features as new diffs are added
 const txids = [
     // Coinbase tx
     '0bf6e9cd974cd5fc6fbbf739a42447d41a301890e2db242295c64df63dc3ee7e', // Coinbase tx with staking rwds
 
     // eToken mint tx
     '010114b9bbe776def1a512ad1e96a4a06ec4c34fc79bcb5d908845f5102f6b0f', // etoken genesis txs
 
     // Cashtab CACHET rewards
     '004e018dd98520aa722ee76c608771dd578a044f38103a8298f25e6ffbc7c3ba',
     '0110cd886ecd2d9570e98b7501cd039f4e5352d69659a46f1a49cc19c1869701',
     '327101f6f3b740280a6e9fbd8edc41f4f0500633672975a5974a4147c94016a5',
 
     // Cashtab CACHET send tx that is not a Cashtab Reward
     'aa13c6f214ff58f36ed5e108a7f36d8f98729c50186b27a53b989c7f36fbf517',
 
     // Cashtab XEC rewards
     'd8fe456c89357c23ac6d240fe9319ce9ba393c9c3833631046a265ca7c8349e6',
     '083b7862bae48e78549ccf63833896f5f4f5bdef5c380a108fa99cdb64261fa3',
 
     // eToken send txs
     '6ffcc83e76226bd32821cc6862ce9b363b22594247a4e73ccf3701b0023592b2', // etoken send tx, 0 decimals
     'fb70df00c07749082756054522d3f08691fd9caccd0e0abf736df23d22845a6e', // etoken send tx, 7 decimals
     '25345b0bf921a2a9080c647768ba440bbe84499f4c7773fba8a1b03e88ae7fe7', // etoken send locale string formatting
     '0167e881fcb359cdfc82af5fc6c0821daf55f40767694eea2f23c0d42a9b1c17', // etoken self-send tx, BUX
 
     // ALP send txs
     'b2c9c056339d41ec59341541dda8bd6e570730beba485e14eb54d0a073700c22', // etoken send tx, CRD
     '45ec66bc2440d2f94fa2c645e20a44f6fab7c397053ce77a95484c6053104cdc', // EMPP SLPv2 send
     '413b57617d2c497b137d31c53151fee595415ec273ef7a111160da8093147ed8', // EMPP SLPv2 mint
 
     // eToken burn tx
     '6b139007a0649f99a1a099c7c924716ee1920f74ea83111f6426854d4c3c3c79', // etoken burn tx
 
     // App txs
     'd5be7a4b483f9fdbbe3bf46cfafdd0100d5dbeee0b972f4dabc8ae9d9962fa55', // Cash fusion tx
     'd02d94a1a520877c60d1e3026c3e85f8995d48d7b90140f83e24ede592c30306', // Cashtab msg
     '1083da7ead4779fbab5c5e8291bb7a37abaf4f97f5ff99ee654759b2eaee445b', // Encrypted cashtab msg
     'ad44bf5e214ab71bb60a2eee165f368c139cd49c2380c3352f0a4fffc746b36a', // SWaP SLP Atomic Swap Signal
     'a8c348539a1470b28b9f99693994b918b475634352994dddce80ad544e871b3a', // memo | reply to memo
     '7a0d6ae3384e293183478f681f51a77ef4c71f29957199364bb9ba4d8e1938be', // Airdrop
     '22135bb69435023a84c80b1b93b31fc8898c3507eaa70569ed038f32d59599a9', // alias beta
     '9094e1aab7ac73c680bf66e78cc8311831b3d813e608bff1e07b1854855fc0f1', // Unknown app tx, parsable
     'b5782d3a3b55e5ee9e4330a969c2891042ae05fafab7dc05cd14da63e7242f8e', // Unknown app tx, likely hex
 
     // XEC send txs
     '4f33c81d95641eb0f80e793dc96c58a2438f9bb1f18750d8fb3b56c28cd25035', // πŸ‹, Address in directory, self-send XEC tx
     'f5d4c112cfd22701226ba050cacfacc3aff570964c6196f67e326fc3224300a2', // πŸ¦€ recipient
 ];
 
 async function generateMock(
     chronik: ChronikClient,
     mockedChronik: typeof MockChronikClient,
     telegramBot: TelegramBot,
     mockedTelegramBot: MockTelegramBot,
     channelId: string,
     block: StoredMock,
     txids: string[],
 ) {
     const { outputScriptInfoMap, tokenInfoMap, coingeckoResponse } = block;
     // Get txids from your saved block
     const savedTxids = block.blockTxs.map(tx => {
         return tx.txid;
     });
 
     // Determine which, if any, txids need to be added to savedBlock
-    let newTxids = [];
-    for (let i in txids) {
+    const newTxids: string[] = [];
+    for (const i in txids) {
         if (!savedTxids.includes(txids[i])) {
             newTxids.push(txids[i]);
         }
     }
 
     // Build array of promises to get txid info from chronik
-    let chronikTxidPromises = [];
-    for (let i in newTxids) {
+    const chronikTxidPromises = [];
+    for (const i in newTxids) {
         chronikTxidPromises.push(
             new Promise<Tx>((resolve, reject) => {
                 chronik.tx(newTxids[i]).then(
                     result => {
                         resolve(result as Tx);
                     },
                     err => {
                         reject(err);
                     },
                 );
             }),
         );
     }
     let newChronikTxs: Tx[];
     try {
         newChronikTxs = await Promise.all(chronikTxidPromises);
     } catch (err) {
         console.log(
             '\x1b[31m%s\x1b[0m',
             `Error in Promise.all(chronikTxidPromises)`,
             err,
         );
         // Exit in error condition
         process.exit(1);
     }
     // Add these new chronik tx objects to the txs: key of your savedBlock
     const blockTxs = block.blockTxs.concat(newChronikTxs);
 
     // Mock chronik response for chronik.blockTxs
     mockedChronik.setTxHistoryByBlock(MOCK_HEIGHT, blockTxs);
 
     // Get parsedBlock
     const parsedBlock = parseBlockTxs(MOCK_HASH, MOCK_HEIGHT, blockTxs);
 
     // Tell mockedChronik what response we expect for chronik.tx
     const { tokenIds, outputScripts } = parsedBlock;
 
     // Instead of saving all the chronik responses as mocks, which would be very large
     // Just set them as mocks based on tokenInfoMap, which contains the info we need
     tokenIds.forEach(tokenId => {
         mockedChronik.setMock('token', {
             input: tokenId,
             output: {
                 genesisInfo: tokenInfoMap.has(tokenId)
                     ? tokenInfoMap.get(tokenId)
                     : {
                           tokenTicker: 'STUB',
                           tokenName: 'Placeholder Token Name',
                           decimals: 0,
                       },
             },
         });
     });
 
     outputScripts.forEach(outputScript => {
-        let { type, hash } =
+        const { type, hash } =
             cashaddr.getTypeAndHashFromOutputScript(outputScript);
         mockedChronik.setScript(type, hash);
 
         const outputScriptInfo = outputScriptInfoMap.get(outputScript);
         if (typeof outputScriptInfo !== 'undefined') {
             const { utxos } = outputScriptInfo;
             mockedChronik.setUtxos(type, hash, { outputScript, utxos });
         } else {
             // If you don't have a mock for this particular outputScript in block.js,
             // mock it as an address with a single utxo for 100 XEC
             mockedChronik.setUtxos(type, hash, {
                 outputScript,
                 utxos: [{ value: 10000 }],
             });
         }
     });
 
     // Mock coingecko price response
     // onNoMatch: 'throwException' helps to debug if mock is not being used
     const mock = new MockAdapter(axios, {
         onNoMatch: 'throwException',
     });
 
     // Mock a successful API request
     mock.onGet(getCoingeckoApiUrl(config)).reply(200, coingeckoResponse);
 
     // Generate app mocks using this block
     // TODO need to mock all the calls here
     // so need to manually build outputscriptinfomap, tokeninfomap
     const CACHE_TTL = 2 * config.cacheTtlMsecs;
     const memoryCache = await caching('memory', {
         max: 100,
         ttl: CACHE_TTL,
     });
     const returnedMocks = (await handleBlockFinalized(
         mockedChronik,
         mockedTelegramBot,
         channelId,
         MOCK_HASH,
         MOCK_HEIGHT,
         memoryCache,
         true,
     )) as StoredMock;
 
     // Save it to a file
     // Directory for mocks. Relative to /scripts, ../test/mocks/generated/
     //const mocksDir = path.join(__dirname, '..', 'test', 'mocks', 'generated');
     //const mocksFileName = `uber_block_${Date.now()}.json`;
 
     const mocksDir = path.join(__dirname, '..', 'test', 'mocks');
     const mocksFileName = 'block.ts';
 
     // Create directory if it does not exist
     if (!fs.existsSync(mocksDir)) {
         fs.mkdirSync(mocksDir);
     }
     // We want this string to appear in the generated blocks.js file,
     // but not in this file, as we want this file to show up in phab diffs
 
-    const mocksWrite = `// Copyright (c) 2023 The Bitcoin developers\n// Distributed under the MIT software license, see the accompanying\n// file COPYING or http://www.opensource.org/licenses/mit-license.php.\n\nconst mockedBlock: any =${JSON.stringify(
+    const mocksWrite = `// Copyright (c) 2023 The Bitcoin developers\n// Distributed under the MIT software license, see the accompanying\n// file COPYING or http://www.opensource.org/licenses/mit-license.php.\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst mockedBlock: any =${JSON.stringify(
         returnedMocks,
         jsonReplacer,
         2,
     )};\n\nexport default mockedBlock;\n`;
 
     fs.writeFileSync(`${mocksDir}/${mocksFileName}`, mocksWrite, 'utf-8');
 
     // Send msg(s) to Telegram
 
     const { blockSummaryTgMsgs, blockSummaryTgMsgsApiFailure } = returnedMocks;
 
     // Send msg with successful price API call
     await sendBlockSummary(blockSummaryTgMsgs, telegramBot, channelId);
 
     // Send msg with failed price API call
     await sendBlockSummary(
         blockSummaryTgMsgsApiFailure,
         telegramBot,
         channelId,
     );
 
     console.log(
         '\x1b[32m%s\x1b[0m',
         `βœ” Built mocks and sent msgs for ecash-herald mock block.`,
     );
 
     process.exit(0);
 }
 
 generateMock(
     chronik,
     mockedChronik,
     telegramBotDev,
     mockedTelegramBot,
     channelId,
     blockMocks,
     txids,
 );
diff --git a/apps/ecash-herald/scripts/getCoingeckoPrices.ts b/apps/ecash-herald/scripts/getCoingeckoPrices.ts
index e11bbeab6..d7ecec7fc 100644
--- a/apps/ecash-herald/scripts/getCoingeckoPrices.ts
+++ b/apps/ecash-herald/scripts/getCoingeckoPrices.ts
@@ -1,65 +1,70 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 import { getCoingeckoPrices, formatPrice } from '../src/utils';
 import config from '../config';
 
 const testedPriceObjects = [
     config.priceApi,
     {
         apiBase: 'https://api.coingecko.com/api/v3/simple/price',
         cryptos: [
             { coingeckoSlug: 'ecash', ticker: 'XEC' },
             { coingeckoSlug: 'dogecoin', ticker: 'DOGE' },
             { coingeckoSlug: 'solana', ticker: 'SOL' },
             { coingeckoSlug: 'monero', ticker: 'XMR' },
         ],
         fiat: 'usd',
         precision: 8,
     },
     {
         apiBase: 'https://api.coingecko.com/api/v3/simple/price',
         cryptos: [
             { coingeckoSlug: 'ecash', ticker: 'XEC' },
             { coingeckoSlug: 'dogecoin', ticker: 'DOGE' },
             { coingeckoSlug: 'solana', ticker: 'SOL' },
             { coingeckoSlug: 'monero', ticker: 'XMR' },
         ],
         fiat: 'eur',
         precision: 6,
     },
 ];
 
+// Use any type as this is an overengineered function from before ts implementation
+// not impactful to improve the types since we never use the feature
+// todo change if we need it
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
 async function printGetPricesInfo(priceInfoObj: any) {
     const { cryptos, fiat, precision } = priceInfoObj;
     const resp = await getCoingeckoPrices(priceInfoObj);
     let coingeckoPrices;
     if (resp !== false) {
         coingeckoPrices = resp.coingeckoPrices;
     } else {
         return console.error(`Failed to fetch coingeckoPrices`);
     }
 
     console.log(
         `Price info for ${cryptos
+            // eslint-disable-next-line @typescript-eslint/no-explicit-any
             .map((crypto: any) => {
                 return crypto.ticker;
             })
             .join(
                 ', ',
             )} in ${fiat.toUpperCase()} with ${precision}-decimal precision`,
     );
 
-    for (let i in coingeckoPrices) {
+    for (const i in coingeckoPrices) {
         const { fiat, price, ticker } = coingeckoPrices[i];
         const formattedPrice = formatPrice(price, fiat);
         console.log(`1 ${ticker} = ${formattedPrice} ${fiat.toUpperCase()}`);
     }
     // New line
     console.log('');
 }
 
 for (let i = 0; i < testedPriceObjects.length; i += 1) {
     printGetPricesInfo(testedPriceObjects[i]);
 }
diff --git a/apps/ecash-herald/scripts/sendMsgByBlock.ts b/apps/ecash-herald/scripts/sendMsgByBlock.ts
index 75d13d066..36e87b1ae 100644
--- a/apps/ecash-herald/scripts/sendMsgByBlock.ts
+++ b/apps/ecash-herald/scripts/sendMsgByBlock.ts
@@ -1,121 +1,119 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 /**
  * sendMsgByBlockheight.ts
  *
  * A script to allow developer to generate and broadcast an ecash-herald message
  * by blockheight
  *
  * Use cases
  * - Developing and testing a feature that is not in any of the current test blocks
  * - Proof of concept for future version of app where you may want to send "missed" msgs
  *   if the app is down for some period of time
  *
  * Example use
  *
  * Send msg to test channel for default blockheight (genesis block)
  * node scripts/sendMsgByBlock.js
  *
  * Send msg to test channel for blockheight 700000
  * node scripts/sendMsgByBlock.js 700000
  */
 
 import { handleBlockFinalized } from '../src/events';
 import { sendBlockSummary } from '../src/telegram';
 import { getCoingeckoApiUrl } from '../src/utils';
 import config from '../config';
 import { ChronikClient } from 'chronik-client';
 import secrets from '../secrets';
 import TelegramBot from 'node-telegram-bot-api';
 import { caching } from 'cache-manager';
 import { StoredMock } from '../src/events';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
 
 // Default to the genesis block
 let height = 0;
 
 // Use live API for axios calls and not mocks
 // Default to false as it doesn't take much testing to rate limit coingecko API
 let liveApi = false;
 
 // Look for blockheight specified from command line
 if (process.argv && typeof process.argv[2] !== 'undefined') {
     // user input if available, commas removed
     height = parseInt(process.argv[2].replace(/,/g, ''));
     if (typeof process.argv[3] !== 'undefined' && process.argv[3] === 'true') {
         liveApi = true;
         console.log(`Sending msg with live API calls`);
     }
 }
 
 const chronik = new ChronikClient(config.chronik);
 const { dev } = secrets;
 const { botId, channelId } = dev.telegram;
 const telegramBotDev = new TelegramBot(botId, { polling: true });
 
-// Mock price API call to prevent rate limiting during testing
-const axios = require('axios');
-const MockAdapter = require('axios-mock-adapter');
-
 async function sendMsgByBlock(
     chronik: ChronikClient,
     telegramBot: TelegramBot,
     channelId: string,
     height: number,
 ) {
     // Need cache to pass to function
     const CACHE_TTL = 2 * config.cacheTtlMsecs;
     const memoryCache = await caching('memory', {
         max: 100,
         ttl: CACHE_TTL,
     });
     // We do not need this value if we are not using the live API
     let hash = height.toString();
     if (!liveApi) {
         // Mock price API
         const mock = new MockAdapter(axios, { onNoMatch: 'throwException' });
         const mockResult = {
             bitcoin: { usd: 25000.0 },
             ecash: { usd: 0.00003333 },
             ethereum: { usd: 1900.0 },
         };
         mock.onGet(getCoingeckoApiUrl(config)).reply(200, mockResult);
     } else {
         // Get hash if we are using live API calls
 
         const block = await chronik.block(height);
         hash = block.blockInfo.hash;
     }
 
     const returnedMocks = (await handleBlockFinalized(
         chronik,
         telegramBot,
         channelId,
         hash,
         height,
         memoryCache,
         true,
     )) as StoredMock;
 
     const { blockSummaryTgMsgs, blockSummaryTgMsgsApiFailure } = returnedMocks;
 
     // Send msg with successful price API call
     await sendBlockSummary(blockSummaryTgMsgs, telegramBot, channelId, height);
 
     // Send msg with failed price API call
     await sendBlockSummary(
         blockSummaryTgMsgsApiFailure,
         telegramBot,
         channelId,
     );
 
     console.log(
         '\x1b[32m%s\x1b[0m',
         `βœ” Sent telegram msg for block ${height.toLocaleString()}`,
     );
 
     process.exit(0);
 }
 
 sendMsgByBlock(chronik, telegramBotDev, channelId, height);
diff --git a/apps/ecash-herald/src/chronik.ts b/apps/ecash-herald/src/chronik.ts
index befa30f79..c27e0c639 100644
--- a/apps/ecash-herald/src/chronik.ts
+++ b/apps/ecash-herald/src/chronik.ts
@@ -1,266 +1,266 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 import {
     ChronikClient,
     ScriptType,
     Tx,
     GenesisInfo,
     Utxo,
 } from 'chronik-client';
 import { getEmojiFromBalanceSats } from './utils';
 import cashaddr from 'ecashaddrjs';
 
 // Max txs we can get in one request
 const CHRONIK_MAX_PAGESIZE = 200;
 
 export type TokenInfoMap = Map<string, GenesisInfo>;
 export const getTokenInfoMap = async (
     chronik: ChronikClient,
     tokenIdSet: Set<string>,
 ) => {
-    let tokenInfoMap: TokenInfoMap = new Map();
+    const tokenInfoMap: TokenInfoMap = new Map();
     const tokenInfoPromises: Promise<void>[] = [];
     tokenIdSet.forEach(tokenId => {
         tokenInfoPromises.push(
             new Promise((resolve, reject) => {
                 chronik.token(tokenId).then(
                     response => {
                         // Note: txDetails.slpTxData.genesisInfo only exists for token genesis txs
                         try {
                             const genesisInfo = response.genesisInfo;
                             tokenInfoMap.set(tokenId, genesisInfo);
                             resolve();
                         } catch (err) {
                             console.log(
                                 `Error getting genesis info for ${tokenId}`,
                                 err,
                             );
                             reject(err);
                         }
                     },
                     err => {
                         reject(err);
                     },
                 );
             }),
         );
     });
 
     try {
         await Promise.all(tokenInfoPromises);
     } catch (err) {
         console.log(`Error in await Promise.all(tokenInfoPromises)`, err);
         // Print all tokenIds in event of error
         // Note: any 1 promise failing in Promise.all() will hit this
         // catch block
         console.log(`tokenIdSet:`);
         tokenIdSet.forEach(tokenId => {
             console.log(tokenId);
         });
         return false;
     }
     return tokenInfoMap;
 };
 
 export interface OutputscriptInfo {
     emoji: string;
     balanceSats: number;
     utxos: Utxo[];
 }
 /**
  * Build a reference map of outputScripts and their balance in satoshis
  * @param {object} chronik
  * @param {set} outputScripts
  * @returns {map} addressInfoMap, a map with key = address, value = {balanceSats, emoji, utxos}
  */
 export const getOutputscriptInfoMap = async (
     chronik: ChronikClient,
     outputScripts: Set<string>,
 ): Promise<false | Map<string, OutputscriptInfo>> => {
-    let outputScriptInfoMap = new Map();
+    const outputScriptInfoMap = new Map();
     const outputScriptInfoPromises: Promise<void>[] = [];
 
     // For each outputScript, create a promise to get its balance and add
     // info related to this balance to outputScriptInfoMap
     outputScripts.forEach(outputScript => {
         // Decode output script
         const { type, hash } =
             cashaddr.getTypeAndHashFromOutputScript(outputScript);
         outputScriptInfoPromises.push(
             new Promise((resolve, reject) => {
                 chronik
                     .script(type as ScriptType, hash)
                     .utxos()
                     .then(
                         response => {
                             // If this address has no utxos, then utxos.length is 0
                             // If this address has utxos, then utxos = [{utxos: []}]
                             const balanceSats =
                                 response.utxos.length === 0
                                     ? 0
                                     : response.utxos
                                           .map(utxo => utxo.value)
                                           .reduce(
                                               (prev, curr) => prev + curr,
                                               0,
                                           );
 
                             // Set the map outputScript => emoji
                             outputScriptInfoMap.set(outputScript, {
                                 emoji: getEmojiFromBalanceSats(balanceSats),
                                 balanceSats,
                                 utxos: response.utxos,
                             });
                             resolve();
                         },
                         err => {
                             reject(err);
                         },
                     );
             }),
         );
     });
     try {
         await Promise.all(outputScriptInfoPromises);
     } catch (err) {
         console.log(
             `Error in await Promise.all(outputScriptInfoPromises)`,
             err,
         );
         // Print all outputScripts in event of error
         // Note: any 1 promise failing in Promise.all() will hit this
         // catch block
         console.log(`outputScripts:`);
         outputScripts.forEach(outputScript => {
             console.log(outputScript);
         });
         return false;
     }
     return outputScriptInfoMap;
 };
 /**
  * Get all txs in a block
  * Txs are paginated so this may require more than one API call
  * @param chronik
  * @param blockHeight
  * @throws on chronik error
  */
 export const getAllBlockTxs = async (
     chronik: ChronikClient,
     blockHeight: number,
     pageSize = CHRONIK_MAX_PAGESIZE,
 ): Promise<Tx[]> => {
     const firstPage = await chronik.blockTxs(blockHeight, 0, pageSize);
     const { txs, numPages } = firstPage;
 
     if (numPages === 1) {
         return txs;
     }
 
     const remainingPagesPromises: Promise<Tx[]>[] = [];
 
     // Start with i=1 as you already have the first page of txs, which corresponds with pagenum = 0
     for (let i = 1; i < numPages; i += 1) {
         remainingPagesPromises.push(
             new Promise((resolve, reject) => {
                 chronik.blockTxs(blockHeight, i, pageSize).then(
                     result => {
                         resolve(result.txs);
                     },
                     err => {
                         reject(err);
                     },
                 );
             }),
         );
     }
     const remainingTxs = await Promise.all(remainingPagesPromises);
 
     // Combine all txs into an array
     return txs.concat(remainingTxs.flat());
 };
 /**
  * Get the start and end blockheights that will include all txs within a specified time period
  * Note: This function only works for time intervals relative to "right now"
  * We always return chaintip as the end height
  * @param  chronik
  * @param now unix timestamp in seconds
  * @param  secondsAgo how far back we are interested in getting blocks
  */
 export const getBlocksAgoFromChaintipByTimestamp = async (
     chronik: ChronikClient,
     now: number,
     secondsAgo: number,
 ): Promise<{ chaintip: number; startBlockheight: number }> => {
     // Get the chaintip
     const chaintip = (await chronik.blockchainInfo()).tipHeight;
 
     // Make an educated guess about how many blocks ago the first block we want should be
     // = 10 minutes per block * 60 seconds per minute
     const SECONDS_PER_BLOCK = 600;
     const guessedBlocksAgo = Math.floor(secondsAgo / SECONDS_PER_BLOCK);
     const guessedBlockheight = chaintip - guessedBlocksAgo;
 
     // Get the block from blocksAgo and check its timestamp
     const guessedBlock = (await chronik.block(guessedBlockheight)).blockInfo;
 
     let guessedBlockTimestampDelta = now - guessedBlock.timestamp;
 
     // We won't keep guessing forever
     const ADDITIONAL_BLOCKS_TO_GUESS = 200;
 
     let startBlockheight;
     if (guessedBlockTimestampDelta > secondsAgo) {
         // If the guessed block was further back in time than desired secondsAgo
         // Then we need to guess a higher block
         for (
             let i = guessedBlockheight + 1;
             i <= guessedBlockheight + ADDITIONAL_BLOCKS_TO_GUESS;
             i += 1
         ) {
             const guessedBlock = (await chronik.block(i)).blockInfo;
             const thisBlockTimestampDelta = now - guessedBlock.timestamp;
             if (thisBlockTimestampDelta <= secondsAgo) {
                 startBlockheight = i;
                 break;
             }
         }
     } else {
         // We might already be looking at the right block
         // But mb we some previous blocks are also in this acceptable window
         // If the guessed block was NOT further back in time than desired secondsAgo
         // Then we need to guess a LOWER block
         for (
             let i = guessedBlockheight - 1;
             i >= guessedBlockheight - ADDITIONAL_BLOCKS_TO_GUESS;
             i -= 1
         ) {
             const guessedBlock = (await chronik.block(i)).blockInfo;
             guessedBlockTimestampDelta = now - guessedBlock.timestamp;
             if (guessedBlockTimestampDelta > secondsAgo) {
                 // We keep looking for blocks until we find one that is "too old"
                 // Then we take the immediately newer block
                 startBlockheight = i + 1;
                 break;
             }
         }
     }
 
     if (typeof startBlockheight === 'undefined') {
         console.log(
             `Did not find startBlockheight in ${ADDITIONAL_BLOCKS_TO_GUESS} blocks`,
         );
         console.log(`Chaintip: ${chaintip}`);
         console.log(`guessedBlockheight: ${guessedBlockheight}`);
         console.log(
             `guessedBlockTimestampDelta: ${guessedBlockTimestampDelta}`,
         );
         throw new Error(
             `Start block more than ${ADDITIONAL_BLOCKS_TO_GUESS} off our original guess`,
         );
     }
 
     return { chaintip, startBlockheight };
 };
diff --git a/apps/ecash-herald/src/chronikWsHandler.ts b/apps/ecash-herald/src/chronikWsHandler.ts
index 1ac0ed953..f47b4c5cb 100644
--- a/apps/ecash-herald/src/chronikWsHandler.ts
+++ b/apps/ecash-herald/src/chronikWsHandler.ts
@@ -1,86 +1,87 @@
-// Copyright (c) 2023 The Bitcoin developers
+// Copyright (c) 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 { ChronikClient, WsEndpoint, WsMsgClient } from 'chronik-client';
 import { handleBlockFinalized, handleBlockInvalidated } from './events';
 import TelegramBot from 'node-telegram-bot-api';
 import { MemoryCache } from 'cache-manager';
 import { MockTelegramBot } from '../test/mocks/telegramBotMock';
 
-export const initializeWebsocket = async (
-    chronik: ChronikClient,
-    telegramBot: TelegramBot | MockTelegramBot,
-    channelId: string,
-    memoryCache: MemoryCache,
-): Promise<WsEndpoint> => {
-    // Subscribe to chronik websocket
-    const ws = chronik.ws({
-        onMessage: async msg => {
-            await parseWebsocketMessage(
-                chronik,
-                msg,
-                telegramBot,
-                channelId,
-                memoryCache,
-            );
-        },
-    });
-    // Wait for WS to be connected:
-    await ws.waitForOpen();
-    console.log(`Listening for chronik block msgs`);
-    // Subscribe to blocks
-    ws.subscribeToBlocks();
-    return ws;
-};
-
 export const parseWebsocketMessage = async (
     chronik: ChronikClient,
     wsMsg: WsMsgClient,
     telegramBot: TelegramBot | MockTelegramBot,
     channelId: string,
     memoryCache: MemoryCache,
 ) => {
     // Get height and msg type
     // Note 1: herald only subscribes to blocks, so only MsgBlockClient is expected here
     // Note 2: blockTimestamp and coinbaseData might be undefined, they are
     //         introduced in chronik v0.30.0 and client version 1.3.0
 
     const { type } = wsMsg;
     if (type === 'Error') {
         // Do nothing on ws error msgs
         return false;
     }
     const { msgType } = wsMsg;
 
     switch (msgType) {
         case 'BLK_FINALIZED': {
             const { blockHeight, blockHash } = wsMsg;
             return handleBlockFinalized(
                 chronik,
                 telegramBot,
                 channelId,
                 blockHash,
                 blockHeight,
                 memoryCache,
             );
         }
         case 'BLK_INVALIDATED': {
             // coinbaseData is defined for BLK_INVALIDATED
             const { blockHeight, blockHash, blockTimestamp, coinbaseData } =
                 wsMsg;
             return handleBlockInvalidated(
                 chronik,
                 telegramBot,
                 channelId,
                 blockHash,
                 blockHeight,
                 blockTimestamp,
                 coinbaseData!,
                 memoryCache,
             );
         }
         default:
             // Do nothing for other events
             return false;
     }
 };
+
+export const initializeWebsocket = async (
+    chronik: ChronikClient,
+    telegramBot: TelegramBot | MockTelegramBot,
+    channelId: string,
+    memoryCache: MemoryCache,
+): Promise<WsEndpoint> => {
+    // Subscribe to chronik websocket
+    const ws = chronik.ws({
+        onMessage: async msg => {
+            await parseWebsocketMessage(
+                chronik,
+                msg,
+                telegramBot,
+                channelId,
+                memoryCache,
+            );
+        },
+    });
+    // Wait for WS to be connected:
+    await ws.waitForOpen();
+    console.log(`Listening for chronik block msgs`);
+    // Subscribe to blocks
+    ws.subscribeToBlocks();
+    return ws;
+};
diff --git a/apps/ecash-herald/src/events.ts b/apps/ecash-herald/src/events.ts
index 95caf7d58..87a28e89d 100644
--- a/apps/ecash-herald/src/events.ts
+++ b/apps/ecash-herald/src/events.ts
@@ -1,342 +1,342 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
-'use strict';
 import config from '../config';
 import axios from 'axios';
 import cashaddr from 'ecashaddrjs';
 import {
     parseBlockTxs,
     getBlockTgMessage,
     getMinerFromCoinbaseTx,
     getStakerFromCoinbaseTx,
     guessRejectReason,
     summarizeTxHistory,
     HeraldParsedBlock,
 } from './parse';
 import {
     getCoingeckoPrices,
     jsonReviver,
     getNextStakingReward,
     CoinGeckoPrice,
+    CoinGeckoResponse,
 } from './utils';
 import { sendBlockSummary } from './telegram';
 import {
     getTokenInfoMap,
     getOutputscriptInfoMap,
     getAllBlockTxs,
     getBlocksAgoFromChaintipByTimestamp,
     OutputscriptInfo,
 } from './chronik';
 import knownMinersJson from '../constants/miners';
 import { ChronikClient, CoinbaseData, Tx, GenesisInfo } from 'chronik-client';
 import TelegramBot, { Message } from 'node-telegram-bot-api';
 import { MemoryCache } from 'cache-manager';
 import { MockTelegramBot } from '../test/mocks/telegramBotMock';
 
 const miners = JSON.parse(JSON.stringify(knownMinersJson), jsonReviver);
 
 // This is expected for TelegramBot.sendMessage but is not available in its types
 // Based on Telegram API docs
 export interface SendMessageResponse {
     message_id: number;
     from: {
         id: number;
         is_bot: boolean;
         first_name: string;
         username: string;
     };
     chat: {
         id: number;
         first_name: string;
         username: string;
         type: 'private';
     };
     date: number;
     text: string;
 }
 
 export interface StoredMock {
     blockTxs: Tx[];
     parsedBlock: HeraldParsedBlock;
-    coingeckoResponse: any;
+    coingeckoResponse: CoinGeckoResponse;
     coingeckoPrices: CoinGeckoPrice[];
     tokenInfoMap: Map<string, GenesisInfo>;
     outputScriptInfoMap: Map<string, OutputscriptInfo>;
     blockSummaryTgMsgs: string[];
     blockSummaryTgMsgsApiFailure: string[];
 }
 
 /**
  * Callback function for a new finalized block on the eCash blockchain
  * Summarize on-chain activity in this block
  * @param chronik
  * @param telegramBot A connected telegramBot instance
  * @param channelId The channel ID where the telegram msg(s) will be sent
  * @param height blockheight
  * @param returnMocks If true, return mocks for unit tests
  * @param memoryCache
  */
 export const handleBlockFinalized = async (
     chronik: ChronikClient,
     telegramBot: TelegramBot | MockTelegramBot,
     channelId: string,
     blockHash: string,
     blockHeight: number,
     memoryCache: MemoryCache,
     returnMocks = false,
 ): Promise<
     | StoredMock
     | Message
     | SendMessageResponse
     | boolean
     | (Message | SendMessageResponse)[]
 > => {
     // Get block txs
     // TODO blockTxs are paginated, need a function to get them all
     let blockTxs;
     try {
         blockTxs = await getAllBlockTxs(chronik, blockHeight);
     } catch (err) {
         console.log(`Error in getAllBlockTxs(${blockHeight})`, err);
 
         // Default Telegram message if chronik API error
         const errorTgMsg =
             `New Block Found\n` +
             `\n` +
             `${blockHeight.toLocaleString('en-US')}\n` +
             `\n` +
             `${blockHash}\n` +
             `\n` +
             `<a href="${config.blockExplorer}/block/${blockHash}">explorer</a>`;
 
         try {
             return (await telegramBot.sendMessage(
                 channelId,
                 errorTgMsg,
                 config.tgMsgOptions,
             )) as Message | SendMessageResponse;
         } catch (err) {
             console.log(
                 `Error in telegramBot.sendMessage(channelId=${channelId}, msg=${errorTgMsg}, options=${config.tgMsgOptions}) called from handleBlockFinalized`,
                 err,
             );
             return false;
         }
     }
 
     const parsedBlock = parseBlockTxs(blockHash, blockHeight, blockTxs);
 
     // Get token genesis info for token IDs in this block
     const { tokenIds, outputScripts } = parsedBlock;
 
     const tokenInfoMap = await getTokenInfoMap(chronik, tokenIds);
 
     const outputScriptInfoMap = await getOutputscriptInfoMap(
         chronik,
         outputScripts,
     );
 
     // Get price info for tg msg, if available
     const resp = await getCoingeckoPrices(config.priceApi);
     const coingeckoPrices = resp !== false ? resp.coingeckoPrices : false;
     const coingeckoResponse = resp !== false ? resp.coingeckoResponse : false;
     const blockSummaryTgMsgs = getBlockTgMessage(
         parsedBlock,
         coingeckoPrices,
         tokenInfoMap,
         outputScriptInfoMap,
     );
 
     if (returnMocks) {
         // returnMocks is used in the script function generateMocks
         // Using it as a flag here ensures the script is always using the same function
         // as the app
         // Note you need coingeckoResponse so you can mock the axios response for coingecko
         return {
             blockTxs,
             parsedBlock,
             coingeckoResponse,
             coingeckoPrices,
             tokenInfoMap,
             outputScriptInfoMap,
             blockSummaryTgMsgs,
             blockSummaryTgMsgsApiFailure: getBlockTgMessage(
                 parsedBlock,
                 false, // failed coingecko price lookup
                 false, // failed chronik token ID lookup
                 false, // failed balances lookup for output scripts
             ),
         } as StoredMock;
     }
 
     // Don't await, this can take some time to complete due to remote
     // caching.
     getNextStakingReward(blockHeight + 1, memoryCache);
 
     // Broadcast block summary telegram message(s)
     return await sendBlockSummary(
         blockSummaryTgMsgs,
         telegramBot,
         channelId,
         blockHeight,
     );
 };
 /**
  * Handle block invalidated event
  * @param {ChronikClient} chronik
  * @param {object} telegramBot
  * @param {string} channelId
  * @param {string} blockHash
  * @param {number} blockHeight
  * @param {number} blockTimestamp
  * @param {object} coinbaseData
  * @param {object} memoryCache
  */
 export const handleBlockInvalidated = async (
     chronik: ChronikClient,
     telegramBot: TelegramBot | MockTelegramBot,
     channelId: string,
     blockHash: string,
     blockHeight: number,
     blockTimestamp: number,
     coinbaseData: CoinbaseData,
     memoryCache: MemoryCache,
 ) => {
     const miner = getMinerFromCoinbaseTx(
         coinbaseData.scriptsig,
         coinbaseData.outputs,
         miners,
     );
 
     const stakingRewardWinner = getStakerFromCoinbaseTx(
         blockHeight,
         coinbaseData.outputs,
     );
     let stakingRewardWinnerAddress = 'unknown';
     if (stakingRewardWinner !== false) {
         try {
             stakingRewardWinnerAddress = cashaddr.encodeOutputScript(
                 stakingRewardWinner.staker,
             );
-        } catch (err) {
+        } catch {
             // Use the script
             stakingRewardWinnerAddress = `script ${stakingRewardWinner.staker}`;
         }
     }
 
     const reason = await guessRejectReason(
         chronik,
         blockHeight,
         coinbaseData,
         memoryCache,
     );
 
     const errorTgMsg =
         `Block invalidated by avalanche\n` +
         `\n` +
         `Height: ${blockHeight.toLocaleString('en-US')}\n` +
         `\n` +
         `Hash: ${blockHash}` +
         `\n` +
         `Timestamp: ${blockTimestamp}\n` +
         `Mined by ${miner}\n` +
         `Staking reward winner: ${stakingRewardWinnerAddress}\n` +
         `Guessed reject reason: ${reason}`;
 
     try {
         return await telegramBot.sendMessage(
             channelId,
             errorTgMsg,
             config.tgMsgOptions,
         );
     } catch (err) {
         console.log(
             `Error in telegramBot.sendMessage(channelId=${channelId}, msg=${errorTgMsg}, options=${config.tgMsgOptions}) called from handleBlockInvalidated`,
             err,
         );
     }
 };
 
 export const handleUtcMidnight = async (
     chronik: ChronikClient,
     telegramBot: TelegramBot,
     channelId: string,
 ) => {
     // It is a new day
     // Send the daily summary
 
     // Get a datestring
     // e.g. Wed Oct 23 2024
     const dateString = new Date().toDateString();
 
     // Get timestamp for UTC midnight
     // Will always be divisible by 1000 as will always be a midnight UTC date
     const MS_PER_S = 1000;
     const newDayTimestamp = new Date(dateString).getTime() / MS_PER_S;
 
     const SECONDS_PER_DAY = 86400;
 
     const { startBlockheight, chaintip } =
         await getBlocksAgoFromChaintipByTimestamp(
             chronik,
             newDayTimestamp,
             SECONDS_PER_DAY,
         );
 
     const getAllBlockTxPromises = [];
     for (let i = startBlockheight; i <= chaintip; i += 1) {
         getAllBlockTxPromises.push(getAllBlockTxs(chronik, i));
     }
 
     const allBlockTxs = (await Promise.all(getAllBlockTxPromises)).flat();
 
     // We only want txs in the specified window
     // NB coinbase txs have timeFirstSeen of 0. We include all of them as the block
     // timestamps are in the window
     const timeFirstSeenTxs = allBlockTxs.filter(
         (tx: Tx) =>
             (tx.timeFirstSeen > newDayTimestamp - SECONDS_PER_DAY &&
                 tx.timeFirstSeen <= newDayTimestamp) ||
             tx.isCoinbase,
     );
 
     // Get tokenIds of all tokens seen in this batch of txs
     const tokensToday: Set<string> = new Set();
     for (const tx of timeFirstSeenTxs) {
         const { tokenEntries } = tx;
         for (const tokenEntry of tokenEntries) {
             const { tokenId, groupTokenId } = tokenEntry;
             tokensToday.add(tokenId);
             if (typeof groupTokenId !== 'undefined') {
                 // We want the groupTokenId info even if we only have child txs in this window
                 tokensToday.add(groupTokenId);
             }
         }
     }
     // Get all the token info of tokens from today
     const tokenInfoMap = await getTokenInfoMap(chronik, tokensToday);
 
     // Get XEC price and market info
     let priceInfo;
     try {
         priceInfo = (
             await axios.get(
                 `https://api.coingecko.com/api/v3/simple/price?ids=ecash&vs_currencies=usd&include_market_cap=true&include_24hr_vol=true&include_24hr_change=true`,
             )
         ).data.ecash;
     } catch (err) {
         console.error(`Error getting daily summary price info`, err);
     }
 
     const dailySummaryTgMsgs = summarizeTxHistory(
         newDayTimestamp,
         timeFirstSeenTxs,
         tokenInfoMap,
         priceInfo,
     );
 
     // Send msg with successful price API call
     await sendBlockSummary(dailySummaryTgMsgs, telegramBot, channelId, 'daily');
 };
diff --git a/apps/ecash-herald/src/parse.ts b/apps/ecash-herald/src/parse.ts
index 679f7ff0a..6ebfd8d02 100644
--- a/apps/ecash-herald/src/parse.ts
+++ b/apps/ecash-herald/src/parse.ts
@@ -1,3701 +1,3707 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 import config from '../config';
 import opReturn from '../constants/op_return';
 import { consume, consumeNextPush, swapEndianness } from 'ecash-script';
 import knownMinersJson, { KnownMiners, MinerInfo } from '../constants/miners';
 import cachedTokenInfoMap from '../constants/tokens';
 import {
     jsonReviver,
     bigNumberAmountToLocaleString,
     CoinGeckoPrice,
 } from '../src/utils';
 import cashaddr from 'ecashaddrjs';
 import BigNumber from 'bignumber.js';
 import {
     TOKEN_SERVER_OUTPUTSCRIPT,
     BINANCE_OUTPUTSCRIPT,
 } from '../constants/senders';
 import { prepareStringForTelegramHTML, splitOverflowTgMsg } from './telegram';
 import { OutputscriptInfo } from './chronik';
 import {
     formatPrice,
     satsToFormattedValue,
     returnAddressPreview,
     containsOnlyPrintableAscii,
 } from './utils';
 import lokadMap from '../constants/lokad';
 import { scriptOps } from 'ecash-agora';
 import { Script, fromHex, OP_0 } from 'ecash-lib';
 import {
     ChronikClient,
     CoinbaseData,
     Tx,
     TxOutput,
     GenesisInfo,
 } from 'chronik-client';
 import { MemoryCache } from 'cache-manager';
 
 const miners: KnownMiners = JSON.parse(
     JSON.stringify(knownMinersJson),
     jsonReviver,
 );
 
 // Constants for SLP 1 token types as returned by chronik-client
 const SLP_1_PROTOCOL_NUMBER = 1;
 const SLP_1_NFT_COLLECTION_PROTOCOL_NUMBER = 129;
 const SLP_1_NFT_PROTOCOL_NUMBER = 65;
 
 // Miner fund output script
 const minerFundOutputScript = 'a914d37c4c809fe9840e7bfa77b86bd47163f6fb6c6087';
 
 interface PriceInfo {
     usd: number;
     usd_market_cap: number;
     usd_24h_vol: number;
     usd_24h_change: number;
 }
 interface HeraldStaker {
     staker: string;
     reward: number;
 }
 interface HeraldOpReturnInfo {
     app: string;
     msg: string;
     stackArray?: string[];
     tokenId?: string | false;
 }
 interface TokenSendInfo {
     tokenId: string;
     parsedTokenType: string;
     txType: string;
     tokenChangeOutputs?: Map<string, BigNumber>;
     tokenReceivingOutputs?: Map<string, BigNumber>;
     tokenSendingOutputScripts?: Set<string>;
 }
 interface HeraldParsedTx {
     txid: string;
     genesisInfo: false | { tokenId: string };
     opReturnInfo: false | HeraldOpReturnInfo;
     txFee: number;
     xecSendingOutputScripts: Set<string>;
     xecReceivingOutputs: Map<string, number>;
     totalSatsSent: number;
     tokenSendInfo: false | TokenSendInfo;
     tokenBurnInfo:
         | false
         | {
               tokenId: string;
               undecimalizedTokenBurnAmount: string;
           };
 }
 export interface HeraldParsedBlock {
     hash: string;
     height: number;
     miner: string;
     staker: HeraldStaker | false;
     numTxs: number;
     parsedTxs: HeraldParsedTx[];
     tokenIds: Set<string>;
     outputScripts: Set<string>;
 }
 
 enum TrackedTokenAction {
     Genesis = 'genesis',
     Send = 'send',
     Mint = 'mint',
     Burn = 'burn',
     Buy = 'buy',
     List = 'list',
     AdPrep = 'adPrep',
     Cancel = 'cancel',
 }
 interface TokenAction {
     count: number;
 }
 interface TokenActions {
     actionCount: number;
     send?: TokenAction;
     mint?: TokenAction;
     burn?: TokenAction;
     adPrep?: TokenAction;
     buy?: TokenAction;
     list?: TokenAction;
     cancel?: TokenAction;
     genesis?:
         | TokenAction
         | { hasBaton: boolean; amount: string; count?: number };
 }
-/**
- * Parse a finalized block for newsworthy information
- * @param blockHash
- * @param blockHeight
- * @param txs
- */
-export const parseBlockTxs = (
-    blockHash: string,
-    blockHeight: number,
-    txs: Tx[],
-): HeraldParsedBlock => {
-    // Parse coinbase string
-    const coinbaseTx = txs[0];
-    const miner = getMinerFromCoinbaseTx(
-        coinbaseTx.inputs[0].inputScript,
-        coinbaseTx.outputs,
-        miners,
-    );
-    let staker = getStakerFromCoinbaseTx(blockHeight, coinbaseTx.outputs);
-    if (staker !== false) {
-        try {
-            staker.staker = cashaddr.encodeOutputScript(staker.staker);
-        } catch (err) {
-            staker.staker = 'script(' + staker.staker + ')';
-        }
-    }
-
-    // Start with i=1 to skip Coinbase tx
-    let parsedTxs = [];
-    for (let i = 1; i < txs.length; i += 1) {
-        parsedTxs.push(parseTx(txs[i]));
-    }
-
-    // Sort parsedTxs by totalSatsSent, highest to lowest
-    parsedTxs = parsedTxs.sort((a, b) => {
-        return b.totalSatsSent - a.totalSatsSent;
-    });
-
-    // Collect token info needed to parse token send txs
-    const tokenIds: Set<string> = new Set(); // we only need each tokenId once
-    // Collect outputScripts seen in this block to parse for balance
-    let outputScripts: Set<string> = new Set();
-    for (let i = 0; i < parsedTxs.length; i += 1) {
-        const thisParsedTx = parsedTxs[i];
-        if (thisParsedTx.tokenSendInfo) {
-            tokenIds.add(thisParsedTx.tokenSendInfo.tokenId);
-        }
-        if (thisParsedTx.genesisInfo) {
-            tokenIds.add(thisParsedTx.genesisInfo.tokenId);
-        }
-        if (thisParsedTx.tokenBurnInfo) {
-            tokenIds.add(thisParsedTx.tokenBurnInfo.tokenId);
-        }
-        // Some OP_RETURN txs also have token IDs we need to parse
-        // SWaP txs, (TODO: airdrop txs)
-        if (thisParsedTx.opReturnInfo && thisParsedTx.opReturnInfo.tokenId) {
-            tokenIds.add(thisParsedTx.opReturnInfo.tokenId);
-        }
-        const { xecSendingOutputScripts, xecReceivingOutputs } = thisParsedTx;
-
-        // Only add the first sending and receiving output script,
-        // As you will only render balance emojis for these
-        outputScripts.add(xecSendingOutputScripts.values().next().value!);
 
-        // For receiving outputScripts, add the first that is not OP_RETURN
-        // So, get an array of the outputScripts first
-        const xecReceivingOutputScriptsArray: string[] = Array.from(
-            xecReceivingOutputs.keys(),
-        );
-        for (let j = 0; j < xecReceivingOutputScriptsArray.length; j += 1) {
-            if (
-                !xecReceivingOutputScriptsArray[j].startsWith(
-                    opReturn.opReturnPrefix,
-                )
-            ) {
-                outputScripts.add(xecReceivingOutputScriptsArray[j]);
-                // Exit loop after you've added the first non-OP_RETURN outputScript
-                break;
-            }
-        }
-    }
-    return {
-        hash: blockHash,
-        height: blockHeight,
-        miner,
-        staker,
-        numTxs: txs.length,
-        parsedTxs,
-        tokenIds,
-        outputScripts,
-    };
-};
 export const getStakerFromCoinbaseTx = (
     blockHeight: number,
     coinbaseOutputs: TxOutput[],
 ): HeraldStaker | false => {
     const STAKING_ACTIVATION_HEIGHT = 818670;
     if (blockHeight < STAKING_ACTIVATION_HEIGHT) {
         // Do not parse for staking rwds if they are not expected to exist
         return false;
     }
     const STAKING_REWARDS_PERCENT = 10;
     const totalCoinbaseSats = coinbaseOutputs
         .map(output => output.value)
         .reduce((prev, curr) => prev + curr, 0);
-    for (let output of coinbaseOutputs) {
+    for (const output of coinbaseOutputs) {
         const thisValue = output.value;
         const minStakerValue = Math.floor(
             totalCoinbaseSats * STAKING_REWARDS_PERCENT * 0.01,
         );
         // In practice, the staking reward will almost always be the one that is exactly 10% of totalCoinbaseSats
         // Use a STAKER_PERCENT_PADDING range to exclude miner and ifp outputs
         const STAKER_PERCENT_PADDING = 1;
         const assumedMaxStakerValue = Math.floor(
             totalCoinbaseSats *
                 (STAKING_REWARDS_PERCENT + STAKER_PERCENT_PADDING) *
                 0.01,
         );
         if (thisValue >= minStakerValue && thisValue <= assumedMaxStakerValue) {
             return {
                 // Return the script, there is no guarantee that we can use
                 // an address to display this.
                 staker: output.outputScript,
                 reward: thisValue,
             };
         }
     }
     // If you don't find a staker, don't add it in msg. Can troubleshoot if see this in the app.
     // This can happen if a miner overpays rwds, underpays miner rwds
     return false;
 };
 
 export const getMinerFromCoinbaseTx = (
     coinbaseScriptsig: string,
     coinbaseOutputs: TxOutput[],
     knownMiners: KnownMiners,
 ): string => {
     // When you find the miner, minerInfo will come from knownMiners
     let minerInfo: boolean | MinerInfo = false;
 
     // First, check outputScripts for a known miner
     for (let i = 0; i < coinbaseOutputs.length; i += 1) {
         const thisOutputScript = coinbaseOutputs[i].outputScript;
         const knownMinerInfo = knownMiners.get(thisOutputScript);
         if (typeof knownMinerInfo !== 'undefined') {
             minerInfo = knownMinerInfo;
             break;
         }
     }
 
     if (!minerInfo) {
         // If you still haven't found minerInfo, test by known pattern of coinbase script
         // Possibly a known miner is using a new address
         knownMiners.forEach(knownMinerInfo => {
             const { coinbaseHexFragment } = knownMinerInfo;
             if (coinbaseScriptsig.includes(coinbaseHexFragment)) {
                 minerInfo = knownMinerInfo;
             }
         });
     }
 
     if (!minerInfo) {
         // We're still unable to identify the miner, so resort to
         // indentifying by the last chars of the payout address. For now
         // we assume the ordering of outputs such as the miner reward is at
         // the first position.
         const minerPayoutSript = coinbaseOutputs[0].outputScript;
         try {
             const minerAddress = cashaddr.encodeOutputScript(minerPayoutSript);
             return `unknown, ...${minerAddress.slice(-4)}`;
         } catch (err) {
             console.log(
                 `Error converting miner payout script (${minerPayoutSript}) to eCash address`,
                 err,
             );
             // Give up
             return 'unknown';
         }
     }
 
     // If you have found the miner, parse coinbase hex for additional info
     switch (minerInfo.miner) {
         // This is available for ViaBTC and CK Pool
         // Use a switch statement to easily support adding future miners
         case 'ViaBTC':
         // Intentional fall-through so ViaBTC and CKPool have same parsing
         // es-lint ignore no-fallthrough
         case 'CK Pool': {
             /* For ViaBTC, the interesting info is between '/' characters
              * i.e. /Mined by 260786/
              * In ascii, these are encoded with '2f'
              */
             const infoHexParts = coinbaseScriptsig.split('2f');
 
             // Because the characters before and after the info we are looking for could also
             // contain '2f', we need to find the right part
 
             // The right part is the one that comes immediately after coinbaseHexFragment
             let infoAscii = '';
             for (let i = 0; i < infoHexParts.length; i += 1) {
                 if (infoHexParts[i].includes(minerInfo.coinbaseHexFragment)) {
                     // We want the next one, if it exists
                     if (i + 1 < infoHexParts.length) {
                         infoAscii = Buffer.from(
                             infoHexParts[i + 1],
                             'hex',
                         ).toString('ascii');
                     }
                     break;
                 }
             }
 
             if (infoAscii === 'mined by IceBerg') {
                 // CK Pool, mined by IceBerg
                 // If this is IceBerg, identify uniquely
                 // Iceberg is probably a solo miner using CK Pool software
                 return `IceBerg`;
             }
 
             if (infoAscii === 'mined by iceberg') {
                 // If the miner self identifies as iceberg, go with it
                 return `iceberg`;
             }
 
             // Return your improved 'miner' info
             // ViaBTC, Mined by 260786
             if (infoAscii.length === 0) {
                 // If you did not find anything interesting, just return the miner
                 return minerInfo.miner;
             }
             return `${minerInfo.miner}, ${infoAscii}`;
         }
         default: {
             // Unless the miner has specific parsing rules defined above, no additional info is available
             return minerInfo.miner;
         }
     }
 };
 
 /**
- * Parse an eCash tx as returned by chronik for newsworthy information
+ * Stub method to parse slp two empps
+ * @param {string} slpTwoPush a string of hex characters in an empp tx representing an slp2 push
+ * @returns {string} For now, just the section type, if token type is correct
  */
-export const parseTx = (tx: Tx): HeraldParsedTx => {
-    const { txid, inputs, outputs } = tx;
+export const parseSlpTwo = (slpTwoPush: string): string => {
+    // Parse an empp push hex string with the SLP protocol identifier removed per SLP v2 spec
+    // https://ecashbuilders.notion.site/SLPv2-a862a4130877448387373b9e6a93dd97
 
-    let isTokenTx = false;
-    let genesisInfo: false | { tokenId: string } = false;
-    let opReturnInfo: false | HeraldOpReturnInfo = false;
+    let msg = '';
 
-    /* Token send parsing info
-     *
-     * Note that token send amounts received from chronik do not account for
-     * token decimals. Decimalized amounts require token genesisInfo
-     * decimals param to calculate
-     */
+    // Create a stack to use ecash-script consume function
+    // Note: slp2 parsing is not standard op_return parsing, varchar bytes just use a one-byte push
+    // So, you can use the 'consume' function of ecash-script, but not consumeNextPush
+    const stack = { remainingHex: slpTwoPush };
 
-    /* tokenSendInfo
-     * `false` for txs that are not etoken send txs
-     * an object containing info about the token send for token send txs
-     */
-    let tokenSendInfo: false | TokenSendInfo = false;
-    let tokenSendingOutputScripts: Set<string> = new Set();
-    let tokenReceivingOutputs = new Map();
-    let tokenChangeOutputs = new Map();
-    let undecimalizedTokenInputAmount = new BigNumber(0);
+    // 1.3: Read token type
+    // For now, this can only be 00. If not 00, unknown
+    const tokenType = consume(stack, 1);
 
-    // tokenBurn parsing variables
-    let tokenBurnInfo:
-        | false
-        | {
-              tokenId: string;
-              undecimalizedTokenBurnAmount: string;
-          } = false;
+    if (tokenType !== '00') {
+        msg += 'Unknown token type|';
+    }
 
-    /* Collect xecSendInfo for all txs, since all txs are XEC sends
-     * You may later want to render xecSendInfo for tokenSends, appTxs, etc,
-     * maybe on special conditions, e.g.a token send tx that also sends a bunch of xec
-     */
+    // 1.4: Read section type
+    // These are custom varchar per slp2 spec
+    // <varchar byte hex> <section type>
+    const sectionBytes = parseInt(consume(stack, 1), 16);
+    // Note: these are encoded with push data, so you can use ecash-script
 
-    // xecSend parsing variables
-    let xecSendingOutputScripts: Set<string> = new Set();
-    let xecReceivingOutputs = new Map();
-    let xecInputAmountSats = 0;
-    let xecOutputAmountSats = 0;
-    let totalSatsSent = 0;
-    let changeAmountSats = 0;
+    const sectionType = Buffer.from(
+        consume(stack, sectionBytes),
+        'hex',
+    ).toString('utf8');
+    msg += sectionType;
 
-    if (
-        tx.tokenStatus !== 'TOKEN_STATUS_NON_TOKEN' &&
-        tx.tokenEntries.length > 0
-    ) {
-        isTokenTx = true;
+    // Parsing differs depending on section type
+    // Note that SEND and MINT have same parsing
 
-        // We may have more than one token action in a given tx
-        // chronik will reflect this by having multiple entries in the tokenEntries array
+    const TOKEN_ID_BYTES = 32;
+    switch (sectionType) {
+        case 'SEND':
+        case 'MINT': {
+            // Next up is tokenId
+            const tokenId = swapEndianness(consume(stack, TOKEN_ID_BYTES));
 
-        // For now, just parse the first action
-        // TODO handle txs with multiple tokenEntries
-        const parsedTokenAction = tx.tokenEntries[0];
+            const cachedTokenInfo = cachedTokenInfoMap.get(tokenId);
 
-        const { tokenId, tokenType, txType, burnSummary, actualBurnAmount } =
-            parsedTokenAction;
-        const { protocol, number } = tokenType;
-        const isUnintentionalBurn =
-            burnSummary !== '' && actualBurnAmount !== '0';
+            msg += `|<a href="${config.blockExplorer}/tx/${tokenId}">${
+                typeof cachedTokenInfo === 'undefined'
+                    ? `${tokenId.slice(0, 3)}...${tokenId.slice(-3)}`
+                    : prepareStringForTelegramHTML(cachedTokenInfo.tokenTicker)
+            }</a>`;
 
-        // Get token type
-        // TODO present the token type in msgs
-        let parsedTokenType = '';
-        switch (protocol) {
-            case 'ALP': {
-                parsedTokenType = 'ALP';
-                break;
-            }
-            case 'SLP': {
-                if (number === SLP_1_PROTOCOL_NUMBER) {
-                    parsedTokenType = 'SLP';
-                } else if (number === SLP_1_NFT_COLLECTION_PROTOCOL_NUMBER) {
-                    parsedTokenType = 'NFT Collection';
-                } else if (number === SLP_1_NFT_PROTOCOL_NUMBER) {
-                    parsedTokenType = 'NFT';
-                }
-                break;
-            }
-            default: {
-                parsedTokenType = `${protocol} ${number}`;
-                break;
+            const numOutputs = consume(stack, 1);
+            // Iterate over number of outputs to get total amount sent
+            // Note: this should be handled with an indexer, as we are not parsing for validity here
+            // However, it's still useful information for the herald
+            let totalAmountSent = 0;
+            for (let i = 0; i < numOutputs; i += 1) {
+                totalAmountSent += parseInt(swapEndianness(consume(stack, 6)));
             }
+            msg +=
+                typeof cachedTokenInfo === 'undefined'
+                    ? ''
+                    : `|${bigNumberAmountToLocaleString(
+                          totalAmountSent.toString(),
+                          cachedTokenInfo.decimals,
+                      )}`;
+            break;
         }
 
-        switch (txType) {
-            case 'GENESIS': {
-                // Note that NNG chronik provided genesisInfo in this tx
-                // Now we get it from chronik.token
-                // Initialize genesisInfo object with tokenId so it can be rendered into a msg later
-                genesisInfo = { tokenId };
-                break;
-            }
-            case 'SEND': {
-                if (isUnintentionalBurn) {
-                    tokenBurnInfo = {
-                        tokenId,
-                        undecimalizedTokenBurnAmount: actualBurnAmount,
-                    };
-                } else {
-                    tokenSendInfo = {
-                        tokenId,
-                        parsedTokenType,
-                        txType,
-                    };
-                }
-                break;
-            }
-            // TODO handle MINT
-            default: {
-                // For now, if we can't parse as above, this will be parsed as an eCash tx (or EMPP)
-                break;
-            }
-        }
-    }
-    for (const input of inputs) {
-        if (typeof input.outputScript !== 'undefined') {
-            xecSendingOutputScripts.add(input.outputScript);
+        case 'GENESIS': {
+            // TODO
+            // Have not seen one of these in the wild yet
+            break;
         }
 
-        xecInputAmountSats += input.value;
-        // The input that sent the token utxos will have key 'slpToken'
-        if (typeof input.token !== 'undefined') {
-            // Add amount to undecimalizedTokenInputAmount
-            // TODO make sure this is for the correct tokenID
-            // Could have mistakes in parsing ALP txs otherwise
-            // For now, this is outside the scope of migration
-            undecimalizedTokenInputAmount = undecimalizedTokenInputAmount.plus(
-                input.token.amount,
-            );
-            // Collect the input outputScripts to identify change output
-            if (typeof input.outputScript !== 'undefined') {
-                tokenSendingOutputScripts.add(input.outputScript);
-            }
+        case 'BURN': {
+            // TODO
+            // Have seen some in the wild but not in spec
+            break;
         }
     }
+    // The rest of the parsing rules get quite complicated and should be handled in a dedicated library
+    // or indexer
+    return msg;
+};
 
-    // Iterate over outputs to check for OP_RETURN msgs
-    for (const output of outputs) {
-        const { value, outputScript } = output;
-        xecOutputAmountSats += value;
-        // If this output script is the same as one of the sendingOutputScripts
-        if (xecSendingOutputScripts.has(outputScript)) {
-            // Then this XEC amount is change
-            changeAmountSats += value;
-        } else {
-            // Add an xecReceivingOutput
+/**
+ * Parse an empp stack for a simplified slp v2 description
+ * TODO expand for parsing other types of empp txs as specs or examples are known
+ * @param {array} emppStackArray an array containing a hex string for every push of this memo OP_RETURN outputScript
+ * @returns {object} {app, msg} used to compose a useful telegram msg describing the transaction
+ */
+export const parseMultipushStack = (
+    emppStackArray: string[],
+): HeraldOpReturnInfo => {
+    // Note that an empp push may not necessarily include traditionally parsed pushes
+    // i.e. consumeNextPush({remainingHex:<emppPush>}) may throw an error
+    // For example, SLPv2 txs do not include a push for their prefix
 
-            // Add outputScript and value to map
-            // If this outputScript is already in xecReceivingOutputs, increment its value
-            xecReceivingOutputs.set(
-                outputScript,
-                (xecReceivingOutputs.get(outputScript) ?? 0) + value,
-            );
+    // So, parsing empp txs will require specific rules depending on the type of tx
+    const msgs = [];
 
-            // Increment totalSatsSent
-            totalSatsSent += value;
-        }
-        // Don't parse OP_RETURN values of etoken txs, this info is available from chronik
-        if (outputScript.startsWith(opReturn.opReturnPrefix) && !isTokenTx) {
-            opReturnInfo = parseOpReturn(outputScript.slice(2));
-        }
-        // For etoken send txs, parse outputs for tokenSendInfo object
-        if (typeof output.token !== 'undefined') {
-            // TODO handle EMPP and potential token txs with multiple tokens involved
-            // Check output script to confirm does not match tokenSendingOutputScript
-            if (tokenSendingOutputScripts.has(outputScript)) {
-                // change
-                tokenChangeOutputs.set(
-                    outputScript,
-                    (
-                        tokenChangeOutputs.get(outputScript) ?? new BigNumber(0)
-                    ).plus(output.token.amount),
-                );
-            } else {
-                /* This is the sent token qty
-                 *
-                 * Add outputScript and undecimalizedTokenReceivedAmount to map
-                 * If this outputScript is already in tokenReceivingOutputs, increment undecimalizedTokenReceivedAmount
-                 * note that thisOutput.slpToken.amount is a string so you do not want to add it
-                 * BigNumber library is required for token calculations
-                 */
-                tokenReceivingOutputs.set(
-                    outputScript,
-                    (
-                        tokenReceivingOutputs.get(outputScript) ??
-                        new BigNumber(0)
-                    ).plus(output.token.amount),
-                );
-            }
+    // Start at i=1 because emppStackArray[0] is OP_RESERVED
+    for (let i = 1; i < emppStackArray.length; i += 1) {
+        if (emppStackArray[i].slice(0, 8) === opReturn.knownApps.slp2.prefix) {
+            // Parse string for slp v2
+            const thisMsg = parseSlpTwo(emppStackArray[i].slice(8));
+            msgs.push(`${opReturn.knownApps.slp2.app}:${thisMsg}`);
+        } else {
+            // Since we don't know any spec or parsing rules for other types of EMPP pushes,
+            // Just add an ASCII decode of the whole thing if you see one
+            msgs.push(
+                `${'Unknown App:'}${Buffer.from(
+                    emppStackArray[i],
+                    'hex',
+                ).toString('ascii')}`,
+            );
         }
+        // Do not parse any other empp (haven't seen any in the wild, no existing specs to follow)
     }
-
-    // Determine tx fee
-    const txFee = xecInputAmountSats - xecOutputAmountSats;
-
-    // If this is a token send tx, return token send parsing info and not 'false' for tokenSendInfo
-    if (tokenSendInfo) {
-        tokenSendInfo.tokenChangeOutputs = tokenChangeOutputs;
-        tokenSendInfo.tokenReceivingOutputs = tokenReceivingOutputs;
-        tokenSendInfo.tokenSendingOutputScripts = tokenSendingOutputScripts;
-    }
-
-    // If this tx sent XEC to itself, reassign changeAmountSats to totalSatsSent
-    // Need to do this to prevent self-send txs being sorted at the bottom of msgs
-    if (xecReceivingOutputs.size === 0) {
-        totalSatsSent = changeAmountSats;
-    }
-
-    return {
-        txid,
-        genesisInfo,
-        opReturnInfo,
-        txFee,
-        xecSendingOutputScripts,
-        xecReceivingOutputs,
-        totalSatsSent,
-        tokenSendInfo,
-        tokenBurnInfo,
-    };
+    return { app: 'EMPP', msg: msgs.length > 0 ? msgs.join('|') : '' };
 };
 
 /**
- *
- * @param {string} opReturnHex an OP_RETURN outputScript with '6a' removed
- * @returns {object} {app, msg} an object with app and msg params used to generate msg
+ * Parse a stackArray according to OP_RETURN rules to convert to a useful tg msg
+ * @param stackArray an array containing a hex string for every push of this memo OP_RETURN outputScript
+ * @returns A useful string to describe this tx in a telegram msg
  */
-export const parseOpReturn = (opReturnHex: string): HeraldOpReturnInfo => {
-    // Initialize required vars
-    let app;
-    let msg;
-    let tokenId: string | false = false;
-
-    // Get array of pushes
-    let stack = { remainingHex: opReturnHex };
-    let stackArray = [];
-    while (stack.remainingHex.length > 0) {
-        const { data } = consumeNextPush(stack);
-        if (data !== '') {
-            // You may have an empty push in the middle of a complicated tx for some reason
-            // Mb some libraries erroneously create these
-            // e.g. https://explorer.e.cash/tx/70c2842e1b2c7eb49ee69cdecf2d6f3cd783c307c4cbeef80f176159c5891484
-            // has 4c000100 for last characters. 4c00 is just nothing.
-            // But you want to know 00 and have the correct array index
-            stackArray.push(data);
-        }
-    }
+export const parseMemoOutputScript = (
+    stackArray: string[],
+): HeraldOpReturnInfo => {
+    const app = opReturn.memo.app;
+    let msg = '';
 
-    // Get the protocolIdentifier, the first push
-    const protocolIdentifier = stackArray[0];
+    // Get the action code from stackArray[0]
+    // For memo txs, this will be the last 2 characters of this initial push
+    const actionCode = stackArray[0].slice(-2);
 
-    // Test for memo
-    // Memo prefixes are special in that they are two bytes instead of the usual four
-    // Also, memo has many prefixes, in that the action is also encoded in these two bytes
-    if (
-        protocolIdentifier.startsWith(opReturn.memo.prefix) &&
-        protocolIdentifier.length === 4
-    ) {
-        // If the protocol identifier is two bytes long (4 characters), parse for memo tx
-        // For now, send the same info to this function that it currently parses
-        // TODO parseMemoOutputScript needs to be refactored to use ecash-script
-        return parseMemoOutputScript(stackArray);
+    if (Object.keys(opReturn.memo).includes(actionCode)) {
+        // If you parse for this action code, include its description in the tg msg
+        msg += opReturn.memo[actionCode];
+        // Include a formatting spacer in between action code and newsworthy info
+        msg += '|';
     }
 
-    // Test for other known apps with known msg processing methods
-    switch (protocolIdentifier) {
-        case opReturn.opReserved: {
-            // Parse for empp OP_RETURN
-            // Spec https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/chronik/bitcoinsuite-slp/src/empp/mod.rs
-            return parseMultipushStack(stackArray);
-        }
-        case opReturn.knownApps.alias.prefix: {
-            app = opReturn.knownApps.alias.app;
-            /*
-                For now, parse and render alias txs by going through OP_RETURN
-                When aliases are live, refactor to use alias-server for validation
-                <protocolIdentifier> <version> <alias> <address type + hash>
-
-                Only parse the msg if the tx is constructed correctly
-                */
-            msg =
-                stackArray.length === 4 && stackArray[1] === '00'
-                    ? prepareStringForTelegramHTML(
-                          Buffer.from(stackArray[2], 'hex').toString('utf8'),
-                      )
-                    : 'Invalid alias registration';
+    switch (actionCode) {
+        case '01': // Set name <name> (1-217 bytes)
+        case '02': // Post memo <message> (1-217 bytes)
+        case '05': // Set profile text <text> (1-217 bytes)
+        case '0d': // Topic Follow <topic_name> (1-214 bytes)
+        case '0e': // Topic Unfollow <topic_name> (1-214 bytes)
+            // Action codes with only 1 push after the protocol identifier
+            // that is utf8 encoded
 
+            // Include decoded utf8 msg
+            // Make sure the OP_RETURN msg does not contain telegram html escape characters
+            msg += prepareStringForTelegramHTML(
+                Buffer.from(stackArray[1], 'hex').toString('utf8'),
+            );
             break;
-        }
-        case opReturn.knownApps.airdrop.prefix: {
-            app = opReturn.knownApps.airdrop.app;
+        case '03':
+            /**
+             * 03 - Reply to memo
+             * <tx_hash> (32 bytes)
+             * <message> (1-184 bytes)
+             */
 
-            // Initialize msg as empty string. Need tokenId info to complete.
-            msg = '';
+            // The tx hash is in hex, not utf8 encoded
+            // For now, we don't have much to do with this txid in a telegram bot
 
-            // Airdrop tx has structure
-            // <prefix> <tokenId>
+            // Link to the liked or reposted memo
+            // Do not remove tg escape characters as you want this to parse
+            msg += `<a href="${config.blockExplorer}/tx/${stackArray[1]}">memo</a>`;
 
-            // Cashtab allows sending a cashtab msg with an airdrop
-            // These look like
-            // <prefix> <tokenId> <cashtabMsgPrefix> <msg>
-            if (stackArray.length >= 2 && stackArray[1].length === 64) {
-                tokenId = stackArray[1];
-            }
-            break;
-        }
-        case opReturn.knownApps.cashtabMsg.prefix: {
-            app = opReturn.knownApps.cashtabMsg.app;
-            // For a Cashtab msg, the next push on the stack is the Cashtab msg
-            // Cashtab msgs use utf8 encoding
+            // Include a formatting spacer
+            msg += '|';
 
-            // Valid Cashtab Msg
-            // <protocol identifier> <msg in utf8>
-            msg =
-                stackArray.length >= 2
-                    ? prepareStringForTelegramHTML(
-                          Buffer.from(stackArray[1], 'hex').toString('utf8'),
-                      )
-                    : `Invalid ${app}`;
+            // Add the reply
+            msg += prepareStringForTelegramHTML(
+                Buffer.from(stackArray[2], 'hex').toString('utf8'),
+            );
             break;
-        }
-        case opReturn.knownApps.cashtabMsgEncrypted.prefix: {
-            app = opReturn.knownApps.cashtabMsgEncrypted.app;
-            // For an encrypted cashtab msg, you can't parse and display the msg
-            msg = '';
-            // You will add info about the tx when you build the msg
+        case '04':
+            /**
+             * 04 - Like / tip memo <tx_hash> (32 bytes)
+             */
+
+            // Link to the liked or reposted memo
+            msg += `<a href="${config.blockExplorer}/tx/${stackArray[1]}">memo</a>`;
+            break;
+        case '0b': {
+            // 0b - Repost memo <tx_hash> (32 bytes) <message> (0-184 bytes)
+
+            // Link to the liked or reposted memo
+            msg += `<a href="${config.blockExplorer}/tx/${stackArray[1]}">memo</a>`;
+
+            // Include a formatting spacer
+            msg += '|';
+
+            // Add the msg
+            msg += prepareStringForTelegramHTML(
+                Buffer.from(stackArray[2], 'hex').toString('utf8'),
+            );
+
             break;
         }
-        case opReturn.knownApps.fusionLegacy.prefix:
-        case opReturn.knownApps.fusion.prefix: {
+        case '06':
+        case '07':
+        case '16':
+        case '17': {
             /**
-             * Cash Fusion tx
-             * <protocolIdentifier> <sessionHash>
-             * https://github.com/cashshuffle/spec/blob/master/CASHFUSION.md
+             * Follow user - 06 <address> (20 bytes)
+             * Unfollow user - 07 <address> (20 bytes)
+             * Mute user - 16 <address> (20 bytes)
+             * Unmute user - 17 <address> (20 bytes)
              */
-            app = opReturn.knownApps.fusion.app;
-            // The session hash is not particularly interesting to users
-            // Provide tx info in telegram prep function
-            msg = '';
+
+            // The address is a hex-encoded hash160
+            // all memo addresses are p2pkh
+            const address = cashaddr.encode('ecash', 'P2PKH', stackArray[1]);
+
+            // Link to the address in the msg
+            msg += `<a href="${
+                config.blockExplorer
+            }/address/${address}">${returnAddressPreview(address)}</a>`;
             break;
         }
-        case opReturn.knownApps.swap.prefix: {
-            // Swap txs require special parsing that should be done in getSwapTgMsg
-            // We may need to get info about a token ID before we can
-            // create a good msg
-            app = opReturn.knownApps.swap.app;
-            msg = '';
+        case '0a': {
+            // 01 - Set profile picture
+            // <url> (1-217 bytes)
 
-            if (
-                stackArray.length >= 3 &&
-                stackArray[1] === '01' &&
-                stackArray[2] === '01' &&
-                stackArray[3].length === 64
-            ) {
-                // If this is a signal for buy or sell of a token, save the token id
-                // Ref https://github.com/vinarmani/swap-protocol/blob/master/swap-protocol-spec.md
-                // A buy or sell signal tx will have '01' at stackArray[1] and stackArray[2] and
-                // token id at stackArray[3]
-                tokenId = stackArray[3];
-            }
+            // url is utf8 encoded stack[1]
+            const url = Buffer.from(stackArray[1], 'hex').toString('utf8');
+            // Link to it
+            msg += `<a href="${url}">[img]</a>`;
             break;
         }
-        case opReturn.knownApps.payButton.prefix: {
-            app = opReturn.knownApps.payButton.app;
-            // PayButton v0
-            // https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/doc/standards/paybutton.md
-            // <lokad> <OP_0> <data> <nonce>
-            // The data could be interesting, ignore the rest
-            if (stackArray.length >= 3) {
-                // Version byte is at index 1
-                const payButtonTxVersion = stackArray[1];
-                if (payButtonTxVersion !== '00') {
-                    msg = `Unsupported version: 0x${payButtonTxVersion}`;
-                } else {
-                    const dataPush = stackArray[2];
-                    if (dataPush === '00') {
-                        // Per spec, PayButton txs with no data push OP_0 in this position
-                        msg = 'no data';
-                    } else {
-                        // Data is utf8 encoded
-                        msg = prepareStringForTelegramHTML(
-                            Buffer.from(stackArray[2], 'hex').toString('utf8'),
-                        );
-                    }
-                }
-            } else {
-                msg = '[off spec]';
-            }
+        case '0c': {
+            /**
+             * 0c - Post Topic Message
+             * <topic_name> (1-214 bytes)
+             * <message> (1-[214-len(topic_name)] bytes)
+             */
+
+            // Add the topic
+            msg += prepareStringForTelegramHTML(
+                Buffer.from(stackArray[1], 'hex').toString('utf8'),
+            );
+
+            // Add a format spacer
+            msg += '|';
+
+            // Add the topic msg
+            msg += prepareStringForTelegramHTML(
+                Buffer.from(stackArray[2], 'hex').toString('utf8'),
+            );
             break;
         }
-        case opReturn.knownApps.paywall.prefix: {
-            app = opReturn.knownApps.paywall.app;
-            // https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/doc/standards/op_return-prefix-guideline.md
-            // <lokad> <txid of the article this paywall is paying for>
-            if (stackArray.length === 2) {
-                const articleTxid = stackArray[1];
-                if (
-                    typeof articleTxid === 'undefined' ||
-                    articleTxid.length !== 64
-                ) {
-                    msg = `Invalid paywall article txid`;
-                } else {
-                    msg = `<a href="${config.blockExplorer}/tx/${articleTxid}">Article paywall payment</a>`;
-                }
-            } else {
-                msg = '[off spec paywall payment]';
-            }
+        case '10': {
+            /**
+             * 10 - Create Poll
+             * <poll_type> (1 byte)
+             * <option_count> (1 byte)
+             * <question> (1-209 bytes)
+             * */
+
+            // You only need the question here
+            msg += prepareStringForTelegramHTML(
+                Buffer.from(stackArray[3], 'hex').toString('utf8'),
+            );
+
             break;
         }
-        case opReturn.knownApps.authentication.prefix: {
-            app = opReturn.knownApps.authentication.app;
-            // https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/doc/standards/op_return-prefix-guideline.md
-            // <lokad> <authentication identifier>
-            if (stackArray.length === 2) {
-                const authenticationHex = stackArray[1];
-                if (authenticationHex === '00') {
-                    msg = `Invalid eCashChat authentication identifier`;
-                } else {
-                    msg = 'eCashChat authentication via dust tx';
-                }
-            } else {
-                msg = '[off spec eCashChat authentication]';
-            }
+        case '13': {
+            /**
+             * 13 Add poll option
+             * <poll_tx_hash> (32 bytes)
+             * <option> (1-184 bytes)
+             */
+
+            // Only parse the option for now
+            msg += prepareStringForTelegramHTML(
+                Buffer.from(stackArray[2], 'hex').toString('utf8'),
+            );
+
             break;
         }
-        default: {
-            // If you do not recognize the protocol identifier, just print the pushes in hex
-            // If it is an app or follows a pattern, can be added later
-            app = 'unknown';
-
-            if (containsOnlyPrintableAscii(stackArray.join(''))) {
-                msg = prepareStringForTelegramHTML(
-                    Buffer.from(stackArray.join(''), 'hex').toString('ascii'),
-                );
-            } else {
-                // If you have non-ascii characters, print each push as a hex number
-                msg = '';
-                for (let i = 0; i < stackArray.length; i += 1) {
-                    msg += `0x${stackArray[i]} `;
-                }
-                // Remove the last space
-                msg = msg.slice(0, -1);
+        case '14': {
+            /**
+             * 14 - Poll Vote
+             * <poll_tx_hash> (32 bytes)
+             * <comment> (0-184 bytes)
+             */
 
-                // Trim the msg for Telegram to avoid 200+ char msgs
-                const unknownMaxChars = 20;
-                if (msg.length > unknownMaxChars) {
-                    msg = msg.slice(0, unknownMaxChars) + '...';
-                }
-            }
+            // We just want the comment
+            msg += prepareStringForTelegramHTML(
+                Buffer.from(stackArray[2], 'hex').toString('utf8'),
+            );
 
             break;
         }
-    }
+        case '20':
+        case '24':
+        case '26': {
+            /**
+             * 20 - Link request
+             * 24 - Send money
+             * 26 - Set address alias
+             * <address_hash> (20 bytes)
+             * <message> (1-194 bytes)
+             */
 
-    return { app, msg, stackArray, tokenId };
-};
+            // The address is a hex-encoded hash160
+            // all memo addresses are p2pkh
+            const address = cashaddr.encode('ecash', 'P2PKH', stackArray[1]);
 
-/**
- * Parse an empp stack for a simplified slp v2 description
- * TODO expand for parsing other types of empp txs as specs or examples are known
- * @param {array} emppStackArray an array containing a hex string for every push of this memo OP_RETURN outputScript
- * @returns {object} {app, msg} used to compose a useful telegram msg describing the transaction
- */
-export const parseMultipushStack = (
-    emppStackArray: string[],
-): HeraldOpReturnInfo => {
-    // Note that an empp push may not necessarily include traditionally parsed pushes
-    // i.e. consumeNextPush({remainingHex:<emppPush>}) may throw an error
-    // For example, SLPv2 txs do not include a push for their prefix
+            // Link to the address in the msg
+            msg += `<a href="${
+                config.blockExplorer
+            }/address/${address}">${returnAddressPreview(address)}</a>`;
 
-    // So, parsing empp txs will require specific rules depending on the type of tx
-    let msgs = [];
+            // Add a format spacer
+            msg += '|';
 
-    // Start at i=1 because emppStackArray[0] is OP_RESERVED
-    for (let i = 1; i < emppStackArray.length; i += 1) {
-        if (emppStackArray[i].slice(0, 8) === opReturn.knownApps.slp2.prefix) {
-            // Parse string for slp v2
-            const thisMsg = parseSlpTwo(emppStackArray[i].slice(8));
-            msgs.push(`${opReturn.knownApps.slp2.app}:${thisMsg}`);
-        } else {
-            // Since we don't know any spec or parsing rules for other types of EMPP pushes,
-            // Just add an ASCII decode of the whole thing if you see one
-            msgs.push(
-                `${'Unknown App:'}${Buffer.from(
-                    emppStackArray[i],
-                    'hex',
-                ).toString('ascii')}`,
+            // Add the msg
+            msg += prepareStringForTelegramHTML(
+                Buffer.from(stackArray[2], 'hex').toString('utf8'),
             );
+            break;
         }
-        // Do not parse any other empp (haven't seen any in the wild, no existing specs to follow)
+        case '21':
+        case '22':
+        case '30':
+        case '31':
+        case '32':
+        case '35': {
+            /**
+             * https://github.com/memocash/mips/blob/master/mip-0009/mip-0009.md#specification
+             *
+             * These would require additional processing to get info about the specific tokens
+             * For now, not worth it. Just print the action.
+             *
+             * 21 - Link accept
+             * 22 - Link revoke
+             * 30 - Sell tokens
+             * 31 - Token buy offer
+             * 32 - Attach token sale signature
+             * 35 - Pin token post
+             */
+
+            // Remove formatting spacer
+            msg = msg.slice(0, -1);
+            break;
+        }
+
+        default:
+            msg += `Unknown memo action`;
     }
-    return { app: 'EMPP', msg: msgs.length > 0 ? msgs.join('|') : '' };
+    // Test for msgs that are intended for non-XEC audience
+    if (msg.includes('BCH')) {
+        msg = `[check memo.cash for msg]`;
+    }
+    return { app, msg };
 };
 
 /**
- * Stub method to parse slp two empps
- * @param {string} slpTwoPush a string of hex characters in an empp tx representing an slp2 push
- * @returns {string} For now, just the section type, if token type is correct
+ *
+ * @param {string} opReturnHex an OP_RETURN outputScript with '6a' removed
+ * @returns {object} {app, msg} an object with app and msg params used to generate msg
  */
-export const parseSlpTwo = (slpTwoPush: string): string => {
-    // Parse an empp push hex string with the SLP protocol identifier removed per SLP v2 spec
-    // https://ecashbuilders.notion.site/SLPv2-a862a4130877448387373b9e6a93dd97
-
-    let msg = '';
+export const parseOpReturn = (opReturnHex: string): HeraldOpReturnInfo => {
+    // Initialize required vars
+    let app;
+    let msg;
+    let tokenId: string | false = false;
 
-    // Create a stack to use ecash-script consume function
-    // Note: slp2 parsing is not standard op_return parsing, varchar bytes just use a one-byte push
-    // So, you can use the 'consume' function of ecash-script, but not consumeNextPush
-    let stack = { remainingHex: slpTwoPush };
+    // Get array of pushes
+    const stack = { remainingHex: opReturnHex };
+    const stackArray = [];
+    while (stack.remainingHex.length > 0) {
+        const { data } = consumeNextPush(stack);
+        if (data !== '') {
+            // You may have an empty push in the middle of a complicated tx for some reason
+            // Mb some libraries erroneously create these
+            // e.g. https://explorer.e.cash/tx/70c2842e1b2c7eb49ee69cdecf2d6f3cd783c307c4cbeef80f176159c5891484
+            // has 4c000100 for last characters. 4c00 is just nothing.
+            // But you want to know 00 and have the correct array index
+            stackArray.push(data);
+        }
+    }
 
-    // 1.3: Read token type
-    // For now, this can only be 00. If not 00, unknown
-    const tokenType = consume(stack, 1);
+    // Get the protocolIdentifier, the first push
+    const protocolIdentifier = stackArray[0];
 
-    if (tokenType !== '00') {
-        msg += 'Unknown token type|';
+    // Test for memo
+    // Memo prefixes are special in that they are two bytes instead of the usual four
+    // Also, memo has many prefixes, in that the action is also encoded in these two bytes
+    if (
+        protocolIdentifier.startsWith(opReturn.memo.prefix) &&
+        protocolIdentifier.length === 4
+    ) {
+        // If the protocol identifier is two bytes long (4 characters), parse for memo tx
+        // For now, send the same info to this function that it currently parses
+        // TODO parseMemoOutputScript needs to be refactored to use ecash-script
+        return parseMemoOutputScript(stackArray);
     }
 
-    // 1.4: Read section type
-    // These are custom varchar per slp2 spec
-    // <varchar byte hex> <section type>
-    const sectionBytes = parseInt(consume(stack, 1), 16);
-    // Note: these are encoded with push data, so you can use ecash-script
-
-    const sectionType = Buffer.from(
-        consume(stack, sectionBytes),
-        'hex',
-    ).toString('utf8');
-    msg += sectionType;
+    // Test for other known apps with known msg processing methods
+    switch (protocolIdentifier) {
+        case opReturn.opReserved: {
+            // Parse for empp OP_RETURN
+            // Spec https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/chronik/bitcoinsuite-slp/src/empp/mod.rs
+            return parseMultipushStack(stackArray);
+        }
+        case opReturn.knownApps.alias.prefix: {
+            app = opReturn.knownApps.alias.app;
+            /*
+                For now, parse and render alias txs by going through OP_RETURN
+                When aliases are live, refactor to use alias-server for validation
+                <protocolIdentifier> <version> <alias> <address type + hash>
 
-    // Parsing differs depending on section type
-    // Note that SEND and MINT have same parsing
+                Only parse the msg if the tx is constructed correctly
+                */
+            msg =
+                stackArray.length === 4 && stackArray[1] === '00'
+                    ? prepareStringForTelegramHTML(
+                          Buffer.from(stackArray[2], 'hex').toString('utf8'),
+                      )
+                    : 'Invalid alias registration';
 
-    const TOKEN_ID_BYTES = 32;
-    switch (sectionType) {
-        case 'SEND':
-        case 'MINT': {
-            // Next up is tokenId
-            const tokenId = swapEndianness(consume(stack, TOKEN_ID_BYTES));
+            break;
+        }
+        case opReturn.knownApps.airdrop.prefix: {
+            app = opReturn.knownApps.airdrop.app;
 
-            const cachedTokenInfo = cachedTokenInfoMap.get(tokenId);
+            // Initialize msg as empty string. Need tokenId info to complete.
+            msg = '';
 
-            msg += `|<a href="${config.blockExplorer}/tx/${tokenId}">${
-                typeof cachedTokenInfo === 'undefined'
-                    ? `${tokenId.slice(0, 3)}...${tokenId.slice(-3)}`
-                    : prepareStringForTelegramHTML(cachedTokenInfo.tokenTicker)
-            }</a>`;
+            // Airdrop tx has structure
+            // <prefix> <tokenId>
 
-            const numOutputs = consume(stack, 1);
-            // Iterate over number of outputs to get total amount sent
-            // Note: this should be handled with an indexer, as we are not parsing for validity here
-            // However, it's still useful information for the herald
-            let totalAmountSent = 0;
-            for (let i = 0; i < numOutputs; i += 1) {
-                totalAmountSent += parseInt(swapEndianness(consume(stack, 6)));
+            // Cashtab allows sending a cashtab msg with an airdrop
+            // These look like
+            // <prefix> <tokenId> <cashtabMsgPrefix> <msg>
+            if (stackArray.length >= 2 && stackArray[1].length === 64) {
+                tokenId = stackArray[1];
             }
-            msg +=
-                typeof cachedTokenInfo === 'undefined'
-                    ? ''
-                    : `|${bigNumberAmountToLocaleString(
-                          totalAmountSent.toString(),
-                          cachedTokenInfo.decimals,
-                      )}`;
             break;
         }
+        case opReturn.knownApps.cashtabMsg.prefix: {
+            app = opReturn.knownApps.cashtabMsg.app;
+            // For a Cashtab msg, the next push on the stack is the Cashtab msg
+            // Cashtab msgs use utf8 encoding
 
-        case 'GENESIS': {
-            // TODO
-            // Have not seen one of these in the wild yet
+            // Valid Cashtab Msg
+            // <protocol identifier> <msg in utf8>
+            msg =
+                stackArray.length >= 2
+                    ? prepareStringForTelegramHTML(
+                          Buffer.from(stackArray[1], 'hex').toString('utf8'),
+                      )
+                    : `Invalid ${app}`;
             break;
         }
-
-        case 'BURN': {
-            // TODO
-            // Have seen some in the wild but not in spec
+        case opReturn.knownApps.cashtabMsgEncrypted.prefix: {
+            app = opReturn.knownApps.cashtabMsgEncrypted.app;
+            // For an encrypted cashtab msg, you can't parse and display the msg
+            msg = '';
+            // You will add info about the tx when you build the msg
             break;
         }
-    }
-    // The rest of the parsing rules get quite complicated and should be handled in a dedicated library
-    // or indexer
-    return msg;
-};
-
-/**
- * Parse a stackArray according to OP_RETURN rules to convert to a useful tg msg
- * @param stackArray an array containing a hex string for every push of this memo OP_RETURN outputScript
- * @returns A useful string to describe this tx in a telegram msg
- */
-export const parseMemoOutputScript = (
-    stackArray: string[],
-): HeraldOpReturnInfo => {
-    let app = opReturn.memo.app;
-    let msg = '';
-
-    // Get the action code from stackArray[0]
-    // For memo txs, this will be the last 2 characters of this initial push
-    const actionCode = stackArray[0].slice(-2);
-
-    if (Object.keys(opReturn.memo).includes(actionCode)) {
-        // If you parse for this action code, include its description in the tg msg
-        msg += opReturn.memo[actionCode];
-        // Include a formatting spacer in between action code and newsworthy info
-        msg += '|';
-    }
-
-    switch (actionCode) {
-        case '01': // Set name <name> (1-217 bytes)
-        case '02': // Post memo <message> (1-217 bytes)
-        case '05': // Set profile text <text> (1-217 bytes)
-        case '0d': // Topic Follow <topic_name> (1-214 bytes)
-        case '0e': // Topic Unfollow <topic_name> (1-214 bytes)
-            // Action codes with only 1 push after the protocol identifier
-            // that is utf8 encoded
-
-            // Include decoded utf8 msg
-            // Make sure the OP_RETURN msg does not contain telegram html escape characters
-            msg += prepareStringForTelegramHTML(
-                Buffer.from(stackArray[1], 'hex').toString('utf8'),
-            );
-            break;
-        case '03':
+        case opReturn.knownApps.fusionLegacy.prefix:
+        case opReturn.knownApps.fusion.prefix: {
             /**
-             * 03 - Reply to memo
-             * <tx_hash> (32 bytes)
-             * <message> (1-184 bytes)
+             * Cash Fusion tx
+             * <protocolIdentifier> <sessionHash>
+             * https://github.com/cashshuffle/spec/blob/master/CASHFUSION.md
              */
+            app = opReturn.knownApps.fusion.app;
+            // The session hash is not particularly interesting to users
+            // Provide tx info in telegram prep function
+            msg = '';
+            break;
+        }
+        case opReturn.knownApps.swap.prefix: {
+            // Swap txs require special parsing that should be done in getSwapTgMsg
+            // We may need to get info about a token ID before we can
+            // create a good msg
+            app = opReturn.knownApps.swap.app;
+            msg = '';
 
-            // The tx hash is in hex, not utf8 encoded
-            // For now, we don't have much to do with this txid in a telegram bot
-
-            // Link to the liked or reposted memo
-            // Do not remove tg escape characters as you want this to parse
-            msg += `<a href="${config.blockExplorer}/tx/${stackArray[1]}">memo</a>`;
+            if (
+                stackArray.length >= 3 &&
+                stackArray[1] === '01' &&
+                stackArray[2] === '01' &&
+                stackArray[3].length === 64
+            ) {
+                // If this is a signal for buy or sell of a token, save the token id
+                // Ref https://github.com/vinarmani/swap-protocol/blob/master/swap-protocol-spec.md
+                // A buy or sell signal tx will have '01' at stackArray[1] and stackArray[2] and
+                // token id at stackArray[3]
+                tokenId = stackArray[3];
+            }
+            break;
+        }
+        case opReturn.knownApps.payButton.prefix: {
+            app = opReturn.knownApps.payButton.app;
+            // PayButton v0
+            // https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/doc/standards/paybutton.md
+            // <lokad> <OP_0> <data> <nonce>
+            // The data could be interesting, ignore the rest
+            if (stackArray.length >= 3) {
+                // Version byte is at index 1
+                const payButtonTxVersion = stackArray[1];
+                if (payButtonTxVersion !== '00') {
+                    msg = `Unsupported version: 0x${payButtonTxVersion}`;
+                } else {
+                    const dataPush = stackArray[2];
+                    if (dataPush === '00') {
+                        // Per spec, PayButton txs with no data push OP_0 in this position
+                        msg = 'no data';
+                    } else {
+                        // Data is utf8 encoded
+                        msg = prepareStringForTelegramHTML(
+                            Buffer.from(stackArray[2], 'hex').toString('utf8'),
+                        );
+                    }
+                }
+            } else {
+                msg = '[off spec]';
+            }
+            break;
+        }
+        case opReturn.knownApps.paywall.prefix: {
+            app = opReturn.knownApps.paywall.app;
+            // https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/doc/standards/op_return-prefix-guideline.md
+            // <lokad> <txid of the article this paywall is paying for>
+            if (stackArray.length === 2) {
+                const articleTxid = stackArray[1];
+                if (
+                    typeof articleTxid === 'undefined' ||
+                    articleTxid.length !== 64
+                ) {
+                    msg = `Invalid paywall article txid`;
+                } else {
+                    msg = `<a href="${config.blockExplorer}/tx/${articleTxid}">Article paywall payment</a>`;
+                }
+            } else {
+                msg = '[off spec paywall payment]';
+            }
+            break;
+        }
+        case opReturn.knownApps.authentication.prefix: {
+            app = opReturn.knownApps.authentication.app;
+            // https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/doc/standards/op_return-prefix-guideline.md
+            // <lokad> <authentication identifier>
+            if (stackArray.length === 2) {
+                const authenticationHex = stackArray[1];
+                if (authenticationHex === '00') {
+                    msg = `Invalid eCashChat authentication identifier`;
+                } else {
+                    msg = 'eCashChat authentication via dust tx';
+                }
+            } else {
+                msg = '[off spec eCashChat authentication]';
+            }
+            break;
+        }
+        default: {
+            // If you do not recognize the protocol identifier, just print the pushes in hex
+            // If it is an app or follows a pattern, can be added later
+            app = 'unknown';
 
-            // Include a formatting spacer
-            msg += '|';
+            if (containsOnlyPrintableAscii(stackArray.join(''))) {
+                msg = prepareStringForTelegramHTML(
+                    Buffer.from(stackArray.join(''), 'hex').toString('ascii'),
+                );
+            } else {
+                // If you have non-ascii characters, print each push as a hex number
+                msg = '';
+                for (let i = 0; i < stackArray.length; i += 1) {
+                    msg += `0x${stackArray[i]} `;
+                }
+                // Remove the last space
+                msg = msg.slice(0, -1);
 
-            // Add the reply
-            msg += prepareStringForTelegramHTML(
-                Buffer.from(stackArray[2], 'hex').toString('utf8'),
-            );
-            break;
-        case '04':
-            /**
-             * 04 - Like / tip memo <tx_hash> (32 bytes)
-             */
+                // Trim the msg for Telegram to avoid 200+ char msgs
+                const unknownMaxChars = 20;
+                if (msg.length > unknownMaxChars) {
+                    msg = msg.slice(0, unknownMaxChars) + '...';
+                }
+            }
 
-            // Link to the liked or reposted memo
-            msg += `<a href="${config.blockExplorer}/tx/${stackArray[1]}">memo</a>`;
             break;
-        case '0b': {
-            // 0b - Repost memo <tx_hash> (32 bytes) <message> (0-184 bytes)
+        }
+    }
 
-            // Link to the liked or reposted memo
-            msg += `<a href="${config.blockExplorer}/tx/${stackArray[1]}">memo</a>`;
+    return { app, msg, stackArray, tokenId };
+};
 
-            // Include a formatting spacer
-            msg += '|';
+/**
+ * Parse an eCash tx as returned by chronik for newsworthy information
+ */
+export const parseTx = (tx: Tx): HeraldParsedTx => {
+    const { txid, inputs, outputs } = tx;
 
-            // Add the msg
-            msg += prepareStringForTelegramHTML(
-                Buffer.from(stackArray[2], 'hex').toString('utf8'),
-            );
+    let isTokenTx = false;
+    let genesisInfo: false | { tokenId: string } = false;
+    let opReturnInfo: false | HeraldOpReturnInfo = false;
 
-            break;
-        }
-        case '06':
-        case '07':
-        case '16':
-        case '17': {
-            /**
-             * Follow user - 06 <address> (20 bytes)
-             * Unfollow user - 07 <address> (20 bytes)
-             * Mute user - 16 <address> (20 bytes)
-             * Unmute user - 17 <address> (20 bytes)
-             */
+    /* Token send parsing info
+     *
+     * Note that token send amounts received from chronik do not account for
+     * token decimals. Decimalized amounts require token genesisInfo
+     * decimals param to calculate
+     */
 
-            // The address is a hex-encoded hash160
-            // all memo addresses are p2pkh
-            const address = cashaddr.encode('ecash', 'P2PKH', stackArray[1]);
+    /* tokenSendInfo
+     * `false` for txs that are not etoken send txs
+     * an object containing info about the token send for token send txs
+     */
+    let tokenSendInfo: false | TokenSendInfo = false;
+    const tokenSendingOutputScripts: Set<string> = new Set();
+    const tokenReceivingOutputs = new Map();
+    const tokenChangeOutputs = new Map();
+    let undecimalizedTokenInputAmount = new BigNumber(0);
 
-            // Link to the address in the msg
-            msg += `<a href="${
-                config.blockExplorer
-            }/address/${address}">${returnAddressPreview(address)}</a>`;
-            break;
-        }
-        case '0a': {
-            // 01 - Set profile picture
-            // <url> (1-217 bytes)
+    // tokenBurn parsing variables
+    let tokenBurnInfo:
+        | false
+        | {
+              tokenId: string;
+              undecimalizedTokenBurnAmount: string;
+          } = false;
 
-            // url is utf8 encoded stack[1]
-            const url = Buffer.from(stackArray[1], 'hex').toString('utf8');
-            // Link to it
-            msg += `<a href="${url}">[img]</a>`;
-            break;
-        }
-        case '0c': {
-            /**
-             * 0c - Post Topic Message
-             * <topic_name> (1-214 bytes)
-             * <message> (1-[214-len(topic_name)] bytes)
-             */
+    /* Collect xecSendInfo for all txs, since all txs are XEC sends
+     * You may later want to render xecSendInfo for tokenSends, appTxs, etc,
+     * maybe on special conditions, e.g.a token send tx that also sends a bunch of xec
+     */
 
-            // Add the topic
-            msg += prepareStringForTelegramHTML(
-                Buffer.from(stackArray[1], 'hex').toString('utf8'),
-            );
+    // xecSend parsing variables
+    const xecSendingOutputScripts: Set<string> = new Set();
+    const xecReceivingOutputs = new Map();
+    let xecInputAmountSats = 0;
+    let xecOutputAmountSats = 0;
+    let totalSatsSent = 0;
+    let changeAmountSats = 0;
 
-            // Add a format spacer
-            msg += '|';
+    if (
+        tx.tokenStatus !== 'TOKEN_STATUS_NON_TOKEN' &&
+        tx.tokenEntries.length > 0
+    ) {
+        isTokenTx = true;
 
-            // Add the topic msg
-            msg += prepareStringForTelegramHTML(
-                Buffer.from(stackArray[2], 'hex').toString('utf8'),
+        // We may have more than one token action in a given tx
+        // chronik will reflect this by having multiple entries in the tokenEntries array
+
+        // For now, just parse the first action
+        // TODO handle txs with multiple tokenEntries
+        const parsedTokenAction = tx.tokenEntries[0];
+
+        const { tokenId, tokenType, txType, burnSummary, actualBurnAmount } =
+            parsedTokenAction;
+        const { protocol, number } = tokenType;
+        const isUnintentionalBurn =
+            burnSummary !== '' && actualBurnAmount !== '0';
+
+        // Get token type
+        // TODO present the token type in msgs
+        let parsedTokenType = '';
+        switch (protocol) {
+            case 'ALP': {
+                parsedTokenType = 'ALP';
+                break;
+            }
+            case 'SLP': {
+                if (number === SLP_1_PROTOCOL_NUMBER) {
+                    parsedTokenType = 'SLP';
+                } else if (number === SLP_1_NFT_COLLECTION_PROTOCOL_NUMBER) {
+                    parsedTokenType = 'NFT Collection';
+                } else if (number === SLP_1_NFT_PROTOCOL_NUMBER) {
+                    parsedTokenType = 'NFT';
+                }
+                break;
+            }
+            default: {
+                parsedTokenType = `${protocol} ${number}`;
+                break;
+            }
+        }
+
+        switch (txType) {
+            case 'GENESIS': {
+                // Note that NNG chronik provided genesisInfo in this tx
+                // Now we get it from chronik.token
+                // Initialize genesisInfo object with tokenId so it can be rendered into a msg later
+                genesisInfo = { tokenId };
+                break;
+            }
+            case 'SEND': {
+                if (isUnintentionalBurn) {
+                    tokenBurnInfo = {
+                        tokenId,
+                        undecimalizedTokenBurnAmount: actualBurnAmount,
+                    };
+                } else {
+                    tokenSendInfo = {
+                        tokenId,
+                        parsedTokenType,
+                        txType,
+                    };
+                }
+                break;
+            }
+            // TODO handle MINT
+            default: {
+                // For now, if we can't parse as above, this will be parsed as an eCash tx (or EMPP)
+                break;
+            }
+        }
+    }
+    for (const input of inputs) {
+        if (typeof input.outputScript !== 'undefined') {
+            xecSendingOutputScripts.add(input.outputScript);
+        }
+
+        xecInputAmountSats += input.value;
+        // The input that sent the token utxos will have key 'slpToken'
+        if (typeof input.token !== 'undefined') {
+            // Add amount to undecimalizedTokenInputAmount
+            // TODO make sure this is for the correct tokenID
+            // Could have mistakes in parsing ALP txs otherwise
+            // For now, this is outside the scope of migration
+            undecimalizedTokenInputAmount = undecimalizedTokenInputAmount.plus(
+                input.token.amount,
             );
-            break;
+            // Collect the input outputScripts to identify change output
+            if (typeof input.outputScript !== 'undefined') {
+                tokenSendingOutputScripts.add(input.outputScript);
+            }
         }
-        case '10': {
-            /**
-             * 10 - Create Poll
-             * <poll_type> (1 byte)
-             * <option_count> (1 byte)
-             * <question> (1-209 bytes)
-             * */
+    }
 
-            // You only need the question here
-            msg += prepareStringForTelegramHTML(
-                Buffer.from(stackArray[3], 'hex').toString('utf8'),
+    // Iterate over outputs to check for OP_RETURN msgs
+    for (const output of outputs) {
+        const { value, outputScript } = output;
+        xecOutputAmountSats += value;
+        // If this output script is the same as one of the sendingOutputScripts
+        if (xecSendingOutputScripts.has(outputScript)) {
+            // Then this XEC amount is change
+            changeAmountSats += value;
+        } else {
+            // Add an xecReceivingOutput
+
+            // Add outputScript and value to map
+            // If this outputScript is already in xecReceivingOutputs, increment its value
+            xecReceivingOutputs.set(
+                outputScript,
+                (xecReceivingOutputs.get(outputScript) ?? 0) + value,
             );
 
-            break;
+            // Increment totalSatsSent
+            totalSatsSent += value;
         }
-        case '13': {
-            /**
-             * 13 Add poll option
-             * <poll_tx_hash> (32 bytes)
-             * <option> (1-184 bytes)
-             */
+        // Don't parse OP_RETURN values of etoken txs, this info is available from chronik
+        if (outputScript.startsWith(opReturn.opReturnPrefix) && !isTokenTx) {
+            opReturnInfo = parseOpReturn(outputScript.slice(2));
+        }
+        // For etoken send txs, parse outputs for tokenSendInfo object
+        if (typeof output.token !== 'undefined') {
+            // TODO handle EMPP and potential token txs with multiple tokens involved
+            // Check output script to confirm does not match tokenSendingOutputScript
+            if (tokenSendingOutputScripts.has(outputScript)) {
+                // change
+                tokenChangeOutputs.set(
+                    outputScript,
+                    (
+                        tokenChangeOutputs.get(outputScript) ?? new BigNumber(0)
+                    ).plus(output.token.amount),
+                );
+            } else {
+                /* This is the sent token qty
+                 *
+                 * Add outputScript and undecimalizedTokenReceivedAmount to map
+                 * If this outputScript is already in tokenReceivingOutputs, increment undecimalizedTokenReceivedAmount
+                 * note that thisOutput.slpToken.amount is a string so you do not want to add it
+                 * BigNumber library is required for token calculations
+                 */
+                tokenReceivingOutputs.set(
+                    outputScript,
+                    (
+                        tokenReceivingOutputs.get(outputScript) ??
+                        new BigNumber(0)
+                    ).plus(output.token.amount),
+                );
+            }
+        }
+    }
 
-            // Only parse the option for now
-            msg += prepareStringForTelegramHTML(
-                Buffer.from(stackArray[2], 'hex').toString('utf8'),
-            );
+    // Determine tx fee
+    const txFee = xecInputAmountSats - xecOutputAmountSats;
 
-            break;
-        }
-        case '14': {
-            /**
-             * 14 - Poll Vote
-             * <poll_tx_hash> (32 bytes)
-             * <comment> (0-184 bytes)
-             */
+    // If this is a token send tx, return token send parsing info and not 'false' for tokenSendInfo
+    if (tokenSendInfo) {
+        tokenSendInfo.tokenChangeOutputs = tokenChangeOutputs;
+        tokenSendInfo.tokenReceivingOutputs = tokenReceivingOutputs;
+        tokenSendInfo.tokenSendingOutputScripts = tokenSendingOutputScripts;
+    }
 
-            // We just want the comment
-            msg += prepareStringForTelegramHTML(
-                Buffer.from(stackArray[2], 'hex').toString('utf8'),
-            );
+    // If this tx sent XEC to itself, reassign changeAmountSats to totalSatsSent
+    // Need to do this to prevent self-send txs being sorted at the bottom of msgs
+    if (xecReceivingOutputs.size === 0) {
+        totalSatsSent = changeAmountSats;
+    }
 
-            break;
-        }
-        case '20':
-        case '24':
-        case '26': {
-            /**
-             * 20 - Link request
-             * 24 - Send money
-             * 26 - Set address alias
-             * <address_hash> (20 bytes)
-             * <message> (1-194 bytes)
-             */
+    return {
+        txid,
+        genesisInfo,
+        opReturnInfo,
+        txFee,
+        xecSendingOutputScripts,
+        xecReceivingOutputs,
+        totalSatsSent,
+        tokenSendInfo,
+        tokenBurnInfo,
+    };
+};
 
-            // The address is a hex-encoded hash160
-            // all memo addresses are p2pkh
-            const address = cashaddr.encode('ecash', 'P2PKH', stackArray[1]);
+/**
+ * Parse a finalized block for newsworthy information
+ * @param blockHash
+ * @param blockHeight
+ * @param txs
+ */
+export const parseBlockTxs = (
+    blockHash: string,
+    blockHeight: number,
+    txs: Tx[],
+): HeraldParsedBlock => {
+    // Parse coinbase string
+    const coinbaseTx = txs[0];
+    const miner = getMinerFromCoinbaseTx(
+        coinbaseTx.inputs[0].inputScript,
+        coinbaseTx.outputs,
+        miners,
+    );
+    const staker = getStakerFromCoinbaseTx(blockHeight, coinbaseTx.outputs);
+    if (staker !== false) {
+        try {
+            staker.staker = cashaddr.encodeOutputScript(staker.staker);
+        } catch {
+            staker.staker = 'script(' + staker.staker + ')';
+        }
+    }
 
-            // Link to the address in the msg
-            msg += `<a href="${
-                config.blockExplorer
-            }/address/${address}">${returnAddressPreview(address)}</a>`;
+    // Start with i=1 to skip Coinbase tx
+    let parsedTxs = [];
+    for (let i = 1; i < txs.length; i += 1) {
+        parsedTxs.push(parseTx(txs[i]));
+    }
 
-            // Add a format spacer
-            msg += '|';
+    // Sort parsedTxs by totalSatsSent, highest to lowest
+    parsedTxs = parsedTxs.sort((a, b) => {
+        return b.totalSatsSent - a.totalSatsSent;
+    });
 
-            // Add the msg
-            msg += prepareStringForTelegramHTML(
-                Buffer.from(stackArray[2], 'hex').toString('utf8'),
-            );
-            break;
+    // Collect token info needed to parse token send txs
+    const tokenIds: Set<string> = new Set(); // we only need each tokenId once
+    // Collect outputScripts seen in this block to parse for balance
+    const outputScripts: Set<string> = new Set();
+    for (let i = 0; i < parsedTxs.length; i += 1) {
+        const thisParsedTx = parsedTxs[i];
+        if (thisParsedTx.tokenSendInfo) {
+            tokenIds.add(thisParsedTx.tokenSendInfo.tokenId);
         }
-        case '21':
-        case '22':
-        case '30':
-        case '31':
-        case '32':
-        case '35': {
-            /**
-             * https://github.com/memocash/mips/blob/master/mip-0009/mip-0009.md#specification
-             *
-             * These would require additional processing to get info about the specific tokens
-             * For now, not worth it. Just print the action.
-             *
-             * 21 - Link accept
-             * 22 - Link revoke
-             * 30 - Sell tokens
-             * 31 - Token buy offer
-             * 32 - Attach token sale signature
-             * 35 - Pin token post
-             */
-
-            // Remove formatting spacer
-            msg = msg.slice(0, -1);
-            break;
+        if (thisParsedTx.genesisInfo) {
+            tokenIds.add(thisParsedTx.genesisInfo.tokenId);
+        }
+        if (thisParsedTx.tokenBurnInfo) {
+            tokenIds.add(thisParsedTx.tokenBurnInfo.tokenId);
+        }
+        // Some OP_RETURN txs also have token IDs we need to parse
+        // SWaP txs, (TODO: airdrop txs)
+        if (thisParsedTx.opReturnInfo && thisParsedTx.opReturnInfo.tokenId) {
+            tokenIds.add(thisParsedTx.opReturnInfo.tokenId);
         }
+        const { xecSendingOutputScripts, xecReceivingOutputs } = thisParsedTx;
 
-        default:
-            msg += `Unknown memo action`;
-    }
-    // Test for msgs that are intended for non-XEC audience
-    if (msg.includes('BCH')) {
-        msg = `[check memo.cash for msg]`;
+        // Only add the first sending and receiving output script,
+        // As you will only render balance emojis for these
+        outputScripts.add(xecSendingOutputScripts.values().next().value!);
+
+        // For receiving outputScripts, add the first that is not OP_RETURN
+        // So, get an array of the outputScripts first
+        const xecReceivingOutputScriptsArray: string[] = Array.from(
+            xecReceivingOutputs.keys(),
+        );
+        for (let j = 0; j < xecReceivingOutputScriptsArray.length; j += 1) {
+            if (
+                !xecReceivingOutputScriptsArray[j].startsWith(
+                    opReturn.opReturnPrefix,
+                )
+            ) {
+                outputScripts.add(xecReceivingOutputScriptsArray[j]);
+                // Exit loop after you've added the first non-OP_RETURN outputScript
+                break;
+            }
+        }
     }
-    return { app, msg };
+    return {
+        hash: blockHash,
+        height: blockHeight,
+        miner,
+        staker,
+        numTxs: txs.length,
+        parsedTxs,
+        tokenIds,
+        outputScripts,
+    };
 };
 
 /**
  * Build a msg about an encrypted cashtab msg tx
  * @param sendingAddress
  * @param xecReceivingOutputs
  * @param coingeckoPrices
  * @returns msg
  */
 export const getEncryptedCashtabMsg = (
     sendingAddress: string,
     xecReceivingOutputs: Map<string, number>,
     totalSatsSent: number,
     coingeckoPrices: false | CoinGeckoPrice[],
 ): string => {
-    let displayedSentQtyString = satsToFormattedValue(
+    const displayedSentQtyString = satsToFormattedValue(
         totalSatsSent,
         coingeckoPrices,
     );
 
     // Remove OP_RETURNs from xecReceivingOutputs
-    let receivingOutputscripts = [];
+    const receivingOutputscripts = [];
     for (const outputScript of xecReceivingOutputs.keys()) {
         if (!outputScript.startsWith(opReturn.opReturnPrefix)) {
             receivingOutputscripts.push(outputScript);
         }
     }
 
     let msgRecipientString = `${returnAddressPreview(
         cashaddr.encodeOutputScript(receivingOutputscripts[0]),
     )}`;
     if (receivingOutputscripts.length > 1) {
         // Subtract 1 because you have already rendered one receiving address
         msgRecipientString += ` and ${receivingOutputscripts.length - 1} other${
             receivingOutputscripts.length > 2 ? 's' : ''
         }`;
     }
     return `${returnAddressPreview(
         sendingAddress,
     )} sent an encrypted message and ${displayedSentQtyString} to ${msgRecipientString}`;
 };
 
 /**
  * Parse the stackArray of an airdrop tx to generate a useful telegram msg
  * @param stackArray
  * @param airdropSendingAddress
  * @param airdropRecipientsMap
  * @param tokenInfo token info for the swapped token. optional. Bool False if API call failed.
  * @param coingeckoPrices object containing price info from coingecko. Bool False if API call failed.
  * @returns msg ready to send through Telegram API
  */
 export const getAirdropTgMsg = (
     stackArray: string[],
     airdropSendingAddress: string,
     airdropRecipientsMap: Map<string, number>,
     totalSatsAirdropped: number,
     tokenInfo: false | GenesisInfo,
     coingeckoPrices: false | CoinGeckoPrice[],
 ): string => {
     // stackArray for an airdrop tx will be
     // [airdrop_protocol_identifier, airdropped_tokenId, optional_cashtab_msg_protocol_identifier, optional_cashtab_msg]
 
     // Validate expected format
     if (stackArray.length < 2 || stackArray[1].length !== 64) {
         return `Invalid ${opReturn.knownApps.airdrop.app}`;
     }
 
     // get tokenId
     const tokenId = stackArray[1];
 
     // Intialize msg with preview of sending address
     let msg = `${returnAddressPreview(airdropSendingAddress)} airdropped `;
 
-    let displayedAirdroppedQtyString = satsToFormattedValue(
+    const displayedAirdroppedQtyString = satsToFormattedValue(
         totalSatsAirdropped,
         coingeckoPrices,
     );
 
     // Add to msg
     msg += `${displayedAirdroppedQtyString} to ${airdropRecipientsMap.size} holders of `;
 
     if (tokenInfo) {
         // If API call to get tokenInfo was successful to tokenInfo !== false
         const { tokenTicker } = tokenInfo;
 
         // Link to token id
         msg += `<a href="${
             config.blockExplorer
         }/tx/${tokenId}">${prepareStringForTelegramHTML(tokenTicker)}</a>`;
     } else {
         // Note: tokenInfo is false if the API call to chronik fails
         // Link to token id
         msg += `<a href="${config.blockExplorer}/tx/${tokenId}">${
             tokenId.slice(0, 3) + '...' + tokenId.slice(-3)
         }</a>`;
     }
     // Add Cashtab msg if present
     if (
         stackArray.length > 3 &&
         stackArray[2] === opReturn.knownApps.cashtabMsg.prefix
     ) {
         msg += '|';
         msg += prepareStringForTelegramHTML(
             Buffer.from(stackArray[3], 'hex').toString('utf8'),
         );
     }
     return msg;
 };
 
 /**
  * Parse the stackArray of a SWaP tx according to spec to generate a useful telegram msg
  * @param stackArray
  * @param tokenInfo token info for the swapped token. optional.
  * @returns msg ready to send through Telegram API
  */
 export const getSwapTgMsg = (
     stackArray: string[],
     tokenInfo: false | GenesisInfo,
 ): string => {
     // Intialize msg
     let msg = '';
 
     // Generic validation to handle possible txs with SWaP protocol identifier but unexpected stack
     if (stackArray.length < 3) {
         // If stackArray[1] and stackArray[2] do not exist
         return 'Invalid SWaP';
     }
 
     // SWaP txs are complex. Parse stackArray to build msg.
     // https://github.com/vinarmani/swap-protocol/blob/master/swap-protocol-spec.md
 
     // First, get swp_msg_class at stackArray[1]
     // 01 - A Signal
     // 02 - A payment
     const swp_msg_class = stackArray[1];
 
     // Second , get swp_msg_type at stackArray[2]
     // 01 - SLP Atomic Swap
     // 02 - Multi-Party Escrow
     // 03 - Threshold Crowdfunding
     const swp_msg_type = stackArray[2];
 
     // Build msg by class and type
 
     if (swp_msg_class === '01') {
         msg += 'Signal';
         msg += '|';
         switch (swp_msg_type) {
             case '01': {
                 msg += 'SLP Atomic Swap';
                 msg += '|';
                 /*
                     <token_id_bytes> <BUY_or_SELL_ascii> <rate_in_sats_int> 
                     <proof_of_reserve_int> <exact_utxo_vout_hash_bytes> <exact_utxo_index_int> 
                     <minimum_sats_to_exchange_int>
 
                     Note that <rate_in_sats_int> is in hex value in the spec example,
                     but some examples on chain appear to encode this value in ascii
                     */
 
                 if (tokenInfo) {
                     const { tokenTicker } = tokenInfo;
 
                     // Link to token id
                     msg += `<a href="${config.blockExplorer}/tx/${
                         stackArray[3]
                     }">${prepareStringForTelegramHTML(tokenTicker)}</a>`;
                     msg += '|';
                 } else {
                     // Note: tokenInfo is false if the API call to chronik fails
                     // Also false if tokenId is invalid for some reason
                     // Link to token id if valid
                     if (stackArray.length >= 3 && stackArray[3].length === 64) {
                         msg += `<a href="${config.blockExplorer}/tx/${stackArray[3]}">Unknown Token</a>`;
                         msg += '|';
                     } else {
                         msg += 'Invalid tokenId|';
                     }
                 }
 
                 // buy or sell?
                 msg += Buffer.from(stackArray[4], 'hex').toString('ascii');
 
                 // Add price info if present
                 // price in XEC, must convert <rate_in_sats_int> from sats to XEC
                 if (stackArray.length >= 6) {
                     // In the wild, have seen some SWaP txs use ASCII for encoding rate_in_sats_int
                     // Make a determination. Spec does not indicate either way, though spec
                     // example does use hex.
                     // If stackArray[5] is more than 4 characters long, assume ascii encoding
                     let rate_in_sats_int;
                     if (stackArray[5].length > 4) {
                         rate_in_sats_int = parseInt(
                             Buffer.from(stackArray[5], 'hex').toString('ascii'),
                         );
                     } else {
                         rate_in_sats_int = parseInt(stackArray[5], 16);
                     }
 
                     msg += ` for ${(rate_in_sats_int / 100).toLocaleString(
                         'en-US',
                         {
                             maximumFractionDigits: 2,
                         },
                     )} XEC`;
                 }
 
                 // Display minimum_sats_to_exchange_int
                 // Note: sometimes a SWaP tx will not have this info
                 if (stackArray.length >= 10) {
                     // In the wild, have seen some SWaP txs use ASCII for encoding minimum_sats_to_exchange_int
                     // Make a determination. Spec does not indicate either way, though spec
                     // example does use hex.
                     // If stackArray[9] is more than 4 characters long, assume ascii encoding
                     let minimum_sats_to_exchange_int;
                     if (stackArray[9].length > 4) {
                         minimum_sats_to_exchange_int = parseInt(
                             Buffer.from(stackArray[9], 'hex').toString('ascii'),
                         );
                     } else {
                         minimum_sats_to_exchange_int = parseInt(
                             stackArray[9],
                             16,
                         );
                     }
                     msg += '|';
                     msg += `Min trade: ${(
                         minimum_sats_to_exchange_int / 100
                     ).toLocaleString('en-US', {
                         maximumFractionDigits: 2,
                     })} XEC`;
                 }
                 break;
             }
             case '02': {
                 msg += 'Multi-Party Escrow';
                 // TODO additional parsing
                 break;
             }
             case '03': {
                 msg += 'Threshold Crowdfunding';
                 // TODO additional parsing
                 break;
             }
             default: {
                 // Malformed SWaP tx
                 msg += 'Invalid SWaP';
                 break;
             }
         }
     } else if (swp_msg_class === '02') {
         msg += 'Payment';
         msg += '|';
         switch (swp_msg_type) {
             case '01': {
                 msg += 'SLP Atomic Swap';
                 // TODO additional parsing
                 break;
             }
             case '02': {
                 msg += 'Multi-Party Escrow';
                 // TODO additional parsing
                 break;
             }
             case '03': {
                 msg += 'Threshold Crowdfunding';
                 // TODO additional parsing
                 break;
             }
             default: {
                 // Malformed SWaP tx
                 msg += 'Invalid SWaP';
                 break;
             }
         }
     } else {
         // Malformed SWaP tx
         msg += 'Invalid SWaP';
     }
     return msg;
 };
 
 /**
  * Build a string formatted for Telegram's API using HTML encoding
  * @param {object} parsedBlock
  * @param {array or false} coingeckoPrices if no coingecko API error
  * @param {Map or false} tokenInfoMap if no chronik API error
  * @param {Map or false} addressInfoMap if no chronik API error
  * @returns {function} splitOverflowTgMsg(tgMsg)
  */
 export const getBlockTgMessage = (
     parsedBlock: HeraldParsedBlock,
     coingeckoPrices: false | CoinGeckoPrice[],
     tokenInfoMap: false | Map<string, GenesisInfo>,
     outputScriptInfoMap: false | Map<string, OutputscriptInfo>,
 ): string[] => {
     const { hash, height, miner, staker, numTxs, parsedTxs } = parsedBlock;
     const { emojis } = config;
 
     // Define newsworthy types of txs in parsedTxs
     // These arrays will be used to present txs in batches by type
     const genesisTxTgMsgLines = [];
     let cashtabTokenRewards = 0;
     let cashtabXecRewardTxs = 0;
     let cashtabXecRewardsTotalXec = 0;
     const tokenSendTxTgMsgLines: string[] = [];
     const tokenBurnTxTgMsgLines = [];
     const opReturnTxTgMsgLines = [];
     let xecSendTxTgMsgLines = [];
 
     // We do not get that much newsworthy value from a long list of individual token send txs
     // So, we organize token send txs by tokenId
     const tokenSendTxMap = new Map();
 
     // Iterate over parsedTxs to find anything newsworthy
     for (let i = 0; i < parsedTxs.length; i += 1) {
         const thisParsedTx = parsedTxs[i];
         const {
             txid,
             genesisInfo,
             opReturnInfo,
             txFee,
             xecSendingOutputScripts,
             xecReceivingOutputs,
             tokenSendInfo,
             tokenBurnInfo,
             totalSatsSent,
         } = thisParsedTx;
 
         if (genesisInfo && tokenInfoMap) {
             // The txid of a genesis tx is the tokenId
             const tokenId = txid;
             const genesisInfoForThisToken = tokenInfoMap.get(tokenId);
-            let { tokenTicker, tokenName, url } = genesisInfoForThisToken!;
+            let { tokenTicker, tokenName } = genesisInfoForThisToken!;
+            const { url } = genesisInfoForThisToken!;
             // Make sure tokenName does not contain telegram html escape characters
             tokenName = prepareStringForTelegramHTML(tokenName);
             // Make sure tokenName does not contain telegram html escape characters
             tokenTicker = prepareStringForTelegramHTML(tokenTicker);
             // Do not apply this parsing to tokenDocumentUrl, as this could change the URL
             // If this breaks the msg, so be it
             // Would only happen for bad URLs
             genesisTxTgMsgLines.push(
                 `${emojis.tokenGenesis}<a href="${config.blockExplorer}/tx/${tokenId}">${tokenName}</a> (${tokenTicker}) <a href="${url}">[doc]</a>`,
             );
             // This parsed tx has a tg msg line. Move on to the next one.
             continue;
         }
         if (opReturnInfo) {
-            let { app, msg, stackArray, tokenId } = opReturnInfo;
+            let { app, msg } = opReturnInfo;
+            const { stackArray, tokenId } = opReturnInfo;
             let appEmoji = '';
 
             switch (app) {
                 case opReturn.memo.app: {
                     appEmoji = emojis.memo;
                     break;
                 }
                 case opReturn.knownApps.alias.app: {
                     appEmoji = emojis.alias;
                     break;
                 }
                 case opReturn.knownApps.payButton.app: {
                     appEmoji = emojis.payButton;
                     break;
                 }
                 case opReturn.knownApps.paywall.app: {
                     appEmoji = emojis.paywall;
                     break;
                 }
                 case opReturn.knownApps.authentication.app: {
                     appEmoji = emojis.authentication;
                     break;
                 }
                 case opReturn.knownApps.cashtabMsg.app: {
                     appEmoji = emojis.cashtabMsg;
 
                     const displayedSentAmount = satsToFormattedValue(
                         totalSatsSent,
                         coingeckoPrices,
                     );
 
                     const displayedTxFee = satsToFormattedValue(
                         txFee,
                         coingeckoPrices,
                     );
 
                     app += `, ${displayedSentAmount} for ${displayedTxFee}`;
                     break;
                 }
                 case opReturn.knownApps.cashtabMsgEncrypted.app: {
                     msg = getEncryptedCashtabMsg(
                         cashaddr.encodeOutputScript(
                             xecSendingOutputScripts.values().next().value!,
                         ), // Assume first input is sender
                         xecReceivingOutputs,
                         totalSatsSent,
                         coingeckoPrices,
                     );
                     appEmoji = emojis.cashtabEncrypted;
                     break;
                 }
                 case opReturn.knownApps.airdrop.app: {
                     msg = getAirdropTgMsg(
                         stackArray!,
                         cashaddr.encodeOutputScript(
                             xecSendingOutputScripts.values().next().value!,
                         ), // Assume first input is sender
                         xecReceivingOutputs,
                         totalSatsSent,
                         tokenId && tokenInfoMap
                             ? tokenInfoMap.get(tokenId)!
                             : false,
                         coingeckoPrices,
                     );
                     appEmoji = emojis.airdrop;
                     break;
                 }
                 case opReturn.knownApps.swap.app: {
                     msg = getSwapTgMsg(
                         stackArray!,
                         tokenId && tokenInfoMap
                             ? tokenInfoMap.get(tokenId)!
                             : false,
                     );
                     appEmoji = emojis.swap;
                     break;
                 }
                 case opReturn.knownApps.fusion.app: {
                     // totalSatsSent is total amount fused
-                    let displayedFusedQtyString = satsToFormattedValue(
+                    const displayedFusedQtyString = satsToFormattedValue(
                         totalSatsSent,
                         coingeckoPrices,
                     );
 
                     msg += `Fused ${displayedFusedQtyString} from ${xecSendingOutputScripts.size} inputs into ${xecReceivingOutputs.size} outputs`;
                     appEmoji = emojis.fusion;
                     break;
                 }
                 default: {
                     appEmoji = emojis.unknown;
                     break;
                 }
             }
 
             opReturnTxTgMsgLines.push(
                 `${appEmoji}<a href="${config.blockExplorer}/tx/${txid}">${app}:</a> ${msg}`,
             );
             // This parsed tx has a tg msg line. Move on to the next one.
             continue;
         }
 
         if (tokenSendInfo && tokenInfoMap && !tokenBurnInfo) {
             // If this is a token send tx that does not burn any tokens and you have tokenInfoMap
-            let { tokenId, tokenChangeOutputs, tokenReceivingOutputs } =
+            const { tokenId, tokenChangeOutputs, tokenReceivingOutputs } =
                 tokenSendInfo;
 
             // Special handling for Cashtab rewards
             if (
                 // CACHET token id
                 tokenId ===
                     'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1' &&
                 // outputScript of token-server
                 xecSendingOutputScripts.values().next().value ===
                     TOKEN_SERVER_OUTPUTSCRIPT
             ) {
                 cashtabTokenRewards += 1;
                 // No further parsing for this tx
                 continue;
             }
 
             // See if you already have info for txs from this token
             const tokenSendTxInfo = tokenSendTxMap.get(tokenId);
             if (typeof tokenSendTxInfo === 'undefined') {
                 // We don't have any other txs for this token, initialize an info object
                 // Get token info from tokenInfoMap
                 const thisTokenInfo = tokenInfoMap.get(tokenId);
 
-                let { tokenTicker, tokenName, decimals } = thisTokenInfo!;
+                let { tokenTicker, tokenName } = thisTokenInfo!;
+                const { decimals } = thisTokenInfo!;
                 // Note: tokenDocumentUrl and tokenDocumentHash are also available from thisTokenInfo
 
                 // Make sure tokenName does not contain telegram html escape characters
                 tokenName = prepareStringForTelegramHTML(tokenName);
                 // Make sure tokenName does not contain telegram html escape characters
                 tokenTicker = prepareStringForTelegramHTML(tokenTicker);
 
                 // Initialize token outputs (could be receiving or change depending on tx type)
-                let tokenOutputs =
+                const tokenOutputs =
                     tokenReceivingOutputs!.size === 0
                         ? tokenChangeOutputs
                         : tokenReceivingOutputs;
 
                 let undecimalizedTokenReceivedAmount = new BigNumber(0);
                 for (const tokenReceivedAmount of tokenOutputs!.values()) {
                     undecimalizedTokenReceivedAmount =
                         undecimalizedTokenReceivedAmount.plus(
                             tokenReceivedAmount,
                         );
                 }
 
                 tokenSendTxMap.set(tokenId, {
                     sendTxs: 1,
                     tokenName,
                     tokenTicker,
                     decimals,
                     undecimalizedTokenReceivedAmount,
                 });
             } else {
                 // We do have other txs for this token, increment the tx count and amount sent
                 // Initialize token outputs (could be receiving or change depending on tx type)
-                let tokenOutputs =
+                const tokenOutputs =
                     tokenReceivingOutputs!.size === 0
                         ? tokenChangeOutputs
                         : tokenReceivingOutputs;
 
                 let undecimalizedTokenReceivedAmount = new BigNumber(0);
                 for (const tokenReceivedAmount of tokenOutputs!.values()) {
                     undecimalizedTokenReceivedAmount =
                         undecimalizedTokenReceivedAmount.plus(
                             tokenReceivedAmount,
                         );
                 }
 
                 tokenSendTxMap.set(tokenId, {
                     ...tokenSendTxInfo,
                     sendTxs: tokenSendTxInfo.sendTxs + 1,
                     undecimalizedTokenReceivedAmount:
                         tokenSendTxInfo.undecimalizedTokenReceivedAmount.plus(
                             undecimalizedTokenReceivedAmount,
                         ),
                 });
             }
 
             // This parsed tx has info needed to build a tg msg line. Move on to the next one.
             continue;
         }
 
         if (tokenBurnInfo && tokenInfoMap) {
             // If this is a token burn tx and you have tokenInfoMap
             const { tokenId, undecimalizedTokenBurnAmount } = tokenBurnInfo;
 
             if (typeof tokenId !== 'undefined' && tokenInfoMap.has(tokenId)) {
                 // Some txs may have tokenBurnInfo, but did not get tokenSendInfo
                 // e.g. 0bb7e38d7f3968d3c91bba2d7b32273f203bc8b1b486633485f76dc7416a3eca
                 // This is a token burn tx but it is not indexed as such and requires more sophisticated burn parsing
                 // So, for now, just parse txs like this as XEC sends
 
                 // Get token info from tokenInfoMap
                 const thisTokenInfo = tokenInfoMap.get(tokenId);
-                let { tokenTicker, decimals } = thisTokenInfo!;
+                let { tokenTicker } = thisTokenInfo!;
+                const { decimals } = thisTokenInfo!;
 
                 // Make sure tokenName does not contain telegram html escape characters
                 tokenTicker = prepareStringForTelegramHTML(tokenTicker);
 
                 // Calculate true tokenReceivedAmount using decimals
                 // Use decimals to calculate the burned amount as string
                 const decimalizedTokenBurnAmount =
                     bigNumberAmountToLocaleString(
                         undecimalizedTokenBurnAmount,
                         decimals,
                     );
 
                 const tokenBurningAddressStr = returnAddressPreview(
                     cashaddr.encodeOutputScript(
                         xecSendingOutputScripts.values().next().value!,
                     ),
                 );
 
                 tokenBurnTxTgMsgLines.push(
                     `${emojis.tokenBurn}${tokenBurningAddressStr} <a href="${config.blockExplorer}/tx/${txid}">burned</a> ${decimalizedTokenBurnAmount} <a href="${config.blockExplorer}/tx/${tokenId}">${tokenTicker}</a> `,
                 );
 
                 // This parsed tx has a tg msg line. Move on to the next one.
                 continue;
             }
         }
 
         // Txs not parsed above are parsed as xec send txs
 
         const displayedSentAmount = satsToFormattedValue(
             totalSatsSent,
             coingeckoPrices,
         );
 
         const displayedTxFee = satsToFormattedValue(txFee, coingeckoPrices);
 
         // Clone xecReceivingOutputs so that you don't modify unit test mocks
-        let xecReceivingAddressOutputs = new Map(xecReceivingOutputs);
+        const xecReceivingAddressOutputs = new Map(xecReceivingOutputs);
 
         // Throw out OP_RETURN outputs for txs parsed as XEC send txs
         xecReceivingAddressOutputs.forEach((value, key, map) => {
             if (key.startsWith(opReturn.opReturnPrefix)) {
                 map.delete(key);
             }
         });
 
         // Get address balance emojis for rendered addresses
         // NB you are using xecReceivingAddressOutputs to avoid OP_RETURN outputScripts
         let xecSenderEmoji = '';
         let xecReceiverEmoji = '';
 
         if (outputScriptInfoMap) {
             // If you have information about address balances, get balance emojis
             const firstXecSendingOutputScript = xecSendingOutputScripts
                 .values()
                 .next().value;
 
             if (firstXecSendingOutputScript === TOKEN_SERVER_OUTPUTSCRIPT) {
                 cashtabXecRewardTxs += 1;
                 cashtabXecRewardsTotalXec += totalSatsSent;
                 continue;
             }
 
             const firstXecReceivingOutputScript = xecReceivingAddressOutputs
                 .keys()
                 .next().value;
             const xecSenderInfoMap = outputScriptInfoMap.get(
                 firstXecSendingOutputScript!,
             );
             xecSenderEmoji =
                 typeof xecSenderInfoMap !== 'undefined'
                     ? xecSenderInfoMap.emoji
                     : '';
             const xecReceiverInfoMap = outputScriptInfoMap.get(
                 firstXecReceivingOutputScript!,
             );
             xecReceiverEmoji =
                 typeof xecReceiverInfoMap !== 'undefined'
                     ? xecReceiverInfoMap.emoji
                     : '';
         }
 
         let xecSendMsg;
         if (xecReceivingAddressOutputs.size === 0) {
             // self send tx
             // In this case, totalSatsSent has already been assigned to changeAmountSats
 
             xecSendMsg = `${emojis.xecSend}<a href="${
                 config.blockExplorer
             }/tx/${txid}">${displayedSentAmount} for ${displayedTxFee}</a>${
                 xecSenderEmoji !== ''
                     ? ` ${xecSenderEmoji} ${
                           xecSendingOutputScripts.size > 1
                               ? `${xecSendingOutputScripts.size} addresses`
                               : returnAddressPreview(
                                     cashaddr.encodeOutputScript(
                                         xecSendingOutputScripts.values().next()
                                             .value!,
                                     ),
                                 )
                       } ${config.emojis.arrowRight} ${
                           xecSendingOutputScripts.size > 1
                               ? 'themselves'
                               : 'itself'
                       }`
                     : ''
             }`;
         } else {
             xecSendMsg = `${emojis.xecSend}<a href="${
                 config.blockExplorer
             }/tx/${txid}">${displayedSentAmount} for ${displayedTxFee}</a>${
                 xecSenderEmoji !== '' || xecReceiverEmoji !== ''
                     ? ` ${xecSenderEmoji}${returnAddressPreview(
                           cashaddr.encodeOutputScript(
                               xecSendingOutputScripts.values().next().value!,
                           ),
                       )} ${config.emojis.arrowRight} ${
                           xecReceivingAddressOutputs.keys().next().value ===
                           xecSendingOutputScripts.values().next().value
                               ? 'itself'
                               : `${xecReceiverEmoji}${returnAddressPreview(
                                     cashaddr.encodeOutputScript(
                                         xecReceivingAddressOutputs.keys().next()
                                             .value!,
                                     ),
                                 )}`
                       }${
                           xecReceivingAddressOutputs.size > 1
                               ? ` and ${
                                     xecReceivingAddressOutputs.size - 1
                                 } other${
                                     xecReceivingAddressOutputs.size - 1 > 1
                                         ? 's'
                                         : ''
                                 }`
                               : ''
                       }`
                     : ''
             }`;
         }
 
         xecSendTxTgMsgLines.push(xecSendMsg);
     }
 
     // Build up message as an array, with each line as an entry
     let tgMsg = [];
 
     // Header
     // <emojis.block><height> | <numTxs> | <miner>
     tgMsg.push(
         `${emojis.block}<a href="${
             config.blockExplorer
         }/block/${hash}">${height}</a> | ${numTxs} tx${
             numTxs > 1 ? `s` : ''
         } | ${miner}`,
     );
 
     // Halving countdown
     const HALVING_HEIGHT = 840000;
     const blocksLeft = HALVING_HEIGHT - height;
     if (blocksLeft > 0) {
         // countdown
         tgMsg.push(
             `⏰ ${blocksLeft.toLocaleString('en-US')} block${
                 blocksLeft !== 1 ? 's' : ''
             } until eCash halving`,
         );
     }
     if (height === HALVING_HEIGHT) {
         tgMsg.push(`πŸŽ‰πŸŽ‰πŸŽ‰ eCash block reward reduced by 50% πŸŽ‰πŸŽ‰πŸŽ‰`);
     }
 
     // Staker
     // Staking rewards to <staker>
     if (staker) {
         // Get fiat amount of staking rwds
         tgMsg.push(
             `${emojis.staker}${satsToFormattedValue(
                 staker.reward,
                 coingeckoPrices,
             )} to <a href="${config.blockExplorer}/address/${
                 staker.staker
             }">${returnAddressPreview(staker.staker)}</a>`,
         );
     }
 
     // Display prices as set in config.js
     if (coingeckoPrices) {
         // Iterate over prices and add a line for each price in the object
 
         for (let i = 0; i < coingeckoPrices.length; i += 1) {
             const { fiat, ticker, price } = coingeckoPrices[i];
             const thisFormattedPrice = formatPrice(price, fiat);
             tgMsg.push(`1 ${ticker} = ${thisFormattedPrice}`);
         }
     }
 
     // Genesis txs
     if (genesisTxTgMsgLines.length > 0) {
         // Line break for new section
         tgMsg.push('');
 
         // 1 new eToken created:
         // or
         // <n> new eTokens created:
         tgMsg.push(
             `<b>${genesisTxTgMsgLines.length} new eToken${
                 genesisTxTgMsgLines.length > 1 ? `s` : ''
             } created</b>`,
         );
 
         tgMsg = tgMsg.concat(genesisTxTgMsgLines);
     }
 
     // Cashtab rewards
     if (cashtabTokenRewards > 0 || cashtabXecRewardTxs > 0) {
         tgMsg.push('');
         tgMsg.push(`<a href="https://cashtab.com/">Cashtab</a>`);
         if (cashtabTokenRewards > 0) {
             // 1 CACHET reward:
             // or
             // <n> CACHET rewards:
             tgMsg.push(
                 `<b>${cashtabTokenRewards}</b> <a href="${
                     config.blockExplorer
                 }/tx/aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1">CACHET</a> reward${
                     cashtabTokenRewards > 1 ? `s` : ''
                 }`,
             );
         }
 
         // Cashtab XEC rewards
         if (cashtabXecRewardTxs > 0) {
             // 1 new user received 42 XEC
             // or
             // <n> new users received <...>
             tgMsg.push(
                 `<b>${cashtabXecRewardTxs}</b> new user${
                     cashtabXecRewardTxs > 1 ? `s` : ''
                 } received <b>${satsToFormattedValue(
                     cashtabXecRewardsTotalXec,
                 )}</b>`,
             );
         }
     }
     if (tokenSendTxMap.size > 0) {
         // eToken Send txs
         // Line break for new section
         tgMsg.push('');
 
         // We include a 1-line summary for token send txs for each token ID
         tokenSendTxMap.forEach((tokenSendInfo, tokenId) => {
             const {
                 sendTxs,
                 tokenName,
                 tokenTicker,
                 decimals,
                 undecimalizedTokenReceivedAmount,
             } = tokenSendInfo;
 
             // Get decimalized receive amount
             const decimalizedTokenReceivedAmount =
                 bigNumberAmountToLocaleString(
                     undecimalizedTokenReceivedAmount.toString(),
                     decimals,
                 );
 
             tgMsg.push(
                 `${sendTxs} tx${
                     sendTxs > 1 ? `s` : ''
                 } sent ${decimalizedTokenReceivedAmount} <a href="${
                     config.blockExplorer
                 }/tx/${tokenId}">${tokenName} (${tokenTicker})</a>`,
             );
         });
 
         tgMsg = tgMsg.concat(tokenSendTxTgMsgLines);
     }
 
     // eToken burn txs
     if (tokenBurnTxTgMsgLines.length > 0) {
         // Line break for new section
         tgMsg.push('');
 
         // 1 eToken burn tx:
         // or
         // <n> eToken burn txs:
         tgMsg.push(
             `<b>${tokenBurnTxTgMsgLines.length} eToken burn tx${
                 tokenBurnTxTgMsgLines.length > 1 ? `s` : ''
             }</b>`,
         );
 
         tgMsg = tgMsg.concat(tokenBurnTxTgMsgLines);
     }
 
     // OP_RETURN txs
     if (opReturnTxTgMsgLines.length > 0) {
         // Line break for new section
         tgMsg.push('');
 
         // App txs
         // or
         // App tx
         tgMsg.push(
             `<b>${opReturnTxTgMsgLines.length} app tx${
                 opReturnTxTgMsgLines.length > 1 ? `s` : ''
             }</b>`,
         );
 
         // <appName> : <parsedAppData>
         // alias: newlyregisteredalias
         // Cashtab Msg: This is a Cashtab Msg
         tgMsg = tgMsg.concat(opReturnTxTgMsgLines);
     }
 
     // XEC txs
     const totalXecSendCount = xecSendTxTgMsgLines.length;
     if (totalXecSendCount > 0) {
         // Line break for new section
         tgMsg.push('');
 
         // Don't show more than config-adjustable amount of these txs
         if (totalXecSendCount > config.xecSendDisplayCount) {
             xecSendTxTgMsgLines = xecSendTxTgMsgLines.slice(
                 0,
                 config.xecSendDisplayCount,
             );
             xecSendTxTgMsgLines.push(
                 `...and <a href="${config.blockExplorer}/block/${hash}">${
                     totalXecSendCount - config.xecSendDisplayCount
                 } more</a>`,
             );
         }
         // 1 eCash tx
         // or
         // n eCash txs
         tgMsg.push(
             `<b>${totalXecSendCount} eCash tx${
                 totalXecSendCount > 1 ? `s` : ''
             }</b>`,
         );
 
         tgMsg = tgMsg.concat(xecSendTxTgMsgLines);
     }
 
     return splitOverflowTgMsg(tgMsg);
 };
 
 /**
  * Guess the reason why an block was invalidated by avalanche
  * @param {ChronikClient} chronik
  * @param {number} blockHeight
  * @param {object} coinbaseData
  * @param {object} memoryCache
  * @returns {string} reason
  */
 export const guessRejectReason = async (
     chronik: ChronikClient,
     blockHeight: number,
     coinbaseData: CoinbaseData,
     memoryCache: MemoryCache,
 ): Promise<string | undefined> => {
     // Let's guess the reject reason by looking for the common cases in order:
     //  1. Missing the miner fund output
     //  2. Missing the staking reward output
     //  3. Wrong staking reward winner
     //  4. Normal orphan (another block exists at the same height)
     //  5. RTT rejection
     if (typeof coinbaseData === 'undefined') {
         return undefined;
     }
 
     // 1. Missing the miner fund output
     // This output is a constant so it's easy to look for
     let hasMinerFundOuptut = false;
     for (let i = 0; i < coinbaseData.outputs.length; i += 1) {
         if (coinbaseData.outputs[i].outputScript === minerFundOutputScript) {
             hasMinerFundOuptut = true;
             break;
         }
     }
     if (!hasMinerFundOuptut) {
         return 'missing miner fund output';
     }
 
     // 2. Missing the staking reward output
     // We checked for missing miner fund output already, so if there are
     // fewer than 3 outputs we are sure the staking reward is missing
     if (coinbaseData.outputs.length < 3) {
         return 'missing staking reward output';
     }
 
     // 3. Wrong staking reward winner
     const expectedWinner: undefined | { address: string; scriptHex: string } =
         await memoryCache.get(`${blockHeight}`);
     // We might have failed to fetch the expected winner for this block, in
     // which case we can't determine if staking reward is the likely cause.
     if (typeof expectedWinner !== 'undefined') {
         const { address, scriptHex } = expectedWinner;
 
         let stakingRewardOutputIndex = -1;
         for (let i = 0; i < coinbaseData.outputs.length; i += 1) {
             if (coinbaseData.outputs[i].outputScript === scriptHex) {
                 stakingRewardOutputIndex = i;
                 break;
             }
         }
 
         // We didn't find the expected staking reward output
         if (stakingRewardOutputIndex < 0) {
             const wrongWinner = getStakerFromCoinbaseTx(
                 blockHeight,
                 coinbaseData.outputs,
             );
 
             if (wrongWinner !== false) {
                 // Try to show the eCash address and fallback to script hex
                 // if it is not possible.
                 if (typeof address !== 'undefined') {
                     try {
                         const wrongWinnerAddress = cashaddr.encodeOutputScript(
                             wrongWinner.staker,
                         );
                         return `wrong staking reward payout (${wrongWinnerAddress} instead of ${address})`;
-                    } catch (err) {
+                    } catch {
                         // Fallthrough
                     }
                 }
 
                 return `wrong staking reward payout (${wrongWinner.staker} instead of ${scriptHex})`;
             }
         }
     }
 
     // 4. Normal orphan (another block exists at the same height)
     // If chronik returns a block at the same height, assume it orphaned
     // the current invalidated block. It's very possible the block is not
     // finalized yet so we have no better way to check it's actually what
     // happened.
     try {
         const blockAtSameHeight = await chronik.block(blockHeight);
         return `orphaned by block ${blockAtSameHeight.blockInfo.hash}`;
-    } catch (err) {
+    } catch {
         // Block not found, keep guessing
     }
 
     // 5. RTT rejection
     // FIXME There is currently no way to determine if the block was
     // rejected due to RTT violation.
 
     return 'unknown';
 };
 
+/**
+ * Initialize action data for a token if not yet intialized
+ * Update action count if initialized
+ * @param tokenActionMap
+ * @param existingAction result from tokenActionMap.get(tokenId)
+ * @param tokenId
+ * @param action
+ */
+export const initializeOrIncrementTokenData = (
+    tokenActionMap: Map<string, TokenActions>,
+    existingActions: undefined | TokenActions,
+    tokenId: string,
+    action: TrackedTokenAction,
+) => {
+    tokenActionMap.set(
+        tokenId,
+        typeof existingActions === 'undefined'
+            ? {
+                  [action]: {
+                      count: 1,
+                  },
+                  actionCount: 1,
+              }
+            : {
+                  ...existingActions,
+                  [action]: {
+                      count:
+                          action in existingActions
+                              ? existingActions[action]!.count! + 1
+                              : 1,
+                  },
+                  actionCount: existingActions.actionCount + 1,
+              },
+    );
+};
+
 /**
  * Summarize an arbitrary array of chronik txs
  * Different logic vs "per block" herald msgs, as we are looking to
  * get meaningful info from more txs
  * We are interested in what txs were like over a certain time period
  * Not details of a particular block
  *
  * TODO
  * Biggest tx
  * Highest fee
  * Token dex volume
  * Biggest token sales
  * Whale alerts
  *
  * @param now unix timestamp in seconds
  * @param txs array of CONFIRMED Txs
  * @param tokenInfoMap tokenId => genesisInfo
  * @param priceInfo { usd, usd_market_cap, usd_24h_vol, usd_24h_change }
  */
 export const summarizeTxHistory = (
     now: number,
     txs: Tx[],
     tokenInfoMap: false | Map<string, GenesisInfo>,
     priceInfo?: PriceInfo,
 ): string[] => {
     const xecPriceUsd =
         typeof priceInfo !== 'undefined' ? priceInfo.usd : undefined;
     // Throw out any unconfirmed txs
     txs.filter(tx => typeof tx.block !== 'undefined');
 
     // Sort by blockheight
     txs.sort((a, b) => a.block!.height - b.block!.height);
     const txCount = txs.length;
     // Get covered blocks
     // Note we add 1 as we include the block at index 0
     const blockCount =
         txs[txCount - 1].block!.height - txs[0].block!.height + 1;
 
     // Initialize objects useful for summarizing data
 
     // miner => blocks found
     const minerMap = new Map();
 
     // miner pools where we can parse individual miners
     let viaBtcBlocks = 0;
     const viabtcMinerMap = new Map();
 
     // stakerOutputScript => {count, reward}
     const stakerMap = new Map();
 
     // TODO more info about send txs
     // inputs[0].outputScript => {count, satoshisSent}
     // senderMap
 
     // lokad name => count
     const appTxMap = new Map();
 
     let totalStakingRewardSats = 0;
     let cashtabXecRewardCount = 0;
     let cashtabXecRewardSats = 0;
     let cashtabCachetRewardCount = 0;
     let binanceWithdrawalCount = 0;
     let binanceWithdrawalSats = 0;
 
     let slpFungibleTxs = 0;
     let appTxs = 0;
     let unknownLokadTxs = 0;
 
     // tokenId => {info, list, cancel, buy, adPrep, send, burn, mint, genesis: {genesisQty: <>, hasBaton: <>}}
     const tokenActions = new Map();
     let invalidTokenEntries = 0;
     let nftNonAgoraTokenEntries = 0;
     let mintVaultTokenEntries = 0;
     let alpTokenEntries = 0;
 
     let newSlpTokensFixedSupply = 0;
     let newSlpTokensVariableSupply = 0;
 
     // Nft vars
     const nftActions = new Map();
     const nftAgoraActions = new Map();
     const uniqueAgoraNfts = new Set();
     const uniqueNonAgoraNfts = new Set();
     let agoraOneshotTxs = 0;
     let nftMints = 0;
 
     // Agora vars
     let agoraTxs = 0;
     const agoraActions = new Map();
 
     for (const tx of txs) {
         const { inputs, outputs, block, tokenEntries, isCoinbase } = tx;
 
         if (isCoinbase) {
             // Coinbase tx - get miner and staker info
             const miner = getMinerFromCoinbaseTx(
                 tx.inputs[0].inputScript,
                 outputs,
                 miners,
             );
             if (miner.includes('ViaBTC')) {
                 viaBtcBlocks += 1;
                 // ViaBTC pool miner
-                let blocksFoundThisViaMiner = viabtcMinerMap.get(miner);
+                const blocksFoundThisViaMiner = viabtcMinerMap.get(miner);
                 if (typeof blocksFoundThisViaMiner === 'undefined') {
                     viabtcMinerMap.set(miner, 1);
                 } else {
                     viabtcMinerMap.set(miner, blocksFoundThisViaMiner + 1);
                 }
             } else {
                 // Other miner
-                let blocksFoundThisMiner = minerMap.get(miner);
+                const blocksFoundThisMiner = minerMap.get(miner);
                 if (typeof blocksFoundThisMiner === 'undefined') {
                     minerMap.set(miner, 1);
                 } else {
                     minerMap.set(miner, blocksFoundThisMiner + 1);
                 }
             }
 
             const stakerInfo = getStakerFromCoinbaseTx(block!.height, outputs);
             if (stakerInfo) {
                 // The coinbase tx may have no staker
                 // In thise case, we do not have any staking info to update
 
                 const { staker, reward } = stakerInfo;
 
                 totalStakingRewardSats += reward;
 
-                let stakingRewardsThisStaker = stakerMap.get(staker);
+                const stakingRewardsThisStaker = stakerMap.get(staker);
                 if (typeof stakingRewardsThisStaker === 'undefined') {
                     stakerMap.set(staker, { count: 1, reward });
                 } else {
                     stakingRewardsThisStaker.reward += reward;
                     stakingRewardsThisStaker.count += 1;
                 }
             }
             // No further analysis for this tx
             continue;
         }
         const senderOutputScript = inputs[0].outputScript;
         if (senderOutputScript === TOKEN_SERVER_OUTPUTSCRIPT) {
             // If this tx was sent by token-server
             if (tokenEntries.length > 0) {
                 // We assume all token txs sent by token-server are CACHET rewards
                 // CACHET reward
                 cashtabCachetRewardCount += 1;
             } else {
                 // XEC rwd
                 cashtabXecRewardCount += 1;
                 for (const output of outputs) {
                     const { value, outputScript } = output;
                     if (outputScript !== TOKEN_SERVER_OUTPUTSCRIPT) {
                         cashtabXecRewardSats += value;
                     }
                 }
             }
             // No further analysis for this tx
             continue;
         }
         if (senderOutputScript === BINANCE_OUTPUTSCRIPT) {
             // Tx sent by Binance
             // Make sure it's not just a utxo consolidation
             for (const output of outputs) {
                 const { value, outputScript } = output;
                 if (outputScript !== BINANCE_OUTPUTSCRIPT) {
                     // If we have an output that is not sending to the binance hot wallet
                     // Increment total value amount withdrawn
                     binanceWithdrawalSats += value;
                     // We also call this a withdrawal
                     // Note that 1 tx from the hot wallet may include more than 1 withdrawal
                     binanceWithdrawalCount += 1;
                 }
             }
         }
 
         // Other token actions
         if (tokenEntries.length > 0) {
             for (const tokenEntry of tokenEntries) {
                 // Get the tokenId
                 // Note that groupTokenId is only defined for NFT child
                 const {
                     tokenId,
                     tokenType,
                     txType,
                     groupTokenId,
                     isInvalid,
                     actualBurnAmount,
                 } = tokenEntry;
                 const { type } = tokenType;
 
                 if (isInvalid) {
                     // TODO find this for test tx
                     invalidTokenEntries += 1;
                     // Log to console so if we see this tx, we can analyze it for parsing
                     console.info(
                         `Unparsed isInvalid tokenEntry in tx: ${tx.txid}`,
                     );
                     // No other parsing for this tokenEntry
                     continue;
                 }
 
                 if (type === 'ALP_TOKEN_TYPE_STANDARD') {
                     // TODO ALP parsing
                     alpTokenEntries += 1;
                     // Log to console so if we see this tx, we can analyze it for parsing
                     console.info(
                         `Unparsed ALP_TOKEN_TYPE_STANDARD tokenEntry in tx: ${tx.txid}`,
                     );
                     // No other parsing for this tokenEntry
                     continue;
                 }
 
                 if (type === 'SLP_TOKEN_TYPE_MINT_VAULT') {
                     // TODO mint valt parsing
                     mintVaultTokenEntries += 1;
                     // Log to console so if we see this tx, we can analyze it for parsing
                     console.info(
                         `Unparsed SLP_TOKEN_TYPE_MINT_VAULT tokenEntry in tx: ${tx.txid}`,
                     );
                     // No other parsing for this tokenEntry
                     continue;
                 }
 
                 if (type === 'SLP_TOKEN_TYPE_NFT1_CHILD') {
                     if (typeof groupTokenId === 'undefined') {
                         // Should never happen
                         invalidTokenEntries += 1;
                         // Log to console so if we see this tx, we can analyze it for parsing
                         console.info(
                             `Unparsed SLP_TOKEN_TYPE_NFT1_CHILD with undefined groupTokenId: ${tx.txid}`,
                         );
                         // No other parsing for this tokenEntry
                         continue;
                     }
                     // Note that we organize all NFT1 children by their collection for herald purposes
                     // Parse NFT child tx
 
                     switch (txType) {
                         case 'NONE': {
                             invalidTokenEntries += 1;
                             // Log to console so if we see this tx, we can analyze it for parsing
                             console.info(
                                 `Unparsed SLP_TOKEN_TYPE_NFT1_CHILD txType NONE tokenEntry in tx: ${tx.txid}`,
                             );
                             // No other parsing for this tokenEntry
                             continue;
                         }
                         case 'UNKNOWN': {
                             invalidTokenEntries += 1;
                             // Log to console so if we see this tx, we can analyze it for parsing
                             console.info(
                                 `Unparsed SLP_TOKEN_TYPE_NFT1_CHILD txType UNKNOWN tokenEntry in tx: ${tx.txid}`,
                             );
                             // No other parsing for this tokenEntry
                             continue;
                         }
                         case 'GENESIS': {
                             // NFT1 NFTs have special genesis, in that they burn 1 of the group
                             // their txType is still genesis
                             // For the herald, these are better represented as "NFT mints" than
                             // "NFT1 Child Genesis"
                             // But coding side, we organize them this way
                             nftMints += 1;
                             nftNonAgoraTokenEntries += 1;
 
                             // See if we already have tokenActions at this tokenId
                             const existingNftActions =
                                 nftActions.get(groupTokenId);
                             initializeOrIncrementTokenData(
                                 nftActions,
                                 existingNftActions,
                                 groupTokenId,
                                 TrackedTokenAction.Genesis,
                             );
                             uniqueNonAgoraNfts.add(tokenId);
                             // No further parsing for this token entry
                             continue;
                         }
                         case 'SEND': {
                             // SEND may be Agora ONESHOT or Burn
                             const existingNftActions =
                                 nftActions.get(groupTokenId);
                             const existingNftAgoraActions =
                                 nftAgoraActions.get(groupTokenId);
 
                             // For now, we assume that any p2sh token input is agora buy/cancel
                             // and any p2sh token output is an ad setup tx
                             // No other known cases of p2sh for token txs on ecash today
                             // tho multisig is possible, no supporting wallets
 
                             let isAgoraBuySellList = false;
                             for (const input of inputs) {
                                 if (typeof input.token !== 'undefined') {
                                     const { outputScript, inputScript } = input;
                                     // A token input that is p2sh may be
                                     // a listing, an ad setup, a buy, or a cancel
                                     try {
                                         const { type } =
                                             cashaddr.getTypeAndHashFromOutputScript(
                                                 outputScript!,
                                             );
                                         if (type === 'p2sh') {
                                             // Note that a ONESHOT agora tx does not necessarily
                                             // have 0441475230 in the inputscript
                                             // But we do not have any other p2sh token input txs, so parse
 
                                             // Agora tx
                                             // For now, we know all listing txs only have a single p2sh input
 
                                             if (inputs.length === 1) {
                                                 // Agora ONESHOT listing in collection groupTokenId
                                                 initializeOrIncrementTokenData(
                                                     nftAgoraActions,
                                                     existingNftAgoraActions,
                                                     groupTokenId,
                                                     TrackedTokenAction.List,
                                                 );
                                                 isAgoraBuySellList = true;
                                                 // Stop processing inputs for this tx
                                                 break;
                                             }
                                             // Check if this is a cancellation
                                             // See agora.ts from ecash-agora lib
                                             // For now, I don't think it makes sense to have an 'isCanceled' method from ecash-agora
                                             // This is a pretty specific application
                                             const ops = scriptOps(
                                                 new Script(
                                                     fromHex(inputScript),
                                                 ),
                                             );
                                             // isCanceled is always the last pushop (before redeemScript)
                                             const opIsCanceled =
                                                 ops[ops.length - 2];
 
                                             const isCanceled =
                                                 opIsCanceled === OP_0;
 
                                             if (isCanceled) {
                                                 // Agora ONESHOT cancel in collection groupTokenId
                                                 initializeOrIncrementTokenData(
                                                     nftAgoraActions,
                                                     existingNftAgoraActions,
                                                     groupTokenId,
                                                     TrackedTokenAction.Cancel,
                                                 );
                                                 isAgoraBuySellList = true;
                                                 // Stop processing inputs for this tx
                                                 break;
                                             } else {
                                                 // Agora ONESHOT purchase
                                                 initializeOrIncrementTokenData(
                                                     nftAgoraActions,
                                                     existingNftAgoraActions,
                                                     groupTokenId,
                                                     TrackedTokenAction.Buy,
                                                 );
                                                 isAgoraBuySellList = true;
                                                 // Stop processing inputs for this tx
                                                 break;
                                             }
                                         }
-                                    } catch (err) {
+                                    } catch {
                                         console.error(
                                             `Error in cashaddr.getTypeAndHashFromOutputScript(${outputScript}) from txid ${tx.txid}`,
                                         );
                                         // Do not parse it as an agora tx
                                     }
                                     // We don't need to find any other inputs for this case
                                     break;
                                 }
                             }
                             if (isAgoraBuySellList) {
                                 agoraOneshotTxs += 1;
                                 uniqueAgoraNfts.add(tokenId);
                                 // We have already processed this token tx
                                 continue;
                             }
 
                             // Check for ad prep tx
                             let isAdPrep = false;
                             for (const output of outputs) {
                                 if (typeof output.token !== 'undefined') {
                                     const { outputScript } = output;
                                     // We assume a p2sh token output is an ad setup tx
                                     // No other known use cases at the moment
                                     try {
                                         const { type } =
                                             cashaddr.getTypeAndHashFromOutputScript(
                                                 outputScript,
                                             );
 
                                         if (type === 'p2sh') {
                                             // Agora ONESHOT ad setup tx for collection groupTokenId
                                             initializeOrIncrementTokenData(
                                                 nftAgoraActions,
                                                 existingNftAgoraActions,
                                                 groupTokenId,
                                                 TrackedTokenAction.AdPrep,
                                             );
                                             isAdPrep = true;
                                             break;
                                             // Stop iterating over outputs
                                         }
-                                    } catch (err) {
+                                    } catch {
                                         console.error(
                                             `Error in cashaddr.getTypeAndHashFromOutputScript(${outputScript}) for output from txid ${tx.txid}`,
                                         );
                                         // Do not parse it as an agora tx
                                     }
                                 }
                             }
                             if (isAdPrep) {
                                 agoraOneshotTxs += 1;
                                 uniqueAgoraNfts.add(tokenId);
                                 // We have processed this tx as an Agora Ad setup tx
                                 // No further processing
                                 continue;
                             }
 
                             if (actualBurnAmount !== '0') {
                                 nftNonAgoraTokenEntries += 1;
                                 // Parse as burn
                                 // Note this is not currently supported in Cashtab
                                 initializeOrIncrementTokenData(
                                     nftActions,
                                     existingNftActions,
                                     groupTokenId,
                                     TrackedTokenAction.Burn,
                                 );
                                 uniqueNonAgoraNfts.add(tokenId);
                                 // No further parsing
                                 continue;
                             }
 
                             // Parse as send
                             initializeOrIncrementTokenData(
                                 nftActions,
                                 existingNftActions,
                                 groupTokenId,
                                 TrackedTokenAction.Send,
                             );
                             nftNonAgoraTokenEntries += 1;
                             uniqueNonAgoraNfts.add(tokenId);
                             // No further parsing for this tokenEntry
                             continue;
                         }
                         case 'MINT': {
                             // We do not expect to see any MINT txs for NFT1 children
                             // Some confusion as what crypto colloquially calls an "NFT Mint"
                             // is NOT this type of mint, but a genesis tx
                             // Run the map anyway in case we get it
                             invalidTokenEntries += 1;
                             // Log to console so if we see this tx, we can analyze it for parsing
                             console.info(
                                 `Unparsed SLP_TOKEN_TYPE_NFT1_CHILD txType MINT tokenEntry in tx: ${tx.txid}`,
                             );
                             const existingNftActions =
                                 nftActions.get(groupTokenId);
                             initializeOrIncrementTokenData(
                                 nftActions,
                                 existingNftActions,
                                 tokenId,
                                 TrackedTokenAction.Mint,
                             );
                             uniqueNonAgoraNfts.add(tokenId);
                             // No further parsing for this tokenEntry
                             continue;
                         }
                         case 'BURN': {
                             const existingNftActions = nftActions.get(tokenId);
                             initializeOrIncrementTokenData(
                                 nftActions,
                                 existingNftActions,
                                 tokenId,
                                 TrackedTokenAction.Burn,
                             );
                             nftNonAgoraTokenEntries += 1;
                             uniqueNonAgoraNfts.add(tokenId);
                             // No further parsing for this tokenEntry
                             continue;
                         }
                         default:
                             // Can we get here?
                             // Log for analysis if it happens
                             invalidTokenEntries += 1;
                             console.info(
                                 `Switch default token action for SLP_TOKEN_TYPE_NFT1_CHILD in tx: ${tx.txid}`,
                             );
                             // No further analysis this tokenEntry
                             continue;
                     }
                 }
                 if (type === 'SLP_TOKEN_TYPE_FUNGIBLE') {
                     slpFungibleTxs += 1;
                     switch (txType) {
                         case 'NONE': {
                             invalidTokenEntries += 1;
                             // Log to console so if we see this tx, we can analyze it for parsing
                             console.info(
                                 `Unparsed SLP_TOKEN_TYPE_FUNGIBLE txType NONE tokenEntry in tx: ${tx.txid}`,
                             );
                             // No other parsing for this tokenEntry
                             continue;
                         }
                         case 'UNKNOWN': {
                             invalidTokenEntries += 1;
                             // Log to console so if we see this tx, we can analyze it for parsing
                             console.info(
                                 `Unparsed SLP_TOKEN_TYPE_FUNGIBLE txType UNKNOWN tokenEntry in tx: ${tx.txid}`,
                             );
                             // No other parsing for this tokenEntry
                             continue;
                         }
                         case 'GENESIS': {
                             const genesis = {
                                 amount: '0',
                                 hasBaton: false,
                             };
                             // See if we already have tokenActions at this tokenId
                             const existingActions = tokenActions.get(tokenId);
                             for (const output of outputs) {
                                 if (typeof output.token !== 'undefined') {
                                     if (output.token.tokenId === tokenId) {
                                         // Per spec, SLP 1 genesis qty is always at output index 1
                                         // But we iterate over all outputs to check for mint batons
                                         const { amount, isMintBaton } =
                                             output.token;
                                         if (isMintBaton) {
                                             newSlpTokensVariableSupply += 1;
                                             genesis.hasBaton = true;
                                         } else {
                                             newSlpTokensFixedSupply += 1;
                                             genesis.amount = amount;
                                         }
                                     }
                                     // We do not use initializeOrIncrementTokenData here
                                     // genesis does not follow the same structure
                                     // Count is not important but we have more info for genesis
                                     tokenActions.set(
                                         tokenId,
                                         typeof existingActions === 'undefined'
                                             ? { genesis, actionCount: 1 }
                                             : {
                                                   ...existingActions,
                                                   genesis,
                                                   actionCount:
                                                       existingActions.actionCount +
                                                       1,
                                               },
                                     );
                                     // No further parsing for this tokenEntry
                                     continue;
                                 }
                             }
                             break;
                         }
                         case 'SEND': {
                             // SEND may be Agora or Burn
                             const existingTokenActions =
                                 tokenActions.get(tokenId);
                             const existingAgoraActions =
                                 agoraActions.get(tokenId);
 
                             // For now, we assume that any p2sh token input is agora buy/cancel
                             // and any p2sh token output is an ad setup tx
                             // No other known cases of p2sh for token txs on ecash today
                             // tho multisig is possible, no supporting wallets
 
                             // mb parse for ad setup first, which is p2sh output?
 
                             let isAgoraBuySellList = false;
                             for (const input of inputs) {
                                 if (typeof input.token !== 'undefined') {
                                     const { outputScript, inputScript } = input;
                                     // A token input that is p2sh may be
                                     // a listing, an ad setup, a buy, or a cancel
                                     try {
                                         const { type } =
                                             cashaddr.getTypeAndHashFromOutputScript(
                                                 outputScript!,
                                             );
                                         if (type === 'p2sh') {
                                             // We are only parsing SLP agora txs here
                                             // A listing will have AGR0 lokad in input script
                                             const AGORA_LOKAD_STARTSWITH =
                                                 '0441475230';
 
                                             if (
                                                 inputScript.startsWith(
                                                     AGORA_LOKAD_STARTSWITH,
                                                 )
                                             ) {
                                                 // Agora tx
                                                 // For now, we know all listing txs only have a single p2sh input
 
                                                 if (inputs.length === 1) {
                                                     // Agora listing
                                                     initializeOrIncrementTokenData(
                                                         agoraActions,
                                                         existingAgoraActions,
                                                         tokenId,
                                                         TrackedTokenAction.List,
                                                     );
                                                     isAgoraBuySellList = true;
                                                     // Stop processing inputs for this tx
                                                     break;
                                                 }
                                                 // Check if this is a cancellation
                                                 // See agora.ts from ecash-agora lib
                                                 // For now, I don't think it makes sense to have an 'isCanceled' method from ecash-agora
                                                 // This is a pretty specific application
                                                 const ops = scriptOps(
                                                     new Script(
                                                         fromHex(inputScript),
                                                     ),
                                                 );
                                                 // isCanceled is always the last pushop (before redeemScript)
                                                 const opIsCanceled =
                                                     ops[ops.length - 2];
 
                                                 const isCanceled =
                                                     opIsCanceled === OP_0;
 
                                                 if (isCanceled) {
                                                     // Agora cancel
                                                     initializeOrIncrementTokenData(
                                                         agoraActions,
                                                         existingAgoraActions,
                                                         tokenId,
                                                         TrackedTokenAction.Cancel,
                                                     );
                                                     isAgoraBuySellList = true;
                                                     // Stop processing inputs for this tx
                                                     break;
                                                 } else {
                                                     // Agora purchase
                                                     initializeOrIncrementTokenData(
                                                         agoraActions,
                                                         existingAgoraActions,
                                                         tokenId,
                                                         TrackedTokenAction.Buy,
                                                     );
                                                     isAgoraBuySellList = true;
                                                     // Stop processing inputs for this tx
                                                     break;
                                                 }
                                             }
                                         }
-                                    } catch (err) {
+                                    } catch {
                                         console.error(
                                             `Error in cashaddr.getTypeAndHashFromOutputScript(${outputScript}) from txid ${tx.txid}`,
                                         );
                                         // Do not parse it as an agora tx
                                     }
                                     // We don't need to find any other inputs for this case
                                     break;
                                 }
                             }
                             if (isAgoraBuySellList) {
                                 agoraTxs += 1;
                                 // We have already processed this token tx
                                 continue;
                             }
 
                             // Check for ad prep tx
                             let isAdPrep = false;
                             for (const output of outputs) {
                                 if (typeof output.token !== 'undefined') {
                                     const { outputScript } = output;
                                     // We assume a p2sh token output is an ad setup tx
                                     // No other known use cases at the moment
                                     try {
                                         const { type } =
                                             cashaddr.getTypeAndHashFromOutputScript(
                                                 outputScript,
                                             );
                                         if (type === 'p2sh') {
                                             // Agora ad setup tx for SLP1
                                             initializeOrIncrementTokenData(
                                                 agoraActions,
                                                 existingAgoraActions,
                                                 tokenId,
                                                 TrackedTokenAction.AdPrep,
                                             );
                                             isAdPrep = true;
                                             break;
                                             // Stop iterating over outputs
                                         }
-                                    } catch (err) {
+                                    } catch {
                                         console.error(
                                             `Error in cashaddr.getTypeAndHashFromOutputScript(${outputScript}) for output from txid ${tx.txid}`,
                                         );
                                         // Do not parse it as an agora tx
                                     }
                                 }
                             }
                             if (isAdPrep) {
                                 agoraTxs += 1;
                                 // We have processed this tx as an Agora Ad setup tx
                                 // No further processing
                                 continue;
                             }
 
                             // Parse as burn
                             if (actualBurnAmount !== '0') {
                                 initializeOrIncrementTokenData(
                                     tokenActions,
                                     existingTokenActions,
                                     tokenId,
                                     TrackedTokenAction.Burn,
                                 );
                                 // No further parsing
                                 continue;
                             }
 
                             // Parse as send
                             initializeOrIncrementTokenData(
                                 tokenActions,
                                 existingTokenActions,
                                 tokenId,
                                 TrackedTokenAction.Send,
                             );
                             // No further parsing for this tokenEntry
                             continue;
                         }
                         case 'MINT': {
                             const existingTokenActions =
                                 tokenActions.get(tokenId);
                             initializeOrIncrementTokenData(
                                 tokenActions,
                                 existingTokenActions,
                                 tokenId,
                                 TrackedTokenAction.Mint,
                             );
                             // No further parsing for this tokenEntry
                             continue;
                         }
                         case 'BURN': {
                             const existingTokenActions =
                                 tokenActions.get(tokenId);
                             initializeOrIncrementTokenData(
                                 tokenActions,
                                 existingTokenActions,
                                 tokenId,
                                 TrackedTokenAction.Burn,
                             );
                             // No further parsing for this tokenEntry
                             continue;
                         }
                         default:
                             // Can we get here?
                             // Log for analysis if it happens
                             invalidTokenEntries += 1;
                             console.info(
                                 `Switch default token action in tx: ${tx.txid}`,
                             );
                             // No further analysis this tokenEntry
                             continue;
                     }
                 }
             }
 
             // No further action this tx
             continue;
         }
         const firstOutputScript = outputs[0].outputScript;
         const LOKAD_OPRETURN_STARTSWITH = '6a04';
         if (firstOutputScript.startsWith(LOKAD_OPRETURN_STARTSWITH)) {
             appTxs += 1;
             // We only parse minimally-pushed lokad ids
 
             // Get the lokadId (the 4-byte first push)
             const lokadId = firstOutputScript.slice(4, 12);
 
             // Add to map
             const countThisLokad = appTxMap.get(lokadId);
             appTxMap.set(
                 lokadId,
                 typeof countThisLokad === 'undefined' ? 1 : countThisLokad + 1,
             );
         }
     }
 
     // Add ViaBTC as a single entity to minerMap
     minerMap.set(`ViaBTC`, viaBtcBlocks);
     // Sort miner map by blocks found
     const sortedMinerMap = new Map(
         [...minerMap.entries()].sort(
             (keyValueArrayA, keyValueArrayB) =>
                 keyValueArrayB[1] - keyValueArrayA[1],
         ),
     );
     const sortedStakerMap = new Map(
         [...stakerMap.entries()].sort(
             (keyValueArrayA, keyValueArrayB) =>
                 keyValueArrayB[1].count - keyValueArrayA[1].count,
         ),
     );
 
     // Build your msg
     const tgMsg = [];
 
     tgMsg.push(
         `<b>${new Date(now * 1000).toLocaleDateString('en-GB', {
             year: 'numeric',
             month: 'short',
             day: 'numeric',
             timeZone: 'UTC',
         })}</b>`,
     );
     tgMsg.push(
         `${config.emojis.block}${blockCount.toLocaleString('en-US')} blocks`,
     );
     tgMsg.push(
         `${config.emojis.arrowRight}${txs.length.toLocaleString('en-US')} txs`,
     );
     tgMsg.push('');
 
     // Market summary
     if (typeof priceInfo !== 'undefined') {
         const { usd_market_cap, usd_24h_vol, usd_24h_change } = priceInfo;
         tgMsg.push(
             `${
                 usd_24h_change > 0
                     ? config.emojis.priceUp
                     : config.emojis.priceDown
             }<b>1 XEC = ${formatPrice(
                 xecPriceUsd!,
                 'usd',
             )}</b> <i>(${usd_24h_change.toFixed(2)}%)</i>`,
         );
         tgMsg.push(
             `Trading volume: $${usd_24h_vol.toLocaleString('en-US', {
                 maximumFractionDigits: 0,
             })}`,
         );
         tgMsg.push(
             `Market cap: $${usd_market_cap.toLocaleString('en-US', {
                 maximumFractionDigits: 0,
             })}`,
         );
         tgMsg.push('');
     }
 
     // Top miners
     const MINERS_TO_SHOW = 3;
     tgMsg.push(
         `<b><i>${config.emojis.miner}${sortedMinerMap.size} miners found blocks</i></b>`,
     );
     tgMsg.push(`<u>Top ${MINERS_TO_SHOW}</u>`);
 
     const topMiners = [...sortedMinerMap.entries()].slice(0, MINERS_TO_SHOW);
     for (let i = 0; i < topMiners.length; i += 1) {
         const count = topMiners[i][1];
         const pct = (100 * (count / blockCount)).toFixed(0);
         tgMsg.push(`${i + 1}. ${topMiners[i][0]}, ${count} <i>(${pct}%)</i>`);
     }
     tgMsg.push('');
 
     const SATOSHIS_PER_XEC = 100;
     const totalStakingRewardsXec = totalStakingRewardSats / SATOSHIS_PER_XEC;
     const renderedTotalStakingRewards =
         typeof xecPriceUsd !== 'undefined'
             ? `$${(totalStakingRewardsXec * xecPriceUsd).toLocaleString(
                   'en-US',
                   {
                       minimumFractionDigits: 0,
                       maximumFractionDigits: 0,
                   },
               )}`
             : `${totalStakingRewardsXec.toLocaleString('en-US', {
                   minimumFractionDigits: 0,
                   maximumFractionDigits: 0,
               })} XEC`;
 
     // Top stakers
     const STAKERS_TO_SHOW = 3;
     tgMsg.push(
         `<b><i>${config.emojis.staker}${sortedStakerMap.size} stakers earned ${renderedTotalStakingRewards}</i></b>`,
     );
     tgMsg.push(`<u>Top ${STAKERS_TO_SHOW}</u>`);
     const topStakers = [...sortedStakerMap.entries()].slice(0, STAKERS_TO_SHOW);
     for (let i = 0; i < topStakers.length; i += 1) {
         const staker = topStakers[i];
         const count = staker[1].count;
         const pct = (100 * (count / blockCount)).toFixed(0);
         const addr = cashaddr.encodeOutputScript(staker[0]);
         tgMsg.push(
             `${i + 1}. ${`<a href="${
                 config.blockExplorer
             }/address/${addr}">${returnAddressPreview(addr)}</a>`}, ${
                 staker[1].count
             } <i>(${pct}%)</i>`,
         );
     }
 
     // Tx breakdown
 
     // Cashtab rewards
     if (cashtabXecRewardCount > 0 || cashtabCachetRewardCount > 0) {
         tgMsg.push('');
         tgMsg.push(`<a href="https://cashtab.com/">Cashtab</a>`);
         // Cashtab XEC rewards
         if (cashtabXecRewardCount > 0) {
             // 1 new user received 42 XEC
             // or
             // <n> new users received <...>
             tgMsg.push(
                 `${
                     config.emojis.gift
                 } <b>${cashtabXecRewardCount}</b> new user${
                     cashtabXecRewardCount > 1 ? `s` : ''
                 } received <b>${satsToFormattedValue(
                     cashtabXecRewardSats,
                 )}</b>`,
             );
         }
         if (cashtabCachetRewardCount > 0) {
             // 1 CACHET reward:
             // or
             // <n> CACHET rewards:
             tgMsg.push(
                 `${
                     config.emojis.tokenSend
                 } <b>${cashtabCachetRewardCount}</b> <a href="${
                     config.blockExplorer
                 }/tx/aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1">CACHET</a> reward${
                     cashtabCachetRewardCount > 1 ? `s` : ''
                 }`,
             );
         }
         tgMsg.push('');
     }
 
     // Agora partials
     if (agoraTxs > 0) {
         // Zero out counters for sorting purposes
         agoraActions.forEach((agoraActionInfo, tokenId) => {
             // Note we do not check adPrep as any token with adPrep has listing
             const { buy, list, cancel } = agoraActionInfo;
 
             if (typeof buy === 'undefined') {
                 agoraActionInfo.buy = { count: 0 };
             }
             if (typeof list === 'undefined') {
                 agoraActionInfo.list = { count: 0 };
             }
             if (typeof cancel === 'undefined') {
                 agoraActionInfo.cancel = { count: 0 };
             }
             agoraActions.set(tokenId, agoraActionInfo);
         });
 
         // Sort agoraActions by buys
         const sortedAgoraActions = new Map(
             [...agoraActions.entries()].sort(
                 (keyValueArrayA, keyValueArrayB) =>
                     keyValueArrayB[1].buy.count - keyValueArrayA[1].buy.count,
             ),
         );
 
         const agoraTokens = Array.from(sortedAgoraActions.keys());
         const agoraTokenCount = agoraTokens.length;
 
         tgMsg.push(
             `${config.emojis.agora}${
                 config.emojis.token
             } <b><i>${agoraTxs.toLocaleString('en-US')} Agora token tx${
                 agoraTxs > 1 ? 's' : ''
             } from ${agoraTokenCount} token${
                 agoraTokenCount > 1 ? 's' : ''
             }</i></b>`,
         );
 
         const AGORA_TOKENS_TO_SHOW = 10;
 
         // Handle case where we do not see as many agora tokens as our max
         const agoraTokensToShow =
             agoraTokenCount < AGORA_TOKENS_TO_SHOW
                 ? agoraTokenCount
                 : AGORA_TOKENS_TO_SHOW;
         const newsworthyAgoraTokens = agoraTokens.slice(0, agoraTokensToShow);
 
         if (agoraTokenCount > AGORA_TOKENS_TO_SHOW) {
             tgMsg.push(`<u>Top ${AGORA_TOKENS_TO_SHOW}</u>`);
         }
 
         // Emoji key
         tgMsg.push(
             `${config.emojis.agoraBuy}Buy, ${config.emojis.agoraList}List, ${config.emojis.agoraCancel}Cancel`,
         );
 
         for (let i = 0; i < newsworthyAgoraTokens.length; i += 1) {
             const tokenId = newsworthyAgoraTokens[i];
             const tokenActionInfo = sortedAgoraActions.get(tokenId);
             const genesisInfo =
                 tokenInfoMap === false ? undefined : tokenInfoMap.get(tokenId);
 
             const { buy, list, cancel } = tokenActionInfo;
 
             tgMsg.push(
                 `<a href="${config.blockExplorer}/tx/${tokenId}">${
                     typeof genesisInfo === 'undefined'
                         ? `${tokenId.slice(0, 3)}...${tokenId.slice(-3)}`
                         : genesisInfo.tokenName
                 }</a>${
                     typeof genesisInfo === 'undefined'
                         ? ''
                         : genesisInfo.tokenTicker !== ''
                         ? ` (${genesisInfo.tokenTicker})`
                         : ''
                 }: ${
                     buy.count > 0
                         ? `${config.emojis.agoraBuy}${
                               buy.count > 1 ? `x${buy.count}` : ''
                           }`
                         : ''
                 }${
                     list.count > 0
                         ? `${config.emojis.agoraList}${
                               list.count > 1 ? `x${list.count}` : ''
                           }`
                         : ''
                 }${
                     cancel.count > 0
                         ? `${config.emojis.agoraCancel}${
                               cancel.count > 1 ? `x${cancel.count}` : ''
                           }`
                         : ''
                 }`,
             );
         }
         // Newline after agora section
         tgMsg.push('');
     }
     // Agora ONESHOT (NFTs)
     if (agoraOneshotTxs > 0) {
         // Zero out counters for sorting purposes
         nftAgoraActions.forEach((agoraActionInfo, tokenId) => {
             // Note we do not check adPrep as any token with adPrep has listing
             const { buy, list, cancel } = agoraActionInfo;
 
             if (typeof buy === 'undefined') {
                 agoraActionInfo.buy = { count: 0 };
             }
             if (typeof list === 'undefined') {
                 agoraActionInfo.list = { count: 0 };
             }
             if (typeof cancel === 'undefined') {
                 agoraActionInfo.cancel = { count: 0 };
             }
             nftAgoraActions.set(tokenId, agoraActionInfo);
         });
 
         // Sort agoraActions by buys
         const sortedNftAgoraActions = new Map(
             [...nftAgoraActions.entries()].sort(
                 (keyValueArrayA, keyValueArrayB) =>
                     keyValueArrayB[1].buy.count - keyValueArrayA[1].buy.count,
             ),
         );
 
         const agoraNftCollections = Array.from(sortedNftAgoraActions.keys());
 
         const agoraCollectionCount = agoraNftCollections.length;
         const agoraNftCount = uniqueAgoraNfts.size;
 
         tgMsg.push(
             `${config.emojis.agora}${
                 config.emojis.nft
             } <b><i>${agoraOneshotTxs.toLocaleString('en-US')} Agora NFT tx${
                 agoraTxs > 1 ? 's' : ''
             } from ${agoraNftCount} NFT${
                 agoraNftCount > 1 ? 's' : ''
             } in ${agoraCollectionCount} collection${
                 agoraCollectionCount > 1 ? 's' : ''
             }</i></b>`,
         );
 
         const AGORA_COLLECTIONS_TO_SHOW = 10;
 
         // Handle case where we do not see as many agora tokens as our max
         const agoraCollectionsToShow =
             agoraCollectionCount < AGORA_COLLECTIONS_TO_SHOW
                 ? agoraCollectionCount
                 : AGORA_COLLECTIONS_TO_SHOW;
         const newsworthyAgoraCollections = agoraNftCollections.slice(
             0,
             agoraCollectionsToShow,
         );
 
         if (agoraCollectionCount > AGORA_COLLECTIONS_TO_SHOW) {
             tgMsg.push(`<u>Top ${AGORA_COLLECTIONS_TO_SHOW}</u>`);
         }
 
         // Repeat emoji key
         tgMsg.push(
             `${config.emojis.agoraBuy}Buy, ${config.emojis.agoraList}List, ${config.emojis.agoraCancel}Cancel`,
         );
 
         for (let i = 0; i < newsworthyAgoraCollections.length; i += 1) {
             const tokenId = newsworthyAgoraCollections[i];
             const tokenActionInfo = sortedNftAgoraActions.get(tokenId);
             const genesisInfo =
                 tokenInfoMap === false ? undefined : tokenInfoMap.get(tokenId);
 
             const { buy, list, cancel } = tokenActionInfo;
 
             tgMsg.push(
                 `<a href="${config.blockExplorer}/tx/${tokenId}">${
                     typeof genesisInfo === 'undefined'
                         ? `${tokenId.slice(0, 3)}...${tokenId.slice(-3)}`
                         : genesisInfo.tokenName
                 }</a>${
                     typeof genesisInfo === 'undefined'
                         ? ''
                         : genesisInfo.tokenTicker !== ''
                         ? ` (${genesisInfo.tokenTicker})`
                         : ''
                 }: ${
                     buy.count > 0
                         ? `${config.emojis.agoraBuy}${
                               buy.count > 1 ? `x${buy.count}` : ''
                           }`
                         : ''
                 }${
                     list.count > 0
                         ? `${config.emojis.agoraList}${
                               list.count > 1 ? `x${list.count}` : ''
                           }`
                         : ''
                 }${
                     cancel.count > 0
                         ? `${config.emojis.agoraCancel}${
                               cancel.count > 1 ? `x${cancel.count}` : ''
                           }`
                         : ''
                 }`,
             );
         }
         // Newline after agora section
         tgMsg.push('');
     }
 
     // SLP 1 fungible summary
     if (slpFungibleTxs > 0) {
         // Sort tokenActions map by number of token actions
         const sortedTokenActions = new Map(
             [...tokenActions.entries()].sort(
                 (keyValueArrayA, keyValueArrayB) =>
                     keyValueArrayB[1].actionCount -
                     keyValueArrayA[1].actionCount,
             ),
         );
 
         // nonAgoraTokens will probably include tokens with agora actions
         // It's just that we want to present how many tokens had non-agora actions
         const nonAgoraTokens = Array.from(sortedTokenActions.keys());
 
         const nonAgoraTokenCount = nonAgoraTokens.length;
         tgMsg.push(
             `${config.emojis.token} <b><i>${slpFungibleTxs.toLocaleString(
                 'en-US',
             )} token tx${
                 slpFungibleTxs > 1 ? 's' : ''
             } from ${nonAgoraTokenCount} token${
                 nonAgoraTokenCount > 1 ? 's' : ''
             }</i></b>`,
         );
 
         const NON_AGORA_TOKENS_TO_SHOW = 5;
         const nonAgoraTokensToShow =
             nonAgoraTokenCount < NON_AGORA_TOKENS_TO_SHOW
                 ? nonAgoraTokenCount
                 : NON_AGORA_TOKENS_TO_SHOW;
         const newsworthyTokens = nonAgoraTokens.slice(0, nonAgoraTokensToShow);
 
         if (nonAgoraTokenCount > NON_AGORA_TOKENS_TO_SHOW) {
             tgMsg.push(`<u>Top ${NON_AGORA_TOKENS_TO_SHOW}</u>`);
         }
 
         for (let i = 0; i < newsworthyTokens.length; i += 1) {
             const tokenId = newsworthyTokens[i];
             const tokenActionInfo = sortedTokenActions.get(tokenId);
             const genesisInfo =
                 tokenInfoMap === false ? undefined : tokenInfoMap.get(tokenId);
 
             const { send, genesis, burn, mint } = tokenActionInfo;
 
             tgMsg.push(
                 `<a href="${config.blockExplorer}/tx/${tokenId}">${
                     typeof genesisInfo === 'undefined'
                         ? `${tokenId.slice(0, 3)}...${tokenId.slice(-3)}`
                         : genesisInfo.tokenName
                 }</a>${
                     typeof genesisInfo === 'undefined'
                         ? ''
                         : genesisInfo.tokenTicker !== ''
                         ? ` (${genesisInfo.tokenTicker})`
                         : ''
                 }: ${
                     typeof genesis !== 'undefined'
                         ? config.emojis.tokenGenesis
                         : ''
                 }${
                     typeof send !== 'undefined'
                         ? `${config.emojis.arrowRight}${
                               send.count > 1 ? `x${send.count}` : ''
                           }`
                         : ''
                 }${
                     typeof burn !== 'undefined'
                         ? `${config.emojis.tokenBurn}${
                               burn.count > 1 ? `x${burn.count}` : ''
                           }`
                         : ''
                 }${
                     typeof mint !== 'undefined'
                         ? `${config.emojis.tokenMint}${
                               mint.count > 1 ? `x${mint.count}` : ''
                           }`
                         : ''
                 }`,
             );
         }
 
         // Line break for new section
         tgMsg.push('');
     }
 
     // NFT summary
     if (nftNonAgoraTokenEntries > 0) {
         // Sort tokenActions map by number of token actions
         const sortedNftActions = new Map(
             [...nftActions.entries()].sort(
                 (keyValueArrayA, keyValueArrayB) =>
                     keyValueArrayB[1].actionCount -
                     keyValueArrayA[1].actionCount,
             ),
         );
         const collectionsWithNonAgoraActions = Array.from(
             sortedNftActions.keys(),
         );
         const collectionsWithNonAgoraActionsCount =
             collectionsWithNonAgoraActions.length;
 
         // Note that uniqueNonAgoraNfts and uniqueAgoraNfts can have some of the same members
         // Some NFTs will have both agora actions and non-agora actions
 
         tgMsg.push(
             `${
                 config.emojis.nft
             } <b><i>${nftNonAgoraTokenEntries.toLocaleString('en-US')} NFT tx${
                 nftNonAgoraTokenEntries > 1 ? 's' : ''
             } from ${uniqueNonAgoraNfts.size} NFT${
                 uniqueNonAgoraNfts.size > 1 ? 's' : ''
             } in ${collectionsWithNonAgoraActionsCount} collection${
                 collectionsWithNonAgoraActionsCount > 1 ? 's' : ''
             }</i></b>`,
         );
 
         const NON_AGORA_COLLECTIONS_TO_SHOW = 5;
         const nonAgoraCollectionsToShow =
             collectionsWithNonAgoraActionsCount < NON_AGORA_COLLECTIONS_TO_SHOW
                 ? collectionsWithNonAgoraActionsCount
                 : NON_AGORA_COLLECTIONS_TO_SHOW;
         const newsworthyCollections = collectionsWithNonAgoraActions.slice(
             0,
             nonAgoraCollectionsToShow,
         );
 
         if (
             collectionsWithNonAgoraActionsCount > NON_AGORA_COLLECTIONS_TO_SHOW
         ) {
             tgMsg.push(`<u>Top ${NON_AGORA_COLLECTIONS_TO_SHOW}</u>`);
         }
 
         for (let i = 0; i < newsworthyCollections.length; i += 1) {
             const tokenId = newsworthyCollections[i];
             const tokenActionInfo = sortedNftActions.get(tokenId);
             const genesisInfo =
                 tokenInfoMap === false ? undefined : tokenInfoMap.get(tokenId);
 
             const { send, genesis, burn, mint } = tokenActionInfo;
 
             tgMsg.push(
                 `<a href="${config.blockExplorer}/tx/${tokenId}">${
                     typeof genesisInfo === 'undefined'
                         ? `${tokenId.slice(0, 3)}...${tokenId.slice(-3)}`
                         : genesisInfo.tokenName
                 }</a>${
                     typeof genesisInfo === 'undefined'
                         ? ''
                         : genesisInfo.tokenTicker !== ''
                         ? ` (${genesisInfo.tokenTicker})`
                         : ''
                 }: ${
                     typeof genesis !== 'undefined'
                         ? `${config.emojis.tokenGenesis}${
                               genesis.count > 1 ? `x${genesis.count}` : ''
                           }`
                         : ''
                 }${
                     typeof send !== 'undefined'
                         ? `${config.emojis.arrowRight}${
                               send.count > 1 ? `x${send.count}` : ''
                           }`
                         : ''
                 }${
                     typeof burn !== 'undefined'
                         ? `${config.emojis.tokenBurn}${
                               burn.count > 1 ? `x${burn.count}` : ''
                           }`
                         : ''
                 }${
                     typeof mint !== 'undefined'
                         ? `${config.emojis.tokenMint}${
                               mint.count > 1 ? `x${mint.count}` : ''
                           }`
                         : ''
                 }`,
             );
         }
         // Line break for new section
         tgMsg.push('');
     }
 
     // Genesis and mints token summary
     const unparsedTokenEntries =
         alpTokenEntries > 0 ||
         mintVaultTokenEntries > 0 ||
         invalidTokenEntries > 0;
     const hasTokenSummaryLines =
         nftMints > 0 ||
         newSlpTokensFixedSupply > 0 ||
         newSlpTokensVariableSupply > 0 ||
         unparsedTokenEntries;
     if (nftMints > 0) {
         tgMsg.push(
             `${config.emojis.nft} <b><i>${nftMints} NFT mint${
                 nftMints > 1 ? 's' : ''
             }</i></b>`,
         );
     }
     if (newSlpTokensFixedSupply > 0) {
         tgMsg.push(
             `${
                 config.emojis.tokenFixed
             } <b><i>${newSlpTokensFixedSupply} new fixed-supply token${
                 newSlpTokensFixedSupply > 1 ? 's' : ''
             }</i></b>`,
         );
     }
     if (newSlpTokensVariableSupply > 0) {
         tgMsg.push(
             `${
                 config.emojis.tokenMint
             } <b><i>${newSlpTokensVariableSupply} new variable-supply token${
                 newSlpTokensVariableSupply > 1 ? 's' : ''
             }</i></b>`,
         );
     }
 
     // Unparsed token summary
     if (alpTokenEntries > 0) {
         tgMsg.push(
             `${config.emojis.alp} <b><i>${alpTokenEntries.toLocaleString(
                 'en-US',
             )} ALP tx${alpTokenEntries > 1 ? 's' : ''}</i></b>`,
         );
     }
     if (mintVaultTokenEntries > 0) {
         tgMsg.push(
             `${
                 config.emojis.mintvault
             } <b><i>${mintVaultTokenEntries.toLocaleString(
                 'en-US',
             )} Mint Vault tx${mintVaultTokenEntries > 1 ? 's' : ''}</i></b>`,
         );
     }
     if (invalidTokenEntries > 0) {
         tgMsg.push(
             `${
                 config.emojis.invalid
             } <b><i>${invalidTokenEntries.toLocaleString(
                 'en-US',
             )} invalid token tx${invalidTokenEntries > 1 ? 's' : ''}</i></b>`,
         );
     }
     if (hasTokenSummaryLines) {
         tgMsg.push('');
     }
     if (appTxs > 0) {
         // Sort appTxMap by most common app txs
         const sortedAppTxMap = new Map(
             [...appTxMap.entries()].sort(
                 (keyValueArrayA, keyValueArrayB) =>
                     keyValueArrayB[1] - keyValueArrayA[1],
             ),
         );
         tgMsg.push(
             `${config.emojis.app} <b><i>${appTxs.toLocaleString(
                 'en-US',
             )} app tx${appTxs > 1 ? 's' : ''}</i></b>`,
         );
         sortedAppTxMap.forEach((count, lokadId) => {
             // Do we recognize this app?
             const supportedLokadApp = lokadMap.get(lokadId);
             if (typeof supportedLokadApp === 'undefined') {
                 unknownLokadTxs += count;
                 // Go to the next lokadId
                 return;
             }
             const { name, emoji, url } = supportedLokadApp;
             if (typeof url === 'undefined') {
                 tgMsg.push(
                     `${emoji} <b>${count.toLocaleString('en-US')}</b> ${name}${
                         count > 1 ? 's' : ''
                     }`,
                 );
             } else {
                 tgMsg.push(
                     `${emoji} <b>${count.toLocaleString(
                         'en-US',
                     )}</b> <a href="${url}">${name}${count > 1 ? 's' : ''}</a>`,
                 );
             }
         });
         // Add line for unknown txs
         if (unknownLokadTxs > 0) {
             tgMsg.push(
                 `${config.emojis.unknown} <b>${unknownLokadTxs.toLocaleString(
                     'en-US',
                 )}</b> Unknown app tx${unknownLokadTxs > 1 ? 's' : ''}`,
             );
         }
         tgMsg.push('');
     }
 
     if (binanceWithdrawalCount > 0) {
         // Binance hot wallet
         const binanceWithdrawalXec = binanceWithdrawalSats / SATOSHIS_PER_XEC;
         const renderedBinanceWithdrawalSats =
             typeof xecPriceUsd !== 'undefined'
                 ? `$${(binanceWithdrawalXec * xecPriceUsd).toLocaleString(
                       'en-US',
                       {
                           minimumFractionDigits: 0,
                           maximumFractionDigits: 0,
                       },
                   )}`
                 : `${binanceWithdrawalXec.toLocaleString('en-US', {
                       minimumFractionDigits: 0,
                       maximumFractionDigits: 0,
                   })} XEC`;
         tgMsg.push(`${config.emojis.bank} <b><i>Binance</i></b>`);
         tgMsg.push(
             `<b>${binanceWithdrawalCount}</b> withdrawal${
                 binanceWithdrawalCount > 1 ? 's' : ''
             }, ${renderedBinanceWithdrawalSats}`,
         );
     }
 
     return splitOverflowTgMsg(tgMsg);
 };
-
-/**
- * Initialize action data for a token if not yet intialized
- * Update action count if initialized
- * @param tokenActionMap
- * @param existingAction result from tokenActionMap.get(tokenId)
- * @param tokenId
- * @param action
- */
-export const initializeOrIncrementTokenData = (
-    tokenActionMap: Map<string, TokenActions>,
-    existingActions: undefined | TokenActions,
-    tokenId: string,
-    action: TrackedTokenAction,
-) => {
-    tokenActionMap.set(
-        tokenId,
-        typeof existingActions === 'undefined'
-            ? {
-                  [action]: {
-                      count: 1,
-                  },
-                  actionCount: 1,
-              }
-            : {
-                  ...existingActions,
-                  [action]: {
-                      count:
-                          action in existingActions
-                              ? existingActions[action]!.count! + 1
-                              : 1,
-                  },
-                  actionCount: existingActions.actionCount + 1,
-              },
-    );
-};
diff --git a/apps/ecash-herald/src/telegram.ts b/apps/ecash-herald/src/telegram.ts
index 9a5738cfa..65dafd6e1 100644
--- a/apps/ecash-herald/src/telegram.ts
+++ b/apps/ecash-herald/src/telegram.ts
@@ -1,155 +1,155 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 import config from '../config';
 import TelegramBot, {
     Message,
     SendMessageOptions,
 } from 'node-telegram-bot-api';
 import { MockTelegramBot } from '../test/mocks/telegramBotMock';
 import { SendMessageResponse } from './events';
 // undocumented API behavior of HTML parsing mode, discovered through brute force
 const TG_MSG_MAX_LENGTH = 4096;
 
 export const prepareStringForTelegramHTML = (string: string): string => {
     /*
         See "HTML Style" at https://core.telegram.org/bots/api
 
         Replace < with &lt;
         Replace > with &gt;
         Replace & with &amp;
       */
     let tgReadyString = string;
     // need to replace the '&' characters first
     tgReadyString = tgReadyString.replace(/&/g, '&amp;');
     tgReadyString = tgReadyString.replace(/</g, '&lt;');
     tgReadyString = tgReadyString.replace(/>/g, '&gt;');
 
     return tgReadyString;
 };
 export const splitOverflowTgMsg = (tgMsgArray: string[]): string[] => {
     /* splitOverflowTgMsg
      *
      * Params
      * tgMsgArray - an array of unjoined strings prepared by getBlockTgMessage
      *              each string has length <= 4096 characters
      *
      * Output
      * tgMsgStrings - an array of ready-to-broadcast HTML-parsed telegram messages, all under
      *                the 4096 character limit
      */
 
     // Iterate over tgMsgArray to build an array of messages under the TG_MSG_MAX_LENGTH ceiling
     const tgMsgStrings = [];
 
     let thisTgMsgStringLength = 0;
     let sliceStartIndex = 0;
     for (let i = 0; i < tgMsgArray.length; i += 1) {
         const thisLine = tgMsgArray[i];
         // Account for the .join('\n'), each line has an extra 2 characters
         // Note: this is undocumented behavior of telegram API HTML parsing mode
         // '\n' is counted as 2 characters and also is parsed as a new line in HTML mode
         thisTgMsgStringLength += thisLine.length + 2;
         console.assert(thisLine.length + 2 <= TG_MSG_MAX_LENGTH, '%o', {
             length: thisLine.length + 2,
             line: thisLine,
             error: 'Telegram message line is longer than 4096 characters',
         });
 
         // If this particular message line pushes the message over TG_MSG_MAX_LENGTH
         // less 2 as there is no `\n` at the end of the last line of the msg
         if (thisTgMsgStringLength - 2 > TG_MSG_MAX_LENGTH) {
             // Build a msg string with preceding lines, i.e. do not include this i'th line
             const sliceEndIndex = i; // Note that the slice end index is not included
             tgMsgStrings.push(
                 tgMsgArray.slice(sliceStartIndex, sliceEndIndex).join('\n'),
             );
             // Reset sliceStartIndex and thisTgMsgStringLength for the next message
             sliceStartIndex = sliceEndIndex;
 
             // Reset thisTgMsgStringLength to thisLine.length + 2;
             // The line of the current index will go into the next batched slice
             thisTgMsgStringLength = thisLine.length + 2;
         }
     }
 
     // Build a tg msg of all unused lines, if you have them
     if (sliceStartIndex < tgMsgArray.length) {
         tgMsgStrings.push(tgMsgArray.slice(sliceStartIndex).join('\n'));
     }
 
     return tgMsgStrings;
 };
 
 export const sendBlockSummary = async (
     tgMsgStrings: string[],
     telegramBot: TelegramBot | MockTelegramBot,
     channelId: string,
     blockheightOrMsgDesc?: number | string,
 ) => {
     /* sendBlockSummary
      *
      * Params
      * tgMsgStrings - an array of ready-to-be broadcast HTML-parsed telegram messages,
      * all under the 4096 character length limit
      * telegramBot - a telegram bot instance
      * channelId - the channel where the messages will be broadcast
      *
      * Output
      * Message(s) will be broadcast by telegramBot to channelId
      * If there are multiple messages, each message will be sent as a reply to its
      * preceding message
      * Function returns 'false' if there is an error in sending any one message
      * Function returns an array of msgSuccess objects for each successfully send msg
      */
 
     let msgReplyId;
-    let msgSuccessArray = [];
+    const msgSuccessArray = [];
     for (let i = 0; i < tgMsgStrings.length; i += 1) {
         const thisMsg = tgMsgStrings[i];
         let msgSuccess: Message | SendMessageResponse;
         const thisMsgOptions: SendMessageOptions =
             typeof msgReplyId === 'number'
                 ? {
                       ...config.tgMsgOptions,
                       reply_to_message_id: msgReplyId,
                   }
                 : config.tgMsgOptions;
         try {
             msgSuccess = (await telegramBot.sendMessage(
                 channelId,
                 thisMsg,
                 thisMsgOptions,
             )) as SendMessageResponse;
             msgReplyId = msgSuccess.message_id;
             msgSuccessArray.push(msgSuccess);
         } catch (err) {
             console.log(
                 `Error in sending msg in sendBlockSummary, telegramBot.send(${thisMsg}) for msg ${
                     i + 1
                 } of ${tgMsgStrings.length}`,
                 err,
             );
             return false;
         }
     }
     if (msgSuccessArray.length === tgMsgStrings.length) {
         if (typeof blockheightOrMsgDesc === 'number') {
             console.log('\x1b[32m%s\x1b[0m', `βœ” ${blockheightOrMsgDesc}`);
         } else if (blockheightOrMsgDesc === 'daily') {
             console.log(
                 '\x1b[32m%s\x1b[0m',
                 `βœ” Sent daily summary of last 24 hrs`,
             );
         }
         return msgSuccessArray;
     }
     // Catch potential edge case
     console.log({
         msgsSent: msgSuccessArray.length,
         msgsAttempted: tgMsgStrings.length,
         error: 'Failed to send all messages',
     });
     return false;
 };
diff --git a/apps/ecash-herald/src/utils.ts b/apps/ecash-herald/src/utils.ts
index 6f738af40..9ef3704b0 100644
--- a/apps/ecash-herald/src/utils.ts
+++ b/apps/ecash-herald/src/utils.ts
@@ -1,479 +1,490 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 import axios from 'axios';
 import config, { HeraldConfig, HeraldPriceApi, FiatCode } from '../config';
 import BigNumber from 'bignumber.js';
 import addressDirectory from '../constants/addresses';
 import { consume } from 'ecash-script';
 import { MemoryCache } from 'cache-manager';
 
 export const returnAddressPreview = (
     cashAddress: string,
     sliceSize = 3,
 ): string => {
     // Check known addresses for a tag
     const addrInfo = addressDirectory.get(cashAddress);
     if (typeof addrInfo?.tag !== 'undefined') {
         return addrInfo.tag;
     }
     const addressParts = cashAddress.split(':');
     const unprefixedAddress = addressParts[addressParts.length - 1];
     return `${unprefixedAddress.slice(
         0,
         sliceSize,
     )}...${unprefixedAddress.slice(-sliceSize)}`;
 };
 
 /**
  * Get the price API url herald would use for specified config
  * @param config ecash-herald config object
  * @returns expected URL of price API call
  */
 export const getCoingeckoApiUrl = (config: HeraldConfig): string => {
     return `${config.priceApi.apiBase}?ids=${config.priceApi.cryptos
         .map(crypto => crypto.coingeckoSlug)
         .join(',')}&vs_currencies=${
         config.priceApi.fiat
     }&precision=${config.priceApi.precision.toString()}`;
 };
 
-// CoinGeckoResponse: any
 export interface CoinGeckoPrice {
     fiat: FiatCode;
     price: number;
     ticker: string;
 }
+export interface CoinGeckoResponse {
+    bitcoin: { usd: number };
+    ethereum: { usd: number };
+    ecash: { usd: number };
+}
 interface GetCoingeckPricesResponse {
-    coingeckoResponse: any;
+    coingeckoResponse: CoinGeckoResponse;
     coingeckoPrices: CoinGeckoPrice[];
 }
 export const getCoingeckoPrices = async (
     priceInfoObj: HeraldPriceApi,
 ): Promise<false | GetCoingeckPricesResponse> => {
     const { apiBase, cryptos, fiat, precision } = priceInfoObj;
-    let coingeckoSlugs = cryptos.map(crypto => crypto.coingeckoSlug);
-    let apiUrl = `${apiBase}?ids=${coingeckoSlugs.join(
+    const coingeckoSlugs = cryptos.map(crypto => crypto.coingeckoSlug);
+    const apiUrl = `${apiBase}?ids=${coingeckoSlugs.join(
         ',',
     )}&vs_currencies=${fiat}&precision=${precision.toString()}`;
     // https://api.coingecko.com/api/v3/simple/price?ids=ecash,bitcoin,ethereum&vs_currencies=usd&precision=8
     let coingeckoApiResponse;
     try {
         coingeckoApiResponse = await axios.get(apiUrl);
         const { data } = coingeckoApiResponse;
         // Validate for expected shape
         // For each key in `cryptoIds`, data must contain {<fiat>: <price>}
-        let coingeckoPriceArray = [];
+        const coingeckoPriceArray = [];
         if (data && typeof data === 'object') {
             for (let i = 0; i < coingeckoSlugs.length; i += 1) {
                 const thisCoingeckoSlug = coingeckoSlugs[i];
                 if (
                     !data[thisCoingeckoSlug] ||
                     !data[thisCoingeckoSlug][fiat]
                 ) {
                     return false;
                 }
                 // Create more useful output format
                 const thisPriceInfo = {
                     fiat,
                     price: data[thisCoingeckoSlug][fiat],
                     ticker: cryptos.filter(
                         el => el.coingeckoSlug === thisCoingeckoSlug,
                     )[0].ticker,
                 };
                 if (thisPriceInfo.ticker === 'XEC') {
                     coingeckoPriceArray.unshift(thisPriceInfo);
                 } else {
                     coingeckoPriceArray.push(thisPriceInfo);
                 }
             }
             return {
                 coingeckoResponse: data,
                 coingeckoPrices: coingeckoPriceArray,
             };
         }
         return false;
     } catch (err) {
         console.log(
             `Error fetching prices of ${coingeckoSlugs.join(
                 ',',
             )} from ${apiUrl}`,
             err,
         );
     }
     return false;
 };
 
 export const formatPrice = (price: number, fiatCode: FiatCode): string => {
     // Get symbol
     let fiatSymbol = config.fiatReference[fiatCode];
 
     // If you can't find the symbol, don't show one
     if (typeof fiatSymbol === 'undefined') {
         fiatSymbol = '';
     }
 
     // No decimal points for prices greater than 100
     if (price > 100) {
         return `${fiatSymbol}${price.toLocaleString('en-US', {
             maximumFractionDigits: 0,
         })}`;
     }
     // 2 decimal places for prices between 1 and 100
     if (price > 1) {
         return `${fiatSymbol}${price.toLocaleString('en-US', {
             maximumFractionDigits: 2,
         })}`;
     }
     // All decimal places for lower prices
     // For now, these will only be XEC prices
     return `${fiatSymbol}${price.toLocaleString('en-US', {
         maximumFractionDigits: 8,
     })}`;
 };
 
 /**
  * Return a formatted string for a telegram msg given an amount of satoshis     *
  * @param xecAmount amount of XEC as a number
  */
 export const formatXecAmount = (xecAmount: number): string => {
     // Initialize displayed string variables
     let displayedAmount, descriptor;
 
     // Initialize displayedDecimals as 0
     let displayedDecimals = 0;
 
     // Build format string for fixed levels
     if (xecAmount < 10) {
         // If xecAmount is less than 10, return un-rounded
         displayedAmount = xecAmount;
         descriptor = '';
         displayedDecimals = 2;
     } else if (xecAmount < 1000) {
         displayedAmount = xecAmount;
         descriptor = '';
         // If xecAmount is between 10 and 1k, return rounded
     } else if (xecAmount < 1000000) {
         // If xecAmount is between 1k and 1 million, return formatted + rounded
         displayedAmount = xecAmount / 1000; // thousands
         descriptor = 'k';
     } else if (xecAmount < 1000000000) {
         // If xecAmount is between 1 million and 1 billion, return formatted + rounded
         displayedAmount = xecAmount / 1000000; // millions
         descriptor = 'M';
     } else if (xecAmount < 1000000000000) {
         // If xecAmount is between 1 billion and 1 trillion, return formatted + rounded
         displayedAmount = xecAmount / 1000000000; // billions
         descriptor = 'B';
     } else if (xecAmount >= 1000000000000) {
         // If xecAmount is greater than 1 trillion, return formatted + rounded
         displayedAmount = xecAmount / 1000000000000;
         descriptor = 'T';
     }
 
     return `${displayedAmount!.toLocaleString('en-US', {
         maximumFractionDigits: displayedDecimals,
     })}${descriptor} XEC`;
 };
 
 /**
  * Return a formatted string of fiat if price info is available and > $1
  * Otherwise return formatted XEC amount
  * @param {integer} satoshis
  * @param {array or false} coingeckoPrices [{fiat, price}...{fiat, price}] with xec price at index 0
  */
 export const satsToFormattedValue = (
     satoshis: number,
     coingeckoPrices?: false | CoinGeckoPrice[],
 ) => {
     // Get XEC qty
     const xecAmount = satoshis / 100;
 
     if (!coingeckoPrices) {
         return formatXecAmount(xecAmount);
     }
     // Get XEC price from index 0
     const { fiat, price } = coingeckoPrices[0];
 
     // Get fiat price
-    let fiatAmount = xecAmount * price;
+    const fiatAmount = xecAmount * price;
     const fiatSymbol: string = config.fiatReference[fiat] as string;
 
     // Format fiatAmount for different tiers
     let displayedAmount;
     let localeOptions: Intl.NumberFormatOptions = { maximumFractionDigits: 0 };
     let descriptor = '';
 
     if (fiatAmount === 0) {
         // Txs that send nothing, e.g. a one-input tx of 5.46 XEC, should keep defaults above
     } else if (fiatAmount < 0.01) {
         // enough decimal places to show one significant digit
         localeOptions = {
             minimumFractionDigits: -Math.floor(Math.log10(fiatAmount)),
         };
     } else if (fiatAmount < 1) {
         // TODO two decimal places
         localeOptions = { minimumFractionDigits: 2 };
     }
 
     if (fiatAmount < 1000) {
         displayedAmount = fiatAmount;
         descriptor = '';
     } else if (fiatAmount < 1000000) {
         // thousands
         displayedAmount = fiatAmount / 1000;
         descriptor = 'k';
     } else if (fiatAmount < 1000000000) {
         // millions
         displayedAmount = fiatAmount / 1000000;
         descriptor = 'M';
     } else if (fiatAmount >= 1000000000) {
         // billions or more
         displayedAmount = fiatAmount / 1000000000;
         descriptor = 'B';
     }
 
     return `${fiatSymbol}${displayedAmount!.toLocaleString(
         'en-US',
         localeOptions,
     )}${descriptor}`;
 };
-export const jsonReplacer = function (key: any, value: any) {
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export const jsonReplacer = function (key: string, value: any) {
     if (value instanceof Map) {
         const keyValueArray = Array.from(value.entries());
 
         for (let i = 0; i < keyValueArray.length; i += 1) {
             const thisKeyValue = keyValueArray[i]; // [key, value]
             // If this is not an empty map
             if (typeof thisKeyValue !== 'undefined') {
                 // Note: this value is an array of length 2
                 // [key, value]
                 // Check if value is a big number
                 if (thisKeyValue[1] instanceof BigNumber) {
                     // Replace it
                     thisKeyValue[1] = {
                         // Note, if you use dataType: 'BigNumber', it will not work
                         // This must be reserved
                         // Use a term that is definitely not reserved but also recognizable as
                         // "the dev means BigNumber here"
                         dataType: 'BigNumberReplacer',
                         value: thisKeyValue[1].toString(),
                     };
                 }
             }
         }
 
         return {
             dataType: 'Map',
             value: keyValueArray,
         };
     } else if (value instanceof Set) {
         return {
             dataType: 'Set',
             value: Array.from(value.keys()),
         };
     } else {
         return value;
     }
 };
-export const jsonReviver = (key: any, value: any) => {
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export const jsonReviver = (key: string, value: any) => {
     if (typeof value === 'object' && value !== null) {
         if (value.dataType === 'Map') {
             // If the map is not empty
             if (typeof value.value[0] !== 'undefined') {
                 /* value.value is an array of keyValue arrays
                  * e.g.
                  * [
                  *  [key1, value1],
                  *  [key2, value2],
                  *  [key3, value3],
                  * ]
                  */
                 // Iterate over each keyValue of the map
                 for (let i = 0; i < value.value.length; i += 1) {
                     const thisKeyValuePair = value.value[i]; // [key, value]
-                    let thisValue = thisKeyValuePair[1];
+                    const thisValue = thisKeyValuePair[1];
                     if (
                         thisValue &&
                         thisValue.dataType === 'BigNumberReplacer'
                     ) {
                         // If this is saved BigNumber, replace it with an actual BigNumber
                         // note, you can't use thisValue = new BigNumber(thisValue.value)
                         // Need to use this specific array entry
                         value.value[i][1] = new BigNumber(
                             value.value[i][1].value,
                         );
                     }
                 }
             }
             return new Map(value.value);
         }
         if (value.dataType === 'Set') {
             return new Set(value.value);
         }
     }
     return value;
 };
 
 /**
  * Convert a map to a key value array
  * Useful to generate test vectors by `console.log(mapToKeyValueArray(someMap))` in a function
  * @param {map} map
  * @returns array
  */
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
 export const mapToKeyValueArray = (map: Map<any, any>): Array<[any, any]> => {
-    let kvArray: Array<[any, any]> = [];
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
+    const kvArray: Array<[any, any]> = [];
     map.forEach((value, key) => {
         kvArray.push([key, value]);
     });
     return kvArray;
 };
 
 /**
  * Assign appropriate emoji based on a balance in satoshis
  * @param  balanceSats
  * @returns  emoji determined by thresholds set in config
  */
 export const getEmojiFromBalanceSats = (balanceSats: number): string => {
     const { whaleSats, emojis } = config;
     if (balanceSats >= whaleSats.bigWhale) {
         return emojis.bigWhale;
     }
     if (balanceSats >= whaleSats.modestWhale) {
         return emojis.modestWhale;
     }
     if (balanceSats >= whaleSats.shark) {
         return emojis.shark;
     }
     if (balanceSats >= whaleSats.swordfish) {
         return emojis.swordfish;
     }
     if (balanceSats >= whaleSats.barracuda) {
         return emojis.barracuda;
     }
     if (balanceSats >= whaleSats.octopus) {
         return emojis.octopus;
     }
     if (balanceSats >= whaleSats.piranha) {
         return emojis.piranha;
     }
     if (balanceSats >= whaleSats.crab) {
         return emojis.crab;
     }
     return emojis.shrimp;
 };
 
 /**
  * Convert an integer-stored number with known decimals into a formatted decimal string
  * Useful for converting token send quantities to a human-readable string
  * @param {string} bnString an integer value as a string, e.g 100000012
  * @param {number} decimals // in practice 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9,
  * @returns {string} e.g. 1,000,000.12
  */
 export const bigNumberAmountToLocaleString = (
     bnString: string,
     decimals: number,
 ): string => {
     const totalLength = bnString.length;
 
     // Get the values that come after the decimal place
     const decimalValues = decimals === 0 ? '' : bnString.slice(-1 * decimals);
     const decimalLength = decimalValues.length;
 
     // Get the values that come before the decimal place
     const intValue = bnString.slice(0, totalLength - decimalLength);
 
     // Use toLocaleString() to format the amount before the decimal place with commas
     return `${BigInt(intValue).toLocaleString('en-US', {
         maximumFractionDigits: 0,
     })}${decimals !== 0 ? `.${decimalValues}` : ''}`;
 };
 
 /**
  * Determine if an OP_RETURN's hex values include characters outside of printable ASCII range
  * @param {string} hexString hex string containing an even number of characters
  */
 export const containsOnlyPrintableAscii = (hexString: string): boolean => {
     if (hexString.length % 2 !== 0) {
         // If hexString has an odd number of characters, it is certainly not ascii
         return false;
     }
 
     // Values lower than 32 are control characters (127 also control char)
     // We could tolerate LF and CR which are in this range, but they make
     // the msg awkward in Telegram -- so they are left out
     const MIN_ASCII_PRINTABLE_DECIMAL = 32;
     const MAX_ASCII_PRINTABLE_DECIMAL = 126;
     const stack = { remainingHex: hexString };
 
     while (stack.remainingHex.length > 0) {
         const thisByte = parseInt(consume(stack, 1), 16);
 
         if (
             thisByte > MAX_ASCII_PRINTABLE_DECIMAL ||
             thisByte < MIN_ASCII_PRINTABLE_DECIMAL
         ) {
             return false;
         }
     }
     return true;
 };
 
 interface StakingRewardApiResponse {
     previousBlockHash: string;
     nextBlockHeight: number;
     address: string;
     minimumValue: number;
     scriptHex: string;
 }
 /**
  * Get the expected next staking reward winner and store it in the memory
  * cache if the returned value targets the expected next block height.
  * @param {number} nextBlockHeight The next block height
  * @param {object} memoryCache The cache to store the result
  */
 export const getNextStakingReward = async (
     nextBlockHeight: number,
     memoryCache: MemoryCache,
 ): Promise<boolean> => {
     let retries = 10;
 
     while (retries > 0) {
         try {
             const nextStakingReward: StakingRewardApiResponse = (
                 await axios.get(config.stakingRewardApiUrl)
             ).data;
 
             if (nextStakingReward.nextBlockHeight === nextBlockHeight) {
                 const { address, scriptHex } = nextStakingReward;
 
                 const cachedObject: { scriptHex: string; address?: string } = {
                     scriptHex: scriptHex,
                 };
 
                 // Note: address can be undefined
                 if (typeof address !== 'undefined') {
                     cachedObject.address = address;
                 }
 
                 memoryCache.set(`${nextBlockHeight}`, cachedObject);
 
                 return true;
             }
         } catch (err) {
             // Fallthrough
+            console.error(`Error in getting next staking reward`, err);
         }
 
         retries -= 1;
 
         // Wait for 2 seconds before retrying
         await new Promise(resolve => setTimeout(resolve, 2000));
     }
 
     console.log(
         `Failed to fetch the expected staking reward for block ${nextBlockHeight}`,
     );
 
     return false;
 };
diff --git a/apps/ecash-herald/test/chronikWsHandler.test.ts b/apps/ecash-herald/test/chronikWsHandler.test.ts
index 348f42ec3..743f6965b 100644
--- a/apps/ecash-herald/test/chronikWsHandler.test.ts
+++ b/apps/ecash-herald/test/chronikWsHandler.test.ts
@@ -1,407 +1,407 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 import assert from 'assert';
 import config from '../config';
 import cashaddr from 'ecashaddrjs';
 import unrevivedBlock from './mocks/block';
 import { jsonReviver, getCoingeckoApiUrl } from '../src/utils';
 import { blockInvalidedTgMsg } from './mocks/blockInvalidated';
 import {
     initializeWebsocket,
     parseWebsocketMessage,
 } from '../src/chronikWsHandler';
 import { MockChronikClient } from '../../../modules/mock-chronik-client';
 import { MockTelegramBot, mockChannelId } from './mocks/telegramBotMock';
 import axios from 'axios';
 import MockAdapter from 'axios-mock-adapter';
 import { caching, MemoryCache } from 'cache-manager';
 import { WsMsgClient } from 'chronik-client';
 import { StoredMock } from '../src/events';
 const block: StoredMock = JSON.parse(
     JSON.stringify(unrevivedBlock),
     jsonReviver,
 );
 
 describe('ecash-herald chronikWsHandler.js', async function () {
     let memoryCache: MemoryCache;
     before(async () => {
         const CACHE_TTL = config.cacheTtlMsecs;
         memoryCache = await caching('memory', {
             max: 100,
             ttl: CACHE_TTL,
         });
     });
     it('initializeWebsocket returns expected websocket object for a p2pkh address', async function () {
         // Initialize chronik mock
         const mockedChronik = new MockChronikClient();
         const telegramBot = new MockTelegramBot();
         const channelId = mockChannelId;
 
         const result = await initializeWebsocket(
             mockedChronik,
             telegramBot,
             channelId,
             memoryCache,
         );
 
         // Confirm websocket opened
         assert.strictEqual(mockedChronik.wsWaitForOpenCalled, true);
         // Confirm subscribed to blocks
         assert.deepEqual(result.subs.blocks, true);
     });
     it('initializeWebsocket returns expected websocket object for a p2sh address', async function () {
         // Initialize chronik mock
         const mockedChronik = new MockChronikClient();
         const telegramBot = new MockTelegramBot();
         const channelId = mockChannelId;
 
         const result = await initializeWebsocket(
             mockedChronik,
             telegramBot,
             channelId,
             memoryCache,
         );
 
         // Confirm websocket opened
         assert.strictEqual(mockedChronik.wsWaitForOpenCalled, true);
         // Confirm subscribed to blocks
         assert.deepEqual(result.subs.blocks, true);
     });
     it('parseWebsocketMessage returns false for a msg other than BLK_CONNECTED, BLK_FINALIZED or BLK_INVALIDATED', async function () {
         // Initialize chronik mock
         const mockedChronik = new MockChronikClient();
 
         const thisBlock = block;
 
         // Tell mockedChronik what response we expect for chronik.block(thisBlockHash)
         mockedChronik.setTxHistoryByBlock(
             thisBlock.parsedBlock.height,
             thisBlock.blockTxs,
         );
 
         const telegramBot = new MockTelegramBot();
         const channelId = mockChannelId;
 
         const unsupportedWebsocketMsgs = [
             {
                 msgType: 'BLK_DISCONNECTED',
             },
         ];
 
         for (let i = 0; i < unsupportedWebsocketMsgs.length; i += 1) {
             const thisUnsupportedMsg = unsupportedWebsocketMsgs[i];
             const result = await parseWebsocketMessage(
                 mockedChronik,
                 thisUnsupportedMsg as WsMsgClient,
                 telegramBot,
                 channelId,
                 memoryCache,
             );
 
             // Check that sendMessage was not called
             assert.strictEqual(telegramBot.messageSent, false);
 
             assert.deepEqual(result, false);
         }
     });
     it('parseWebsocketMessage creates and sends a telegram msg with prices and token send info for mocked block on successful API calls', async function () {
         // Initialize chronik mock
         const mockedChronik = new MockChronikClient();
 
         const thisBlock = block;
 
         // Tell mockedChronik what response we expect for chronik.block(thisBlockHash)
         mockedChronik.setTxHistoryByBlock(
             thisBlock.parsedBlock.height,
             thisBlock.blockTxs,
         );
 
         // Tell mockedChronik what response we expect for chronik.script(type, hash).utxos
         const { outputScriptInfoMap } = thisBlock;
         outputScriptInfoMap.forEach((info, outputScript) => {
-            let { type, hash } =
+            const { type, hash } =
                 cashaddr.getTypeAndHashFromOutputScript(outputScript);
             const { utxos } = info;
             mockedChronik.setScript(type, hash);
             mockedChronik.setUtxos(type, hash, { outputScript, utxos });
         });
 
         // Tell mockedChronik what response we expect for chronik.tx
         const { parsedBlock, tokenInfoMap } = thisBlock;
         const { tokenIds } = parsedBlock;
         // Will only have chronik call if the set is not empty
         if (tokenIds.size > 0) {
             // Instead of saving all the chronik responses as mocks, which would be very large
             // Just set them as mocks based on tokenInfoMap, which contains the info we need
             tokenIds.forEach(tokenId => {
                 mockedChronik.setMock('token', {
                     input: tokenId,
                     output: {
                         genesisInfo: tokenInfoMap.get(tokenId),
                     },
                 });
             });
         }
         const thisBlockExpectedMsgs = thisBlock.blockSummaryTgMsgs;
 
         // Mock a chronik websocket msg of correct format
         const mockWsMsg = {
             msgType: 'BLK_FINALIZED',
             blockHash: thisBlock.parsedBlock.hash,
             blockHeight: thisBlock.parsedBlock.height,
         };
         const telegramBot = new MockTelegramBot();
         const channelId = mockChannelId;
 
         // Mock coingecko price response
         // onNoMatch: 'throwException' helps to debug if mock is not being used
         const mock = new MockAdapter(axios, {
             onNoMatch: 'throwException',
         });
 
         const mockResult = thisBlock.coingeckoResponse;
 
         // Mock a successful API request
         mock.onGet(getCoingeckoApiUrl(config)).reply(200, mockResult);
 
         // Mock a successful staking reward API request
         mock.onGet(config.stakingRewardApiUrl).reply(200, {
             nextBlockHeight: thisBlock.parsedBlock.height + 1,
             scriptHex: thisBlock.blockTxs[0].outputs[2].outputScript,
             address: cashaddr.encodeOutputScript(
                 thisBlock.blockTxs[0].outputs[2].outputScript,
             ),
         });
 
         const result = await parseWebsocketMessage(
             mockedChronik,
             mockWsMsg as WsMsgClient,
             telegramBot,
             channelId,
             memoryCache,
         );
 
         // Build expected array of successful msg returns
-        let msgSuccessArray = [];
+        const msgSuccessArray = [];
         for (let i = 0; i < thisBlockExpectedMsgs.length; i += 1) {
             msgSuccessArray.push({
                 success: true,
                 channelId,
                 msg: thisBlockExpectedMsgs[i],
                 options: config.tgMsgOptions,
             });
         }
 
         // Check that the correct msg info was sent
         assert.deepEqual(result, msgSuccessArray);
     });
     it('parseWebsocketMessage creates and sends a telegram msg without prices or token send info for mocked block on failed API calls', async function () {
         // Initialize chronik mock with successful blockTxs call
         const mockedChronik = new MockChronikClient();
 
         const thisBlock = block;
 
         // Tell mockedChronik what response we expect for chronik.block(thisBlockHash)
         mockedChronik.setTxHistoryByBlock(
             thisBlock.parsedBlock.height,
             thisBlock.blockTxs,
         );
 
         // Tell mockedChronik what response we expect for chronik.tx
         const { parsedBlock, tokenInfoMap } = thisBlock;
         const { tokenIds } = parsedBlock;
         // Will only have chronik call if the set is not empty
         if (tokenIds.size > 0) {
             // Instead of saving all the chronik responses as mocks, which would be very large
             // Just set them as mocks based on tokenInfoMap, which contains the info we need
             let index = 0;
             tokenIds.forEach(tokenId => {
                 // If this is the first one, set an error response
                 if (index === 0) {
                     mockedChronik.setMock('token', {
                         input: tokenId,
                         output: new Error('some error'),
                     });
                 } else {
                     index += 1;
                     mockedChronik.setMock('tx', {
                         input: tokenId,
                         output: {
                             genesisInfo: tokenInfoMap.get(tokenId),
                         },
                     });
                 }
             });
         }
         const thisBlockExpectedMsgs = thisBlock.blockSummaryTgMsgsApiFailure;
 
         // Mock a chronik websocket msg of correct format
         const mockWsMsg = {
             msgType: 'BLK_FINALIZED',
             blockHash: thisBlock.parsedBlock.hash,
             blockHeight: thisBlock.parsedBlock.height,
         };
         const telegramBot = new MockTelegramBot();
         const channelId = mockChannelId;
 
         // Mock coingecko price response
         // onNoMatch: 'throwException' helps to debug if mock is not being used
         const mock = new MockAdapter(axios, {
             onNoMatch: 'throwException',
         });
 
         // Mock a failed API request
         mock.onGet(getCoingeckoApiUrl(config)).reply(500, { error: 'error' });
 
         // Mock a successful staking reward API request
         mock.onGet(config.stakingRewardApiUrl).reply(200, {
             nextBlockHeight: thisBlock.parsedBlock.height + 1,
             scriptHex: thisBlock.blockTxs[0].outputs[2].outputScript,
             address: cashaddr.encodeOutputScript(
                 thisBlock.blockTxs[0].outputs[2].outputScript,
             ),
         });
 
         const result = await parseWebsocketMessage(
             mockedChronik,
             mockWsMsg as WsMsgClient,
             telegramBot,
             channelId,
             memoryCache,
         );
 
         // Build expected array of successful msg returns
-        let msgSuccessArray = [];
+        const msgSuccessArray = [];
         for (let i = 0; i < thisBlockExpectedMsgs.length; i += 1) {
             msgSuccessArray.push({
                 success: true,
                 channelId,
                 msg: thisBlockExpectedMsgs[i],
                 options: config.tgMsgOptions,
             });
         }
 
         // Check that sendMessage was called successfully
         assert.strictEqual(telegramBot.messageSent, true);
 
         // Check that the correct msg info was sent
         assert.deepEqual(result, msgSuccessArray);
     });
     it('parseWebsocketMessage returns false if telegram msg fails to send', async function () {
         // Initialize chronik mock with successful blockTxs call
         const mockedChronik = new MockChronikClient();
 
         const thisBlock = block;
 
         // Tell mockedChronik what response we expect for chronik.block(thisBlockHash)
         mockedChronik.setTxHistoryByBlock(
             thisBlock.parsedBlock.height,
             thisBlock.blockTxs,
         );
 
         // Tell mockedChronik what response we expect for chronik.tx
         const { parsedBlock, tokenInfoMap } = thisBlock;
         const { tokenIds } = parsedBlock;
         // Will only have chronik call if the set is not empty
         if (tokenIds.size > 0) {
             // Instead of saving all the chronik responses as mocks, which would be very large
             // Just set them as mocks based on tokenInfoMap, which contains the info we need
             let index = 0;
             tokenIds.forEach(tokenId => {
                 // If this is the first one, set an error response
                 if (index === 0) {
                     mockedChronik.setMock('token', {
                         input: tokenId,
                         output: new Error('some error'),
                     });
                 } else {
                     index += 1;
                     mockedChronik.setMock('token', {
                         input: tokenId,
                         output: {
                             genesisInfo: tokenInfoMap.get(tokenId),
                         },
                     });
                 }
             });
         }
 
         // Mock a chronik websocket msg of correct format
         const mockWsMsg = {
             type: 'BLK_FINALIZED',
             blockHash: thisBlock.parsedBlock.hash,
             blockHeight: thisBlock.parsedBlock.height,
         };
         const telegramBot = new MockTelegramBot();
         telegramBot.setExpectedError(
             'sendMessage',
             'Error: message failed to send',
         );
         const channelId = mockChannelId;
 
         // Mock a successful staking reward API request
         const mock = new MockAdapter(axios, {
             onNoMatch: 'throwException',
         });
         mock.onGet(config.stakingRewardApiUrl).reply(200, {
             nextBlockHeight: thisBlock.parsedBlock.height + 1,
             scriptHex: thisBlock.blockTxs[0].outputs[2].outputScript,
             address: cashaddr.encodeOutputScript(
                 thisBlock.blockTxs[0].outputs[2].outputScript,
             ),
         });
 
         const result = await parseWebsocketMessage(
             mockedChronik,
             mockWsMsg as WsMsgClient,
             telegramBot,
             channelId,
             memoryCache,
         );
 
         // Check that the function returns false
         assert.strictEqual(result, false);
     });
     it('parseWebsocketMessage creates and sends a telegram msg for invalidated blocks', async function () {
         // Initialize chronik mock
         const mockedChronik = new MockChronikClient();
 
         const thisBlock = block;
 
         // Mock a chronik websocket msg of correct format
         const mockWsMsg = {
             msgType: 'BLK_INVALIDATED',
             blockHash: thisBlock.blockTxs[0].block!.hash,
             blockHeight: thisBlock.blockTxs[0].block!.height,
             blockTimestamp: thisBlock.blockTxs[0].block!.timestamp,
             coinbaseData: {
                 scriptsig: thisBlock.blockTxs[0].inputs[0].inputScript,
                 outputs: thisBlock.blockTxs[0].outputs,
             },
         };
         const telegramBot = new MockTelegramBot();
         const channelId = mockChannelId;
 
         const result = await parseWebsocketMessage(
             mockedChronik,
             mockWsMsg as WsMsgClient,
             telegramBot,
             channelId,
             memoryCache,
         );
 
         assert.strictEqual(telegramBot.messageSent, true);
 
-        let msgSuccess = {
+        const msgSuccess = {
             success: true,
             channelId,
             msg: blockInvalidedTgMsg,
             options: config.tgMsgOptions,
         };
 
         // Check that the correct msg info was sent
         assert.deepEqual(result, msgSuccess);
     });
 });
diff --git a/apps/ecash-herald/test/events.test.ts b/apps/ecash-herald/test/events.test.ts
index e3ab06610..4c04b28a4 100644
--- a/apps/ecash-herald/test/events.test.ts
+++ b/apps/ecash-herald/test/events.test.ts
@@ -1,342 +1,342 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 import assert from 'assert';
 import config from '../config';
 import unrevivedBlock from './mocks/block';
 import { jsonReviver, getCoingeckoApiUrl } from '../src/utils';
 import { blockInvalidedTgMsg } from './mocks/blockInvalidated';
 import cashaddr from 'ecashaddrjs';
 import {
     handleBlockFinalized,
     handleBlockInvalidated,
     StoredMock,
 } from '../src/events';
 import { MockChronikClient } from '../../../modules/mock-chronik-client';
 import { MockTelegramBot, mockChannelId } from './mocks/telegramBotMock';
 import axios from 'axios';
 import MockAdapter from 'axios-mock-adapter';
 import { caching, MemoryCache } from 'cache-manager';
-import FakeTimers from '@sinonjs/fake-timers';
+import FakeTimers, { InstalledClock } from '@sinonjs/fake-timers';
 const block: StoredMock = JSON.parse(
     JSON.stringify(unrevivedBlock),
     jsonReviver,
 );
 
 describe('ecash-herald events.js', async function () {
     let memoryCache: MemoryCache;
     before(async () => {
         const CACHE_TTL = config.cacheTtlMsecs;
         memoryCache = await caching('memory', {
             max: 100,
             ttl: CACHE_TTL,
         });
     });
 
-    let clock: any;
+    let clock: InstalledClock;
     beforeEach(() => {
         clock = FakeTimers.install();
     });
     afterEach(() => {
         // Restore timers
         clock.uninstall();
     });
     it('handleBlockFinalized creates and sends a telegram msg with price and token send info for mocked block if api call succeeds', async function () {
         // Initialize chronik mock
         const mockedChronik = new MockChronikClient();
 
         const thisBlock = block;
 
         // Tell mockedChronik what response we expect for chronik.block(thisBlockHash)
         mockedChronik.setTxHistoryByBlock(
             thisBlock.parsedBlock.height,
             thisBlock.blockTxs,
         );
 
         // Tell mockedChronik what response we expect for chronik.script(type, hash).utxos
         const { outputScriptInfoMap } = thisBlock;
         outputScriptInfoMap.forEach((info, outputScript) => {
-            let { type, hash } =
+            const { type, hash } =
                 cashaddr.getTypeAndHashFromOutputScript(outputScript);
             const { utxos } = info;
             mockedChronik.setScript(type, hash);
             mockedChronik.setUtxos(type, hash, { outputScript, utxos });
         });
 
         // Tell mockedChronik what response we expect for chronik.tx
         const { parsedBlock, tokenInfoMap } = thisBlock;
         const { tokenIds } = parsedBlock;
         // Will only have chronik call if the set is not empty
         if (tokenIds.size > 0) {
             // Instead of saving all the chronik responses as mocks, which would be very large
             // Just set them as mocks based on tokenInfoMap, which contains the info we need
             tokenIds.forEach(tokenId => {
                 mockedChronik.setMock('token', {
                     input: tokenId,
                     output: {
                         genesisInfo: tokenInfoMap.get(tokenId),
                     },
                 });
             });
         }
 
         const thisBlockExpectedMsgs = thisBlock.blockSummaryTgMsgs;
 
         const telegramBot = new MockTelegramBot();
         const channelId = mockChannelId;
 
         // Mock coingecko price response
         // onNoMatch: 'throwException' helps to debug if mock is not being used
         const mock = new MockAdapter(axios, {
             onNoMatch: 'throwException',
         });
 
         const mockResult = thisBlock.coingeckoResponse;
 
         // Mock a successful API request
         mock.onGet(getCoingeckoApiUrl(config)).reply(200, mockResult);
 
         const result = await handleBlockFinalized(
             mockedChronik,
             telegramBot,
             channelId,
             thisBlock.parsedBlock.hash,
             thisBlock.parsedBlock.height,
             memoryCache,
         );
 
         // Check that sendMessage was called successfully
         assert.strictEqual(telegramBot.messageSent, true);
 
         // Build expected array of successful msg returns
-        let msgSuccessArray = [];
+        const msgSuccessArray = [];
         for (let i = 0; i < thisBlockExpectedMsgs.length; i += 1) {
             msgSuccessArray.push({
                 success: true,
                 channelId,
                 msg: thisBlockExpectedMsgs[i],
                 options: config.tgMsgOptions,
             });
         }
 
         // Check that the correct msg info was sent
         assert.deepEqual(result, msgSuccessArray);
     });
     it('handleBlockFinalized creates and sends a telegram msg without price or token info for mocked block if api calls fail', async function () {
         // Initialize chronik mock
         const mockedChronik = new MockChronikClient();
 
         const thisBlock = block;
 
         // Tell mockedChronik what response we expect for chronik.block(thisBlockHash)
         mockedChronik.setTxHistoryByBlock(
             thisBlock.parsedBlock.height,
             thisBlock.blockTxs,
         );
 
         // Tell mockedChronik what response we expect for chronik.tx
         const { parsedBlock, tokenInfoMap } = thisBlock;
         const { tokenIds } = parsedBlock;
         // Will only have chronik call if the set is not empty
         if (tokenIds.size > 0) {
             // Instead of saving all the chronik responses as mocks, which would be very large
             // Just set them as mocks based on tokenInfoMap, which contains the info we need
             let index = 0;
             tokenIds.forEach(tokenId => {
                 // If this is the first one, set an error response
                 if (index === 0) {
                     mockedChronik.setMock('token', {
                         input: tokenId,
                         output: new Error('some error'),
                     });
                 } else {
                     index += 1;
                     mockedChronik.setMock('token', {
                         input: tokenId,
                         output: {
                             genesisInfo: tokenInfoMap.get(tokenId),
                         },
                     });
                 }
             });
         }
         const thisBlockExpectedMsgs = thisBlock.blockSummaryTgMsgsApiFailure;
 
         const telegramBot = new MockTelegramBot();
         const channelId = mockChannelId;
 
         // Mock coingecko price response
         // onNoMatch: 'throwException' helps to debug if mock is not being used
         const mock = new MockAdapter(axios, {
             onNoMatch: 'throwException',
         });
 
         // Mock a failed API request
         mock.onGet(getCoingeckoApiUrl(config)).reply(500, { error: 'error' });
 
         const result = await handleBlockFinalized(
             mockedChronik,
             telegramBot,
             channelId,
             thisBlock.parsedBlock.hash,
             thisBlock.parsedBlock.height,
             memoryCache,
         );
 
         // Check that sendMessage was called successfully
         assert.strictEqual(telegramBot.messageSent, true);
 
         // Build expected array of successful msg returns
-        let msgSuccessArray = [];
+        const msgSuccessArray = [];
         for (let i = 0; i < thisBlockExpectedMsgs.length; i += 1) {
             msgSuccessArray.push({
                 success: true,
                 channelId,
                 msg: thisBlockExpectedMsgs[i],
                 options: config.tgMsgOptions,
             });
         }
 
         // Check that the correct msg info was sent
         assert.deepEqual(result, msgSuccessArray);
     });
     it('handleBlockFinalized sends desired backup msg if it encounters an error in message creation', async function () {
         // Initialize chronik mock
         const mockedChronik = new MockChronikClient();
 
         const thisBlock = block;
 
         // Tell mockedChronik what response we expect for chronik.block(thisBlockHash)
         mockedChronik.setTxHistoryByBlock(
             thisBlock.parsedBlock.height,
             new Error('error getting block'),
         );
 
         const telegramBot = new MockTelegramBot();
         const channelId = mockChannelId;
 
         const result = await handleBlockFinalized(
             mockedChronik,
             telegramBot,
             channelId,
             thisBlock.parsedBlock.hash,
             thisBlock.parsedBlock.height,
             memoryCache,
         );
 
         // Check that sendMessage was called successfully
         assert.strictEqual(telegramBot.messageSent, true);
 
         // Expect the backup msg
         const expectedMsg = `New Block Found\n\n${thisBlock.parsedBlock.height.toLocaleString(
             'en-US',
         )}\n\n${
             thisBlock.parsedBlock.hash
         }\n\n<a href="https://explorer.e.cash/block/${
             thisBlock.parsedBlock.hash
         }">explorer</a>`;
 
         // Check that the correct msg info was sent
         assert.deepEqual(result, {
             success: true,
             channelId,
             msg: expectedMsg,
             options: config.tgMsgOptions,
         });
     });
     it('handleBlockFinalized returns false if it encounters an error in telegram bot sendMessage routine', async function () {
         // Initialize chronik mock
         const mockedChronik = new MockChronikClient();
 
         const thisBlock = block;
 
         // Tell mockedChronik what response we expect for chronik.block(thisBlockHash)
         mockedChronik.setTxHistoryByBlock(
             thisBlock.parsedBlock.height,
             thisBlock.blockTxs,
         );
 
         // Tell mockedChronik what response we expect for chronik.token
         const { parsedBlock, tokenInfoMap } = thisBlock;
         const { tokenIds } = parsedBlock;
         // Will only have chronik call if the set is not empty
         if (tokenIds.size > 0) {
             // Instead of saving all the chronik responses as mocks, which would be very large
             // Just set them as mocks based on tokenInfoMap, which contains the info we need
             let index = 0;
             tokenIds.forEach(tokenId => {
                 // If this is the first one, set an error response
                 if (index === 0) {
                     mockedChronik.setMock('token', {
                         input: tokenId,
                         output: new Error('some error'),
                     });
                 } else {
                     index += 1;
                     mockedChronik.setMock('token', {
                         input: tokenId,
                         output: {
                             genesisInfo: tokenInfoMap.get(tokenId),
                         },
                     });
                 }
             });
         }
 
         const telegramBot = new MockTelegramBot();
         telegramBot.setExpectedError(
             'sendMessage',
             'Error: message failed to send',
         );
         const channelId = mockChannelId;
 
         const result = await handleBlockFinalized(
             mockedChronik,
             telegramBot,
             channelId,
             thisBlock.parsedBlock.hash,
             thisBlock.parsedBlock.height,
             memoryCache,
         );
 
         // Check that the correct msg info was sent
         assert.deepEqual(result, false);
     });
     it('handleBlockInvalidated creates and sends a telegram msg upon invalidated blocks', async function () {
         // Initialize chronik mock
         const mockedChronik = new MockChronikClient();
 
         const thisBlock = block;
 
         const telegramBot = new MockTelegramBot();
         const channelId = mockChannelId;
 
         const result = await handleBlockInvalidated(
             mockedChronik,
             telegramBot,
             channelId,
             thisBlock.blockTxs[0].block!.hash,
             thisBlock.blockTxs[0].block!.height,
             thisBlock.blockTxs[0].block!.timestamp,
             {
                 scriptsig: thisBlock.blockTxs[0].inputs[0].inputScript,
                 outputs: thisBlock.blockTxs[0].outputs,
             },
             memoryCache,
         );
 
         // Check that sendMessage was called successfully
         assert.strictEqual(telegramBot.messageSent, true);
 
-        let msgSuccess = {
+        const msgSuccess = {
             success: true,
             channelId,
             msg: blockInvalidedTgMsg,
             options: config.tgMsgOptions,
         };
 
         // Check that the correct msg info was sent
         assert.deepEqual(result, msgSuccess);
     });
 });
diff --git a/apps/ecash-herald/test/mocks/appTxSamples.ts b/apps/ecash-herald/test/mocks/appTxSamples.ts
index 3a073032a..8576802d8 100644
--- a/apps/ecash-herald/test/mocks/appTxSamples.ts
+++ b/apps/ecash-herald/test/mocks/appTxSamples.ts
@@ -1,734 +1,733 @@
-// Copyright (c) 2023 The Bitcoin developers
+// Copyright (c) 2024 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
-// Disable as these are "used" to match the expected tg format
-/* eslint no-useless-escape: 0 */
+
 import { GenesisInfo } from 'chronik-client';
 import opReturn from '../../constants/op_return';
 import { CoinGeckoPrice } from '../../src/utils';
 
 interface SwapMock {
     hex: string;
     msg: string;
     stackArray: string[];
     tokenId: false | string;
     tokenInfo: false | GenesisInfo;
 }
 
 type RecipientEntry = [string, number];
 
 // Define the type for the entire array
 type RecipientsArray = RecipientEntry[];
 interface AirdropMock {
     txid: string;
     hex: string;
     stackArray: string[];
     airdropSendingAddress: string;
     airdropRecipientsKeyValueArray: RecipientsArray;
     tokenId: false | string;
     tokenInfo: false | GenesisInfo;
     coingeckoPrices: CoinGeckoPrice[];
     msg: string;
     msgApiFailure: string;
 }
 
 interface CashtabMsgMock {
     txid: string;
     hex: string;
     stackArray: string[];
     msg: string;
 }
 interface EncryptedCashtabMsgMock {
     txid: string;
     hex: string;
     sendingAddress: string;
     xecReceivingOutputsKeyValueArray: RecipientsArray;
     stackArray: string[];
     coingeckoPrices: CoinGeckoPrice[];
     msg: string;
     msgApiFailure: string;
 }
 interface SlpTwoPushVector {
     push: string;
     msg: string;
 }
 interface SlpTwoTxVector {
     txid: string;
     hex: string;
     emppStackArray: string[];
     msg: string;
 }
 interface AliasRegistrationVector {
     txid: string;
     hex: string;
     stackArray: string[];
     msg: string;
 }
 interface PayButtonTx {
     txid: string;
     hex: string;
     stackArray: string[];
     msg: string;
 }
 interface PaywallTxVector {
     txid: string;
     hex: string;
     stackArray: string[];
     msg: string;
 }
 interface AuthTxVector {
     txid: string;
     hex: string;
     stackArray: string[];
     msg: string;
 }
 interface AppTxSamples {
     swaps: SwapMock[];
     airdrops: AirdropMock[];
     cashtabMsgs: CashtabMsgMock[];
     encryptedCashtabMsgs: EncryptedCashtabMsgMock[];
     slp2PushVectors: SlpTwoPushVector[];
     slp2TxVectors: SlpTwoTxVector[];
     aliasRegistrations: AliasRegistrationVector[];
     payButtonTxs: PayButtonTx[];
     paywallTxs: PaywallTxVector[];
     authenticationTxs: AuthTxVector[];
 }
 
 const BASE_GENESIS_INFO: GenesisInfo = {
     tokenName: 'test',
     tokenTicker: 'test',
     url: 'https://cashtab.com/',
     decimals: 0,
 };
 const appTxSamples: AppTxSamples = {
     // https://github.com/vinarmani/swap-protocol/blob/master/swap-protocol-spec.md
     swaps: [
         // 0101 https://explorer.e.cash/tx/b03883ca0b106ea5e7113d6cbe46b9ec37ac6ba437214283de2d9cf2fbdc997f
         {
             hex: '045357500001010101204de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf0453454c4c02025801002090dfb75fef5f07e384df4703b853a2741b8e6f3ef31ef8e5187a17fb107547f801010100',
             msg: 'Signal|SLP Atomic Swap|<a href="https://explorer.e.cash/tx/4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf">SPICE</a>|SELL for 6 XEC|Min trade: 0 XEC',
             stackArray: [
                 '53575000',
                 '01',
                 '01',
                 '4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf',
                 '53454c4c',
                 '0258',
                 '00',
                 '90dfb75fef5f07e384df4703b853a2741b8e6f3ef31ef8e5187a17fb107547f8',
                 '01',
                 '00',
             ],
             tokenId:
                 '4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf',
             tokenInfo: { ...BASE_GENESIS_INFO, tokenTicker: 'SPICE' },
         },
         // 0101 ascii example https://explorer.e.cash/tx/2308e1c36d8355edd86dd7d643da41994ab780c852fdfa8d032b1a337bf18bb6
         // Sell price is hex, min price is ascii
         {
             hex: '04535750000101010120fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa0453454c4c01320100202b08df65b0b265be60fbc3346c70729d1378ddfca66da8e6645b74e26d75e61501010831303030303030300100',
             msg: `Signal|SLP Atomic Swap|<a href="https://explorer.e.cash/tx/fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa">GRP</a>|SELL for 0.5 XEC|Min trade: 100,000 XEC`,
             stackArray: [
                 '53575000',
                 '01',
                 '01',
                 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
                 '53454c4c',
                 '32',
                 '00',
                 '2b08df65b0b265be60fbc3346c70729d1378ddfca66da8e6645b74e26d75e615',
                 '01',
                 '3130303030303030', // ASCII for 10000000 or hex for 3,544,385,890,265,608,000, greater than total XEC supply
                 '00', // Unknown extra info, seems like mb they mean for this to be 0 hex as the min sell amount
             ],
             tokenId:
                 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
             tokenInfo: { ...BASE_GENESIS_INFO, tokenTicker: 'GRP' },
         },
         // 0101 ascii 2, https://explorer.e.cash/tx/dfad6b85a8f0e4b338f4f3bc67d2b7f73fb27f82b6d71ad3e2be955643fe6e42
         // Both are ascii
         {
             hex: '04535750000101010120b46c6e0a485f0fade147696e54d3b523071860fd745fbfa97a515846bd3019a60453454c4c0434343030010020c2e13f79c49f8825832f57df10985ecdd6e28253cf589ffe28e4e95ece174629010204343430300100',
             msg: 'Signal|SLP Atomic Swap|<a href="https://explorer.e.cash/tx/b46c6e0a485f0fade147696e54d3b523071860fd745fbfa97a515846bd3019a6">BTCinu</a>|SELL for 44 XEC|Min trade: 44 XEC',
             stackArray: [
                 '53575000',
                 '01',
                 '01',
                 'b46c6e0a485f0fade147696e54d3b523071860fd745fbfa97a515846bd3019a6',
                 '53454c4c',
                 '34343030', // ASCII 4400
                 '00',
                 'c2e13f79c49f8825832f57df10985ecdd6e28253cf589ffe28e4e95ece174629',
                 '02',
                 '34343030', // ASCII 4400
                 '00', // Unknown extra info, seems like mb they mean for this to be 0 hex as the min sell amount
             ],
             tokenId:
                 'b46c6e0a485f0fade147696e54d3b523071860fd745fbfa97a515846bd3019a6',
             tokenInfo: { ...BASE_GENESIS_INFO, tokenTicker: 'BTCinu' },
         },
         // 0101 ascii 3, https://explorer.e.cash/tx/e52daad4006ab27b9e103c7ca0e58bd483f8c6c377ba5075cf7f412fbb272971
         // Recent gorbeious tx
         {
             hex: '04535750000101010120aebcae9afe88d61d8b8ed7b8c83c7c2a555583bf8f8591c94a2c9eb82f34816c0453454c4c093130303030303030300100206338e4674afaa2ef153187ae774ca5e26f0f3447e4dd398c9945b467056a28cf010201000566616c7365',
             msg: 'Signal|SLP Atomic Swap|<a href="https://explorer.e.cash/tx/aebcae9afe88d61d8b8ed7b8c83c7c2a555583bf8f8591c94a2c9eb82f34816c">GORB</a>|SELL for 1,000,000 XEC|Min trade: 0 XEC',
             stackArray: [
                 '53575000',
                 '01',
                 '01',
                 'aebcae9afe88d61d8b8ed7b8c83c7c2a555583bf8f8591c94a2c9eb82f34816c',
                 '53454c4c',
                 '313030303030303030', // ASCII 100,000,000
                 '00',
                 '6338e4674afaa2ef153187ae774ca5e26f0f3447e4dd398c9945b467056a28cf',
                 '02',
                 '00', // hex 00
                 '66616c7365', // ASCII for 'false' ... does not match spec, mb used for something. Weird to do this in ASCII
             ],
             tokenId:
                 'aebcae9afe88d61d8b8ed7b8c83c7c2a555583bf8f8591c94a2c9eb82f34816c',
             tokenInfo: { ...BASE_GENESIS_INFO, tokenTicker: 'GORB' },
         },
         // 0102 https://explorer.e.cash/tx/70c2842e1b2c7eb49ee69cdecf2d6f3cd783c307c4cbeef80f176159c5891484
         // Note, this example uses faulty pushdata at the end
         {
             hex: '045357500001010102202ee326cabee15bab127baad3aadbe39f18877933ea064203de5d08bba9654e69056a65746f6e0e657363726f772d706172656a617301002102f5515a2e17826c72011f608d2e8458580ea8cbaba3128abe7f4ae2df4d51572920b6919ed649c4710799cb01e2e66bf0fdb2eccee219fd8c4775d3a85431a9984f0101222102188904278ebf33059093f596a2697cf3668b3bec9a3a0c6408a455147ab3db934c000100',
             msg: 'Signal|Multi-Party Escrow',
             stackArray: [
                 '53575000',
                 '01',
                 '02',
                 '2ee326cabee15bab127baad3aadbe39f18877933ea064203de5d08bba9654e69',
                 '6a65746f6e',
                 '657363726f772d706172656a6173',
                 '00',
                 '02f5515a2e17826c72011f608d2e8458580ea8cbaba3128abe7f4ae2df4d515729',
                 'b6919ed649c4710799cb01e2e66bf0fdb2eccee219fd8c4775d3a85431a9984f',
                 '01',
                 '2102188904278ebf33059093f596a2697cf3668b3bec9a3a0c6408a455147ab3db93',
                 '00',
             ],
             tokenId: false,
             tokenInfo: false,
         },
         // 0103 https://explorer.e.cash/tx/565c84990aacfbd006d4ed2ee14bfb0f3bb27a84a6c9adcabccb6fb8e17e64c5
         {
             hex: '0453575000010101032668747470733a2f2f7377617063726f776466756e642e636f6d2f736f6d6563616d706169676e4502a0860100000000001976a914da74026d67264c0acfede38e8302704ef7d8cfb288acf0490200000000001976a914ac656e2dd5378ca9c45fd5cd44aa7da87c7bfa8288ac',
             msg: 'Signal|Threshold Crowdfunding',
             stackArray: [
                 '53575000',
                 '01',
                 '03',
                 '68747470733a2f2f7377617063726f776466756e642e636f6d2f736f6d6563616d706169676e',
                 '02a0860100000000001976a914da74026d67264c0acfede38e8302704ef7d8cfb288acf0490200000000001976a914ac656e2dd5378ca9c45fd5cd44aa7da87c7bfa8288ac',
             ],
             tokenId: false,
             tokenInfo: false,
         },
         // 0201 | Payment - SLP Atomic Swap
         {
             hex: '045357500001020101206350c611819b7e84a2afd9611d33a98de5b3426c33561f516d49147dc1c4106b',
             msg: 'Payment|SLP Atomic Swap',
             stackArray: [
                 '53575000',
                 '02',
                 '01',
                 '6350c611819b7e84a2afd9611d33a98de5b3426c33561f516d49147dc1c4106b',
             ],
             tokenId: false,
             tokenInfo: false,
         },
         // 0202 N/A in spec, pending spotting in the wild
         // 0203 N/A in spec, pending spotting in the wild
         // Malformed swap
         {
             hex: '045357500001010105204de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf0453454c4c02025801002090dfb75fef5f07e384df4703b853a2741b8e6f3ef31ef8e5187a17fb107547f801010100',
             msg: 'Signal|Invalid SWaP',
             stackArray: [
                 '53575000',
                 '01',
                 '05', // instead of 01
                 '4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf',
                 '53454c4c',
                 '0258',
                 '00',
                 '90dfb75fef5f07e384df4703b853a2741b8e6f3ef31ef8e5187a17fb107547f8',
                 '01',
                 '00',
             ],
             tokenId: false,
             tokenInfo: { ...BASE_GENESIS_INFO, tokenTicker: 'SPICE' },
         },
         // Mod 0101 https://explorer.e.cash/tx/b03883ca0b106ea5e7113d6cbe46b9ec37ac6ba437214283de2d9cf2fbdc997f
         {
             hex: '0453575000',
             msg: 'Invalid SWaP',
             stackArray: ['53575000'],
             tokenId: false,
             tokenInfo: false,
         },
         // Mod 0101 with bad tokenId
         {
             hex: '0453575000010101011fe69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf0453454c4c02025801002090dfb75fef5f07e384df4703b853a2741b8e6f3ef31ef8e5187a17fb107547f801010100',
             msg: 'Signal|SLP Atomic Swap|Invalid tokenId|SELL for 6 XEC|Min trade: 0 XEC',
             stackArray: [
                 '53575000',
                 '01',
                 '01',
                 'e69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf', // 63 char, invalid tokenId
                 '53454c4c',
                 '0258',
                 '00',
                 '90dfb75fef5f07e384df4703b853a2741b8e6f3ef31ef8e5187a17fb107547f8',
                 '01',
                 '00',
             ],
             tokenId: false,
             tokenInfo: false,
         },
     ],
     airdrops: [
         // With a cashtab msg, non-empp
         {
             txid: 'f86c75efd60be3e46c032dfd45125f90d1730852141a7e742266473d12cad116',
             hex: '0464726f70207c06091e745037b46c5ea60def8ad526274c2caabb1fae6c4ac89fad02fedf9a04007461624643736f6e676f72206261627920686173206265656e20626f726e2e2054616b652074686973206c6974746c6520676966742066726f6d20612070726f75642066617468657221',
             stackArray: [
                 '64726f70',
                 '7c06091e745037b46c5ea60def8ad526274c2caabb1fae6c4ac89fad02fedf9a',
                 '00746162',
                 '43736f6e676f72206261627920686173206265656e20626f726e2e2054616b652074686973206c6974746c6520676966742066726f6d20612070726f75642066617468657221',
             ],
             airdropSendingAddress:
                 'ecash:qqft3ujdpn45h0phqkwdw0nnxfu8y7zm7qdwlh5yd0',
             airdropRecipientsKeyValueArray: [
                 [
                     '6a0464726f70207c06091e745037b46c5ea60def8ad526274c2caabb1fae6c4ac89fad02fedf9a04007461624643736f6e676f72206261627920686173206265656e20626f726e2e2054616b652074686973206c6974746c6520676966742066726f6d20612070726f75642066617468657221',
                     0,
                 ],
                 ['76a9142ec5281864fc989dab543b054631c9703809689e88ac', 892857],
                 ['76a914efa3a87fc4022378a5f7e8e0a5c112094f3fb9be88ac', 892857],
                 ['76a9142a6572780193dbcb3422773c2e353048805c2cb888ac', 892857],
                 ['76a914ce9650c2d64f487739798d2815ab9e0a38fe8f9b88ac', 89286],
                 ['76a91473ef17c5b9f551eae3f3b4fadf61f93cae5e6aea88ac', 89286],
                 ['76a9143efd4899993b5c6e554238187577b81ed1f6bb4188ac', 89286],
                 ['76a914198d8c7a32b750cbdbe1f97103d404f5e6a9465788ac', 892857],
                 ['76a91457499920b99c483d745f9925adf9eecbe46c583d88ac', 535714],
                 ['76a9140d17fb5b181b676fc5ed2825c0b2b25cc578f3ea88ac', 89286],
                 ['76a9142a96944d06700882bbd984761d9c9e4215f2d78e88ac', 446429],
                 ['76a91469003998c2c32ac81951b88416a9a15df3a1992988ac', 89286],
             ],
             tokenId:
                 '7c06091e745037b46c5ea60def8ad526274c2caabb1fae6c4ac89fad02fedf9a',
             tokenInfo: {
                 tokenTicker: 'ePLK',
                 tokenName: 'ePalinka',
                 url: 'http://www.hungarikum.hu/en',
                 hash: '',
                 decimals: 3,
             },
             coingeckoPrices: [
                 { fiat: 'usd', price: 0.00003333, ticker: 'XEC' },
                 { fiat: 'usd', price: 25000, ticker: 'BTC' },
                 { fiat: 'usd', price: 1900, ticker: 'ETH' },
             ],
             msg: 'qqf...yd0 airdropped $2 to 12 holders of <a href="https://explorer.e.cash/tx/7c06091e745037b46c5ea60def8ad526274c2caabb1fae6c4ac89fad02fedf9a">ePLK</a>|Csongor baby has been born. Take this little gift from a proud father!',
             msgApiFailure:
                 'qqf...yd0 airdropped 50k XEC to 12 holders of <a href="https://explorer.e.cash/tx/7c06091e745037b46c5ea60def8ad526274c2caabb1fae6c4ac89fad02fedf9a">7c0...f9a</a>|Csongor baby has been born. Take this little gift from a proud father!',
         },
         // no cashtab msg, non-empp
         {
             txid: '4403b0cc00ca159b64f219a7cc7cccd2e4440ddecbbcb6a0b82e78e350f8f72e',
             hex: '0464726f70201c6c9c64d70b285befe733f175d0f384538576876bd280b10587df81279d3f5e0400746162',
             stackArray: [
                 '64726f70',
                 '1c6c9c64d70b285befe733f175d0f384538576876bd280b10587df81279d3f5e',
                 '00746162', // prefix for msg is there but no msg
             ],
             airdropSendingAddress:
                 'ecash:qrmz0egsqxj35x5jmzf8szrszdeu72fx0uxgwk3r48',
             airdropRecipientsKeyValueArray: [
                 [
                     '6a0464726f70201c6c9c64d70b285befe733f175d0f384538576876bd280b10587df81279d3f5e0400746162',
                     0,
                 ],
                 ['76a9147ab07df481649eb27c7ad9afda52b2a93d2f722a88ac', 2000],
                 ['76a9149846b6b38ff713334ac19fe3cf851a1f98c07b0088ac', 1000],
                 ['76a914b82361c5851f4ec48b995175a2e1c3646338e07688ac', 2000],
             ],
             tokenId:
                 '1c6c9c64d70b285befe733f175d0f384538576876bd280b10587df81279d3f5e',
             tokenInfo: {
                 tokenTicker: 'DET',
                 tokenName: 'Dividend eToken',
                 url: 'https://cashtab.com/',
                 hash: '',
                 decimals: 8,
             },
             coingeckoPrices: [
                 { fiat: 'usd', price: 0.00003333, ticker: 'XEC' },
                 { fiat: 'usd', price: 25000, ticker: 'BTC' },
                 { fiat: 'usd', price: 1900, ticker: 'ETH' },
             ],
             msg: 'qrm...r48 airdropped $0.002 to 4 holders of <a href="https://explorer.e.cash/tx/1c6c9c64d70b285befe733f175d0f384538576876bd280b10587df81279d3f5e">DET</a>',
             msgApiFailure:
                 'qrm...r48 airdropped 50 XEC to 4 holders of <a href="https://explorer.e.cash/tx/1c6c9c64d70b285befe733f175d0f384538576876bd280b10587df81279d3f5e">1c6...f5e</a>',
         },
         // Token id is not 64 char
         {
             txid: 'mod of 4403b0cc00ca159b64f219a7cc7cccd2e4440ddecbbcb6a0b82e78e350f8f72e',
             hex: '0464726f701f6c9c64d70b285befe733f175d0f384538576876bd280b10587df81279d3f5e0400746162',
             stackArray: [
                 '64726f70',
                 '6c9c64d70b285befe733f175d0f384538576876bd280b10587df81279d3f5e', // 63 chars
                 '00746162', // prefix for msg is there but no msg
             ],
             airdropSendingAddress:
                 'ecash:qrmz0egsqxj35x5jmzf8szrszdeu72fx0uxgwk3r48',
             airdropRecipientsKeyValueArray: [
                 [
                     '6a0464726f701f6c9c64d70b285befe733f175d0f384538576876bd280b10587df81279d3f5e0400746162',
                     0,
                 ],
                 ['76a9147ab07df481649eb27c7ad9afda52b2a93d2f722a88ac', 2000],
                 ['76a9149846b6b38ff713334ac19fe3cf851a1f98c07b0088ac', 1000],
                 ['76a914b82361c5851f4ec48b995175a2e1c3646338e07688ac', 2000],
             ],
             tokenId: false,
             tokenInfo: false,
             coingeckoPrices: [
                 { fiat: 'usd', price: 0.00003333, ticker: 'XEC' },
                 { fiat: 'usd', price: 25000, ticker: 'BTC' },
                 { fiat: 'usd', price: 1900, ticker: 'ETH' },
             ],
             msg: 'Invalid Airdrop',
             msgApiFailure: 'Invalid Airdrop',
         },
         // No stackArray[1]
         {
             txid: 'mod of 4403b0cc00ca159b64f219a7cc7cccd2e4440ddecbbcb6a0b82e78e350f8f72e',
             hex: '0464726f70',
             stackArray: ['64726f70'],
             airdropSendingAddress:
                 'ecash:qrmz0egsqxj35x5jmzf8szrszdeu72fx0uxgwk3r48',
             airdropRecipientsKeyValueArray: [
                 ['6a0464726f70', 0],
                 ['76a9147ab07df481649eb27c7ad9afda52b2a93d2f722a88ac', 2000],
                 ['76a9149846b6b38ff713334ac19fe3cf851a1f98c07b0088ac', 1000],
                 ['76a914b82361c5851f4ec48b995175a2e1c3646338e07688ac', 2000],
             ],
             tokenId: false,
             tokenInfo: false,
             coingeckoPrices: [
                 { fiat: 'usd', price: 0.00003333, ticker: 'XEC' },
                 { fiat: 'usd', price: 25000, ticker: 'BTC' },
                 { fiat: 'usd', price: 1900, ticker: 'ETH' },
             ],
             msg: 'Invalid Airdrop',
             msgApiFailure: 'Invalid Airdrop',
         },
     ],
     cashtabMsgs: [
         {
             txid: 'b9c95c8cb8436be0574946071932aed3b82e5a8631d4de7a64ea29f7fba84759',
             hex: '04007461623165436173684461793a2058454346617563657420546f70757020666f722045617374657220456767206769766561776179',
             stackArray: [
                 '00746162',
                 '65436173684461793a2058454346617563657420546f70757020666f722045617374657220456767206769766561776179',
             ],
             msg: 'eCashDay: XECFaucet Topup for Easter Egg giveaway',
         },
         // no stackArray[1]
         {
             txid: 'N/A, mod of b9c95c8cb8436be0574946071932aed3b82e5a8631d4de7a64ea29f7fba84759',
             hex: '0400746162',
             stackArray: ['00746162'],
             msg: 'Invalid Cashtab Msg',
         },
     ],
     encryptedCashtabMsgs: [
         {
             txid: 'c9abffe59ef104408bf2fd4f602f76096a7ab78f2801ae320cadac53e1be4c5d',
             hex: '04657461624c810281d8b3db5585bf24903022d9c5f3b8cafed757f254840c0f7bc872fda070745cb6cef3d645fc7e4403e2bc212e616db6691ab415cd1f7e9abcebdd8738e775a05ebeb14fadbdbf5941e0e4804e0c075239d0906ca5d5c00a93ebae11df7770c4aeeaef5b804abca08c10520fa47a6dc3df018378334a15f7ea3075bc9b8840a8',
             sendingAddress: 'ecash:qq4fd9zdqecq3q4mmxz8v8vunepptukh3czav3gjyt',
             xecReceivingOutputsKeyValueArray: [
                 [
                     '6a04657461624c810281d8b3db5585bf24903022d9c5f3b8cafed757f254840c0f7bc872fda070745cb6cef3d645fc7e4403e2bc212e616db6691ab415cd1f7e9abcebdd8738e775a05ebeb14fadbdbf5941e0e4804e0c075239d0906ca5d5c00a93ebae11df7770c4aeeaef5b804abca08c10520fa47a6dc3df018378334a15f7ea3075bc9b8840a8',
                     0,
                 ],
                 [
                     '76a914f5f740bc76e56b77bcab8b4d7f888167f416fc6888ac',
                     24242424,
                 ],
             ],
             stackArray: [
                 '65746162',
                 '0281d8b3db5585bf24903022d9c5f3b8cafed757f254840c0f7bc872fda070745cb6cef3d645fc7e4403e2bc212e616db6691ab415cd1f7e9abcebdd8738e775a05ebeb14fadbdbf5941e0e4804e0c075239d0906ca5d5c00a93ebae11df7770c4aeeaef5b804abca08c10520fa47a6dc3df018378334a15f7ea3075bc9b8840a8',
             ],
             coingeckoPrices: [
                 { fiat: 'usd', price: 0.00003333, ticker: 'XEC' },
                 { fiat: 'usd', price: 25000, ticker: 'BTC' },
                 { fiat: 'usd', price: 1900, ticker: 'ETH' },
             ],
             msg: 'qq4...jyt sent an encrypted message and $8 to qr6...xkv',
             msgApiFailure:
                 'qq4...jyt sent an encrypted message and 242k XEC to qr6...xkv',
         },
         {
             txid: 'c43c01feb0563ed7293e86bccbc695fdce88807c4bf6dfb0b48134eb16d076b7',
             hex: '04657461624cd1034e582d3789a6ff5119c9ef243b4e126eacc51a922504439b2edba9cbb313a170a34e9e763943a59af3345867aa364ba8f089f992d1072cefedf02ce0dbb9b56023aa115ab180cc521b25553735f5ae58fbd2ff6bb750c710792dcbb356cf816604deec3ee9767e7a76fd757f617d174b127cef0b3162dc888075e99147b25014ab61d86108abae51421efbc060f6eff7edffff9d54f17f64ced6b0f973a8f44164b58337470a5a60d9f8ecb43a82dd8c989f409285e97ec3417426ceaca6a919a7b3bb8cdcfa679c9af950972ee43160',
             sendingAddress: 'ecash:qq9h6d0a5q65fgywv4ry64x04ep906mdku8f0gxfgx',
             xecReceivingOutputsKeyValueArray: [
                 [
                     '6a04657461624cd1026d3ebca7776500d72ee640e56509cefcedee044b25584f0cc32d15c54766bc8960b179d07838f6ffb221c49c7f74d9a9bf4101cdb4a78d5507620ca020eab052d24995bcca37e9dd5b1baa210045b2942438e31a43062ef35c019250cef35dff2fd4b6999b98a103344d05c70847aa5124ac76d8528f737f4a504e96b46dbbe05b8a80bdc4b98bb0bb0f12ad12a3271550e79524ebae01dece0a231bfd546dab7714167bc73989613b73d94a5b48fbeda4913dbf42daedd52a3239a1654e4d3ded120b714eecffc3f3b1a37aed9e2d3b',
                     0,
                 ],
                 ['76a914f627e51001a51a1a92d8927808701373cf29267f88ac', 600],
                 // manually give it another output to test
                 ['76a914f5f740bc76e56b77bcab8b4d7f888167f416fc6888ac', 100],
             ],
             stackArray: [
                 '65746162',
                 '034e582d3789a6ff5119c9ef243b4e126eacc51a922504439b2edba9cbb313a170a34e9e763943a59af3345867aa364ba8f089f992d1072cefedf02ce0dbb9b56023aa115ab180cc521b25553735f5ae58fbd2ff6bb750c710792dcbb356cf816604deec3ee9767e7a76fd757f617d174b127cef0b3162dc888075e99147b25014ab61d86108abae51421efbc060f6eff7edffff9d54f17f64ced6b0f973a8f44164b58337470a5a60d9f8ecb43a82dd8c989f409285e97ec3417426ceaca6a919a7b3bb8cdcfa679c9af950972ee43160',
             ],
             coingeckoPrices: [
                 { fiat: 'usd', price: 0.00003333, ticker: 'XEC' },
                 { fiat: 'usd', price: 25000, ticker: 'BTC' },
                 { fiat: 'usd', price: 1900, ticker: 'ETH' },
             ],
             msg: 'qq9...fgx sent an encrypted message and $0.0002 to qrm...r48 and 1 other',
             msgApiFailure:
                 'qq9...fgx sent an encrypted message and 7 XEC to qrm...r48 and 1 other',
         },
     ],
     slp2PushVectors: [
         {
             push: '534c503200044d494e5445e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd0150c30000000000',
             msg: 'MINT|<a href="https://explorer.e.cash/tx/cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145">CRD</a>|0.0',
         },
         {
             push: '534c5032000453454e4445e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd03204e00000000cc7400000000640000000000',
             msg: 'SEND|<a href="https://explorer.e.cash/tx/cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145">CRD</a>|0.142',
         },
         {
             push: '534c503200044255524e45e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd204e00000000',
             msg: 'BURN',
         },
     ],
     slp2TxVectors: [
         {
             txid: '05fbc4dcea9cc73e298b9f7bfe58de7b11dbbb3917c2bbdc5c9c93035e84b9fa',
             hex: '5032534c503200044d494e5445e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd0150c30000000000',
             emppStackArray: [
                 '50',
                 '534c503200044d494e5445e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd0150c30000000000',
             ],
             msg: `${opReturn.knownApps.slp2.app}:MINT|<a href="https://explorer.e.cash/tx/cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145">CRD</a>|0.0`,
         },
         {
             txid: '6f907d8d0f31315fbac8f860052e92899866869326f726393fd4fd4b5f7b8a7f',
             hex: '503d534c5032000453454e4445e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd03204e00000000cc7400000000640000000000',
             emppStackArray: [
                 '50',
                 '534c5032000453454e4445e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd03204e00000000cc7400000000640000000000',
             ],
-            msg: `${opReturn.knownApps.slp2.app}:SEND|<a href=\"https://explorer.e.cash/tx/cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145\">CRD</a>|0.142`,
+            msg: `${opReturn.knownApps.slp2.app}:SEND|<a href="https://explorer.e.cash/tx/cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145">CRD</a>|0.142`,
         },
         {
             txid: 'f0548510095dfbbe31cbeb27e3c0a340aabaad12f98d4ec6f563602a9f3f5499',
             hex: '5030534c503200044255524e45e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd204e00000000',
             emppStackArray: [
                 '50',
                 '534c503200044255524e45e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd204e00000000',
             ],
             msg: `${opReturn.knownApps.slp2.app}:BURN`,
         },
         {
             txid: 'c60db447e7eabee94100567953985ec245a02368e604dd8436733624af38aa3c',
             hex: '5030534c5032c8044255524e0748dae47347c2cf32838eaddedc60866160f0772a022b17463aa435809ac635102700000000',
             emppStackArray: [
                 '50',
                 '534c5032c8044255524e0748dae47347c2cf32838eaddedc60866160f0772a022b17463aa435809ac635102700000000',
             ],
             msg: `${opReturn.knownApps.slp2.app}:Unknown token type|BURN`,
         },
         {
             txid: 'e3e24259c06b6cc61647239f5bab24d4433747ab80456c72a641dc5219d81b94',
             hex: '503d534c5032c80453454e440748dae47347c2cf32838eaddedc60866160f0772a022b17463aa435809ac63503102700000000584d00000000640000000000',
             emppStackArray: [
                 '50',
                 '534c5032c80453454e440748dae47347c2cf32838eaddedc60866160f0772a022b17463aa435809ac63503102700000000584d00000000640000000000',
             ],
             msg: `${opReturn.knownApps.slp2.app}:Unknown token type|SEND|<a href="https://explorer.e.cash/tx/35c69a8035a43a46172b022a77f060618660dcdead8e8332cfc24773e4da4807">35c...807</a>`,
         },
         // Manually add a cashtab msg push
         {
             txid: 'e3e24259c06b6cc61647239f5bab24d4433747ab80456c72a641dc5219d81b94',
             hex: '503d534c5032c80453454e440748dae47347c2cf32838eaddedc60866160f0772a022b17463aa435809ac63503102700000000584d000000006400000000002e04007461622846726f6d20467265657865632c207468616e6b20796f7520666f7220796f757220737570706f7274',
             emppStackArray: [
                 '50',
                 '534c5032c80453454e440748dae47347c2cf32838eaddedc60866160f0772a022b17463aa435809ac63503102700000000584d00000000640000000000',
                 '04007461622846726f6d20467265657865632c207468616e6b20796f7520666f7220796f757220737570706f7274',
             ],
-            msg: `${opReturn.knownApps.slp2.app}:Unknown token type|SEND|<a href=\"https://explorer.e.cash/tx/35c69a8035a43a46172b022a77f060618660dcdead8e8332cfc24773e4da4807\">35c...807</a>|Unknown App:\u0004\u0000tab(From Freexec, thank you for your support`,
+            msg: `${opReturn.knownApps.slp2.app}:Unknown token type|SEND|<a href="https://explorer.e.cash/tx/35c69a8035a43a46172b022a77f060618660dcdead8e8332cfc24773e4da4807">35c...807</a>|Unknown App:\u0004\u0000tab(From Freexec, thank you for your support`,
         },
     ],
     aliasRegistrations: [
         {
             txid: 'dafea3b4ace4d56aec6aed106c6a654d7a1b0bc2f5bfa0599f679da77825e165',
             hex: '042e78656300046c616d6215000b7d35fda03544a08e65464d54cfae4257eb6db7',
             stackArray: [
                 '2e786563',
                 '00',
                 '6c616d62',
                 '000b7d35fda03544a08e65464d54cfae4257eb6db7',
             ],
             msg: 'lamb',
         },
         {
             txid: '79372d596c1dd14189720b5dc205350d46edfd0fffb108c717b9d0afbcf5869f',
             hex: '042e78656300046d6f6f6e15000b7d35fda03544a08e65464d54cfae4257eb6db7',
             stackArray: [
                 '2e786563',
                 '00',
                 '6d6f6f6e',
                 '000b7d35fda03544a08e65464d54cfae4257eb6db7',
             ],
             msg: 'moon',
         },
         {
             txid: '65c6afcf8a90d8b69729a0f048d736fda1a40451c3e83867c5a5f5a4c5226694',
             hex: '042e786563000670616e67616915000b7d35fda03544a08e65464d54cfae4257eb6db7',
             stackArray: [
                 '2e786563',
                 '00',
                 '70616e676169',
                 '000b7d35fda03544a08e65464d54cfae4257eb6db7',
             ],
             msg: 'pangai',
         },
         // Invalid alias tx with correct protocol identifier but incomplete stack
         {
             txid: 'N/A',
             hex: '042e78656305426f6f6d21',
             stackArray: ['2e786563', '426f6f6d21'],
             msg: 'Invalid alias registration',
         },
         // Invalid alias tx with correct protocol identifier but empty stack after protocol identifier
         {
             txid: 'N/A',
             hex: '042e786563',
             stackArray: ['2e786563'],
             msg: 'Invalid alias registration',
         },
         // Different version # for whatever reason
         {
             txid: 'N/A',
             hex: '042e78656301010670616e67616915000b7d35fda03544a08e65464d54cfae4257eb6db7',
             stackArray: [
                 '2e786563',
                 '01',
                 '70616e676169',
                 '000b7d35fda03544a08e65464d54cfae4257eb6db7',
             ],
             msg: 'Invalid alias registration',
         },
     ],
     payButtonTxs: [
         // on spec tx with no data
         {
             txid: 'd1e7036e920ac9c2f50495641a4b9771c6c8f1e932304a5865096a6d3a514303',
             hex: '04504159000000089057dd10be17a66a',
             stackArray: ['50415900', '00', '00', '9057dd10be17a66a'],
             msg: 'no data',
         },
         // on spec tx with data
         {
             txid: 'd1e7036e920ac9c2f50495641a4b9771c6c8f1e932304a5865096a6d3a514303',
             hex: '045041590000087465737464617461089057dd10be17a66a',
             stackArray: [
                 '50415900',
                 '00',
                 '7465737464617461',
                 '9057dd10be17a66a',
             ],
             msg: 'testdata',
         },
         // Unsupported version
         {
             txid: 'd1e7036e920ac9c2f50495641a4b9771c6c8f1e932304a5865096a6d3a514303',
             hex: '04504159000101087465737464617461089057dd10be17a66a',
             stackArray: [
                 '50415900',
                 '01',
                 '7465737464617461',
                 '9057dd10be17a66a',
             ],
             msg: 'Unsupported version: 0x01',
         },
         // Tx does not have enough pushes to parse
         {
             txid: 'd1e7036e920ac9c2f50495641a4b9771c6c8f1e932304a5865096a6d3a514303',
             hex: '04504159000101',
             stackArray: ['50415900', '01'],
             msg: '[off spec]',
         },
     ],
     paywallTxs: [
         // on spec paywall tx with a valid article txid
         {
             txid: 'f86d0b60e66888f8d30ea67167e5e4370fee29f13201cf5f32727d41c8a41868',
             hex: '0470617977200729318a128ee8f11d18b28237c8ae7ffa4e95c88ec69ebce716758e1973c5d4',
             stackArray: [
                 '70617977',
                 '0729318a128ee8f11d18b28237c8ae7ffa4e95c88ec69ebce716758e1973c5d4',
             ],
             msg: '<a href="https://explorer.e.cash/tx/0729318a128ee8f11d18b28237c8ae7ffa4e95c88ec69ebce716758e1973c5d4">Article paywall payment</a>',
         },
         // on spec paywall tx with an invalid article txid
         {
             txid: 'f86d0b60e66888f8d30ea67167e5e4370fee29f13201cf5f32727d41c8a41868',
             hex: '04706179771636343934633165663161316435666333398393832655',
             stackArray: [
                 '70617977',
                 '36343934633165663161316435666333398393832655',
             ],
             msg: 'Invalid paywall article txid',
         },
         // off spec paywall tx
         {
             txid: 'f86d0b60e66888f8d30ea67167e5e4370fee29f13201cf5f32727d41c8a41868',
             hex: '0470617977',
             stackArray: ['70617977'],
             msg: '[off spec paywall payment]',
         },
     ],
     authenticationTxs: [
         // on spec tx
         {
             txid: 'e7a67443354b4df14dcb779de6291ea89e7c0e4fce83d56e87b9694e8f4cb8a9',
             hex: '04617574681414b9b4971454d1a83c33119f3914a0b747f2f7a7',
             stackArray: [
                 '61757468',
                 '14b9b4971454d1a83c33119f3914a0b747f2f7a7',
             ],
             msg: 'eCashChat authentication via dust tx',
         },
         // on spec tx with an empty authentication identifier
         {
             txid: 'e7a67443354b4df14dcb779de6291ea89e7c0e4fce83d56e87b9694e8f4cb8a9',
             hex: '046175746800',
             stackArray: ['61757468', '00'],
             msg: 'Invalid eCashChat authentication identifier',
         },
         // off spec tx
         {
             txid: 'e7a67443354b4df14dcb779de6291ea89e7c0e4fce83d56e87b9694e8f4cb8a9',
             hex: '0461757468',
             stackArray: ['61757468'],
             msg: '[off spec eCashChat authentication]',
         },
     ],
 };
 
 export default appTxSamples;
diff --git a/apps/ecash-herald/test/mocks/block.ts b/apps/ecash-herald/test/mocks/block.ts
index 70d723dcd..c34ab0e58 100644
--- a/apps/ecash-herald/test/mocks/block.ts
+++ b/apps/ecash-herald/test/mocks/block.ts
@@ -1,6105 +1,6106 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
 const mockedBlock: any = {
     blockTxs: [
         {
             txid: '0bf6e9cd974cd5fc6fbbf739a42447d41a301890e2db242295c64df63dc3ee7e',
             version: 1,
             inputs: [
                 {
                     prevOut: {
                         txid: '0000000000000000000000000000000000000000000000000000000000000000',
                         outIdx: 4294967295,
                     },
                     inputScript:
                         '0392800c04904c5d650cfabe6d6d2a5055cb96fc034feb64a6533f9ba428768f019b0efc92797bb1eeae3bda05e410000000000000000800002bed8efca61700000015643839366564326466356633353334353432323837',
                     value: 0,
                     sequenceNo: 0,
                 },
             ],
             outputs: [
                 {
                     value: 362500000,
                     outputScript:
                         '76a914ce8c8cf69a922a607e8e03e27ec014fbc24882e088ac',
                     spentBy: {
                         txid: '2e3399f02280def3908afc561157cbaa159bbacee47dbcdebac15a668d009fc0',
                         outIdx: 1,
                     },
                 },
                 {
                     value: 200000000,
                     outputScript:
                         'a914d37c4c809fe9840e7bfa77b86bd47163f6fb6c6087',
                     spentBy: {
                         txid: '2df7650a9ebebd998d0dc756650144c21d84722c60fe6389c538d272f134d365',
                         outIdx: 226,
                     },
                 },
                 {
                     value: 62500000,
                     outputScript:
                         '76a914c36941af4c8cdf6e3156f7fe1426d05d6177890e88ac',
                     spentBy: {
                         txid: '6da0fa092de6c985365eb40ebe8a9112a62e48a1375dc348b2f2fc9fc27664d1',
                         outIdx: 27,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 239,
             isCoinbase: true,
             tokenEntries: [],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
             block: {
                 height: 819346,
                 hash: '00000000000000001d985578bc11edf9bbfee8daad0f39500e3f429c72fcf282',
                 timestamp: 1700613264,
             },
         },
         {
             txid: '010114b9bbe776def1a512ad1e96a4a06ec4c34fc79bcb5d908845f5102f6b0f',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: '74bc6dd34b94ff3f0e398ef88e0df3b8c04457db274f9f8d098c9471f35593c6',
                         outIdx: 456,
                     },
                     inputScript:
                         '48304502210086860e8ee3721d2ebc919dca21e44ff96a2adc287528e46e12665dc1a5af75ec02206dd0c593becad3d4055ed011f9d61468a378090e1fe4246eeb34b68744ec5e93412103bc01efabf76dafe666a98c88fe72915c4cceb26cacf6772904b3fa1fa5629765',
                     value: 5285,
                     sequenceNo: 4294967294,
                     outputScript:
                         '76a914104e67d912a7aab2a159bba141477e5867c04bfd88ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a04534c500001010747454e45534953054c6f6c6c79054c4f4c4c591468747470733a2f2f636173687461622e636f6d2f4c0001084c00080162ea854d0fc000',
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a914104e67d912a7aab2a159bba141477e5867c04bfd88ac',
                     token: {
                         tokenId:
                             '010114b9bbe776def1a512ad1e96a4a06ec4c34fc79bcb5d908845f5102f6b0f',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '99900000000000000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                 },
                 {
                     value: 4284,
                     outputScript:
                         '76a914104e67d912a7aab2a159bba141477e5867c04bfd88ac',
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 299,
             isCoinbase: false,
             tokenEntries: [
                 {
                     tokenId:
                         '010114b9bbe776def1a512ad1e96a4a06ec4c34fc79bcb5d908845f5102f6b0f',
                     tokenType: {
                         protocol: 'SLP',
                         type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                         number: 1,
                     },
                     txType: 'GENESIS',
                     isInvalid: false,
                     burnSummary: '',
                     failedColorings: [],
                     actualBurnAmount: '0',
                     intentionalBurn: '0',
                     burnsMintBatons: false,
                 },
             ],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NORMAL',
             block: {
                 height: 784969,
                 hash: '0000000000000000071b57edd35439249dce297842995f4940eaefc6e88d0a9d',
                 timestamp: 1679836351,
             },
         },
         {
             txid: '004e018dd98520aa722ee76c608771dd578a044f38103a8298f25e6ffbc7c3ba',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: '825bd04c60b27ef652a5ec706cecaf9cec4dc10ce0010f468f8f3bbef6e1539a',
                         outIdx: 2,
                     },
                     inputScript:
                         '47304402202edcaf6fad2b7789b54ae9283db93f8028249dab78455653f4a1765aae29ca48022060f44bb9fcc82233ba64b4ba1725bfd1d451babb7f96d13c2ef8d833e972946941210353f81d61d41d6e22c73ab449476113dea124afe3972991cd237e654f15950b7c',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '92940000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                 },
                 {
                     prevOut: {
                         txid: '825bd04c60b27ef652a5ec706cecaf9cec4dc10ce0010f468f8f3bbef6e1539a',
                         outIdx: 3,
                     },
                     inputScript:
                         '483045022100917c49035cd87aea0c004121561ec5c7488badbfc9ee51e9c7684c0717306bea02206a197976706fc6d6d05590f14482264e90ca080e561978257ba7df451debffd541210353f81d61d41d6e22c73ab449476113dea124afe3972991cd237e654f15950b7c',
                     value: 14274406,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a04534c500001010453454e4420aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb108000000000000271008000000000589ffd0',
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a914dcc535261a43835ca12352d0926ba06cf07cbe8388ac',
                     token: {
                         tokenId:
                             'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '10000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                     token: {
                         tokenId:
                             'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '92930000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     spentBy: {
                         txid: '4852929bc3809bb1b6fa5b607f4856df1d0cf13816e01c93a3b32f6a59647f73',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 14273379,
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                     spentBy: {
                         txid: '4852929bc3809bb1b6fa5b607f4856df1d0cf13816e01c93a3b32f6a59647f73',
                         outIdx: 1,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 1713483767,
             size: 480,
             isCoinbase: false,
             tokenEntries: [
                 {
                     tokenId:
                         'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                     tokenType: {
                         protocol: 'SLP',
                         type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                         number: 1,
                     },
                     txType: 'SEND',
                     isInvalid: false,
                     burnSummary: '',
                     failedColorings: [],
                     actualBurnAmount: '0',
                     intentionalBurn: '0',
                     burnsMintBatons: false,
                 },
             ],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NORMAL',
             block: {
                 height: 840667,
                 hash: '00000000000000000292a87c1b0a07399bbeceec747e15b63b3d4b44837d0e3f',
                 timestamp: 1713484694,
             },
         },
         {
             txid: '0110cd886ecd2d9570e98b7501cd039f4e5352d69659a46f1a49cc19c1869701',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: '76cf25e029ad119042f956605f9386d82b640b2786fd19a8be22383e71c63066',
                         outIdx: 2,
                     },
                     inputScript:
                         '4830450221008295a1f9391cdcd4b6ce64e3667e50fbd4c2ce37abc15840cc686bb2ad9970bf022006a16801d509b6f72eca4393731604ee0f28ba0d6ce55dcd4c3b706c374eca8341210353f81d61d41d6e22c73ab449476113dea124afe3972991cd237e654f15950b7c',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '92640000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                 },
                 {
                     prevOut: {
                         txid: '76cf25e029ad119042f956605f9386d82b640b2786fd19a8be22383e71c63066',
                         outIdx: 3,
                     },
                     inputScript:
                         '47304402204fd42db620084ff54f32c60fb5cded7040255fdef7b6ba80a1a5a3b9f7c4fef1022042acf826a81e39c4224de432e92a24c1ee11c2a85d6f6f45f8e88cdbb081f4c441210353f81d61d41d6e22c73ab449476113dea124afe3972991cd237e654f15950b7c',
                     value: 14243596,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a04534c500001010453454e4420aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1080000000000002710080000000005856bf0',
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a91469724b96df46096cc95b1a6d408a4240ea80d85588ac',
                     token: {
                         tokenId:
                             'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '10000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                     token: {
                         tokenId:
                             'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '92630000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     spentBy: {
                         txid: 'a998c6bdd2d4755b4be7537a5ba064cc19428ce3a47d0c069ee4241a1a83058e',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 14242569,
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                     spentBy: {
                         txid: 'a998c6bdd2d4755b4be7537a5ba064cc19428ce3a47d0c069ee4241a1a83058e',
                         outIdx: 1,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 1713484515,
             size: 480,
             isCoinbase: false,
             tokenEntries: [
                 {
                     tokenId:
                         'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                     tokenType: {
                         protocol: 'SLP',
                         type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                         number: 1,
                     },
                     txType: 'SEND',
                     isInvalid: false,
                     burnSummary: '',
                     failedColorings: [],
                     actualBurnAmount: '0',
                     intentionalBurn: '0',
                     burnsMintBatons: false,
                 },
             ],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NORMAL',
             block: {
                 height: 840667,
                 hash: '00000000000000000292a87c1b0a07399bbeceec747e15b63b3d4b44837d0e3f',
                 timestamp: 1713484694,
             },
         },
         {
             txid: '327101f6f3b740280a6e9fbd8edc41f4f0500633672975a5974a4147c94016a5',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: 'ddb98796d80acad3a291913e015cfbe30612be00d921533c67513e5d61e8bda5',
                         outIdx: 2,
                     },
                     inputScript:
                         '47304402207223b7e969380eb1c83569a6c217f2d6350f2b3f241d30af9446c04bc36d109f022049bcc4d0a9327f839618a8174af837ac61d6cea1d30962f2866c1dfb4a9d3e8041210353f81d61d41d6e22c73ab449476113dea124afe3972991cd237e654f15950b7c',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '92560000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                 },
                 {
                     prevOut: {
                         txid: 'ddb98796d80acad3a291913e015cfbe30612be00d921533c67513e5d61e8bda5',
                         outIdx: 3,
                     },
                     inputScript:
                         '483045022100f5b0ca73d4d81cba5abf91d9d3531085768ef71b173b1a1701bbefc6cefad65202201540deb6e8c7c3ca96889ef6965abcc61c9c1e3e3ada3d70be1bed146f48bfe341210353f81d61d41d6e22c73ab449476113dea124afe3972991cd237e654f15950b7c',
                     value: 14235380,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a04534c500001010453454e4420aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1080000000000002710080000000005843370',
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a91458cddba2449285814dae43d4ed4a1c9998f3693e88ac',
                     token: {
                         tokenId:
                             'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '10000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                     token: {
                         tokenId:
                             'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '92550000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     spentBy: {
                         txid: '0a77eb6a5b08bc91a60a8ed8752ac2d3dc477e0c94624c486fcef7429be47d0d',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 14234353,
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                     spentBy: {
                         txid: '0a77eb6a5b08bc91a60a8ed8752ac2d3dc477e0c94624c486fcef7429be47d0d',
                         outIdx: 1,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 1713484590,
             size: 480,
             isCoinbase: false,
             tokenEntries: [
                 {
                     tokenId:
                         'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                     tokenType: {
                         protocol: 'SLP',
                         type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                         number: 1,
                     },
                     txType: 'SEND',
                     isInvalid: false,
                     burnSummary: '',
                     failedColorings: [],
                     actualBurnAmount: '0',
                     intentionalBurn: '0',
                     burnsMintBatons: false,
                 },
             ],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NORMAL',
             block: {
                 height: 840667,
                 hash: '00000000000000000292a87c1b0a07399bbeceec747e15b63b3d4b44837d0e3f',
                 timestamp: 1713484694,
             },
         },
         {
             txid: 'aa13c6f214ff58f36ed5e108a7f36d8f98729c50186b27a53b989c7f36fbf517',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: 'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                         outIdx: 1,
                     },
                     inputScript:
                         '483045022100f7f2eac186605f5d37a038b17367a4b6fc5458ca7485ce6b77baf19b4160bcd8022029b5ef41a2ebb4642e9802d32a1649d84c7daf2e978c32ebc7342b90e9427cc1412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '10000000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                 },
                 {
                     prevOut: {
                         txid: 'd8a081bed886b085194410fd879286393734f428c9f64d9ece1c0afffb2695a2',
                         outIdx: 1,
                     },
                     inputScript:
                         '483045022100b0404d5d553867df9ed190ce52ec13565aaf6e3c8986b712c150acac6d3853f70220727abe6d27a333f72249a08f3b40cd15346c6096466b6118248f92279201b5f7412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
                     value: 3899,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a04534c500001010453454e4420aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1080000000000002710080000000000986f70',
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                     token: {
                         tokenId:
                             'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '10000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     spentBy: {
                         txid: '80baab3dc64a3922c8d3ca11bacc6af4f05b103e15e18e9ea7592d926612c829',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                     token: {
                         tokenId:
                             'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '9990000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     spentBy: {
                         txid: '4fb3b37c25c8a5cb43f0130435eb33c19b2fdaf4be98b113e580a66ec9340435',
                         outIdx: 3,
                     },
                 },
                 {
                     value: 2872,
                     outputScript:
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                     spentBy: {
                         txid: 'fb6086e1e98f88fdef7abab312dfb68449d1b43d511e1f15c488a8cb804f1c51',
                         outIdx: 0,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 1713384505,
             size: 481,
             isCoinbase: false,
             tokenEntries: [
                 {
                     tokenId:
                         'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                     tokenType: {
                         protocol: 'SLP',
                         type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                         number: 1,
                     },
                     txType: 'SEND',
                     isInvalid: false,
                     burnSummary: '',
                     failedColorings: [],
                     actualBurnAmount: '0',
                     intentionalBurn: '0',
                     burnsMintBatons: false,
                 },
             ],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NORMAL',
             block: {
                 height: 840499,
                 hash: '000000000000000035b621834b4408d0b1a8da7d975cb14c0b9330d1e2398d8b',
                 timestamp: 1713384866,
             },
         },
         {
             txid: '6ffcc83e76226bd32821cc6862ce9b363b22594247a4e73ccf3701b0023592b2',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: 'b07e3e6a696b7de3c4474107c5a5691d759713060832b2489c353a0718cf8a78',
                         outIdx: 2,
                     },
                     inputScript:
                         '48304502210081ba28d95e619fbc5997299a03a0ae2ffa0bf0af66277b6d57087ac45a1a300502202c8cac931e6e58aac9c318f59e31df3b149d240244f6d74fc1b5aa19fad742c6412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
                     value: 15177819,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                 },
                 {
                     prevOut: {
                         txid: '07ad02a4477d02ee5007e32fdc576769aa3a0e501f978549eb746c83e41fe52f',
                         outIdx: 2,
                     },
                     inputScript:
                         '483045022100d117557506158821beb623a0a9c6ecbc88011a1eca397afe910067a994ad35fd022003355bd201f7f21edeedc2a4f3991530043ee9981021887702152418c2b28b7d412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '999977691',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a04534c500001010453454e442098183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f4808000000000000003708000000003b9a72a4',
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a9146ffbe7c7d7bd01295eb1e371de9550339bdcf9fd88ac',
                     token: {
                         tokenId:
                             '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '55',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                     token: {
                         tokenId:
                             '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '999977636',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                 },
                 {
                     value: 15176136,
                     outputScript:
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                     spentBy: {
                         txid: '5f06207dea4762524dbe2d84900cc78711d079f2b2e909867ec5e9abdeb850aa',
                         outIdx: 0,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 481,
             isCoinbase: false,
             tokenEntries: [
                 {
                     tokenId:
                         '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
                     tokenType: {
                         protocol: 'SLP',
                         type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                         number: 1,
                     },
                     txType: 'SEND',
                     isInvalid: false,
                     burnSummary: '',
                     failedColorings: [],
                     actualBurnAmount: '0',
                     intentionalBurn: '0',
                     burnsMintBatons: false,
                 },
             ],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NORMAL',
             block: {
                 height: 800716,
                 hash: '0000000000000000140fb9e3f5ba1d76a1902ede29aec1b6c93edf9a4e11e44b',
                 timestamp: 1689261128,
             },
         },
         {
             txid: 'fb70df00c07749082756054522d3f08691fd9caccd0e0abf736df23d22845a6e',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: 'b8ed29af5e165f26062bc553406fe642a5a8e9e52dec1f281112f4f16af717b9',
                         outIdx: 2,
                     },
                     inputScript:
                         '47304402206f260f779e10e44d290d7092b4a4f627c5387e30c2e2080e1ac3a726adb33f850220562e7e32bba69f4dad19bf267f1721b9d80e7504135edbb50ff5f1ec1ebf99e8412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
                     value: 17421473,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                 },
                 {
                     prevOut: {
                         txid: '9c0c01c1e8cc3c6d816a3b41d09d65fda69de082b74b6ede7832ed05527ec744',
                         outIdx: 2,
                     },
                     inputScript:
                         '47304402204f6ed41e291f0ad846be2516e7626ed0adbcf64f8a13a05897f61f7ce7f7afba0220559546ea121ad78ae6b2ff91f33e0a083299c0657fb3122a251eb6d05e2a6269412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '5235120638765433',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a04534c500001010453454e44207443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d0800000000068c953f08001299507b7b143a',
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a9146ffbe7c7d7bd01295eb1e371de9550339bdcf9fd88ac',
                     token: {
                         tokenId:
                             '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '109876543',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                     token: {
                         tokenId:
                             '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '5235120528888890',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                 },
                 {
                     value: 17419790,
                     outputScript:
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                     spentBy: {
                         txid: '8f6676b602a9f074f10a7561fb7256bbce3b103a119f809a05485e42489d2233',
                         outIdx: 0,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 479,
             isCoinbase: false,
             tokenEntries: [
                 {
                     tokenId:
                         '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
                     tokenType: {
                         protocol: 'SLP',
                         type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                         number: 1,
                     },
                     txType: 'SEND',
                     isInvalid: false,
                     burnSummary: '',
                     failedColorings: [],
                     actualBurnAmount: '0',
                     intentionalBurn: '0',
                     burnsMintBatons: false,
                 },
             ],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NORMAL',
             block: {
                 height: 800716,
                 hash: '0000000000000000140fb9e3f5ba1d76a1902ede29aec1b6c93edf9a4e11e44b',
                 timestamp: 1689261128,
             },
         },
         {
             txid: '25345b0bf921a2a9080c647768ba440bbe84499f4c7773fba8a1b03e88ae7fe7',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: '1f5f4350b93708ca60b94c51ce3135dcaeef5ce64bb7dbc2934a442917ccad1a',
                         outIdx: 3,
                     },
                     inputScript:
                         '483045022100889c5bc4aac2b8fba02f2414c596f5458d47acc3f21f8893a8fc5c367ca2559702205fe45c504ed024740df74811f8a75b40831cbdbfdad72aa332112fe0f759f0f2412103632f603f43ae61afece65288d7d92e55188783edb74e205be974b8cd1cd36a1e',
                     value: 1528001,
                     sequenceNo: 4294967294,
                     outputScript:
                         '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
                 },
                 {
                     prevOut: {
                         txid: '5ca2cb70c3c351da6fff27d06dec6271449e52e37c38bbf1a5cfb64dd6dde161',
                         outIdx: 2,
                     },
                     inputScript:
                         '473044022016f9ad02f956cb7160099c80a5899bca83e92965665c9b75f2719f4432ab8dcf02206d7b8f1e29eb2761798cb76f96efc623ec72764f79f8d85320c1c4566fbc08b9412103632f603f43ae61afece65288d7d92e55188783edb74e205be974b8cd1cd36a1e',
                     value: 546,
                     sequenceNo: 4294967294,
                     token: {
                         tokenId:
                             'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '34443689000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a04534c500001010453454e4420fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa08000000001dcd65000800000007e7339728',
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a914dadf34cde9c774fdd6340cd2916a9b9c5d57cf4388ac',
                     token: {
                         tokenId:
                             'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '500000000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     spentBy: {
                         txid: '9b4cad218d7743f1610d73577e2c3c4bcd97a2e70a61e69aea67088277dad936',
                         outIdx: 2,
                     },
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
                     token: {
                         tokenId:
                             'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '33943689000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     spentBy: {
                         txid: 'd28244a5f79ed2323c543294d901fc0fe6ecc3c08f2ab4224ac141289daa4da9',
                         outIdx: 1,
                     },
                 },
                 {
                     value: 1526318,
                     outputScript:
                         '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
                     spentBy: {
                         txid: '660d23a32becd5fbca89e87a15981953c1ad092ec148f2f04661b3c54d8b5e25',
                         outIdx: 0,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 480,
             isCoinbase: false,
             tokenEntries: [
                 {
                     tokenId:
                         'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
                     tokenType: {
                         protocol: 'SLP',
                         type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                         number: 1,
                     },
                     txType: 'SEND',
                     isInvalid: false,
                     burnSummary: '',
                     failedColorings: [],
                     actualBurnAmount: '0',
                     intentionalBurn: '0',
                     burnsMintBatons: false,
                 },
             ],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NORMAL',
             block: {
                 height: 782571,
                 hash: '000000000000000003a43161c1d963b1df57f639a4621f56d3dbf69d5a8d0561',
                 timestamp: 1678358652,
             },
         },
         {
             txid: '0167e881fcb359cdfc82af5fc6c0821daf55f40767694eea2f23c0d42a9b1c17',
             version: 1,
             inputs: [
                 {
                     prevOut: {
                         txid: '581464b01626d7ad867f93970338ec2840ce1c97aed658884474e6cb16a02807',
                         outIdx: 1,
                     },
                     inputScript:
                         '4153405b57f5a1969c45891448e99bb69376490bea5ce29240a1152168c72dee5adfb09b84c90b0d4f0e590ba1127b94e2f3ff36877224c1779e04743f2b64d308c121039764908e0122ca735c3470ff3c805b265e54589901fcee0d610f0d31b356f7f3',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '526349',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a9146d69b5cbe7c85d87628473c43620c0daa9a8102988ac',
                 },
                 {
                     prevOut: {
                         txid: 'afd08abc17c78d3f0449f2393e0db9e5266099fca21c141b67879bd7c9330708',
                         outIdx: 1,
                     },
                     inputScript:
                         '41e3558233c98f31574ac950c322f43e45f3fd7c4e5462aeeaf034e7263115ddad77cd37e834a1c5c942e552028e17077ef9ea146fdc18986ccf8449efe8ac9d44c121039764908e0122ca735c3470ff3c805b265e54589901fcee0d610f0d31b356f7f3',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '420181',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a9146d69b5cbe7c85d87628473c43620c0daa9a8102988ac',
                 },
                 {
                     prevOut: {
                         txid: 'f94fc719a8d037cf2df3d8aac753d9b606ca2a60c60dbb80c21a7ae7a6281508',
                         outIdx: 1,
                     },
                     inputScript:
                         '4102b9d0890ef77f2078e1b6899210039480d66bdef4fdc91c740ecaeec5583f55a731717a32e0dd9252d5bdef096b337ad3ecd57636f6bac8067fc3a78d3c0a94c121039764908e0122ca735c3470ff3c805b265e54589901fcee0d610f0d31b356f7f3',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '312605',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a9146d69b5cbe7c85d87628473c43620c0daa9a8102988ac',
                 },
                 {
                     prevOut: {
                         txid: '8d2a0286607ee744c8890c161da4dd083049fff20e23d721702a47a5b139410e',
                         outIdx: 1,
                     },
                     inputScript:
                         '41a81656ffe952c34a011aa55653846abe1db05de068f2e6a6b91de7b5500d72762a8d37b041c2f9a451f58196e7045aaf0a4bb957768395b37b4f4759c823d1e1c121039764908e0122ca735c3470ff3c805b265e54589901fcee0d610f0d31b356f7f3',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '526877',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a9146d69b5cbe7c85d87628473c43620c0daa9a8102988ac',
                 },
                 {
                     prevOut: {
                         txid: 'b4ba6aea60657f80fbf86c73389ea49c5c95817ac2468a2600635bdcb6143310',
                         outIdx: 1,
                     },
                     inputScript:
                         '4112461349af15cabe257ef0290f2a8e923e33cbfcd7f8d34923e95d5afacfff2407a2549f5819760e3c1ece84b20d3276893638ef8636f366338c8c4a0e2b0841c121039764908e0122ca735c3470ff3c805b265e54589901fcee0d610f0d31b356f7f3',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '1780906',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a9146d69b5cbe7c85d87628473c43620c0daa9a8102988ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a04534c500001010453454e44207e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e50800000000002737100800000000000f3636',
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a9146d69b5cbe7c85d87628473c43620c0daa9a8102988ac',
                     token: {
                         tokenId:
                             '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '2570000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     spentBy: {
                         txid: 'ea54f221be5c17dafc852f581f0e20dea0e72d7f0b3c691b4333fc1577bf0724',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a9146d69b5cbe7c85d87628473c43620c0daa9a8102988ac',
                     token: {
                         tokenId:
                             '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '996918',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     spentBy: {
                         txid: 'f490c4dd2b2a7cf14a04af6efaba9851cd233e753e239ff021296aae4b71ad88',
                         outIdx: 3,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 856,
             isCoinbase: false,
             tokenEntries: [
                 {
                     tokenId:
                         '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
                     tokenType: {
                         protocol: 'SLP',
                         type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                         number: 1,
                     },
                     txType: 'SEND',
                     isInvalid: false,
                     burnSummary: '',
                     failedColorings: [],
                     actualBurnAmount: '0',
                     intentionalBurn: '0',
                     burnsMintBatons: false,
                 },
             ],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NORMAL',
             block: {
                 height: 782571,
                 hash: '000000000000000003a43161c1d963b1df57f639a4621f56d3dbf69d5a8d0561',
                 timestamp: 1678358652,
             },
         },
         {
             txid: '6b139007a0649f99a1a099c7c924716ee1920f74ea83111f6426854d4c3c3c79',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: 'b8c9089f0991676d768920225c8614eabdb8c715e79b22411fe69d1916dcf3a7',
                         outIdx: 1,
                     },
                     inputScript:
                         '483045022100a7e929b6748902fe6896d21d6f542994f594c96b50f33963ee967011d6bcae9e02203e11d0cd2ac4c4f5efb56e1b2f86ed53d995164e08e3ca65a0b60118a7dd6b114121032f047c5282b9f24806f6bae65d1505ad60b555c2456004301f6253f14240b0ce',
                     value: 5000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9144bb6f659b8dafd99527e0c0a3289f121b0a0209f88ac',
                 },
                 {
                     prevOut: {
                         txid: '794c366a60d864ffc5fddf1ffeedf11091b5845657d433a03f4fedd302bd2a3b',
                         outIdx: 2,
                     },
                     inputScript:
                         '483045022100ae739cec070e17a943aea0b59b74aa2320e6223a90191e598a0695fde4300bab02207889e7530838df5fa792bcbe062cc3b3c6f5378dff4723bf0ee80755af6c82964121032f047c5282b9f24806f6bae65d1505ad60b555c2456004301f6253f14240b0ce',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '205000000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a9144bb6f659b8dafd99527e0c0a3289f121b0a0209f88ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a04534c500001010453454e4420fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa08000000000c380cdc',
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a9144bb6f659b8dafd99527e0c0a3289f121b0a0209f88ac',
                     token: {
                         tokenId:
                             'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
                         tokenType: {
                             protocol: 'SLP',
                             type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                             number: 1,
                         },
                         amount: '204999900',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a9144bb6f659b8dafd99527e0c0a3289f121b0a0209f88ac',
                 },
                 {
                     value: 3317,
                     outputScript:
                         '76a9144bb6f659b8dafd99527e0c0a3289f121b0a0209f88ac',
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 472,
             isCoinbase: false,
             tokenEntries: [
                 {
                     tokenId:
                         'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
                     tokenType: {
                         protocol: 'SLP',
                         type: 'SLP_TOKEN_TYPE_FUNGIBLE',
                         number: 1,
                     },
                     txType: 'SEND',
                     isInvalid: false,
                     burnSummary: 'Unexpected burn: Burns 100 base tokens',
                     failedColorings: [],
                     actualBurnAmount: '100',
                     intentionalBurn: '0',
                     burnsMintBatons: false,
                 },
             ],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NOT_NORMAL',
             block: {
                 height: 800162,
                 hash: '0000000000000000135015e9513693999b669e5b024c83a4cc3b4db5dea7e414',
                 timestamp: 1688933698,
             },
         },
         {
             txid: 'd5be7a4b483f9fdbbe3bf46cfafdd0100d5dbeee0b972f4dabc8ae9d9962fa55',
             version: 1,
             inputs: [
                 {
                     prevOut: {
                         txid: '025e232886adbd347cdbbfbe53ab8291aca66b3e0fec35e13367260572b1b14a',
                         outIdx: 9,
                     },
                     inputScript:
                         '41976761151559c9edf23b21b314d1003ee8562bce946f3cc56261245354f4536e93320d5f01c16f3efedfd71d8a32798f16ae4ef562ff173297b95ba863bd22df412103b28690ae5178fef9a75901f6c0974e5d5554dcd62ef1962ee26b55d613f0da6b',
                     value: 789283,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91412934a7a99b69a60c3b99f991cd79d257104f5a688ac',
                 },
                 {
                     prevOut: {
                         txid: '025e232886adbd347cdbbfbe53ab8291aca66b3e0fec35e13367260572b1b14a',
                         outIdx: 67,
                     },
                     inputScript:
                         '41343ae6b5573d542ce7fc5c1ad9d3b3982437f9d3d29fb359ff5c725fb379d73f1e09dc0fb01a9e87ebd21f1cc7c1bf5f9605bef90603489f03845b32b851b75f412102facaf89e3fb087741aea79247dcd947765c07cc7a3b61dd1e00a108e7f09c363',
                     value: 19661976,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91415c0b62c9f73847ca9a686561216c20b487a0aad88ac',
                 },
                 {
                     prevOut: {
                         txid: '282e423192b69ad2fd21b07f2bbc28bd0e48659e8b76c8a7cb494e9632d7bd58',
                         outIdx: 2,
                     },
                     inputScript:
                         '419560a571383df383cc335fe89791675f9e45e00c8fc452c85698d6654822a01dfea76cde4ea4411f9a7a5e3a150c7f0f3fde46d7b2bb1f9446d27d9b911dfe32412102b74d3a97c688764abe5e77aa21784881aa98724f10a323af9e7aff6f5dbf31ef',
                     value: 236812,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914a4e299724b8e81474df916c25c7a816a43c8748888ac',
                 },
                 {
                     prevOut: {
                         txid: '282e423192b69ad2fd21b07f2bbc28bd0e48659e8b76c8a7cb494e9632d7bd58',
                         outIdx: 9,
                     },
                     inputScript:
                         '41c7cf7bd61687724127d21a05ae950a88570475f1433fa3a2477407700624d4785b5cf530422de3f461a009b4ac1806cf8ae2e4938613fc412253b5d8f0137435412102f54d7c16ad99d58a1c2118d71584498055247735eddf494b84f5311d1575bced',
                     value: 1481924,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9147afa62562b93fecaff30190ee3a2836dcb95d42f88ac',
                 },
                 {
                     prevOut: {
                         txid: '282e423192b69ad2fd21b07f2bbc28bd0e48659e8b76c8a7cb494e9632d7bd58',
                         outIdx: 12,
                     },
                     inputScript:
                         '41eeeff8f9f55d7a9106346ca430cb15ab38e3ae49518a9bb0377f614f64e1679c6218a4b60cb086ce406fd0eb298a3ccb7dd09fca20d96dcbbb489acb5ec82d37412102e1065480d2c5df584ee53b6a121103c4f084d37d8932dbf04d10fa674b4d258c',
                     value: 1923633,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91468e15e8bfe2d969b7963181b976e6833e294661288ac',
                 },
                 {
                     prevOut: {
                         txid: '282e423192b69ad2fd21b07f2bbc28bd0e48659e8b76c8a7cb494e9632d7bd58',
                         outIdx: 47,
                     },
                     inputScript:
                         '41670d46d9042b979fdbc2ccb50df231dc8f8dfc8c9ea66180a41ca60ad498a05936b8683daa93281bcf46a18ad838f80f284cccc1de04931381d3279c93e109cb4121020be1664f1cc506d056017b7072633452b3571724560bb73dce68a160cd9182e6',
                     value: 12566124,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914f941b2e03f973ce5b13766159eef190963e2393488ac',
                 },
                 {
                     prevOut: {
                         txid: '282e423192b69ad2fd21b07f2bbc28bd0e48659e8b76c8a7cb494e9632d7bd58',
                         outIdx: 63,
                     },
                     inputScript:
                         '412b5195fe17713edc3b58102ef3e60ef06fe50229e65dd143f23a9a6edcd7956a7148c9d038891a866b0e98627bb1f66f1c9f43ab7716bc5455ed1cf599b553f6412103da9dc1e5ff5116e6d8b4535b9e565e0c5323316b240043ede4f9bf8ae6927bf4',
                     value: 20033202,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9146e3430f87a128ac4509fb0547f07ba0e3e8cea7688ac',
                 },
                 {
                     prevOut: {
                         txid: '282e423192b69ad2fd21b07f2bbc28bd0e48659e8b76c8a7cb494e9632d7bd58',
                         outIdx: 69,
                     },
                     inputScript:
                         '41c07981287684a57d6dff05fe35bb9cf49682be07b51fc9bd1aecdb50dfeaf5646d6bcbf04e45d711ef229fa2564197bc7c21994180491218c063cde76f733de64121020c2f45d704ca5ef65d16520512184601411e4704da88ccaa21ae5d116dd62e27',
                     value: 30370886,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914c72166790bc8c779163e17b11939a6bd6022a7e188ac',
                 },
                 {
                     prevOut: {
                         txid: '282e423192b69ad2fd21b07f2bbc28bd0e48659e8b76c8a7cb494e9632d7bd58',
                         outIdx: 72,
                     },
                     inputScript:
                         '41628d99c6f5ffefb2e8b33874caa20b26a9b2b26a3a353738cbe4f82babb6800f13aa0eef1575cbda249a5488407d6f34614c610613e3e27fcb20b93316e0be2c4121021e0eda5f4d41e5388cae8ed899fcde2571a155b23e8d25199eae7b674f8a3335',
                     value: 37898355,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91483c54d6ec805f4db16c935f5bb89da791f971ac888ac',
                 },
                 {
                     prevOut: {
                         txid: '33160635670dab2a6e89425f2be9a1b1fb742c75ff2684a1e62a44f82c1dae6d',
                         outIdx: 10,
                     },
                     inputScript:
                         '412c5a59a5176563765df132213db2d7767112dfc45df859091d8336dc472df44809449bc9bfcdd29dca69d5784976f04401d4910483f6150b955adc08faa7adeb412102d8ba67b96c5a0371d96d5270f85ddb02b6e9fc4801bd1e85b1877edb52ffbda6',
                     value: 2489718,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914336fb64b7e98221f82aced275440c29e7e1d11b388ac',
                 },
                 {
                     prevOut: {
                         txid: '33160635670dab2a6e89425f2be9a1b1fb742c75ff2684a1e62a44f82c1dae6d',
                         outIdx: 18,
                     },
                     inputScript:
                         '41581270a283d4512a3ffc4179ba1c6650534740b2f8c115c6348d029850d00a5cf3acb70cdb059acf3d6dff94753f8f574acc1e3019df797275be79d912709a294121023353579f3a7d6b492db0132190e675f92564aa23d2b9c3d79654bfab0bba4830',
                     value: 5710023,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914b114a9d636ac7558c04e902c3a1f7c1fd9008bcd88ac',
                 },
                 {
                     prevOut: {
                         txid: '33160635670dab2a6e89425f2be9a1b1fb742c75ff2684a1e62a44f82c1dae6d',
                         outIdx: 25,
                     },
                     inputScript:
                         '4181ae55a349cc2864b2839d67764c8a88d9f5f8e322d16465df763529cc56238b4ad990c617431d17607c43421030c3bb83758da3023846ff5f1a425179311d6b412102c69259026f5ad94372a1d98de97374adda25aebc6858dca8511a9ac1cb95287f',
                     value: 8237826,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91411667c453097adf3e71d08986df7766c26f3399088ac',
                 },
                 {
                     prevOut: {
                         txid: '33160635670dab2a6e89425f2be9a1b1fb742c75ff2684a1e62a44f82c1dae6d',
                         outIdx: 26,
                     },
                     inputScript:
                         '41d7f92d59288eff61e959f9c59cda2b33ca15dbececb2d632f08026aae5608167b401f5e39f3e35a812eca83310ec06c89606eb053eabef78b6838f3306584963412102916d2b0bedeef5c35659f8ea8e54871cf3a2241b85e696dfaea797fb3ac19d93',
                     value: 8485409,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914a125966da9024acea37f867323778641ff0e891888ac',
                 },
                 {
                     prevOut: {
                         txid: '33160635670dab2a6e89425f2be9a1b1fb742c75ff2684a1e62a44f82c1dae6d',
                         outIdx: 44,
                     },
                     inputScript:
                         '41b2f767347acd9142d5f0f9754a2dbf79575eaf9f29e124b15b3536d0ceade8bcdd31d04656ba63f44cd144d66ff724e602c3080b66329b29536e4f9c1fae922941210278ea288a9f62d52ac4d9301779ce177a9d8efa2c650205dd80e895c8f10bec4d',
                     value: 24067273,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914e03ba5757763a00aaa8aa9eda71da51610d5ef2788ac',
                 },
                 {
                     prevOut: {
                         txid: '33160635670dab2a6e89425f2be9a1b1fb742c75ff2684a1e62a44f82c1dae6d',
                         outIdx: 46,
                     },
                     inputScript:
                         '41b2c968dfd3653975ede62f15eb0925cad47d06ec2e01a597efe8aa0db73f9af79090dbc3adad9bcc11a9bdb323240ea178cbe8641907a3c9dfa5e01652bceaee412103d0d7f54b4cf2be2f19d4eceac703f445e1223a134fed95fee7d7d6fedaf7f1fe',
                     value: 25912582,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914b13b05d51174d91381b0ea6fb07a6345eea1abf788ac',
                 },
                 {
                     prevOut: {
                         txid: '33160635670dab2a6e89425f2be9a1b1fb742c75ff2684a1e62a44f82c1dae6d',
                         outIdx: 51,
                     },
                     inputScript:
                         '4195760d04133191dce89bf872b61ad771f9b33db8f36c249418d0cea3e1c7f73e4bcaf151103effd88f82911a831f2e552961df731f7cb4d87db42f97f9ef4d11412103dbd5c06a2afaeef2240ba22bb6c7650d51d18ec16e4ea3edf4ebd795760f96d8',
                     value: 32513005,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914349c3f91c2782b235ae0d1a2c3acf053d554170788ac',
                 },
                 {
                     prevOut: {
                         txid: '33160635670dab2a6e89425f2be9a1b1fb742c75ff2684a1e62a44f82c1dae6d',
                         outIdx: 56,
                     },
                     inputScript:
                         '416e3713337d09659305d797115c9281dc060d65f45a491828ae6e6676db691d4f9d0c473000806d2254303b99effab78ace1f85da921bf22c8a47fe89c465a7dd412102258cedf84db0614de15c53a92010e0bf2371c386403457385ed0c1ab8ba38e29',
                     value: 70247919,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9143afafec322ef1a4f70a6ca68dd9090182716181888ac',
                 },
                 {
                     prevOut: {
                         txid: '36fe871b850030281c9325d67ddc3aad32f179f2cfddbfc6f92e1923a4027587',
                         outIdx: 4,
                     },
                     inputScript:
                         '4198de475fa1ce6eaf983ea0a021ed49ef35c3a96cbd4ba88769b1db92c0455b40e50261eca6c7d7a0edf8a8f5fec1fcd405c5cc9c19c2db691ee7652866ec704541210268a9995c00a0588bada4e48264f7cd0fc1c139bc8ee1b009d1672a5700689c14',
                     value: 1199454,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914cb74cf87cd355cd01505645eaf165646a4eb1ce988ac',
                 },
                 {
                     prevOut: {
                         txid: '36fe871b850030281c9325d67ddc3aad32f179f2cfddbfc6f92e1923a4027587',
                         outIdx: 8,
                     },
                     inputScript:
                         '41d735894ba83cdf74b971b1ae8903ac72215378941798b3f98389c845f1092edd186648e1108632bb98ad4b85a5f3aeaaf1468498e8a61c29043f978acba2713e412102c6a66170358d332c880609845feba09445468dbca3977f8243b71f7708a38931',
                     value: 3496387,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914c42245ebeb7fea2996e5e0f65537b56fb58ea97d88ac',
                 },
                 {
                     prevOut: {
                         txid: '36fe871b850030281c9325d67ddc3aad32f179f2cfddbfc6f92e1923a4027587',
                         outIdx: 48,
                     },
                     inputScript:
                         '4127e265aaa3ffb1188d61c01f48597045e0b20cf03d6c0a6d261b825759c1402e8a81ed03d6b7f02dd9d433931d8d56e8c4c3c929bdfe6166864ed13fa6a14c2041210247e436fe91fd245894bdc61f01fac054f2c2a9e14e3b16584d28d0396546b208',
                     value: 30653501,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91447d7bc2240955fd18d53c67c4b814e166b152ec388ac',
                 },
                 {
                     prevOut: {
                         txid: '36fe871b850030281c9325d67ddc3aad32f179f2cfddbfc6f92e1923a4027587',
                         outIdx: 61,
                     },
                     inputScript:
                         '4132fab3b2ee76ff4f2a9608029ff01a499f04b048a53238d09f2ee5545667e5d76053ac9a018530aded8f06e07b096caed77d6d8b436e9325deca58ec33381f1b412102677e892b57954785abea57b508662752d134e1b85b0cf8c924c382e957b424f5',
                     value: 54383530,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91410b45d95195a71957b43bb82762e6cb48e67888f88ac',
                 },
                 {
                     prevOut: {
                         txid: '38aea1067bc178c13d2498b573dd13136d0bbbd59bdd4174d8323efa7925d709',
                         outIdx: 44,
                     },
                     inputScript:
                         '418c33f23f296bd45cc26514ca2acb394e76e0c0085af0f5bb72fe94192f9f81d3cb3eca750aa64d8b73c0ff11d3788b46a08b308de793789a0db203fcaae7f4334121025754d300a9c992376c28aeb2f711579e072ced8a6a9f8f6f5046e2dfb34773ef',
                     value: 48782413,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914894e84afe4b07413c99087067292aca67d286fbf88ac',
                 },
                 {
                     prevOut: {
                         txid: '3e6a7a945ee1141be605f62cd7a36d94532340c736a5db4e822ebca4b0548b57',
                         outIdx: 9,
                     },
                     inputScript:
                         '419585e642c12308cb16dc820f8432ca140ce85050711a2d0ddab19836248a6e8c7327c8256af217010b812593753105959f3b9d957c77f7ae81b1798cbe1322b1412103a3325e9436167659795eb6984a33b890c7e31a2d2b860300a892bd1f6d186220',
                     value: 25031767,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91473b804181c01f16cbf63fe262e9a0c8de929af1e88ac',
                 },
                 {
                     prevOut: {
                         txid: '47162a965a1b9baa086b90427a4dc73ed100e88aa3419fd675cc9c15d7a2264d',
                         outIdx: 50,
                     },
                     inputScript:
                         '4167257a33b15c13d334a2d69bb9b466c3dbac7a9017b1bcf461eb07a3443a6adba372908235a3262685d9d634dd2341547bc086c617ea3df0412452a67b0b291c41210248db002b83e2c614ae5b956b686961823edf5bb0db2bfa4964a24bfbcfea2c7b',
                     value: 29615068,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9147b1a9441467759f8693bdac3e356ab6110bebe1c88ac',
                 },
                 {
                     prevOut: {
                         txid: '5646ba9af331a3d4e66ef46ae34a09be90a101fe6f94efba2a612122f3dbe057',
                         outIdx: 9,
                     },
                     inputScript:
                         '41de35e2cdc2e176b24d8f519d84a27c9b13ac3f01ecfb850c92e9a7c2969f2bb1d86d8e00572785bde21d6da669fa131c20e368ffeb0157349cd609bcde748b6e412103a302b269baec427ad945dcef291a2b9bb5f91ae1d287899a66bb34b3d4d19f95',
                     value: 3563255,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914443f7cf9987b921c10d888c3d617c54aba5e8fb088ac',
                 },
                 {
                     prevOut: {
                         txid: '5646ba9af331a3d4e66ef46ae34a09be90a101fe6f94efba2a612122f3dbe057',
                         outIdx: 21,
                     },
                     inputScript:
                         '41dcb57eb57157c7ae624a100e5f4c71fc2173eb81befff2f15b521105ee553f31118d2eeec770c8e43a6a2ff15e689d81128239184ae7d844a9b382a84906e446412102321799e9dc1c2dc6c9ddfae967c7bb81bb2e64d2c59d57d35c3ca8292de56291',
                     value: 11787007,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91490de1562e4aadc991dc13d28a9d112461fea9cb888ac',
                 },
                 {
                     prevOut: {
                         txid: '5646ba9af331a3d4e66ef46ae34a09be90a101fe6f94efba2a612122f3dbe057',
                         outIdx: 40,
                     },
                     inputScript:
                         '4157367017cd6dc848750f538e5fd32b0d7b1f69bd7b2bca0e43f772374d65b8e1558acf8544c577e2ebc4368b320f07c25f146fa004fb30e45fb8c9ae608b8afd41210360955914b784f0100bce4935f6f17c1417387598b0bebd1d7c15fc2ebb27403f',
                     value: 23443485,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914273808f74a845b9b77345d43cb679ca793c5e9e688ac',
                 },
                 {
                     prevOut: {
                         txid: '5646ba9af331a3d4e66ef46ae34a09be90a101fe6f94efba2a612122f3dbe057',
                         outIdx: 44,
                     },
                     inputScript:
                         '414d146e2e20940c99323f0502114c2afbad68e1d772cd20bdf8a7d7894c5775952af95dcea59dc8e91ac4cde30af03cd308e4092c5d6a0a7ccd7a131599448856412102b7f55d64e8ba20077f2c9e629c312e2da2667689cc7835d6b5f9fde0245d1cbc',
                     value: 26370841,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91402a6a02a8bbdc6a9ebeb74bf5d8b9f7d20ad386688ac',
                 },
                 {
                     prevOut: {
                         txid: '5932b2af9cb1226b9bc59233427afe37c9c7f88f650c5a834e343022bc40bc5b',
                         outIdx: 18,
                     },
                     inputScript:
                         '41ea0603fcf7d14ccdc4efffc0f3c651c4e3ce57c404b2bc9fc5f71fd652a7ce2ba3cb1895206ed3b59ae0d58071912b3ab3f46a1f0dd5539b254ae8b0740a0065412102b7fc7453a54a1ba3f31046d9ec78e102f640cade834efe5edd3a0d0a947844e4',
                     value: 3053762,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914fcc200903ed9167def3df599c599d0c98b2cea0588ac',
                 },
                 {
                     prevOut: {
                         txid: '5932b2af9cb1226b9bc59233427afe37c9c7f88f650c5a834e343022bc40bc5b',
                         outIdx: 22,
                     },
                     inputScript:
                         '41e80a5eba60db24a51c0599b6b2e721cf9a46bf818fe0e9cec40b855ea5a928e24ff25767d3bd34d6d6c184d50590f20dcf73a73f9ee56ecc7a5cdfed65e5f710412102f6553541f1d9cd9faaeaf53342ac09a2c7c6b5a598c112060a6f3f894ca50851',
                     value: 3278623,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914692a38590fe1786dca47d2cbcc0ee30d969ca0c788ac',
                 },
                 {
                     prevOut: {
                         txid: '5932b2af9cb1226b9bc59233427afe37c9c7f88f650c5a834e343022bc40bc5b',
                         outIdx: 26,
                     },
                     inputScript:
                         '415bea41b13af76e10f4807c43fb577363399b369b1d83bf2382fdef48235a7c32a2ef9d3a98156458ce3e85df259b5351d37bf9a144f2eb736fe562542bd0479c41210285cdb2a7fb877c0dde24ab437ae152ee7e8e32e9c850f16fc5f9ed23a95bb53c',
                     value: 3534883,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91486b2a4458787245715865c9ea5e42f8d68e8828988ac',
                 },
                 {
                     prevOut: {
                         txid: '5932b2af9cb1226b9bc59233427afe37c9c7f88f650c5a834e343022bc40bc5b',
                         outIdx: 48,
                     },
                     inputScript:
                         '41751e7046792b1f4961d3c6369d24fad477f0be0120a3b89afe6768d6e4dfed8b24634f020178308fc07065f1c75552277611241313aea2174e355a3a395aecbf412102051de8523c2910874441e60fb9216be126effc875a7fe94bb427fb5c6fa353d6',
                     value: 7546746,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914c472cd5ea7282180aa6a663498e98c2b781afa0488ac',
                 },
                 {
                     prevOut: {
                         txid: '5932b2af9cb1226b9bc59233427afe37c9c7f88f650c5a834e343022bc40bc5b',
                         outIdx: 58,
                     },
                     inputScript:
                         '415750a10a4d6d697b0e7a69c69b5ea5ebc2c382153dafed928cbe1427a9c50bee62dcb3623317b4eec2d1563eab85f8bf7b9c1bc72e981dd4e546e6588ab864b9412102d9e8928fa33d190ff0dad48989804494016914fa7ace7461793a95b4ea4b7928',
                     value: 11875440,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914457a8a10ca1b8ab373c7e5e9ea7d784e8ce2efd188ac',
                 },
                 {
                     prevOut: {
                         txid: '5932b2af9cb1226b9bc59233427afe37c9c7f88f650c5a834e343022bc40bc5b',
                         outIdx: 60,
                     },
                     inputScript:
                         '412dbd961304300e86d8589586f5553757ff2ad49ad7f5f044c4f4b73a95a81d6b853d35f21de4b058743be38b0d3f239690088897006658591294a875f5400f2841210203553bdf5e4c0406661b10b9bba39ae1920144eec88414acd18bd5ec838f31ec',
                     value: 12066672,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91406cbe837f5a8b81ec8fddcf6e46c15b84b43965788ac',
                 },
                 {
                     prevOut: {
                         txid: '5932b2af9cb1226b9bc59233427afe37c9c7f88f650c5a834e343022bc40bc5b',
                         outIdx: 70,
                     },
                     inputScript:
                         '41d6eb014368a0f5afc239a5524ba482f04fbf9f93e5604a60fbf8de342f02f6af70433dd065b9d6c879442d32a1370de5c623796f492f62f703a502f0723bf36f4121029007d7023dd0a6b7bcd1c9ca995d0b707ee727ddf4fa035e93d245554f9dea34',
                     value: 31042739,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9145ab8a85ea3f6bf3a69b15b9f7570aeb021df77b488ac',
                 },
                 {
                     prevOut: {
                         txid: '5932b2af9cb1226b9bc59233427afe37c9c7f88f650c5a834e343022bc40bc5b',
                         outIdx: 71,
                     },
                     inputScript:
                         '41bb8e694016dfb2b475a93fd6478ba4d97ce55b4753b4552e0ce46bf477a66d28f7f8bf63ef1fe770acc281c8305b7579648c60de4b1f4cf7d2ac783f09af5e1341210217c675b14a2e262379af4407533eb2ffb11df17394feb380be4f272b2c3c9b63',
                     value: 34725141,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9149704c9d13afb31a9b84ea5cb56140499e54743bd88ac',
                 },
                 {
                     prevOut: {
                         txid: '5ba0d328f4e845887fab783234db98aa1c4a73cb5cdd14a2503af78f520cba8b',
                         outIdx: 21,
                     },
                     inputScript:
                         '4157fa15e1e46502edabc7a33472cfafd75fd88ff75331cdd6e1cdb28384e69cac7b4529ae34cf37f3e68699d7921da7354bbd9ade45c2487a81b7935d9a46817c4121036e3cf1f1fe4d0be25ab9cfd2acaa0617ad06a6ab6cbffd2ee01380fed51db99f',
                     value: 4898437,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91423dab92affaa336ae18cab2669d116fbfa55b0bf88ac',
                 },
                 {
                     prevOut: {
                         txid: '5ba0d328f4e845887fab783234db98aa1c4a73cb5cdd14a2503af78f520cba8b',
                         outIdx: 24,
                     },
                     inputScript:
                         '4160979fb8cb7cdb2ebf7e3fe9f8d9cd0d287cd574c0192b10d795c9e57f69135250e8bca7cc024c6d3392e6f6e5445d78bfbade6d84633fa88e3bb404a3ec3767412103bf8958e3824e6ef7710b8a212ccf1ad13488ec8951d4efba45e836e921b15da2',
                     value: 5379161,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914c6a520edfedb88ae478c1fdb309739d62d47dbd088ac',
                 },
                 {
                     prevOut: {
                         txid: '5ba0d328f4e845887fab783234db98aa1c4a73cb5cdd14a2503af78f520cba8b',
                         outIdx: 32,
                     },
                     inputScript:
                         '41b79dfb5bf4c291742010c1e0b8972665c1a8e583bff07c26bb2f35125a43f9362fc88f7713547c3b19085eeb3b9933aaeb1820168fb7fb9a1173dd6d9ca011cb4121039060518676dea799bc646eaf5a86e2c6e38e6a48d8c809e125e6ddb29ed63941',
                     value: 8316321,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914388d048805daa142def4833f5cb1e02db7013a6f88ac',
                 },
                 {
                     prevOut: {
                         txid: '5ba0d328f4e845887fab783234db98aa1c4a73cb5cdd14a2503af78f520cba8b',
                         outIdx: 60,
                     },
                     inputScript:
                         '41c2793e60ee18ac376d860fe3a6abbe5e1c8b562c661a5888c24ccb5def8f9fd56b1db4cd28ffd2becba4acce97061cd85432ee7482ba239200a929ada7acf960412103f2e23426245b7e8a64af3b3dfceb9dd6459467b72a58ff7f2fa7f3d885b3861e',
                     value: 35352936,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914cf55018839d8ab8b93de655551357d081f8120c788ac',
                 },
                 {
                     prevOut: {
                         txid: '5ba0d328f4e845887fab783234db98aa1c4a73cb5cdd14a2503af78f520cba8b',
                         outIdx: 62,
                     },
                     inputScript:
                         '414b06e85ca333742e179aa5f2088b44bd40cd403625e6cb5cf8f0e80afe13fa058890656c653a6d6f2a9aa1b22af346928424330e9f701f8214c4409bc2e25495412103efddc9a5ddb955265e7006ddac64c2eb46bafdd882dc65dcaf276c1d0def176a',
                     value: 40175305,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9147eb48844af0ceae69879fd66456a5afffed24cb788ac',
                 },
                 {
                     prevOut: {
                         txid: '5ba0d328f4e845887fab783234db98aa1c4a73cb5cdd14a2503af78f520cba8b',
                         outIdx: 64,
                     },
                     inputScript:
                         '41b0949073aa877f7fa76933c4fd68f9c8b482a844cd6362cfa10fefd782ec74a00a9cb268faa693aeb6861ca8a74a842f1b5b58279314421fa4714688883e94f8412103f0ba973ac5827cfb13ff7015ad2bdc5fbf322e369c71fd1798a9ee3c1faea606',
                     value: 40956943,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914e94c40d02b7860a76057a48b826ef847372eb74388ac',
                 },
                 {
                     prevOut: {
                         txid: '62234103fb01e526293bb3b88696a62dedcc830eac4118265980937471197b11',
                         outIdx: 11,
                     },
                     inputScript:
                         '410e57d52ac09032c8d9b78973af542c65301d16c7c9af11d7e8c5a5ef600bbde36dfa545c88490ce88ddc300658263541132a765895d51deab392f31c95fc2d21412103ec54521d0f77db84614164b9f294e8db801fcbf5c5681192d9b1479cf88287c2',
                     value: 4594328,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9148fddf18aecb230772dec7d9fa6ec5c2eae1303bf88ac',
                 },
                 {
                     prevOut: {
                         txid: '62234103fb01e526293bb3b88696a62dedcc830eac4118265980937471197b11',
                         outIdx: 22,
                     },
                     inputScript:
                         '415a307caf8836205fb11e2464b77ae02919ac3a9dcfcfdc18d9d79860a4c495301389fecf65ea97723717b38d489d71e4db3e53bca9f1c6bd5fdba3204e5421d54121025b736a838ac5bceb5b40988e49c32902d5989f3fbc9051ec98ba0b6808ef073c',
                     value: 7254551,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914687b26740360cae141c61c9e5dcb03b6100dc42b88ac',
                 },
                 {
                     prevOut: {
                         txid: '62234103fb01e526293bb3b88696a62dedcc830eac4118265980937471197b11',
                         outIdx: 30,
                     },
                     inputScript:
                         '415088aa133d722e072f1a090eb676c025de7154a2d2e2bdd6812b58b1101ceb53e6c0b27e24412045044dcdb06e88276f4f4a63e28f98c39b3d67453e5dde9d5741210271ba59b7662f1f7a346065cfa4738cf05521933841761b9cfa31f5e72349f494',
                     value: 9563229,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914c9fd6f67f21b1970264ba239e82d4a3c40e2063188ac',
                 },
                 {
                     prevOut: {
                         txid: '62234103fb01e526293bb3b88696a62dedcc830eac4118265980937471197b11',
                         outIdx: 31,
                     },
                     inputScript:
                         '415a220e9c760930cfceec2c3d60958e313cb5cecf99ef7fb70c6e26dca5c5b13fe4a64db7fbc2cb26b9b619964fd76f35a2f35f0c4c78c68d8b1705737141e26c412102d190001af9db94b3de57d023ac2d17d0d62d7b5b6c351fd25b77ba2be0223539',
                     value: 9731469,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914cfbdaf0aaed19c7fc5e2a39e77cc780db5e333b588ac',
                 },
                 {
                     prevOut: {
                         txid: '62234103fb01e526293bb3b88696a62dedcc830eac4118265980937471197b11',
                         outIdx: 40,
                     },
                     inputScript:
                         '415bd5dd0c5198a32c904eeaf61bcc02e473895b5e7e2f5f8e86486eb9a53f7608981be475a2dd42964d4fca04bca1e29d5b18fe6ebf0d4ebaebd7687b8327e8a4412102822ab05d098e4f0f455263f970104eeb0942ccd5f3e36415af2b202b5ace86f9',
                     value: 15786585,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914a17017d5f758fcc1372746bce8509c3d23f218a788ac',
                 },
                 {
                     prevOut: {
                         txid: '62234103fb01e526293bb3b88696a62dedcc830eac4118265980937471197b11',
                         outIdx: 49,
                     },
                     inputScript:
                         '415f3acedc835b8fceec445222063ca869d4260d89746c16746f237ea244c4412011ede5b644040ecd62e0761216924226b985217ce56cec35054fdf20ab288b6d412103d6fdcf7626fe46d001e5bb777d92423a056054084d61a2c0ffc91a0c0cef8df1',
                     value: 21867579,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914d179b30a22db1d4aa04c163f7c1474fc1fbb5c5588ac',
                 },
                 {
                     prevOut: {
                         txid: '62234103fb01e526293bb3b88696a62dedcc830eac4118265980937471197b11',
                         outIdx: 58,
                     },
                     inputScript:
                         '41fed29d22902a017b75ec8e04c708f964145e791f5c368c318951f9f23b063c4c4777fbfc07c0107fef490fc4d6495a64de759a384f478bf1c12b84d26d21986c41210351b5cbd17fddc51a2add3d88a1d9fabc29c56ca6d3e912bccc71e69a6342728b',
                     value: 71746009,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914f3f590529240d25b82fe10c18efbb64a64f9625988ac',
                 },
                 {
                     prevOut: {
                         txid: '65dbfe80fdf94e042b0e775a66baf02d0ee4e2148fea4b8388500847bb5c982f',
                         outIdx: 0,
                     },
                     inputScript:
                         '41dd8c68989718bf445ab5d7809b6516cdec095eab8acfc2e34d8ca9670c1502b8d1a677ede2d4000f4588a82b78282912aa27f83338f69cbf3fad727e81b80da141210300570f3c1121d37167795f36dbe7bf4bfbfbea4b04507f5ca42d2dfdaa85983b',
                     value: 1688043,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9143856ed1d33df771934e14e0446518fa21c8ef6f188ac',
                 },
                 {
                     prevOut: {
                         txid: '754f2405fe479549e4c51ab41811f5a864fa39e5a9f877265dd0e74d6dad47ec',
                         outIdx: 2,
                     },
                     inputScript:
                         '41319c8dff13ebeec17d74d83a8c728c8ce913e10f4b2291d2a99457b404833558f591d3c174aef7e5c637e0aaf6d2ab3a250af3549ddd6b52d4232ade8aed48b4412103387c765fda65b283de425b4fa1388727056c325bd22fa698a4ace6df5ba6fe91',
                     value: 8049989,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914d26a1fac6b5c02e98e839956f3a7547d0c1b5c0088ac',
                 },
                 {
                     prevOut: {
                         txid: '7fe346109f69368dea5581448d6bd0046bfcb57892ce8757534c05113c7cab3f',
                         outIdx: 45,
                     },
                     inputScript:
                         '41260777d685ff3b0552995d998880509ef6af55383d352cedc88854c40e243832a2dbdd86b1503b93ebb5e2e3f1f6da1dae27a0cefca73d40a8995ad69ee5d033412103ca8f1e6ef5fa63f97fd1b05a6421c1d768df37c2b6b28764c1ecd73bab20a13a',
                     value: 15469696,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9147cf1203b978724009018c3a5e6a605590f6e9fed88ac',
                 },
                 {
                     prevOut: {
                         txid: '961956635297554fd150048a6e2adaf1441caeb8a8f7cb824fdb79329e7915ce',
                         outIdx: 8,
                     },
                     inputScript:
                         '41d50570bf2a07db56c2e28faaa9299ea251b66a0388d0c816c7591c7c8c3b90e013560d12266b45c589e2badcd1753e35bc7caf88db1e80d119c9ad77c73044184121036abcc7db8ffa1dc62c2c0ee5f87011e819e4f15f40d70186cd7acc9e2b705f2f',
                     value: 3192502,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9146e56ad4a85fa5e2d03f3bc16b52cfcab65c5e74188ac',
                 },
                 {
                     prevOut: {
                         txid: '961956635297554fd150048a6e2adaf1441caeb8a8f7cb824fdb79329e7915ce',
                         outIdx: 48,
                     },
                     inputScript:
                         '4149623ef1ee7ace2c8f33db67c9b2ba5d720e47b95242afb1aef62c9d7e4bf7de91cb4236daaced175a55f2946e13b76b7a403c90f77082ed74c922058c2826494121026292302c75da128dfdf92827bad355bb00f677176e630c2fc7f4b8e8e4144177',
                     value: 93002901,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914d17e89b26be59dfdbbd2582afdbf785cc11ad56388ac',
                 },
                 {
                     prevOut: {
                         txid: '9da7a74dd4066e8444630cb3d4557ca8a7f786098733b4ec6d39ade509c6a947',
                         outIdx: 23,
                     },
                     inputScript:
                         '4136f2d23997838269068038af56408bea30e58d2aaa24eac9798cd7fbd544fd2afbb021178360ec86383f54ea6de1c6e32ea83e96acbbbbb87319614e4aed04ce412102d1dad4b5d20dca9c748452c3a3d64e8d589fe31edc8cdef66c6b083a34733af3',
                     value: 2523800,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914888bdff661832d406351713b49c683776b90e7b088ac',
                 },
                 {
                     prevOut: {
                         txid: '9da7a74dd4066e8444630cb3d4557ca8a7f786098733b4ec6d39ade509c6a947',
                         outIdx: 31,
                     },
                     inputScript:
                         '41dce1809ca31e4db35d4406f14d1f7da2810a2c662e281342f64e68315f400428c9d7d574faca017044f616b82c63a5c00016212e85cdf1ed4298a2c8db3d8eea41210279aca93bb100bdc842f277f032c8854d089381350609cf5980f904e994201c52',
                     value: 4330481,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914e58661c82c66669cbaa2d1e813009d0b5d2fafb888ac',
                 },
                 {
                     prevOut: {
                         txid: '9da7a74dd4066e8444630cb3d4557ca8a7f786098733b4ec6d39ade509c6a947',
                         outIdx: 46,
                     },
                     inputScript:
                         '4178d0f9b72584bf409e1c72aa30ef0cbf4449e5d8ecb74d730045bc8397cc870c64af6918f62ce39b4b51f01b56c24c9bbaed750649625ec3eb5383738fb0b5ca4121027ed4bb82bd6ac94dc17035738a21565115f92b842682c9c7fcd6108b767ead7c',
                     value: 7600077,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91463b5940d2fd7d998b343a54986ca375ff8cd2bbd88ac',
                 },
                 {
                     prevOut: {
                         txid: 'b41a4d09e492f66f611bba3ca2cf2c3eaedce811e9cca9a1706ede3b4ae594f1',
                         outIdx: 0,
                     },
                     inputScript:
                         '41569f9dbdf60f88d56bebbc24ebc8a48ffc3e504af9a4fc8d027d2aa30da0113f30a042028a631ed87333b10f988c49af8db233812019e63f0d4892674de2c3d8412102128780d9d337449c3b2b9cd1008a25acf895fedb6f2706e74916943e3c2d33c2',
                     value: 66688896,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91490b66329b172fd43feacbbb461c54183eed1bd5d88ac',
                 },
                 {
                     prevOut: {
                         txid: 'b9a5cb585cba98a1b13d698e0c19d332e8532119de7e1410e9ff1dfd26ac0516',
                         outIdx: 0,
                     },
                     inputScript:
                         '417c5e22211868b30521f5421a1ccaf00e0ae2bbf393f9b33de9e126b4481575eb2baaa6f47bd74c204bdebf8a0c0a522c3f500c92f3df2fcc539dfa2fde91a605412102128780d9d337449c3b2b9cd1008a25acf895fedb6f2706e74916943e3c2d33c2',
                     value: 5668556,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91490b66329b172fd43feacbbb461c54183eed1bd5d88ac',
                 },
                 {
                     prevOut: {
                         txid: 'c76711c1bdeae356b492ed630b0e8044d28458581171e1bccbfb92f2960974c8',
                         outIdx: 33,
                     },
                     inputScript:
                         '413803bd25ba0ff5cd0414441dfc96cf7efaa7b6b944b4611845c4c60e075cf212c57706830e19b4007c7f7ae17c4be3ab20210662bfeb3102ba844ff22f1259c04121020f29f7a7d46ee6c29de9dec33226b4600a83a00a44ac085278c9b7ff3c8fb3b5',
                     value: 9521209,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9142fd4bdafad85abcb999c4bab8a2901f92caf487988ac',
                 },
                 {
                     prevOut: {
                         txid: 'c76711c1bdeae356b492ed630b0e8044d28458581171e1bccbfb92f2960974c8',
                         outIdx: 39,
                     },
                     inputScript:
                         '41f9f621a78ec30bdd9ef8502039d4a6f97732b31f39b591d96b1c2562f951e41cc89f0aebddc39b532a1255951556fbf5bf28544a7f9c85620303bc620dfa99d1412103d3c212b78eeaa67599c99479c11259100f8d44f5e93a2620b1e7264ab4cd222f',
                     value: 13527166,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914979d66b56061bc4b7ac2118f54aecbf86ae5773888ac',
                 },
                 {
                     prevOut: {
                         txid: 'cb3d57f259b0cab6c9a40a8f19b659a96809bafb7fbbf87bea6e9fc10e2c12e9',
                         outIdx: 16,
                     },
                     inputScript:
                         '4154b81b0cad31762ded80ab3f5e159fe0245553e1b6e69d153b8c3cb1d4f9064b89d9d8f29b09be3c8191e93ddc7f45c42c016d9b41859a8da851087e1a73a0be4121032870664b4cf912df5171a4a76b0c7c89bc3f9422070e380bc6ce93e02018d886',
                     value: 76789054,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9144724b6e46690d083ece0390ced609aeb0488486988ac',
                 },
                 {
                     prevOut: {
                         txid: 'cfe05ee47ffbb2a60d93c94d1b2f1cb055e3503f43838d6cbc5565dccb5f1a19',
                         outIdx: 15,
                     },
                     inputScript:
                         '413f34f797ec73f8fc8579008566f790a95da2c02311f1da1f6bfc4a21c72e8bd56bf8b134d2d1e409a53e372825b9c5267d23a87a8599b56129694f25c24a1cf44121030d1c53703449c09a10a12ad03997d2874052f53746f4436d1a108cc20f528407',
                     value: 35013098,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9142342542a4947b9bfcedffa803b369ec8c108b0b488ac',
                 },
                 {
                     prevOut: {
                         txid: 'dbc28e87b613c97c6cdb9c646a257a27a7a5c9ac663d4a049ddfc34163cccbbe',
                         outIdx: 10,
                     },
                     inputScript:
                         '41f6107a78455d9b3db251d5c3e2478ab346c0876c66c96378a05c38eceec88263098b0f704881d6cf3456aa7be47a6894bfcd121c26742e765cc037f37744b2664121036033a99e5fd9bfe41940c466ab043eb27ce45d2f28753559894f84114c34c51d',
                     value: 4158314,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9140f18bea6bafd89a55997c72703006ec7a83d6e6988ac',
                 },
                 {
                     prevOut: {
                         txid: 'dbc28e87b613c97c6cdb9c646a257a27a7a5c9ac663d4a049ddfc34163cccbbe',
                         outIdx: 42,
                     },
                     inputScript:
                         '418b6fcd73acbaaef9a063d64fcd86597e490315edfe709aa302d429c6438b52dcc6e7d324b59612b202d4239bef09d8dff1e42363a0ca4716bf1329d8441b01714121020238ff720ccd27a92f0bb0ea63d0c08b73291cf283bb422fdcb63bd9b0a5254f',
                     value: 17803274,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914a7bf09e5099224ead64cb27cc9eb38283c3cde4288ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a0446555a0020ab3267b0b667ea2252d414b3714d6f08b5fbf16c0026ce454c903dc6ff002255',
                 },
                 {
                     value: 506531,
                     outputScript:
                         '76a914d7fc1d156d8ec4384623bb8ceb135df93f2bd93188ac',
                     spentBy: {
                         txid: 'c5f288c020ec4e8701d2114d0f4d7970e9e01e4396abd10ddaebd6e4b44c3d5f',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 1175076,
                     outputScript:
                         '76a91447da14cfad47a7971dd345821ac7a81e194e474588ac',
                     spentBy: {
                         txid: '9086ca2908df5f06b61ca2ec2040fc3e7bd39843e35b934f23f89ea7196c7036',
                         outIdx: 39,
                     },
                 },
                 {
                     value: 1557619,
                     outputScript:
                         '76a914d6b7baf14352dd9769a9a8bdb1f69cf700766aca88ac',
                     spentBy: {
                         txid: '021b600e1425c69c1977daf2e72a13b83fe40414061641011573eef88834dec1',
                         outIdx: 46,
                     },
                 },
                 {
                     value: 1685802,
                     outputScript:
                         '76a914bc53fc8620ece064004a7bb72f0613a0045f6ae488ac',
                     spentBy: {
                         txid: '021b600e1425c69c1977daf2e72a13b83fe40414061641011573eef88834dec1',
                         outIdx: 47,
                     },
                 },
                 {
                     value: 1957993,
                     outputScript:
                         '76a914ea34af00f2585bddc37607af492a7d5b35d431fe88ac',
                     spentBy: {
                         txid: 'b3368d0b4495896c4e057a0be8df58cdead551057c0103f35a5e3a4dce7cf4b5',
                         outIdx: 43,
                     },
                 },
                 {
                     value: 2280297,
                     outputScript:
                         '76a914dab80f23ec17efe39e3167ac47575f5b102855d288ac',
                     spentBy: {
                         txid: 'b3368d0b4495896c4e057a0be8df58cdead551057c0103f35a5e3a4dce7cf4b5',
                         outIdx: 44,
                     },
                 },
                 {
                     value: 2804591,
                     outputScript:
                         '76a914f10147fbbff24aa9f4f9a9f3726760a4abad6a9688ac',
                     spentBy: {
                         txid: '24863ec1bc8eca7d449a37a5bd3bd85e7ccbd2d77ee51c84e1b5b8ade8bada01',
                         outIdx: 45,
                     },
                 },
                 {
                     value: 2810950,
                     outputScript:
                         '76a9140b8b9344a473853830f3657c7247e4834171d6fd88ac',
                     spentBy: {
                         txid: 'd3942acaefee091f6bf0a9d34282988b31458bb6b10b7cfc3fcd3471be3c2ea7',
                         outIdx: 50,
                     },
                 },
                 {
                     value: 2862208,
                     outputScript:
                         '76a914a0737c0938d04eff2d5074513ee5fd3fd41de38488ac',
                     spentBy: {
                         txid: '9086ca2908df5f06b61ca2ec2040fc3e7bd39843e35b934f23f89ea7196c7036',
                         outIdx: 40,
                     },
                 },
                 {
                     value: 2880530,
                     outputScript:
                         '76a914b5d94938a3665b01fc0afee6b6179bb2b9e46b2e88ac',
                     spentBy: {
                         txid: '9086ca2908df5f06b61ca2ec2040fc3e7bd39843e35b934f23f89ea7196c7036',
                         outIdx: 41,
                     },
                 },
                 {
                     value: 2894084,
                     outputScript:
                         '76a914dbb0e87717a034774a2435db6c9d4791f58bd43f88ac',
                     spentBy: {
                         txid: '1d385f3ca974110728849913177291fc4e303bdb03481b9bef7adba15734d18f',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 3104218,
                     outputScript:
                         '76a9144e3bebebb3ac2785181534094eadccad4ea8dc4688ac',
                     spentBy: {
                         txid: 'ae14b96fc44c7f43c3c2fd268e484b26d8f4794afef5767392fb1c246d7d3e0f',
                         outIdx: 5,
                     },
                 },
                 {
                     value: 3122421,
                     outputScript:
                         '76a91458c2d76cd32e1d30d0e62b641d50bdd89200a7f188ac',
                     spentBy: {
                         txid: 'ae14b96fc44c7f43c3c2fd268e484b26d8f4794afef5767392fb1c246d7d3e0f',
                         outIdx: 7,
                     },
                 },
                 {
                     value: 3419974,
                     outputScript:
                         '76a9142980d02fa9a25306f3dd195ab9c82a2e2877f67e88ac',
                     spentBy: {
                         txid: 'e59775f4ca2828c87a5b31e415e657d571184891c62860acd5a23523830e38a9',
                         outIdx: 3,
                     },
                 },
                 {
                     value: 3594078,
                     outputScript:
                         '76a91451331eca38c944f17ee6354a3ee48193c7eb1b6b88ac',
                     spentBy: {
                         txid: '24863ec1bc8eca7d449a37a5bd3bd85e7ccbd2d77ee51c84e1b5b8ade8bada01',
                         outIdx: 46,
                     },
                 },
                 {
                     value: 3794311,
                     outputScript:
                         '76a914755b984555fcd6305583c21d996a8dea7faa67d488ac',
                     spentBy: {
                         txid: '9086ca2908df5f06b61ca2ec2040fc3e7bd39843e35b934f23f89ea7196c7036',
                         outIdx: 42,
                     },
                 },
                 {
                     value: 4241488,
                     outputScript:
                         '76a914e245bab4243bd6a8f3932c9dab9df496f003eae488ac',
                     spentBy: {
                         txid: '0ec20eea27fcc5eb12211157a64eb34c58b6df3911d5158faa5824e5fd3002a0',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 5771042,
                     outputScript:
                         '76a9147901f7c02a7fb7de87c373c143e15e87989f764b88ac',
                     spentBy: {
                         txid: '021b600e1425c69c1977daf2e72a13b83fe40414061641011573eef88834dec1',
                         outIdx: 48,
                     },
                 },
                 {
                     value: 5801672,
                     outputScript:
                         '76a9149db2a709e1f26df987ecd5a5dcb8db0b36a449ef88ac',
                     spentBy: {
                         txid: '493dd3339fca03c94dd0e9b53359630fa8dc2aaef404a6a2328229ae64eb8721',
                         outIdx: 4,
                     },
                 },
                 {
                     value: 6529646,
                     outputScript:
                         '76a9141c5dd21c29a653e6922c2058852d9f56e483170188ac',
                     spentBy: {
                         txid: '021b600e1425c69c1977daf2e72a13b83fe40414061641011573eef88834dec1',
                         outIdx: 49,
                     },
                 },
                 {
                     value: 6536855,
                     outputScript:
                         '76a9143510f0c92f8b26e26de575140a084773e95f439a88ac',
                     spentBy: {
                         txid: '24863ec1bc8eca7d449a37a5bd3bd85e7ccbd2d77ee51c84e1b5b8ade8bada01',
                         outIdx: 47,
                     },
                 },
                 {
                     value: 7742026,
                     outputScript:
                         '76a914ee542bd41bb07264cf9f6e824e45d3446a26077c88ac',
                     spentBy: {
                         txid: 'b3368d0b4495896c4e057a0be8df58cdead551057c0103f35a5e3a4dce7cf4b5',
                         outIdx: 45,
                     },
                 },
                 {
                     value: 8072753,
                     outputScript:
                         '76a914c4131be628403d70a62e46dfc13b576af05aa5f088ac',
                     spentBy: {
                         txid: 'dbc41978baa1e1b0d1b098a34722eadf351e19383dcc1266118333060847a8e5',
                         outIdx: 35,
                     },
                 },
                 {
                     value: 8820534,
                     outputScript:
                         '76a914f5ffa38db9ffac77b5a1a6c35eebf2415fedf87c88ac',
                     spentBy: {
                         txid: '24863ec1bc8eca7d449a37a5bd3bd85e7ccbd2d77ee51c84e1b5b8ade8bada01',
                         outIdx: 48,
                     },
                 },
                 {
                     value: 9000450,
                     outputScript:
                         '76a914b3e42f44a3dff21f72c90555d0ec62b273f0d4a588ac',
                     spentBy: {
                         txid: 'a96de5afa4eee4b098ff8b7423e90d0131673862cb79e7b02a06e084146d5dfe',
                         outIdx: 56,
                     },
                 },
                 {
                     value: 11771919,
                     outputScript:
                         '76a91463a7fe1eff49be76e18538f3ed380b7386af1c8f88ac',
                     spentBy: {
                         txid: 'a96de5afa4eee4b098ff8b7423e90d0131673862cb79e7b02a06e084146d5dfe',
                         outIdx: 57,
                     },
                 },
                 {
                     value: 13144002,
                     outputScript:
                         '76a91457f118d5f5eecebc88f711a80018bececbeb86e088ac',
                     spentBy: {
                         txid: '262832d24a3b26fd1af1b24f0a7d019579b7ed1f040777d3374c62305c5f4415',
                         outIdx: 39,
                     },
                 },
                 {
                     value: 13393930,
                     outputScript:
                         '76a9148d2a8ce8e95b3047b918d8bd24db8c3e39d906cc88ac',
                     spentBy: {
                         txid: '9086ca2908df5f06b61ca2ec2040fc3e7bd39843e35b934f23f89ea7196c7036',
                         outIdx: 43,
                     },
                 },
                 {
                     value: 13691033,
                     outputScript:
                         '76a914d6a0a87a3a5ea254ed4a2665ac328a7ef769747688ac',
                     spentBy: {
                         txid: 'c2409334c0c33750529e2f9b762e7dab7ca2fb4e67883cd3244b7cbbdc9add14',
                         outIdx: 36,
                     },
                 },
                 {
                     value: 14490346,
                     outputScript:
                         '76a914810c66b72d769d1fefd2c5bb26d20024e25fd35088ac',
                     spentBy: {
                         txid: '493dd3339fca03c94dd0e9b53359630fa8dc2aaef404a6a2328229ae64eb8721',
                         outIdx: 10,
                     },
                 },
                 {
                     value: 15649462,
                     outputScript:
                         '76a914b3f036ee778de53049e0152a140bcba4952081f788ac',
                     spentBy: {
                         txid: '262832d24a3b26fd1af1b24f0a7d019579b7ed1f040777d3374c62305c5f4415',
                         outIdx: 40,
                     },
                 },
                 {
                     value: 16885611,
                     outputScript:
                         '76a9144dbd06c9f304601d8fe89199ee7afa0afc3e5de688ac',
                     spentBy: {
                         txid: '5beda1f52503457c3e2bd93357ad7510e16e69021c589ce91b092215eb37fce5',
                         outIdx: 2,
                     },
                 },
                 {
                     value: 17311755,
                     outputScript:
                         '76a91435cf783dd7fc1a919c5a92d73feedcab1d3e4dd588ac',
                     spentBy: {
                         txid: 'a96de5afa4eee4b098ff8b7423e90d0131673862cb79e7b02a06e084146d5dfe',
                         outIdx: 58,
                     },
                 },
                 {
                     value: 19229444,
                     outputScript:
                         '76a914c570835edbc0de4a525a9ba9501eb0b123b8ab1c88ac',
                     spentBy: {
                         txid: 'd3942acaefee091f6bf0a9d34282988b31458bb6b10b7cfc3fcd3471be3c2ea7',
                         outIdx: 51,
                     },
                 },
                 {
                     value: 19612475,
                     outputScript:
                         '76a9142368a5b973c7d48fa8343b71cfb51b5a4ccfcb2488ac',
                     spentBy: {
                         txid: '9086ca2908df5f06b61ca2ec2040fc3e7bd39843e35b934f23f89ea7196c7036',
                         outIdx: 44,
                     },
                 },
                 {
                     value: 20857697,
                     outputScript:
                         '76a9149163b5cb6618d7d67562270de630da0d62896c1e88ac',
                     spentBy: {
                         txid: '021b600e1425c69c1977daf2e72a13b83fe40414061641011573eef88834dec1',
                         outIdx: 50,
                     },
                 },
                 {
                     value: 21475345,
                     outputScript:
                         '76a91464be00bf5c68a60ae520cfa81d051225457572a788ac',
                     spentBy: {
                         txid: '493dd3339fca03c94dd0e9b53359630fa8dc2aaef404a6a2328229ae64eb8721',
                         outIdx: 9,
                     },
                 },
                 {
                     value: 21879959,
                     outputScript:
                         '76a9148bc944201dec7391def49db52202a009c6a81f2088ac',
                     spentBy: {
                         txid: 'd3942acaefee091f6bf0a9d34282988b31458bb6b10b7cfc3fcd3471be3c2ea7',
                         outIdx: 52,
                     },
                 },
                 {
                     value: 21900743,
                     outputScript:
                         '76a914af6ae4c996d1ab51dd344b1f491c01163169053588ac',
                     spentBy: {
                         txid: '9086ca2908df5f06b61ca2ec2040fc3e7bd39843e35b934f23f89ea7196c7036',
                         outIdx: 45,
                     },
                 },
                 {
                     value: 22276723,
                     outputScript:
                         '76a914c1f421d009c6b36b205721c064c2ae5ea3272a4688ac',
                     spentBy: {
                         txid: 'a96de5afa4eee4b098ff8b7423e90d0131673862cb79e7b02a06e084146d5dfe',
                         outIdx: 59,
                     },
                 },
                 {
                     value: 22828111,
                     outputScript:
                         '76a9146454f4696e5bbb5eb4d368c162b35f6fcc861e6b88ac',
                     spentBy: {
                         txid: 'd3942acaefee091f6bf0a9d34282988b31458bb6b10b7cfc3fcd3471be3c2ea7',
                         outIdx: 53,
                     },
                 },
                 {
                     value: 22829710,
                     outputScript:
                         '76a9142a8af09882e0b5dd047b03e61eb3630e0678325e88ac',
                     spentBy: {
                         txid: '021b600e1425c69c1977daf2e72a13b83fe40414061641011573eef88834dec1',
                         outIdx: 51,
                     },
                 },
                 {
                     value: 23106927,
                     outputScript:
                         '76a9147eec957f14c8c35b491f487a8d777cf3b427f47688ac',
                     spentBy: {
                         txid: 'd3942acaefee091f6bf0a9d34282988b31458bb6b10b7cfc3fcd3471be3c2ea7',
                         outIdx: 54,
                     },
                 },
                 {
                     value: 25043923,
                     outputScript:
                         '76a9148f41a4d08d01a574210a0d99784248d7b718a6b388ac',
                     spentBy: {
                         txid: '021b600e1425c69c1977daf2e72a13b83fe40414061641011573eef88834dec1',
                         outIdx: 52,
                     },
                 },
                 {
                     value: 25946731,
                     outputScript:
                         '76a9149fbf277434a5a0582ffe774693c343e95c442a8188ac',
                     spentBy: {
                         txid: 'c2409334c0c33750529e2f9b762e7dab7ca2fb4e67883cd3244b7cbbdc9add14',
                         outIdx: 37,
                     },
                 },
                 {
                     value: 26216189,
                     outputScript:
                         '76a914d35d6706484afdc79bbaab9ce1f84fed4939317f88ac',
                     spentBy: {
                         txid: '24863ec1bc8eca7d449a37a5bd3bd85e7ccbd2d77ee51c84e1b5b8ade8bada01',
                         outIdx: 49,
                     },
                 },
                 {
                     value: 27153210,
                     outputScript:
                         '76a914fc64d1ceb75ef723b8bb81f53039f239f69de25d88ac',
                     spentBy: {
                         txid: '24863ec1bc8eca7d449a37a5bd3bd85e7ccbd2d77ee51c84e1b5b8ade8bada01',
                         outIdx: 50,
                     },
                 },
                 {
                     value: 27888923,
                     outputScript:
                         '76a9140b395214ae8c35fd7e8bb6921fa478216fd9e41988ac',
                     spentBy: {
                         txid: '9086ca2908df5f06b61ca2ec2040fc3e7bd39843e35b934f23f89ea7196c7036',
                         outIdx: 46,
                     },
                 },
                 {
                     value: 28283566,
                     outputScript:
                         '76a9145c9faf662be3667f760e03535c511085a2bc814488ac',
                     spentBy: {
                         txid: 'f7ffab99cca8005728105f2b93a0afd49444116bcd6131b2fcecd0fea40391ab',
                         outIdx: 53,
                     },
                 },
                 {
                     value: 29688615,
                     outputScript:
                         '76a914f883cd4d8e8b6e1cba5d127e24c57b45c26b46a288ac',
                     spentBy: {
                         txid: 'de39274a222922abfdd373cd373b1f71fb0e58c0c569ac6bc813d01a1dc64f8e',
                         outIdx: 1,
                     },
                 },
                 {
                     value: 32471718,
                     outputScript:
                         '76a9147fe1c85d201af0ab1322d5809aaa03bb7dac05fb88ac',
                     spentBy: {
                         txid: '1ed72329e29d9441dc9fb3ac828fc66d08e52c8e67a9a0b0268b5ce6bb7e0695',
                         outIdx: 4,
                     },
                 },
                 {
                     value: 35209256,
                     outputScript:
                         '76a9141ab1428e336477a213d18207570b5008841d24ea88ac',
                     spentBy: {
                         txid: 'de39274a222922abfdd373cd373b1f71fb0e58c0c569ac6bc813d01a1dc64f8e',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 40404442,
                     outputScript:
                         '76a914219f01df857ef5faa2c1509b8dc958eb9425f5df88ac',
                     spentBy: {
                         txid: '697372648af8320cd2975e4ea52d9772f6f06d9610e5088f4d92ef3f69422c30',
                         outIdx: 35,
                     },
                 },
                 {
                     value: 48107746,
                     outputScript:
                         '76a914a4c2e50019b19c9d152b6327733033253d61efe188ac',
                     spentBy: {
                         txid: 'de39274a222922abfdd373cd373b1f71fb0e58c0c569ac6bc813d01a1dc64f8e',
                         outIdx: 16,
                     },
                 },
                 {
                     value: 54611567,
                     outputScript:
                         '76a91479be8c6a6fc20a9f4cd1e55d8e99fef936a5b4fb88ac',
                     spentBy: {
                         txid: 'd3942acaefee091f6bf0a9d34282988b31458bb6b10b7cfc3fcd3471be3c2ea7',
                         outIdx: 55,
                     },
                 },
                 {
                     value: 54872231,
                     outputScript:
                         '76a914e8f011eded020ed1605848c7b5e6704eb689b33f88ac',
                     spentBy: {
                         txid: 'de39274a222922abfdd373cd373b1f71fb0e58c0c569ac6bc813d01a1dc64f8e',
                         outIdx: 6,
                     },
                 },
                 {
                     value: 56164346,
                     outputScript:
                         '76a9146573038dc2d55422c20b91588f8264f9aa038d6088ac',
                     spentBy: {
                         txid: '9086ca2908df5f06b61ca2ec2040fc3e7bd39843e35b934f23f89ea7196c7036',
                         outIdx: 47,
                     },
                 },
                 {
                     value: 58564003,
                     outputScript:
                         '76a9147077be58e7ead7443259fe5409309edbabef41d388ac',
                     spentBy: {
                         txid: '24863ec1bc8eca7d449a37a5bd3bd85e7ccbd2d77ee51c84e1b5b8ade8bada01',
                         outIdx: 51,
                     },
                 },
                 {
                     value: 59817398,
                     outputScript:
                         '76a9149cf6eb2a055f3340d31d83bf5e29cfe0e9d919f288ac',
                     spentBy: {
                         txid: 'd3942acaefee091f6bf0a9d34282988b31458bb6b10b7cfc3fcd3471be3c2ea7',
                         outIdx: 56,
                     },
                 },
                 {
                     value: 64104923,
                     outputScript:
                         '76a914d12908c4b7be22044226856207328e20e3e1f2c288ac',
                     spentBy: {
                         txid: 'de39274a222922abfdd373cd373b1f71fb0e58c0c569ac6bc813d01a1dc64f8e',
                         outIdx: 15,
                     },
                 },
                 {
                     value: 87305777,
                     outputScript:
                         '76a91437a517f6174aed807cb1f9fb26ff25912c8ea4ee88ac',
                     spentBy: {
                         txid: '021b600e1425c69c1977daf2e72a13b83fe40414061641011573eef88834dec1',
                         outIdx: 53,
                     },
                 },
                 {
                     value: 91558238,
                     outputScript:
                         '76a914b2094f7a6f5c39a66ddff6852bfef1f6dac495fb88ac',
                     spentBy: {
                         txid: '14483f95867cb556833f90ef73485fc883a04fa31404a650c11208dfc391183e',
                         outIdx: 1,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 11331,
             isCoinbase: false,
             tokenEntries: [],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
             block: {
                 height: 787920,
                 hash: '000000000000000000ecda3dc336cd44ddf32eac28cebdee3c4a0abda75471e0',
                 timestamp: 1681610827,
             },
         },
         {
             txid: 'd02d94a1a520877c60d1e3026c3e85f8995d48d7b90140f83e24ede592c30306',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: '02cafc6812b1193207d9b336fd109c4044eb02a4ee7d39599d4411f0e797f08e',
                         outIdx: 2,
                     },
                     inputScript:
                         '48304502210097bb101905c26f6198cd862b64a4174e3263fa3dda571cef058e3fb6576fe1da022002c086b779f8129d6f44697e403c7607c26589659134a9468d4471da65b116774121037f36f6573744fbf433eafc2579737e041a99b242eb0fd88dfe8570b5f6a829c7',
                     value: 98396406,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9147d432e8ccc646fe6c52e36c285bce2b75f0f500b88ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript: '6a04007461620c49206c696b65206543617368',
                 },
                 {
                     value: 1000000,
                     outputScript:
                         '76a9144fb74b44c66ab529428a943131f236c80d99b82088ac',
                     spentBy: {
                         txid: 'b16ef7b4c184201dd858325c43cd67459bce352f041f7bf44f4b99972cba81bd',
                         outIdx: 5,
                     },
                 },
                 {
                     value: 97395927,
                     outputScript:
                         '76a9147d432e8ccc646fe6c52e36c285bce2b75f0f500b88ac',
                     spentBy: {
                         txid: '2c644fba674af09cec58af30be0a93b6ebe4f48b976e0531aaacb0b3220a1556',
                         outIdx: 0,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 254,
             isCoinbase: false,
             tokenEntries: [],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
             block: {
                 height: 800715,
                 hash: '00000000000000000e5fdea738d0f7e1c30aec453c380b03edf7788ccc154906',
                 timestamp: 1689255059,
             },
         },
         {
             txid: '1083da7ead4779fbab5c5e8291bb7a37abaf4f97f5ff99ee654759b2eaee445b',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: 'afda16412e7b9770dd15286295d02544cdf5eec2ebe827616c6357647c31b950',
                         outIdx: 0,
                     },
                     inputScript:
                         '483045022100ad2200533b3fc6cf4d06b1450a0e10cbb493933fe5927e4a9d53e7005547eeea02207f1e406d9a6a33cab711461219cd085ae33c9b605f40c479b7d072659904f35d412102394542bf928bc707dcc156acf72e87c9d2fef77eaefc5f6b836d9ceeb0fc6a3e',
                     value: 1000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9140b7d35fda03544a08e65464d54cfae4257eb6db788ac',
                 },
                 {
                     prevOut: {
                         txid: 'aff8fdde86ccf5a1afb83fe9600b0b4d598a7317a9ee2a5f799e9f5fe724ab0c',
                         outIdx: 1,
                     },
                     inputScript:
                         '483045022100a7e1c2bab17698871a4b5d88e15fbcb64578bf1ac525b38c73f21c8ea7e697d702201841b8459beb066fcf388b50a3b4db6a0fd8e0f525fb5353d2de40dbc314c565412102394542bf928bc707dcc156acf72e87c9d2fef77eaefc5f6b836d9ceeb0fc6a3e',
                     value: 550,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9140b7d35fda03544a08e65464d54cfae4257eb6db788ac',
                 },
                 {
                     prevOut: {
                         txid: '691bcc03b07fa12d5e54628eab24497456af57c76a13d646393ad62105a37382',
                         outIdx: 2,
                     },
                     inputScript:
                         '483045022100d1e6a7051b3a641c490f6f9129903138a9a5d1f11cbdc4727d4272e1b5fc4b170220429f7d0e7e38265e8f2ced7311a6cc39868e930f6d35457164c891e2ac3e7f79412102394542bf928bc707dcc156acf72e87c9d2fef77eaefc5f6b836d9ceeb0fc6a3e',
                     value: 64959,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9140b7d35fda03544a08e65464d54cfae4257eb6db788ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a04657461624c71036bdec11e461033145b5d96661e45ba2a40081aad01d34c4da4dac5e42b9961c990fc603ad5c6fed77fff016d57caa7ba8cbcebb33bd47e5eb0707628c0331e4d714054ab773ae4a555c9ea432af23a83104209e5299e86081f5fabe4a744e96eac6675149ce4e7680e342270498d0e68',
                 },
                 {
                     value: 2000,
                     outputScript:
                         '76a9149846b6b38ff713334ac19fe3cf851a1f98c07b0088ac',
                     spentBy: {
                         txid: '00dbc347e48d2d422541057f2d3d1a6c32542ec2bea9e59664edbd8613774e7d',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 63232,
                     outputScript:
                         '76a9140b7d35fda03544a08e65464d54cfae4257eb6db788ac',
                     spentBy: {
                         txid: 'f189376fd662b113e5da5904e318123aee5f573221e57a2545849ac556f31130',
                         outIdx: 0,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 652,
             isCoinbase: false,
             tokenEntries: [],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
             block: {
                 height: 798057,
                 hash: '00000000000000001007743cd991fa1832e391e147bf75fa6648467ee4e98410',
                 timestamp: 1687751968,
             },
         },
         {
             txid: 'ad44bf5e214ab71bb60a2eee165f368c139cd49c2380c3352f0a4fffc746b36a',
             version: 1,
             inputs: [
                 {
                     prevOut: {
                         txid: 'd5530ac59da5f357713f3294afdced768584232d2cc21e63d9e3d60f4aaeba62',
                         outIdx: 2,
                     },
                     inputScript:
                         '41176c28f0b30bbd8b985a5960a6e29c3f8cfae093349d48bc609d0957b2eab91ecaf98b5de8b13bd5df66331ae6b9ae5dd73d8a9042bb8d54ae833e826d318cd74121037b28c10168dfb8007d25638ceb6bc13a168a6e4ddcd0aec28591d14387958796',
                     value: 546,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914aed3f8a5add35a9ddaf0a07986c2b73a2202727d88ac',
                 },
                 {
                     prevOut: {
                         txid: 'd5530ac59da5f357713f3294afdced768584232d2cc21e63d9e3d60f4aaeba62',
                         outIdx: 3,
                     },
                     inputScript:
                         '41bf1a7934dd1c5997953a1cf500bfb2b928b66574782b1dae33546e758d278c58b9527d1ff3b2913d113924eaa3af18d059ae61d49274893af1bc7f233f7bff454121022c2394a4ed0a2d8fb9c30185ea7173a15d69adceda08b96ad408fce866bcd1f9',
                     value: 43110,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914d50ec518d64850fda86e926764ce1bce1ba01a1988ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a04535750000101010120aebcae9afe88d61d8b8ed7b8c83c7c2a555583bf8f8591c94a2c9eb82f34816c0453454c4c0831353938383335340100203dd9beaedcbb3ad90eec2214fcf71381fa89b08b899813e182a7a393e1ab06190101010012333236322e39393939393939393939393935',
                 },
                 {
                     value: 43190,
                     outputScript:
                         '76a914aed3f8a5add35a9ddaf0a07986c2b73a2202727d88ac',
                     spentBy: {
                         txid: '09fe3d1b848dcc23006393604811cd1e79cfb12f79c44b0d76a8822c8910ca69',
                         outIdx: 1,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 450,
             isCoinbase: false,
             tokenEntries: [],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
             block: {
                 height: 800700,
                 hash: '00000000000000000f9a3ee0a9455329c7a66830ff9fbcbc5bd7223263e4afc4',
                 timestamp: 1689250180,
             },
         },
         {
             txid: 'a8c348539a1470b28b9f99693994b918b475634352994dddce80ad544e871b3a',
             version: 1,
             inputs: [
                 {
                     prevOut: {
                         txid: '0fceef4c1425e44171a26a9d089d77dc9bf68b8ab5c1020b411afa1ad253382c',
                         outIdx: 2,
                     },
                     inputScript:
                         '483045022100fe0f77633de5e95397f2a0fba128e1de7c2467e6d70558c5ef632b5afd504c62022013b4704186e5934f46547212dbd2054a5c8ab08546db945b83477542c51b3b46412103a16e0df390d377ffda5195c4b06148d674a331144fab6ad08e9ec5e8a4e5a4b4',
                     value: 21944557,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9148fa951904f6d0ebbc92dc29e761b9eb0a837545c88ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a026d0320eae5710aba50a0a22b266ddbb445e05b7348d15c88cbc2e012a91a09bec3861a4c9654776974746572206b65657073207475726e696e6720746865697220415049206f6e20616e64206f66662e20536f6d6574696d657320697420776f726b732c20736f6d6574696d657320697420646f65736e27742e204665617475726520746f20637265617465207477656574732066726f6d206d656d6f206d617920776f726b20616761696e20617420736f6d6520706f696e742e',
                 },
                 {
                     value: 21944167,
                     outputScript:
                         '76a9148fa951904f6d0ebbc92dc29e761b9eb0a837545c88ac',
                     spentBy: {
                         txid: 'ce4a58281bda100a572a1d365cb4a83b85d08874daff194179708b18e3f651cf',
                         outIdx: 0,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 390,
             isCoinbase: false,
             tokenEntries: [],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
             block: {
                 height: 800324,
                 hash: '0000000000000000017ec312fd2d03fee5e52ab163733d5f07e380d36138e58e',
                 timestamp: 1689021150,
             },
         },
         {
             txid: '7a0d6ae3384e293183478f681f51a77ef4c71f29957199364bb9ba4d8e1938be',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: 'a3b227c732f71b8c66b5593923fb41ac19529b4f87d453082bb2289382dbb4c1',
                         outIdx: 1,
                     },
                     inputScript:
                         '47304402204b55cb0e0a458f41be000f28ac41d23b0ce7ac6184c009a08e21cde04736602a02204e2e36d24c17d174c96e0d716a0d9d51d3009bde27a37d1961cac10fe483bec3412103f1f48963ab04429f0cacf2db96ec8189598b56afd2cde8a614440c78479ae037',
                     value: 500000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914f93029e7593327c5b864ea6896ecfda4fffb6ab888ac',
                 },
                 {
                     prevOut: {
                         txid: 'ed234d8854c599d88304e807b04b9e41a04b6a9fdfd92b1970e7a27c89a68473',
                         outIdx: 3,
                     },
                     inputScript:
                         '47304402202ddc33dd6e31885d3ae5c8f35adce3c6af89ba4c7e6bcec60e90f9ac059eb42c022037d2fefcb1ad7e13f066b4bf336cdebf54cb90d59a7375c09f64d5340cf6ceaf412103f1f48963ab04429f0cacf2db96ec8189598b56afd2cde8a614440c78479ae037',
                     value: 28351,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914f93029e7593327c5b864ea6896ecfda4fffb6ab888ac',
                 },
                 {
                     prevOut: {
                         txid: '0a4e28b70b6b1e26e02ea160261edfc7e6ffdb4ee9d7a53cf5e9c50686b4c5cb',
                         outIdx: 1,
                     },
                     inputScript:
                         '4830450221009d35c5646c47be48040aaa781bce22cc287b2f54d71ea028d9c12fd11dc2115d022025cf6916dfe0c4ad695b8a948eadeafb2bcdc0304dcc701637e33cbf79a401a7412103f1f48963ab04429f0cacf2db96ec8189598b56afd2cde8a614440c78479ae037',
                     value: 200000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914f93029e7593327c5b864ea6896ecfda4fffb6ab888ac',
                 },
                 {
                     prevOut: {
                         txid: '5909dd3d0cf37141651b629f9ada6b8c45901889e3153e27bc0673461f67fafd',
                         outIdx: 1,
                     },
                     inputScript:
                         '483045022100cf624e1a8cbc2cb9fd61f55c443490ba9eb922296bdc698c0a7db6a23b9cd33b02206f57d5f503c70a68097f0866c9b46bc7a35b130673b0b9a72b8b71b82b2d004e412103f1f48963ab04429f0cacf2db96ec8189598b56afd2cde8a614440c78479ae037',
                     value: 48995,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914f93029e7593327c5b864ea6896ecfda4fffb6ab888ac',
                 },
                 {
                     prevOut: {
                         txid: '8b837074b3d1f36066c9f0d880e69e3476368e905039fbeebb4bebab083c21fa',
                         outIdx: 0,
                     },
                     inputScript:
                         '47304402202b097ee4881fc57fe7a1551f8ee8bf9e0b40b6639a038d2c744e399850690e1d022063b5ff44314df2ec83b163683ff46c963a2f021f3e59caf3fa96914cc17342f1412103f1f48963ab04429f0cacf2db96ec8189598b56afd2cde8a614440c78479ae037',
                     value: 4000000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914f93029e7593327c5b864ea6896ecfda4fffb6ab888ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a0464726f7020b76878b29eff39c8c28aaed7d18a166c20057c43beeb90b630264470983c984a04007461624c525374617920776974682075732c2065436173682041667269636120697320746865206e6578742062696720636f6d6d756e69747920696e20746865204166726963616e2063727970746f7370686572652e20',
                 },
                 {
                     value: 264706,
                     outputScript:
                         '76a914957b59a2bfa17ea7fc234e532b263169b6d34aa988ac',
                     spentBy: {
                         txid: '33b640c3f87a5d7d148bdf8870a3cdfad4dbfdad7abfb39fa97787ca9744b912',
                         outIdx: 1,
                     },
                 },
                 {
                     value: 529412,
                     outputScript:
                         '76a9148f882b02e1040f83c2f73007bb334716c38dbffc88ac',
                     spentBy: {
                         txid: '54d7c32d64ac3cb94c55ae4a9ca5c0519ea2dcf65962485e668ebb0bd7b0e990',
                         outIdx: 1,
                     },
                 },
                 {
                     value: 529412,
                     outputScript:
                         '76a914f43ac7271cee240bee3796938203105fb54c045c88ac',
                 },
                 {
                     value: 264706,
                     outputScript:
                         '76a914d5a79acda6dbbe14a686a0c59466f52656330a9588ac',
                 },
                 {
                     value: 529412,
                     outputScript:
                         '76a91429207c3d229d6163521fbe87e52e64bbe584dbc988ac',
                     spentBy: {
                         txid: '80129555a3900a8d1084a6ecaf24f60dfb4fb25fa93ffed057536f0655d4df24',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 264706,
                     outputScript:
                         '76a914e735901add6ea366a0964ab54ad9d9158597f50c88ac',
                 },
                 {
                     value: 264706,
                     outputScript:
                         '76a91407acf15b7cc6a4c18d8d1c3a5611ea30718c2a0d88ac',
                 },
                 {
                     value: 529412,
                     outputScript:
                         '76a9146671b4690e282cb79707b1ee696d54a6072329fa88ac',
                 },
                 {
                     value: 264706,
                     outputScript:
                         '76a914d4f7e7b420eb1c5410abf698c72d790f0c4cc1b388ac',
                 },
                 {
                     value: 264706,
                     outputScript:
                         '76a914b19e12ae2aa186102486e8348f22b87ae426eafd88ac',
                 },
                 {
                     value: 529412,
                     outputScript:
                         '76a914e6309418b6e60b8119928ec45b8ba87de8e735f788ac',
                     spentBy: {
                         txid: 'e58c868250f4e2949d5b72a1975d3a90247d59ea019edf4aebd214ed0d4c62b3',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 264706,
                     outputScript:
                         '76a914cdba2655ee5abf18a5b6203da5b7d8cc28c36ca888ac',
                     spentBy: {
                         txid: 'f33e2516b93628e6f3608a2233e35af00426eb8ec3cba5836af827ba62cc0bf9',
                         outIdx: 2,
                     },
                 },
                 {
                     value: 274783,
                     outputScript:
                         '76a914f93029e7593327c5b864ea6896ecfda4fffb6ab888ac',
                     spentBy: {
                         txid: 'a2d019cffeb34decfe11f6135ee6aec09aeed439f34369ea9216b78a5d2040a0',
                         outIdx: 0,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 1326,
             isCoinbase: false,
             tokenEntries: [],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
             block: {
                 height: 800392,
                 hash: '00000000000000000ce15f89ed2d06604932e5ff53fceebc9a3e1dd6fdff8438',
                 timestamp: 1689078229,
             },
         },
         {
             txid: '22135bb69435023a84c80b1b93b31fc8898c3507eaa70569ed038f32d59599a9',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: 'd5626b4441deba5ffdb52f32352726e87db432f66c183c7f1c2dc23a81080915',
                         outIdx: 0,
                     },
                     inputScript:
                         '4730440220718019bbe581cd2d505837df7c76be53f7ea3798cbe2c8e9985b32d95b4f3c9202200db9c710c07e3dc7b2e6153e6af3fc0c6d9a1e9b953a2c5812c3f6a12bcfb8c8412102394542bf928bc707dcc156acf72e87c9d2fef77eaefc5f6b836d9ceeb0fc6a3e',
                     value: 1000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9140b7d35fda03544a08e65464d54cfae4257eb6db788ac',
                 },
                 {
                     prevOut: {
                         txid: 'd5626b4441deba5ffdb52f32352726e87db432f66c183c7f1c2dc23a81080915',
                         outIdx: 1,
                     },
                     inputScript:
                         '483045022100a309d82c4a00ea00b2a9f11bc0a1625b4272fbf9c627c723377ee81428c9cc5a0220523f45935bbc9bb8cfa2454cd3be1c9ee3322e5c849c5f4384bb72736958a628412102394542bf928bc707dcc156acf72e87c9d2fef77eaefc5f6b836d9ceeb0fc6a3e',
                     value: 28091,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9140b7d35fda03544a08e65464d54cfae4257eb6db788ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a042e7865630005646f67653215000b7d35fda03544a08e65464d54cfae4257eb6db7',
                 },
                 {
                     value: 554,
                     outputScript:
                         'a914d37c4c809fe9840e7bfa77b86bd47163f6fb6c6087',
                     spentBy: {
                         txid: '9b9bc49c18a513f04c9d05dcff2d5e1164408b837d95ef695d24524520fb9358',
                         outIdx: 196,
                     },
                 },
                 {
                     value: 27785,
                     outputScript:
                         '76a9140b7d35fda03544a08e65464d54cfae4257eb6db788ac',
                     spentBy: {
                         txid: 'c3bae8350772a99d52086720d2712813f8e47313d20f5d914a728cb7a2bcd9ea',
                         outIdx: 0,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 415,
             isCoinbase: false,
             tokenEntries: [],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
             block: {
                 height: 800458,
                 hash: '00000000000000000360b4edae6ac5cf508cf728d508bd6521d4fd9495a24ac6',
                 timestamp: 1689130494,
             },
         },
         {
             txid: '45ec66bc2440d2f94fa2c645e20a44f6fab7c397053ce77a95484c6053104cdc',
             version: 1,
             inputs: [
                 {
                     prevOut: {
                         txid: '979888d682e351714e6a3d6a96dedb57a0f19471a8eb7f4edc20f033f9b359b3',
                         outIdx: 3,
                     },
                     inputScript:
                         '41597c9b4eff3b012afb56e745c46d3f9cddfbd72fbec655d63d0bfd4b4a23225aa237a425a25685b54a8f767becb9109f1b0951c3ecfe7fa3d1a519a8f49ef6a9c1210363bbf8cf60612f89a8da03416a7ff0f398b315c7217b0c7a15ca52d5fcecb316',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                         tokenType: {
                             protocol: 'ALP',
                             type: 'ALP_TOKEN_TYPE_STANDARD',
                             number: 0,
                         },
                         amount: '39976',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a9147276ae7693883fa1165628e298899d8ee9248e7c88ac',
                 },
                 {
                     prevOut: {
                         txid: '6f6da390386a97d5ce9a585422c11e60e1a4dd30ac6abecef5887ceb1632151c',
                         outIdx: 1,
                     },
                     inputScript:
                         '410dc4415d0ef25301d74f5fa770bb0b8e4f3bc1b9c87f3d9c65efdbe246468c364ad4a696c9b6491a215643807db3e3ac209e38590bbecd0185d23d045cea8c07c1210363bbf8cf60612f89a8da03416a7ff0f398b315c7217b0c7a15ca52d5fcecb316',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                         tokenType: {
                             protocol: 'ALP',
                             type: 'ALP_TOKEN_TYPE_STANDARD',
                             number: 0,
                         },
                         amount: '228263',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a9147276ae7693883fa1165628e298899d8ee9248e7c88ac',
                 },
                 {
                     prevOut: {
                         txid: '714b40aaf824007782c0af61b0e72ad4e825446111633fbe1b7c5b4a82a1b911',
                         outIdx: 0,
                     },
                     inputScript:
                         '41d2966d687a9ad26c155c99fcf87b94b2a54b9ecbbf6caee7f6063b756aafa63113c5a16abc21495aaff02b5e558853043038de716c3adbaae2bd69356be4e3ce412102f49a7fd4e0c6cea6401aed57b76b2fb358e1ebbb65fc5782e3c2165c9e850b31',
                     value: 1000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9148b9b3ba9199d98e131b762081c0c31754fb904c288ac',
                 },
                 {
                     prevOut: {
                         txid: '714b40aaf824007782c0af61b0e72ad4e825446111633fbe1b7c5b4a82a1b911',
                         outIdx: 1,
                     },
                     inputScript:
                         '41839e901cd8f3f8d20d99c02ffbc6268baa5f6e5d410ec3207f5a582b4a2731b4baa472afec7c78f834bb16900bbc7fb16d2db446cb895a36a18bd520524ae60c412102f49a7fd4e0c6cea6401aed57b76b2fb358e1ebbb65fc5782e3c2165c9e850b31',
                     value: 1000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9148b9b3ba9199d98e131b762081c0c31754fb904c288ac',
                 },
                 {
                     prevOut: {
                         txid: '714b40aaf824007782c0af61b0e72ad4e825446111633fbe1b7c5b4a82a1b911',
                         outIdx: 2,
                     },
                     inputScript:
                         '413ba7dddc6fed541f666086c4db0420b03a279f3926c5acc7dbc0d8d51c95cc1f0ad28f030bc4b76d6c42b94caed9750d7f9d7274c017e04049ae64b194299c49412102f49a7fd4e0c6cea6401aed57b76b2fb358e1ebbb65fc5782e3c2165c9e850b31',
                     value: 1000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9148b9b3ba9199d98e131b762081c0c31754fb904c288ac',
                 },
                 {
                     prevOut: {
                         txid: '714b40aaf824007782c0af61b0e72ad4e825446111633fbe1b7c5b4a82a1b911',
                         outIdx: 3,
                     },
                     inputScript:
                         '41a14fe12995bd1fbd3e53b00767121e4504a5a97be0482f936cedf3cbc3c04449a3155293522afd213bf4c6e5655c6335179eae63b94afd70a979d63ae7621c04412102f49a7fd4e0c6cea6401aed57b76b2fb358e1ebbb65fc5782e3c2165c9e850b31',
                     value: 1000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9148b9b3ba9199d98e131b762081c0c31754fb904c288ac',
                 },
                 {
                     prevOut: {
                         txid: '714b40aaf824007782c0af61b0e72ad4e825446111633fbe1b7c5b4a82a1b911',
                         outIdx: 4,
                     },
                     inputScript:
                         '416c5a43be467820cb14fb8c82a389a80507816dae3649c28f06def267ca9de2c52089d8f7be41076bf1baea97f29538b3a8cbc6cca2e22d7227a58824a676e43f412102f49a7fd4e0c6cea6401aed57b76b2fb358e1ebbb65fc5782e3c2165c9e850b31',
                     value: 1000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9148b9b3ba9199d98e131b762081c0c31754fb904c288ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a503d534c5032000453454e4445e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd03401f000000006067010000002f9102000000',
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a914dee50f576362377dd2f031453c0bb09009acaf8188ac',
                     token: {
                         tokenId:
                             'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                         tokenType: {
                             protocol: 'ALP',
                             type: 'ALP_TOKEN_TYPE_STANDARD',
                             number: 0,
                         },
                         amount: '8000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                 },
                 {
                     value: 2588,
                     outputScript:
                         'a914f71cf8cb91804a2205901cc0972c3f4a088a1aae87',
                     token: {
                         tokenId:
                             'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                         tokenType: {
                             protocol: 'ALP',
                             type: 'ALP_TOKEN_TYPE_STANDARD',
                             number: 0,
                         },
                         amount: '92000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     spentBy: {
                         txid: '73ce0b742131ace72e8598a9585971220c4ddcd4d4d13a058bbcc52c355dca2c',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a9147276ae7693883fa1165628e298899d8ee9248e7c88ac',
                     token: {
                         tokenId:
                             'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                         tokenType: {
                             protocol: 'ALP',
                             type: 'ALP_TOKEN_TYPE_STANDARD',
                             number: 0,
                         },
                         amount: '168239',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     spentBy: {
                         txid: '292057e2071f8245317ff4e504a0b57ce3c841f4a9505cfbe7ecc7521d0054ff',
                         outIdx: 4,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 1170,
             isCoinbase: false,
             tokenEntries: [
                 {
                     tokenId:
                         'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                     tokenType: {
                         protocol: 'ALP',
                         type: 'ALP_TOKEN_TYPE_STANDARD',
                         number: 0,
                     },
                     txType: 'SEND',
                     isInvalid: false,
                     burnSummary: '',
                     failedColorings: [],
                     actualBurnAmount: '0',
                     intentionalBurn: '0',
                     burnsMintBatons: false,
                 },
             ],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NORMAL',
             block: {
                 height: 800378,
                 hash: '0000000000000000089a8326edc4a36fd34ecf37fcfcdb2b7ffe9f3dd10bad2a',
                 timestamp: 1689065237,
             },
         },
         {
             txid: '413b57617d2c497b137d31c53151fee595415ec273ef7a111160da8093147ed8',
             version: 1,
             inputs: [
                 {
                     prevOut: {
                         txid: 'ff06c312bef229f6f27989326d9be7e0e142aaa84538967b104b262af69f7f00',
                         outIdx: 41,
                     },
                     inputScript:
                         '40e9025766015ff3fb2bb1a0643540589de84a6bd74799f6a5130e5f4793bb04b6614eda7d11f0e3c6edba32e8f97952f87fd0065e08d7d5700d668b72880356184730450221009aa1063132f8fe88d11d69438be0320201ec79e74b43af57ec91f6697f9eedc10220294cc6f123ef35a2a92146b3af9f19a8b84745df28ff81b0f918547c0f316aa020912cacf95b220116236c81840549456ae3cc3a537d94e9a5a7691eb609b9e1bb2102ccd325f41c9e343dcfb2b767e9fd1be0b60636c2f08c403bb72d1dc5751a1f0d2c6fbb7b01417e78ad7e21022b7c4d310cd9aee3a0256b2f6399d2d737da47f14582667ea30a159ed879f003ba',
                     value: 1000,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                         tokenType: {
                             protocol: 'ALP',
                             type: 'ALP_TOKEN_TYPE_STANDARD',
                             number: 0,
                         },
                         amount: '0',
                         isMintBaton: true,
                         entryIdx: 0,
                     },
                     outputScript:
                         'a914ea826cc1a3a981d048cd78b66711222bece8ebf287',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a5032534c503200044d494e5445e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd0160ae0a00000000',
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a91472a92e48c5ab72566959db1dbf1b8dce83afabb788ac',
                     token: {
                         tokenId:
                             'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                         tokenType: {
                             protocol: 'ALP',
                             type: 'ALP_TOKEN_TYPE_STANDARD',
                             number: 0,
                         },
                         amount: '700000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     spentBy: {
                         txid: '4307458f1952db756e959e68aacae82c73a4b86d6e996636d66bf79bca28cbbe',
                         outIdx: 0,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 396,
             isCoinbase: false,
             tokenEntries: [
                 {
                     tokenId:
                         'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                     tokenType: {
                         protocol: 'ALP',
                         type: 'ALP_TOKEN_TYPE_STANDARD',
                         number: 0,
                     },
                     txType: 'MINT',
                     isInvalid: false,
                     burnSummary: '',
                     failedColorings: [],
                     actualBurnAmount: '0',
                     intentionalBurn: '0',
                     burnsMintBatons: false,
                 },
             ],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NORMAL',
             block: {
                 height: 800218,
                 hash: '0000000000000000024133f7d5dcce943020d32452704aab90d00e7bf8c8025e',
                 timestamp: 1688956131,
             },
         },
         {
             txid: '9094e1aab7ac73c680bf66e78cc8311831b3d813e608bff1e07b1854855fc0f1',
             version: 1,
             inputs: [
                 {
                     prevOut: {
                         txid: 'c211f534b17dfe5356c7e83e16202a4621bb7720bb2efb96cfcae14a6bae49ca',
                         outIdx: 1,
                     },
                     inputScript:
                         '473044022035f1526804dbc6164f905280e1b3ff09841b14471344bb676985ac5ded00bf3602206981faee987c646a169538a8bbef38c5d0e2f377b6d6beb7a56d01a961ca65b1412102063d93675f351cb3b95e671fb2b8b20fa2e0ff624079ab7d32c49cf462286c23',
                     value: 8862751,
                     sequenceNo: 0,
                     outputScript:
                         '76a914d95a60cea21479569e6b1ad39416c8fbc97323c588ac',
                 },
             ],
             outputs: [
                 {
                     value: 8419613,
                     outputScript:
                         '76a914453c8c15aee05fe5a027d4bf5681cd0bc682c0b788ac',
                 },
                 {
                     value: 442686,
                     outputScript:
                         '76a914d95a60cea21479569e6b1ad39416c8fbc97323c588ac',
                 },
                 {
                     value: 0,
                     outputScript:
                         '6a403d3a4554482e4554483a3078613961614633304636353935354336396331364233333435423531443432364439423838426138373a3834313332313a74723a30',
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 300,
             isCoinbase: false,
             tokenEntries: [],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
             block: {
                 height: 800383,
                 hash: '000000000000000014f30e80baf015eab61fb92f62813708fe8ee38ce27a46be',
                 timestamp: 1689070486,
             },
         },
         {
             txid: 'b5782d3a3b55e5ee9e4330a969c2891042ae05fafab7dc05cd14da63e7242f8e',
             version: 1,
             inputs: [
                 {
                     prevOut: {
                         txid: 'f75274016ff26983635008c3c1500c5aa3412e37c55f82bdf2542873376cbec6',
                         outIdx: 1,
                     },
                     inputScript:
                         '47304402207dd238f4aea9210eb5e311ec38a38c079290f89ba39a436cf1d7c4b3ee10a1b002202516389f5631a67d7eb89e03598dd90a20cae966049445cb1cf82059feb1cd49412103c918521e29ff4986c49c48750d18f1f586a34578ab37f2d206ed8d25abd95d39',
                     value: 12966881,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9142cc3608fe629c4f402e511878982bc01bde3445d88ac',
                 },
             ],
             outputs: [
                 {
                     value: 12966621,
                     outputScript:
                         'a9145aafaadba9ff909067a640e5e2a46b756aeaf71387',
                     spentBy: {
                         txid: '56f1c0813d1b44697deccdd32b5182448e8c4c1bd6db771ceed779d4a5021ab9',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 0,
                     outputScript:
                         '6a14663ddd99990bcd969994ec2288a2a86dc532e1a8',
                 },
             ],
             lockTime: 1692219709,
             timeFirstSeen: 0,
             size: 220,
             isCoinbase: false,
             tokenEntries: [],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
             block: {
                 height: 805569,
                 hash: '000000000000000013999983f42bc6270ca0cb0f0247872458546c381a270d01',
                 timestamp: 1692219954,
             },
         },
         {
             txid: '4f33c81d95641eb0f80e793dc96c58a2438f9bb1f18750d8fb3b56c28cd25035',
             version: 1,
             inputs: [
                 {
                     prevOut: {
                         txid: '87e03ed9f2b1690a0c32484a9084d0a5a494a084616c8a2cda2d967bf58f4758',
                         outIdx: 0,
                     },
                     inputScript:
                         '483045022100d48813ecde5c1878587111e2b6a931414acfcd133af250f3b6f15363afb554570220780fc409af09dfe10b6b0bcbea7c1e588456a8fb029571363e31f3e4174f652b412103562731a08eb23e6260b516c4564f746033e9080bc9f61ad2158a63927500b8b1',
                     value: 584106362127,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914231f7087937684790d1049294f3aef9cfb7b05dd88ac',
                 },
             ],
             outputs: [
                 {
                     value: 214748364700,
                     outputScript:
                         '76a914231f7087937684790d1049294f3aef9cfb7b05dd88ac',
                     spentBy: {
                         txid: '63edf584e527ec15d6d3ffa33db55cd6055a5d8af3dd778a8ffaad35a594a180',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 154609632467,
                     outputScript:
                         '76a914231f7087937684790d1049294f3aef9cfb7b05dd88ac',
                     spentBy: {
                         txid: '99eec6fec03c1c3d2043a07f38488aae9416e676f859a940e521b619f9308d6d',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 214748364700,
                     outputScript:
                         '76a914231f7087937684790d1049294f3aef9cfb7b05dd88ac',
                     spentBy: {
                         txid: '63edf584e527ec15d6d3ffa33db55cd6055a5d8af3dd778a8ffaad35a594a180',
                         outIdx: 1,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 260,
             isCoinbase: false,
             tokenEntries: [],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
             block: {
                 height: 800230,
                 hash: '00000000000000000684570e0d5280b19e0bda62d3a620c0f90d1d7943b17fed',
                 timestamp: 1688964211,
             },
         },
         {
             txid: 'f5d4c112cfd22701226ba050cacfacc3aff570964c6196f67e326fc3224300a2',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: 'bafb00bf336f89b3e82af6c9692fcfa9c0c485fd296f6e2d11a9aeffdf0658c9',
                         outIdx: 0,
                     },
                     inputScript:
                         '483045022100b868d4ead08172bcd2dd666173f108476d6ad83536b1d669063ad48281271fa002202a1ed3f7217cf0dbc6c6114d6087a06d9d2fdcd60e3a8301f9e311be53eb91e6412102bda582a4bf42f9b5520d5023f37e53744a8f048a404d477f3187ccf3fdb0a43e',
                     value: 30426563453,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9147c09e7cf1b2c40d4e08057e47bda9cabcdfd208588ac',
                 },
                 {
                     prevOut: {
                         txid: 'f67df2c2b0cbe6bbbf2d364305e5e5b57498bc688f5062a46ce6b273c160999b',
                         outIdx: 0,
                     },
                     inputScript:
                         '483045022100d5d1c650af14f2fc58ede519385f184c81cc26ab7e49bcb81700bb4fd91a33cb02204dc0c91c915dadf5bff6bb2d54713bb338072e229a9053c557a11c8df7aedf92412102bda582a4bf42f9b5520d5023f37e53744a8f048a404d477f3187ccf3fdb0a43e',
                     value: 30225350654,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9147c09e7cf1b2c40d4e08057e47bda9cabcdfd208588ac',
                 },
                 {
                     prevOut: {
                         txid: '28b8e29e2450dbe72f23e759de05466aad90a6a21161617ec4eddbe2f16cf0dc',
                         outIdx: 0,
                     },
                     inputScript:
                         '4730440220299867647c651e087b2362cb46cea041d1340cc9d292a747b79f60a39c5e6ed802200ce28ec8453004aed4698cc91572571c3fb6c7dcab27e5b81838ba11b7fcf47b41210347225b9b5059b0ecd55f4d3c611396893be1e4ddbc4f6fb359344d66d90603f1',
                     value: 16816891900,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9149f27f41b828019c141516179ab00e538a3f65a1788ac',
                 },
                 {
                     prevOut: {
                         txid: '7292db20773561ff63fdccbe0860333a2cfed8efac6077257219a9d9d0e6c7c2',
                         outIdx: 2,
                     },
                     inputScript:
                         '473044022025398b595b52b1960da327514ecfa26c764d996336b983ef8a7824082e421c93022016691118624efe4eba4c70faca860f41e36b68ee39a8d7513d170ff43c984a84412102b56ea6bd49408c797271d772223ac85b92b10237d160e5ad4ff4c44c8ed00a50',
                     value: 6908486500,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9142d9c4a5a292f5fef07b8cfe76b0c66d90d15a5d688ac',
                 },
                 {
                     prevOut: {
                         txid: '7292db20773561ff63fdccbe0860333a2cfed8efac6077257219a9d9d0e6c7c2',
                         outIdx: 0,
                     },
                     inputScript:
                         '473044022004f43cc3b9ceb7f913ee80e128b08ecfa4b610c70e1099fa406f275b3df23dfc022061fd494601553d29396bba36c60510e8d2b8c3383144c917ef20a7c6866d13a64121037b692abf35a795b78711ef5455f47579360375d96eca666e2c48c85260f2eb4b',
                     value: 5101721000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9149d1cd75ff25c555213ab5fef4bbd6a180a5e5e7d88ac',
                 },
                 {
                     prevOut: {
                         txid: 'da7a6212606e606a58a933794140c6cd61766f9ba7d818d6a8c81132f2b4fa7e',
                         outIdx: 0,
                     },
                     inputScript:
                         '47304402200ffaa112a2dd2dc15616ad307375c48ca838d0ad181e0ad832e288f664d821a40220734a342dd82e175c422831ef59ae0023c01ce38589b9f1748157176533d7164f412102b56ea6bd49408c797271d772223ac85b92b10237d160e5ad4ff4c44c8ed00a50',
                     value: 4810263100,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9142d9c4a5a292f5fef07b8cfe76b0c66d90d15a5d688ac',
                 },
                 {
                     prevOut: {
                         txid: '440e06a33ca6313a4fe046f1376940494f3eb1cd0691c72b8ee0969d76470a12',
                         outIdx: 0,
                     },
                     inputScript:
                         '483045022100aaff5eb83c7bada3dd363f528ea7c8cf0e48d745d994d1d4bb2b906da832a24c02205430989a4dd0955690eb9a2e41b7c91bfefd3b79b82f27e0ac434f9cc55aca86412103dea874528abd36e4f0484357f510dd3875c8a2aec1baeac73dfaf5ea860bd510',
                     value: 4000000000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9143d1ee2681911f344e77097a8bd25576e1da1c51788ac',
                 },
                 {
                     prevOut: {
                         txid: 'bb1f39fc82315bac41cfe967f435c11a928c3b2a1bb6562880c04f25b8eafd29',
                         outIdx: 0,
                     },
                     inputScript:
                         '483045022100f0a2b357da363c552f8ddcc9ce6e2e7554a90ea7214a80af62c0195d1df1ad0b02202847981fc03cb4f751b7640b283f722a241896e5a1b6221cb9c31ead0b44e524412102b56ea6bd49408c797271d772223ac85b92b10237d160e5ad4ff4c44c8ed00a50',
                     value: 3463133300,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9142d9c4a5a292f5fef07b8cfe76b0c66d90d15a5d688ac',
                 },
                 {
                     prevOut: {
                         txid: 'e9c35dd14fbb770d497160a4119aefbd17d0e920ebaf91a12639d58e6f6a3fc4',
                         outIdx: 0,
                     },
                     inputScript:
                         '483045022100a5df4cf238b2014f748f3ebe6c7e83cd1a32322bcea736d169b1576e0f1604c70220363170a21ae3c612dc4ef6bd4b6348ac528956e499f7c5d28a3cb40d439024d9412102b56ea6bd49408c797271d772223ac85b92b10237d160e5ad4ff4c44c8ed00a50',
                     value: 3295559900,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9142d9c4a5a292f5fef07b8cfe76b0c66d90d15a5d688ac',
                 },
                 {
                     prevOut: {
                         txid: '76c2cd906a42adb530b9cecd184c49230786f8ccdd6c498d743c17e197c53a1f',
                         outIdx: 0,
                     },
                     inputScript:
                         '483045022100dd42a76f7d99703eb5f08adbdf0a55b76ca80ba84668a181a26a0a4586e894bc0220754cd7b68540db2cd51cd599880585c6005e43953ca7af282d3929b9234703a741210297dffbcf8f417222ddadba818df5110a4b83fccdce773479c2044f25d3cb0071',
                     value: 1412324900,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a91429981fd0910f0851fcb3422b37abb5de442de33188ac',
                 },
                 {
                     prevOut: {
                         txid: '66d8b183d7fd40dc5e8d06e16a6189b8d80b07a7615601e008ec476cb847e6be',
                         outIdx: 0,
                     },
                     inputScript:
                         '4730440220219e5b506570bc1d259d792a2ef33ed04a4a5ad01614bfab79d2f0f903b257d102205bd60750fca96273264c6f736397693198203f2047e457c3878b166d6145a46d412103020f6e4ca80517db5a8ce83bf33169e018f75aa55a399678a8a33dcf0506c3fc',
                     value: 99900000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914ef95330c2b65976c5c63b03d544207b5e55bb58b88ac',
                 },
                 {
                     prevOut: {
                         txid: '5acbc53048b80ce6f0caa7fe402ec8719f6b5d0a679b9a7646a099bfe4453bd0',
                         outIdx: 0,
                     },
                     inputScript:
                         '483045022100f74b49fa395d8cd8d92d23e9c076e090a654ab30d0fd28dcf862fe827bb35d3c02206cd85e601f7b183934553e829e2e97c20062ecc23316fd8b033a29781e7261bf412102609d0ef47f50c17d99aa5db555e267ab2f91521c8f9c6be0301ae3e69c031176',
                     value: 8625006,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9144d746dbe5864a2635376326a3995f8ada2ec339d88ac',
                 },
                 {
                     prevOut: {
                         txid: '434b32c3cb3583a5ce0d27dcfdf8a8c99266d5a909af28e914c62526e9cc0d60',
                         outIdx: 1,
                     },
                     inputScript:
                         '47304402205260a686c8b3d2272a92930d76fda2dae5f9a16afee43c3b2ddb2c3d2742ab930220176b484e84b26a422481e2e6fb690484c2f6cab7d1b03af31f44a8b77aa4b58a412102609d0ef47f50c17d99aa5db555e267ab2f91521c8f9c6be0301ae3e69c031176',
                     value: 8625000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9144d746dbe5864a2635376326a3995f8ada2ec339d88ac',
                 },
             ],
             outputs: [
                 {
                     value: 106577441836,
                     outputScript:
                         '76a914a520c86a08366941cd90d22e11ac1c7eefa2db3788ac',
                     spentBy: {
                         txid: '78bc65dce0917bf1d3c29f8a9cce02204cc85f90dfeda68356d7338e4d68be4f',
                         outIdx: 1,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 0,
             size: 1962,
             isCoinbase: false,
             tokenEntries: [],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
             block: {
                 height: 800383,
                 hash: '000000000000000014f30e80baf015eab61fb92f62813708fe8ee38ce27a46be',
                 timestamp: 1689070486,
             },
         },
         {
             txid: 'b2c9c056339d41ec59341541dda8bd6e570730beba485e14eb54d0a073700c22',
             version: 1,
             inputs: [
                 {
                     prevOut: {
                         txid: '8918611f5a0a432269a4e1dc560e9189b9423089d2dbe94d972515b7c96b214a',
                         outIdx: 1,
                     },
                     inputScript:
                         '419e644b0b2da83425baffd1d591632fb07216568e0e63c93f4794541aad34801779ce531c546bc8896086670cb59c27afe70972d7e9c058d9c6c43da43ecf6ba4c121020cd8434356c9c73fe2efb9cce867cd86e2649fb77fc28b9bd72f17cf9c4b221a',
                     value: 546,
                     sequenceNo: 4294967295,
                     token: {
                         tokenId:
                             'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                         tokenType: {
                             protocol: 'ALP',
                             type: 'ALP_TOKEN_TYPE_STANDARD',
                             number: 0,
                         },
                         amount: '2000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                     outputScript:
                         '76a914378c3b416e77e01198c01ad215b8afd0bb72799488ac',
                 },
                 {
                     prevOut: {
                         txid: '696ec00c645c715a146ad6a910295ece67d846e0e6e7f925519df07880a968e9',
                         outIdx: 14,
                     },
                     inputScript:
                         '41c865813618b58d4e6f311d70392b4f1cc15d160ef6813ea95255246b0da2ee3dbfc057138998354b81c67df5e23f75ebd39c6d5b2071b0c7ae4d8521469beef7412102f49a7fd4e0c6cea6401aed57b76b2fb358e1ebbb65fc5782e3c2165c9e850b31',
                     value: 1000,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a9148b9b3ba9199d98e131b762081c0c31754fb904c288ac',
                 },
             ],
             outputs: [
                 {
                     value: 0,
                     outputScript:
                         '6a5031534c5032000453454e4445e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd01d00700000000',
                 },
                 {
                     value: 546,
                     outputScript:
                         '76a914acdbf937b086ddaa970072a610daa8d10f14549a88ac',
                     token: {
                         tokenId:
                             'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                         tokenType: {
                             protocol: 'ALP',
                             type: 'ALP_TOKEN_TYPE_STANDARD',
                             number: 0,
                         },
                         amount: '2000',
                         isMintBaton: false,
                         entryIdx: 0,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 1715869910,
             size: 387,
             isCoinbase: false,
             tokenEntries: [
                 {
                     tokenId:
                         'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                     tokenType: {
                         protocol: 'ALP',
                         type: 'ALP_TOKEN_TYPE_STANDARD',
                         number: 0,
                     },
                     txType: 'SEND',
                     isInvalid: false,
                     burnSummary: '',
                     failedColorings: [],
                     actualBurnAmount: '0',
                     intentionalBurn: '0',
                     burnsMintBatons: false,
                 },
             ],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NORMAL',
             block: {
                 height: 844893,
                 hash: '00000000000000001e5a53b3ee70596a3c02f847a295a01116302af25529cc68',
                 timestamp: 1715871026,
             },
         },
         {
             txid: 'd8fe456c89357c23ac6d240fe9319ce9ba393c9c3833631046a265ca7c8349e6',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: '00e43308683a7b97dbfa97f8e8a83dc76c0a49b36c646ef0e31410c546b1bacd',
                         outIdx: 1,
                     },
                     inputScript:
                         '415baa3f7a0f8294ec0555e1f825c43043eb229f4e2c0bf9a5a676838a881daca32346bbdee05b346f95c39cd69ef709990fd19bbf574f69bf898cd9a1cba001a341210353f81d61d41d6e22c73ab449476113dea124afe3972991cd237e654f15950b7c',
                     value: 2531619,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                 },
             ],
             outputs: [
                 {
                     value: 4200,
                     outputScript:
                         '76a91430f16ad77116a4b9e7f337743e35271323d63e0d88ac',
                     spentBy: {
                         txid: '16eb156e4b2688706f9e3da8bdcba69f363d1975ccb363b02274a7ff13d3220a',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 2527200,
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                     spentBy: {
                         txid: '6f77cfe3148f28de4b982c18d34e79b8d51a368a7c94354b7399133318daf129',
                         outIdx: 1,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 1727906695,
             size: 219,
             isCoinbase: false,
             tokenEntries: [],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
             block: {
                 height: 864888,
                 hash: '000000000000000004fd9bd9e95cdc1d6b6bf963c743fec7c808d407d4e52c46',
                 timestamp: 1727906948,
             },
         },
         {
             txid: '083b7862bae48e78549ccf63833896f5f4f5bdef5c380a108fa99cdb64261fa3',
             version: 2,
             inputs: [
                 {
                     prevOut: {
                         txid: 'c7bde74f7a8ebfc57dc373036aac13277ae23f4f94593f0accf87a4317900fd4',
                         outIdx: 3,
                     },
                     inputScript:
                         '41f9e93665c2d65431ce4142cc4fb93ec0818b50732c52be2de33df3fc4d056fb923351bdef771f46bb235371b5def9fec16590484c0525f27d1179e7e32ab30d641210353f81d61d41d6e22c73ab449476113dea124afe3972991cd237e654f15950b7c',
                     value: 2524161,
                     sequenceNo: 4294967295,
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                 },
             ],
             outputs: [
                 {
                     value: 4200,
                     outputScript:
                         '76a914eeae0fea781c26c93879523ba5a47c244c768ece88ac',
                     spentBy: {
                         txid: 'afde4b9345a7bdbb20eaf7a0da3c730ca28334b8ceffce0a3e7b720b0c5d5a09',
                         outIdx: 0,
                     },
                 },
                 {
                     value: 2519742,
                     outputScript:
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                     spentBy: {
                         txid: '68d48755e671dbd6946d811dff04532ede483cee2f3c284e08dddec3d7c351d9',
                         outIdx: 0,
                     },
                 },
             ],
             lockTime: 0,
             timeFirstSeen: 1727907007,
             size: 219,
             isCoinbase: false,
             tokenEntries: [],
             tokenFailedParsings: [],
             tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
         },
     ],
     parsedBlock: {
         hash: '0000000000000000000000000000000000000000000000000000000000000000',
         height: 819346,
         miner: 'unknown, ...863u',
         staker: {
             staker: 'ecash:qrpkjsd0fjxd7m332mmlu9px6pwkzaufpcn2u7jcwt',
             reward: 62500000,
         },
         numTxs: 27,
         parsedTxs: [
             {
                 txid: '4f33c81d95641eb0f80e793dc96c58a2438f9bb1f18750d8fb3b56c28cd25035',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 260,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a914231f7087937684790d1049294f3aef9cfb7b05dd88ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [],
                 },
                 totalSatsSent: 584106361867,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
             {
                 txid: 'f5d4c112cfd22701226ba050cacfacc3aff570964c6196f67e326fc3224300a2',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 2877,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a9147c09e7cf1b2c40d4e08057e47bda9cabcdfd208588ac',
                         '76a9149f27f41b828019c141516179ab00e538a3f65a1788ac',
                         '76a9142d9c4a5a292f5fef07b8cfe76b0c66d90d15a5d688ac',
                         '76a9149d1cd75ff25c555213ab5fef4bbd6a180a5e5e7d88ac',
                         '76a9143d1ee2681911f344e77097a8bd25576e1da1c51788ac',
                         '76a91429981fd0910f0851fcb3422b37abb5de442de33188ac',
                         '76a914ef95330c2b65976c5c63b03d544207b5e55bb58b88ac',
                         '76a9144d746dbe5864a2635376326a3995f8ada2ec339d88ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '76a914a520c86a08366941cd90d22e11ac1c7eefa2db3788ac',
                             106577441836,
                         ],
                     ],
                 },
                 totalSatsSent: 106577441836,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
             {
                 txid: 'd5be7a4b483f9fdbbe3bf46cfafdd0100d5dbeee0b972f4dabc8ae9d9962fa55',
                 genesisInfo: false,
                 opReturnInfo: {
                     app: 'CashFusion',
                     msg: '',
                     stackArray: [
                         '46555a00',
                         'ab3267b0b667ea2252d414b3714d6f08b5fbf16c0026ce454c903dc6ff002255',
                     ],
                     tokenId: false,
                 },
                 txFee: 11430,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a91412934a7a99b69a60c3b99f991cd79d257104f5a688ac',
                         '76a91415c0b62c9f73847ca9a686561216c20b487a0aad88ac',
                         '76a914a4e299724b8e81474df916c25c7a816a43c8748888ac',
                         '76a9147afa62562b93fecaff30190ee3a2836dcb95d42f88ac',
                         '76a91468e15e8bfe2d969b7963181b976e6833e294661288ac',
                         '76a914f941b2e03f973ce5b13766159eef190963e2393488ac',
                         '76a9146e3430f87a128ac4509fb0547f07ba0e3e8cea7688ac',
                         '76a914c72166790bc8c779163e17b11939a6bd6022a7e188ac',
                         '76a91483c54d6ec805f4db16c935f5bb89da791f971ac888ac',
                         '76a914336fb64b7e98221f82aced275440c29e7e1d11b388ac',
                         '76a914b114a9d636ac7558c04e902c3a1f7c1fd9008bcd88ac',
                         '76a91411667c453097adf3e71d08986df7766c26f3399088ac',
                         '76a914a125966da9024acea37f867323778641ff0e891888ac',
                         '76a914e03ba5757763a00aaa8aa9eda71da51610d5ef2788ac',
                         '76a914b13b05d51174d91381b0ea6fb07a6345eea1abf788ac',
                         '76a914349c3f91c2782b235ae0d1a2c3acf053d554170788ac',
                         '76a9143afafec322ef1a4f70a6ca68dd9090182716181888ac',
                         '76a914cb74cf87cd355cd01505645eaf165646a4eb1ce988ac',
                         '76a914c42245ebeb7fea2996e5e0f65537b56fb58ea97d88ac',
                         '76a91447d7bc2240955fd18d53c67c4b814e166b152ec388ac',
                         '76a91410b45d95195a71957b43bb82762e6cb48e67888f88ac',
                         '76a914894e84afe4b07413c99087067292aca67d286fbf88ac',
                         '76a91473b804181c01f16cbf63fe262e9a0c8de929af1e88ac',
                         '76a9147b1a9441467759f8693bdac3e356ab6110bebe1c88ac',
                         '76a914443f7cf9987b921c10d888c3d617c54aba5e8fb088ac',
                         '76a91490de1562e4aadc991dc13d28a9d112461fea9cb888ac',
                         '76a914273808f74a845b9b77345d43cb679ca793c5e9e688ac',
                         '76a91402a6a02a8bbdc6a9ebeb74bf5d8b9f7d20ad386688ac',
                         '76a914fcc200903ed9167def3df599c599d0c98b2cea0588ac',
                         '76a914692a38590fe1786dca47d2cbcc0ee30d969ca0c788ac',
                         '76a91486b2a4458787245715865c9ea5e42f8d68e8828988ac',
                         '76a914c472cd5ea7282180aa6a663498e98c2b781afa0488ac',
                         '76a914457a8a10ca1b8ab373c7e5e9ea7d784e8ce2efd188ac',
                         '76a91406cbe837f5a8b81ec8fddcf6e46c15b84b43965788ac',
                         '76a9145ab8a85ea3f6bf3a69b15b9f7570aeb021df77b488ac',
                         '76a9149704c9d13afb31a9b84ea5cb56140499e54743bd88ac',
                         '76a91423dab92affaa336ae18cab2669d116fbfa55b0bf88ac',
                         '76a914c6a520edfedb88ae478c1fdb309739d62d47dbd088ac',
                         '76a914388d048805daa142def4833f5cb1e02db7013a6f88ac',
                         '76a914cf55018839d8ab8b93de655551357d081f8120c788ac',
                         '76a9147eb48844af0ceae69879fd66456a5afffed24cb788ac',
                         '76a914e94c40d02b7860a76057a48b826ef847372eb74388ac',
                         '76a9148fddf18aecb230772dec7d9fa6ec5c2eae1303bf88ac',
                         '76a914687b26740360cae141c61c9e5dcb03b6100dc42b88ac',
                         '76a914c9fd6f67f21b1970264ba239e82d4a3c40e2063188ac',
                         '76a914cfbdaf0aaed19c7fc5e2a39e77cc780db5e333b588ac',
                         '76a914a17017d5f758fcc1372746bce8509c3d23f218a788ac',
                         '76a914d179b30a22db1d4aa04c163f7c1474fc1fbb5c5588ac',
                         '76a914f3f590529240d25b82fe10c18efbb64a64f9625988ac',
                         '76a9143856ed1d33df771934e14e0446518fa21c8ef6f188ac',
                         '76a914d26a1fac6b5c02e98e839956f3a7547d0c1b5c0088ac',
                         '76a9147cf1203b978724009018c3a5e6a605590f6e9fed88ac',
                         '76a9146e56ad4a85fa5e2d03f3bc16b52cfcab65c5e74188ac',
                         '76a914d17e89b26be59dfdbbd2582afdbf785cc11ad56388ac',
                         '76a914888bdff661832d406351713b49c683776b90e7b088ac',
                         '76a914e58661c82c66669cbaa2d1e813009d0b5d2fafb888ac',
                         '76a91463b5940d2fd7d998b343a54986ca375ff8cd2bbd88ac',
                         '76a91490b66329b172fd43feacbbb461c54183eed1bd5d88ac',
                         '76a9142fd4bdafad85abcb999c4bab8a2901f92caf487988ac',
                         '76a914979d66b56061bc4b7ac2118f54aecbf86ae5773888ac',
                         '76a9144724b6e46690d083ece0390ced609aeb0488486988ac',
                         '76a9142342542a4947b9bfcedffa803b369ec8c108b0b488ac',
                         '76a9140f18bea6bafd89a55997c72703006ec7a83d6e6988ac',
                         '76a914a7bf09e5099224ead64cb27cc9eb38283c3cde4288ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a0446555a0020ab3267b0b667ea2252d414b3714d6f08b5fbf16c0026ce454c903dc6ff002255',
                             0,
                         ],
                         [
                             '76a914d7fc1d156d8ec4384623bb8ceb135df93f2bd93188ac',
                             506531,
                         ],
                         [
                             '76a91447da14cfad47a7971dd345821ac7a81e194e474588ac',
                             1175076,
                         ],
                         [
                             '76a914d6b7baf14352dd9769a9a8bdb1f69cf700766aca88ac',
                             1557619,
                         ],
                         [
                             '76a914bc53fc8620ece064004a7bb72f0613a0045f6ae488ac',
                             1685802,
                         ],
                         [
                             '76a914ea34af00f2585bddc37607af492a7d5b35d431fe88ac',
                             1957993,
                         ],
                         [
                             '76a914dab80f23ec17efe39e3167ac47575f5b102855d288ac',
                             2280297,
                         ],
                         [
                             '76a914f10147fbbff24aa9f4f9a9f3726760a4abad6a9688ac',
                             2804591,
                         ],
                         [
                             '76a9140b8b9344a473853830f3657c7247e4834171d6fd88ac',
                             2810950,
                         ],
                         [
                             '76a914a0737c0938d04eff2d5074513ee5fd3fd41de38488ac',
                             2862208,
                         ],
                         [
                             '76a914b5d94938a3665b01fc0afee6b6179bb2b9e46b2e88ac',
                             2880530,
                         ],
                         [
                             '76a914dbb0e87717a034774a2435db6c9d4791f58bd43f88ac',
                             2894084,
                         ],
                         [
                             '76a9144e3bebebb3ac2785181534094eadccad4ea8dc4688ac',
                             3104218,
                         ],
                         [
                             '76a91458c2d76cd32e1d30d0e62b641d50bdd89200a7f188ac',
                             3122421,
                         ],
                         [
                             '76a9142980d02fa9a25306f3dd195ab9c82a2e2877f67e88ac',
                             3419974,
                         ],
                         [
                             '76a91451331eca38c944f17ee6354a3ee48193c7eb1b6b88ac',
                             3594078,
                         ],
                         [
                             '76a914755b984555fcd6305583c21d996a8dea7faa67d488ac',
                             3794311,
                         ],
                         [
                             '76a914e245bab4243bd6a8f3932c9dab9df496f003eae488ac',
                             4241488,
                         ],
                         [
                             '76a9147901f7c02a7fb7de87c373c143e15e87989f764b88ac',
                             5771042,
                         ],
                         [
                             '76a9149db2a709e1f26df987ecd5a5dcb8db0b36a449ef88ac',
                             5801672,
                         ],
                         [
                             '76a9141c5dd21c29a653e6922c2058852d9f56e483170188ac',
                             6529646,
                         ],
                         [
                             '76a9143510f0c92f8b26e26de575140a084773e95f439a88ac',
                             6536855,
                         ],
                         [
                             '76a914ee542bd41bb07264cf9f6e824e45d3446a26077c88ac',
                             7742026,
                         ],
                         [
                             '76a914c4131be628403d70a62e46dfc13b576af05aa5f088ac',
                             8072753,
                         ],
                         [
                             '76a914f5ffa38db9ffac77b5a1a6c35eebf2415fedf87c88ac',
                             8820534,
                         ],
                         [
                             '76a914b3e42f44a3dff21f72c90555d0ec62b273f0d4a588ac',
                             9000450,
                         ],
                         [
                             '76a91463a7fe1eff49be76e18538f3ed380b7386af1c8f88ac',
                             11771919,
                         ],
                         [
                             '76a91457f118d5f5eecebc88f711a80018bececbeb86e088ac',
                             13144002,
                         ],
                         [
                             '76a9148d2a8ce8e95b3047b918d8bd24db8c3e39d906cc88ac',
                             13393930,
                         ],
                         [
                             '76a914d6a0a87a3a5ea254ed4a2665ac328a7ef769747688ac',
                             13691033,
                         ],
                         [
                             '76a914810c66b72d769d1fefd2c5bb26d20024e25fd35088ac',
                             14490346,
                         ],
                         [
                             '76a914b3f036ee778de53049e0152a140bcba4952081f788ac',
                             15649462,
                         ],
                         [
                             '76a9144dbd06c9f304601d8fe89199ee7afa0afc3e5de688ac',
                             16885611,
                         ],
                         [
                             '76a91435cf783dd7fc1a919c5a92d73feedcab1d3e4dd588ac',
                             17311755,
                         ],
                         [
                             '76a914c570835edbc0de4a525a9ba9501eb0b123b8ab1c88ac',
                             19229444,
                         ],
                         [
                             '76a9142368a5b973c7d48fa8343b71cfb51b5a4ccfcb2488ac',
                             19612475,
                         ],
                         [
                             '76a9149163b5cb6618d7d67562270de630da0d62896c1e88ac',
                             20857697,
                         ],
                         [
                             '76a91464be00bf5c68a60ae520cfa81d051225457572a788ac',
                             21475345,
                         ],
                         [
                             '76a9148bc944201dec7391def49db52202a009c6a81f2088ac',
                             21879959,
                         ],
                         [
                             '76a914af6ae4c996d1ab51dd344b1f491c01163169053588ac',
                             21900743,
                         ],
                         [
                             '76a914c1f421d009c6b36b205721c064c2ae5ea3272a4688ac',
                             22276723,
                         ],
                         [
                             '76a9146454f4696e5bbb5eb4d368c162b35f6fcc861e6b88ac',
                             22828111,
                         ],
                         [
                             '76a9142a8af09882e0b5dd047b03e61eb3630e0678325e88ac',
                             22829710,
                         ],
                         [
                             '76a9147eec957f14c8c35b491f487a8d777cf3b427f47688ac',
                             23106927,
                         ],
                         [
                             '76a9148f41a4d08d01a574210a0d99784248d7b718a6b388ac',
                             25043923,
                         ],
                         [
                             '76a9149fbf277434a5a0582ffe774693c343e95c442a8188ac',
                             25946731,
                         ],
                         [
                             '76a914d35d6706484afdc79bbaab9ce1f84fed4939317f88ac',
                             26216189,
                         ],
                         [
                             '76a914fc64d1ceb75ef723b8bb81f53039f239f69de25d88ac',
                             27153210,
                         ],
                         [
                             '76a9140b395214ae8c35fd7e8bb6921fa478216fd9e41988ac',
                             27888923,
                         ],
                         [
                             '76a9145c9faf662be3667f760e03535c511085a2bc814488ac',
                             28283566,
                         ],
                         [
                             '76a914f883cd4d8e8b6e1cba5d127e24c57b45c26b46a288ac',
                             29688615,
                         ],
                         [
                             '76a9147fe1c85d201af0ab1322d5809aaa03bb7dac05fb88ac',
                             32471718,
                         ],
                         [
                             '76a9141ab1428e336477a213d18207570b5008841d24ea88ac',
                             35209256,
                         ],
                         [
                             '76a914219f01df857ef5faa2c1509b8dc958eb9425f5df88ac',
                             40404442,
                         ],
                         [
                             '76a914a4c2e50019b19c9d152b6327733033253d61efe188ac',
                             48107746,
                         ],
                         [
                             '76a91479be8c6a6fc20a9f4cd1e55d8e99fef936a5b4fb88ac',
                             54611567,
                         ],
                         [
                             '76a914e8f011eded020ed1605848c7b5e6704eb689b33f88ac',
                             54872231,
                         ],
                         [
                             '76a9146573038dc2d55422c20b91588f8264f9aa038d6088ac',
                             56164346,
                         ],
                         [
                             '76a9147077be58e7ead7443259fe5409309edbabef41d388ac',
                             58564003,
                         ],
                         [
                             '76a9149cf6eb2a055f3340d31d83bf5e29cfe0e9d919f288ac',
                             59817398,
                         ],
                         [
                             '76a914d12908c4b7be22044226856207328e20e3e1f2c288ac',
                             64104923,
                         ],
                         [
                             '76a91437a517f6174aed807cb1f9fb26ff25912c8ea4ee88ac',
                             87305777,
                         ],
                         [
                             '76a914b2094f7a6f5c39a66ddff6852bfef1f6dac495fb88ac',
                             91558238,
                         ],
                     ],
                 },
                 totalSatsSent: 1308715143,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
             {
                 txid: 'b5782d3a3b55e5ee9e4330a969c2891042ae05fafab7dc05cd14da63e7242f8e',
                 genesisInfo: false,
                 opReturnInfo: {
                     app: 'unknown',
                     msg: '0x663ddd99990bcd9699...',
                     stackArray: ['663ddd99990bcd969994ec2288a2a86dc532e1a8'],
                     tokenId: false,
                 },
                 txFee: 260,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a9142cc3608fe629c4f402e511878982bc01bde3445d88ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             'a9145aafaadba9ff909067a640e5e2a46b756aeaf71387',
                             12966621,
                         ],
                         ['6a14663ddd99990bcd969994ec2288a2a86dc532e1a8', 0],
                     ],
                 },
                 totalSatsSent: 12966621,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
             {
                 txid: '9094e1aab7ac73c680bf66e78cc8311831b3d813e608bff1e07b1854855fc0f1',
                 genesisInfo: false,
                 opReturnInfo: {
                     app: 'unknown',
                     msg: '=:ETH.ETH:0xa9aaF30F65955C69c16B3345B51D426D9B88Ba87:841321:tr:0',
                     stackArray: [
                         '3d3a4554482e4554483a3078613961614633304636353935354336396331364233333435423531443432364439423838426138373a3834313332313a74723a30',
                     ],
                     tokenId: false,
                 },
                 txFee: 452,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a914d95a60cea21479569e6b1ad39416c8fbc97323c588ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '76a914453c8c15aee05fe5a027d4bf5681cd0bc682c0b788ac',
                             8419613,
                         ],
                         [
                             '6a403d3a4554482e4554483a3078613961614633304636353935354336396331364233333435423531443432364439423838426138373a3834313332313a74723a30',
                             0,
                         ],
                     ],
                 },
                 totalSatsSent: 8419613,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
             {
                 txid: '7a0d6ae3384e293183478f681f51a77ef4c71f29957199364bb9ba4d8e1938be',
                 genesisInfo: false,
                 opReturnInfo: {
                     app: 'Airdrop',
                     msg: '',
                     stackArray: [
                         '64726f70',
                         'b76878b29eff39c8c28aaed7d18a166c20057c43beeb90b630264470983c984a',
                         '00746162',
                         '5374617920776974682075732c2065436173682041667269636120697320746865206e6578742062696720636f6d6d756e69747920696e20746865204166726963616e2063727970746f7370686572652e20',
                     ],
                     tokenId:
                         'b76878b29eff39c8c28aaed7d18a166c20057c43beeb90b630264470983c984a',
                 },
                 txFee: 2561,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a914f93029e7593327c5b864ea6896ecfda4fffb6ab888ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a0464726f7020b76878b29eff39c8c28aaed7d18a166c20057c43beeb90b630264470983c984a04007461624c525374617920776974682075732c2065436173682041667269636120697320746865206e6578742062696720636f6d6d756e69747920696e20746865204166726963616e2063727970746f7370686572652e20',
                             0,
                         ],
                         [
                             '76a914957b59a2bfa17ea7fc234e532b263169b6d34aa988ac',
                             264706,
                         ],
                         [
                             '76a9148f882b02e1040f83c2f73007bb334716c38dbffc88ac',
                             529412,
                         ],
                         [
                             '76a914f43ac7271cee240bee3796938203105fb54c045c88ac',
                             529412,
                         ],
                         [
                             '76a914d5a79acda6dbbe14a686a0c59466f52656330a9588ac',
                             264706,
                         ],
                         [
                             '76a91429207c3d229d6163521fbe87e52e64bbe584dbc988ac',
                             529412,
                         ],
                         [
                             '76a914e735901add6ea366a0964ab54ad9d9158597f50c88ac',
                             264706,
                         ],
                         [
                             '76a91407acf15b7cc6a4c18d8d1c3a5611ea30718c2a0d88ac',
                             264706,
                         ],
                         [
                             '76a9146671b4690e282cb79707b1ee696d54a6072329fa88ac',
                             529412,
                         ],
                         [
                             '76a914d4f7e7b420eb1c5410abf698c72d790f0c4cc1b388ac',
                             264706,
                         ],
                         [
                             '76a914b19e12ae2aa186102486e8348f22b87ae426eafd88ac',
                             264706,
                         ],
                         [
                             '76a914e6309418b6e60b8119928ec45b8ba87de8e735f788ac',
                             529412,
                         ],
                         [
                             '76a914cdba2655ee5abf18a5b6203da5b7d8cc28c36ca888ac',
                             264706,
                         ],
                     ],
                 },
                 totalSatsSent: 4500002,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
             {
                 txid: 'd02d94a1a520877c60d1e3026c3e85f8995d48d7b90140f83e24ede592c30306',
                 genesisInfo: false,
                 opReturnInfo: {
                     app: 'Cashtab Msg',
                     msg: 'I like eCash',
                     stackArray: ['00746162', '49206c696b65206543617368'],
                     tokenId: false,
                 },
                 txFee: 479,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a9147d432e8ccc646fe6c52e36c285bce2b75f0f500b88ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         ['6a04007461620c49206c696b65206543617368', 0],
                         [
                             '76a9144fb74b44c66ab529428a943131f236c80d99b82088ac',
                             1000000,
                         ],
                     ],
                 },
                 totalSatsSent: 1000000,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
             {
                 txid: 'd8fe456c89357c23ac6d240fe9319ce9ba393c9c3833631046a265ca7c8349e6',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 219,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '76a91430f16ad77116a4b9e7f337743e35271323d63e0d88ac',
                             4200,
                         ],
                     ],
                 },
                 totalSatsSent: 4200,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
             {
                 txid: '083b7862bae48e78549ccf63833896f5f4f5bdef5c380a108fa99cdb64261fa3',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 219,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '76a914eeae0fea781c26c93879523ba5a47c244c768ece88ac',
                             4200,
                         ],
                     ],
                 },
                 totalSatsSent: 4200,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
             {
                 txid: '45ec66bc2440d2f94fa2c645e20a44f6fab7c397053ce77a95484c6053104cdc',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 2412,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a9147276ae7693883fa1165628e298899d8ee9248e7c88ac',
                         '76a9148b9b3ba9199d98e131b762081c0c31754fb904c288ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a503d534c5032000453454e4445e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd03401f000000006067010000002f9102000000',
                             0,
                         ],
                         [
                             '76a914dee50f576362377dd2f031453c0bb09009acaf8188ac',
                             546,
                         ],
                         [
                             'a914f71cf8cb91804a2205901cc0972c3f4a088a1aae87',
                             2588,
                         ],
                     ],
                 },
                 totalSatsSent: 3134,
                 tokenSendInfo: {
                     tokenId:
                         'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                     parsedTokenType: 'ALP',
                     txType: 'SEND',
                     tokenChangeOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a9147276ae7693883fa1165628e298899d8ee9248e7c88ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '168239',
                                 },
                             ],
                         ],
                     },
                     tokenReceivingOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a914dee50f576362377dd2f031453c0bb09009acaf8188ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '8000',
                                 },
                             ],
                             [
                                 'a914f71cf8cb91804a2205901cc0972c3f4a088a1aae87',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '92000',
                                 },
                             ],
                         ],
                     },
                     tokenSendingOutputScripts: {
                         dataType: 'Set',
                         value: [
                             '76a9147276ae7693883fa1165628e298899d8ee9248e7c88ac',
                         ],
                     },
                 },
                 tokenBurnInfo: false,
             },
             {
                 txid: '1083da7ead4779fbab5c5e8291bb7a37abaf4f97f5ff99ee654759b2eaee445b',
                 genesisInfo: false,
                 opReturnInfo: {
                     app: 'Cashtab Encrypted',
                     msg: '',
                     stackArray: [
                         '65746162',
                         '036bdec11e461033145b5d96661e45ba2a40081aad01d34c4da4dac5e42b9961c990fc603ad5c6fed77fff016d57caa7ba8cbcebb33bd47e5eb0707628c0331e4d714054ab773ae4a555c9ea432af23a83104209e5299e86081f5fabe4a744e96eac6675149ce4e7680e342270498d0e68',
                     ],
                     tokenId: false,
                 },
                 txFee: 1277,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a9140b7d35fda03544a08e65464d54cfae4257eb6db788ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a04657461624c71036bdec11e461033145b5d96661e45ba2a40081aad01d34c4da4dac5e42b9961c990fc603ad5c6fed77fff016d57caa7ba8cbcebb33bd47e5eb0707628c0331e4d714054ab773ae4a555c9ea432af23a83104209e5299e86081f5fabe4a744e96eac6675149ce4e7680e342270498d0e68',
                             0,
                         ],
                         [
                             '76a9149846b6b38ff713334ac19fe3cf851a1f98c07b0088ac',
                             2000,
                         ],
                     ],
                 },
                 totalSatsSent: 2000,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
             {
                 txid: '22135bb69435023a84c80b1b93b31fc8898c3507eaa70569ed038f32d59599a9',
                 genesisInfo: false,
                 opReturnInfo: {
                     app: 'Alias (beta)',
                     msg: 'doge2',
                     stackArray: [
                         '2e786563',
                         '00',
                         '646f676532',
                         '000b7d35fda03544a08e65464d54cfae4257eb6db7',
                     ],
                     tokenId: false,
                 },
                 txFee: 752,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a9140b7d35fda03544a08e65464d54cfae4257eb6db788ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a042e7865630005646f67653215000b7d35fda03544a08e65464d54cfae4257eb6db7',
                             0,
                         ],
                         ['a914d37c4c809fe9840e7bfa77b86bd47163f6fb6c6087', 554],
                     ],
                 },
                 totalSatsSent: 554,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
             {
                 txid: '004e018dd98520aa722ee76c608771dd578a044f38103a8298f25e6ffbc7c3ba',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 481,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a04534c500001010453454e4420aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb108000000000000271008000000000589ffd0',
                             0,
                         ],
                         [
                             '76a914dcc535261a43835ca12352d0926ba06cf07cbe8388ac',
                             546,
                         ],
                     ],
                 },
                 totalSatsSent: 546,
                 tokenSendInfo: {
                     tokenId:
                         'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                     parsedTokenType: 'SLP',
                     txType: 'SEND',
                     tokenChangeOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '92930000',
                                 },
                             ],
                         ],
                     },
                     tokenReceivingOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a914dcc535261a43835ca12352d0926ba06cf07cbe8388ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '10000',
                                 },
                             ],
                         ],
                     },
                     tokenSendingOutputScripts: {
                         dataType: 'Set',
                         value: [
                             '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                         ],
                     },
                 },
                 tokenBurnInfo: false,
             },
             {
                 txid: '0110cd886ecd2d9570e98b7501cd039f4e5352d69659a46f1a49cc19c1869701',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 481,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a04534c500001010453454e4420aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1080000000000002710080000000005856bf0',
                             0,
                         ],
                         [
                             '76a91469724b96df46096cc95b1a6d408a4240ea80d85588ac',
                             546,
                         ],
                     ],
                 },
                 totalSatsSent: 546,
                 tokenSendInfo: {
                     tokenId:
                         'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                     parsedTokenType: 'SLP',
                     txType: 'SEND',
                     tokenChangeOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '92630000',
                                 },
                             ],
                         ],
                     },
                     tokenReceivingOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a91469724b96df46096cc95b1a6d408a4240ea80d85588ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '10000',
                                 },
                             ],
                         ],
                     },
                     tokenSendingOutputScripts: {
                         dataType: 'Set',
                         value: [
                             '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                         ],
                     },
                 },
                 tokenBurnInfo: false,
             },
             {
                 txid: '327101f6f3b740280a6e9fbd8edc41f4f0500633672975a5974a4147c94016a5',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 481,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a04534c500001010453454e4420aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1080000000000002710080000000005843370',
                             0,
                         ],
                         [
                             '76a91458cddba2449285814dae43d4ed4a1c9998f3693e88ac',
                             546,
                         ],
                     ],
                 },
                 totalSatsSent: 546,
                 tokenSendInfo: {
                     tokenId:
                         'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                     parsedTokenType: 'SLP',
                     txType: 'SEND',
                     tokenChangeOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '92550000',
                                 },
                             ],
                         ],
                     },
                     tokenReceivingOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a91458cddba2449285814dae43d4ed4a1c9998f3693e88ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '10000',
                                 },
                             ],
                         ],
                     },
                     tokenSendingOutputScripts: {
                         dataType: 'Set',
                         value: [
                             '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                         ],
                     },
                 },
                 tokenBurnInfo: false,
             },
             {
                 txid: 'aa13c6f214ff58f36ed5e108a7f36d8f98729c50186b27a53b989c7f36fbf517',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 481,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a04534c500001010453454e4420aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1080000000000002710080000000000986f70',
                             0,
                         ],
                         [
                             '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                             546,
                         ],
                     ],
                 },
                 totalSatsSent: 546,
                 tokenSendInfo: {
                     tokenId:
                         'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                     parsedTokenType: 'SLP',
                     txType: 'SEND',
                     tokenChangeOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '9990000',
                                 },
                             ],
                         ],
                     },
                     tokenReceivingOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '10000',
                                 },
                             ],
                         ],
                     },
                     tokenSendingOutputScripts: {
                         dataType: 'Set',
                         value: [
                             '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                         ],
                     },
                 },
                 tokenBurnInfo: false,
             },
             {
                 txid: '6ffcc83e76226bd32821cc6862ce9b363b22594247a4e73ccf3701b0023592b2',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 1137,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a04534c500001010453454e442098183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f4808000000000000003708000000003b9a72a4',
                             0,
                         ],
                         [
                             '76a9146ffbe7c7d7bd01295eb1e371de9550339bdcf9fd88ac',
                             546,
                         ],
                     ],
                 },
                 totalSatsSent: 546,
                 tokenSendInfo: {
                     tokenId:
                         '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
                     parsedTokenType: 'SLP',
                     txType: 'SEND',
                     tokenChangeOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '999977636',
                                 },
                             ],
                         ],
                     },
                     tokenReceivingOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a9146ffbe7c7d7bd01295eb1e371de9550339bdcf9fd88ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '55',
                                 },
                             ],
                         ],
                     },
                     tokenSendingOutputScripts: {
                         dataType: 'Set',
                         value: [
                             '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                         ],
                     },
                 },
                 tokenBurnInfo: false,
             },
             {
                 txid: 'fb70df00c07749082756054522d3f08691fd9caccd0e0abf736df23d22845a6e',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 1137,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a04534c500001010453454e44207443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d0800000000068c953f08001299507b7b143a',
                             0,
                         ],
                         [
                             '76a9146ffbe7c7d7bd01295eb1e371de9550339bdcf9fd88ac',
                             546,
                         ],
                     ],
                 },
                 totalSatsSent: 546,
                 tokenSendInfo: {
                     tokenId:
                         '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
                     parsedTokenType: 'SLP',
                     txType: 'SEND',
                     tokenChangeOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '5235120528888890',
                                 },
                             ],
                         ],
                     },
                     tokenReceivingOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a9146ffbe7c7d7bd01295eb1e371de9550339bdcf9fd88ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '109876543',
                                 },
                             ],
                         ],
                     },
                     tokenSendingOutputScripts: {
                         dataType: 'Set',
                         value: [
                             '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                         ],
                     },
                 },
                 tokenBurnInfo: false,
             },
             {
                 txid: '25345b0bf921a2a9080c647768ba440bbe84499f4c7773fba8a1b03e88ae7fe7',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 1137,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a04534c500001010453454e4420fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa08000000001dcd65000800000007e7339728',
                             0,
                         ],
                         [
                             '76a914dadf34cde9c774fdd6340cd2916a9b9c5d57cf4388ac',
                             546,
                         ],
                     ],
                 },
                 totalSatsSent: 546,
                 tokenSendInfo: {
                     tokenId:
                         'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
                     parsedTokenType: 'SLP',
                     txType: 'SEND',
                     tokenChangeOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '33943689000',
                                 },
                             ],
                         ],
                     },
                     tokenReceivingOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a914dadf34cde9c774fdd6340cd2916a9b9c5d57cf4388ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '500000000',
                                 },
                             ],
                         ],
                     },
                     tokenSendingOutputScripts: {
                         dataType: 'Set',
                         value: [
                             '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
                         ],
                     },
                 },
                 tokenBurnInfo: false,
             },
             {
                 txid: '413b57617d2c497b137d31c53151fee595415ec273ef7a111160da8093147ed8',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 454,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: ['a914ea826cc1a3a981d048cd78b66711222bece8ebf287'],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a5032534c503200044d494e5445e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd0160ae0a00000000',
                             0,
                         ],
                         [
                             '76a91472a92e48c5ab72566959db1dbf1b8dce83afabb788ac',
                             546,
                         ],
                     ],
                 },
                 totalSatsSent: 546,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
             {
                 txid: 'b2c9c056339d41ec59341541dda8bd6e570730beba485e14eb54d0a073700c22',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 1000,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a914378c3b416e77e01198c01ad215b8afd0bb72799488ac',
                         '76a9148b9b3ba9199d98e131b762081c0c31754fb904c288ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a5031534c5032000453454e4445e1f25de444e399b6d46fa66e3424c04549a85a14b12bc9a4ddc9cdcdcdcdcd01d00700000000',
                             0,
                         ],
                         [
                             '76a914acdbf937b086ddaa970072a610daa8d10f14549a88ac',
                             546,
                         ],
                     ],
                 },
                 totalSatsSent: 546,
                 tokenSendInfo: {
                     tokenId:
                         'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                     parsedTokenType: 'ALP',
                     txType: 'SEND',
                     tokenChangeOutputs: {
                         dataType: 'Map',
                         value: [],
                     },
                     tokenReceivingOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a914acdbf937b086ddaa970072a610daa8d10f14549a88ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '2000',
                                 },
                             ],
                         ],
                     },
                     tokenSendingOutputScripts: {
                         dataType: 'Set',
                         value: [
                             '76a914378c3b416e77e01198c01ad215b8afd0bb72799488ac',
                         ],
                     },
                 },
                 tokenBurnInfo: false,
             },
             {
                 txid: '010114b9bbe776def1a512ad1e96a4a06ec4c34fc79bcb5d908845f5102f6b0f',
                 genesisInfo: {
                     tokenId:
                         '010114b9bbe776def1a512ad1e96a4a06ec4c34fc79bcb5d908845f5102f6b0f',
                 },
                 opReturnInfo: false,
                 txFee: 455,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a914104e67d912a7aab2a159bba141477e5867c04bfd88ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a04534c500001010747454e45534953054c6f6c6c79054c4f4c4c591468747470733a2f2f636173687461622e636f6d2f4c0001084c00080162ea854d0fc000',
                             0,
                         ],
                     ],
                 },
                 totalSatsSent: 0,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
             {
                 txid: '0167e881fcb359cdfc82af5fc6c0821daf55f40767694eea2f23c0d42a9b1c17',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 1638,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a9146d69b5cbe7c85d87628473c43620c0daa9a8102988ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a04534c500001010453454e44207e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e50800000000002737100800000000000f3636',
                             0,
                         ],
                     ],
                 },
                 totalSatsSent: 0,
                 tokenSendInfo: {
                     tokenId:
                         '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
                     parsedTokenType: 'SLP',
                     txType: 'SEND',
                     tokenChangeOutputs: {
                         dataType: 'Map',
                         value: [
                             [
                                 '76a9146d69b5cbe7c85d87628473c43620c0daa9a8102988ac',
                                 {
                                     dataType: 'BigNumberReplacer',
                                     value: '3566918',
                                 },
                             ],
                         ],
                     },
                     tokenReceivingOutputs: {
                         dataType: 'Map',
                         value: [],
                     },
                     tokenSendingOutputScripts: {
                         dataType: 'Set',
                         value: [
                             '76a9146d69b5cbe7c85d87628473c43620c0daa9a8102988ac',
                         ],
                     },
                 },
                 tokenBurnInfo: false,
             },
             {
                 txid: '6b139007a0649f99a1a099c7c924716ee1920f74ea83111f6426854d4c3c3c79',
                 genesisInfo: false,
                 opReturnInfo: false,
                 txFee: 1137,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a9144bb6f659b8dafd99527e0c0a3289f121b0a0209f88ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a04534c500001010453454e4420fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa08000000000c380cdc',
                             0,
                         ],
                     ],
                 },
                 totalSatsSent: 0,
                 tokenSendInfo: false,
                 tokenBurnInfo: {
                     tokenId:
                         'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
                     undecimalizedTokenBurnAmount: '100',
                 },
             },
             {
                 txid: 'ad44bf5e214ab71bb60a2eee165f368c139cd49c2380c3352f0a4fffc746b36a',
                 genesisInfo: false,
                 opReturnInfo: {
                     app: 'SWaP',
                     msg: '',
                     stackArray: [
                         '53575000',
                         '01',
                         '01',
                         'aebcae9afe88d61d8b8ed7b8c83c7c2a555583bf8f8591c94a2c9eb82f34816c',
                         '53454c4c',
                         '3135393838333534',
                         '00',
                         '3dd9beaedcbb3ad90eec2214fcf71381fa89b08b899813e182a7a393e1ab0619',
                         '01',
                         '00',
                         '333236322e39393939393939393939393935',
                     ],
                     tokenId:
                         'aebcae9afe88d61d8b8ed7b8c83c7c2a555583bf8f8591c94a2c9eb82f34816c',
                 },
                 txFee: 466,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a914aed3f8a5add35a9ddaf0a07986c2b73a2202727d88ac',
                         '76a914d50ec518d64850fda86e926764ce1bce1ba01a1988ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a04535750000101010120aebcae9afe88d61d8b8ed7b8c83c7c2a555583bf8f8591c94a2c9eb82f34816c0453454c4c0831353938383335340100203dd9beaedcbb3ad90eec2214fcf71381fa89b08b899813e182a7a393e1ab06190101010012333236322e39393939393939393939393935',
                             0,
                         ],
                     ],
                 },
                 totalSatsSent: 0,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
             {
                 txid: 'a8c348539a1470b28b9f99693994b918b475634352994dddce80ad544e871b3a',
                 genesisInfo: false,
                 opReturnInfo: {
                     app: 'memo',
                     msg: 'Reply to memo|<a href="https://explorer.e.cash/tx/eae5710aba50a0a22b266ddbb445e05b7348d15c88cbc2e012a91a09bec3861a">memo</a>|Twitter keeps turning their API on and off. Sometimes it works, sometimes it doesn\'t. Feature to create tweets from memo may work again at some point.',
                 },
                 txFee: 390,
                 xecSendingOutputScripts: {
                     dataType: 'Set',
                     value: [
                         '76a9148fa951904f6d0ebbc92dc29e761b9eb0a837545c88ac',
                     ],
                 },
                 xecReceivingOutputs: {
                     dataType: 'Map',
                     value: [
                         [
                             '6a026d0320eae5710aba50a0a22b266ddbb445e05b7348d15c88cbc2e012a91a09bec3861a4c9654776974746572206b65657073207475726e696e6720746865697220415049206f6e20616e64206f66662e20536f6d6574696d657320697420776f726b732c20736f6d6574696d657320697420646f65736e27742e204665617475726520746f20637265617465207477656574732066726f6d206d656d6f206d617920776f726b20616761696e20617420736f6d6520706f696e742e',
                             0,
                         ],
                     ],
                 },
                 totalSatsSent: 0,
                 tokenSendInfo: false,
                 tokenBurnInfo: false,
             },
         ],
         tokenIds: {
             dataType: 'Set',
             value: [
                 'b76878b29eff39c8c28aaed7d18a166c20057c43beeb90b630264470983c984a',
                 'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                 'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                 '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
                 '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
                 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
                 '010114b9bbe776def1a512ad1e96a4a06ec4c34fc79bcb5d908845f5102f6b0f',
                 '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
                 'aebcae9afe88d61d8b8ed7b8c83c7c2a555583bf8f8591c94a2c9eb82f34816c',
             ],
         },
         outputScripts: {
             dataType: 'Set',
             value: [
                 '76a914231f7087937684790d1049294f3aef9cfb7b05dd88ac',
                 '76a9147c09e7cf1b2c40d4e08057e47bda9cabcdfd208588ac',
                 '76a914a520c86a08366941cd90d22e11ac1c7eefa2db3788ac',
                 '76a91412934a7a99b69a60c3b99f991cd79d257104f5a688ac',
                 '76a914d7fc1d156d8ec4384623bb8ceb135df93f2bd93188ac',
                 '76a9142cc3608fe629c4f402e511878982bc01bde3445d88ac',
                 'a9145aafaadba9ff909067a640e5e2a46b756aeaf71387',
                 '76a914d95a60cea21479569e6b1ad39416c8fbc97323c588ac',
                 '76a914453c8c15aee05fe5a027d4bf5681cd0bc682c0b788ac',
                 '76a914f93029e7593327c5b864ea6896ecfda4fffb6ab888ac',
                 '76a914957b59a2bfa17ea7fc234e532b263169b6d34aa988ac',
                 '76a9147d432e8ccc646fe6c52e36c285bce2b75f0f500b88ac',
                 '76a9144fb74b44c66ab529428a943131f236c80d99b82088ac',
                 '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                 '76a91430f16ad77116a4b9e7f337743e35271323d63e0d88ac',
                 '76a914eeae0fea781c26c93879523ba5a47c244c768ece88ac',
                 '76a9147276ae7693883fa1165628e298899d8ee9248e7c88ac',
                 '76a914dee50f576362377dd2f031453c0bb09009acaf8188ac',
                 '76a9140b7d35fda03544a08e65464d54cfae4257eb6db788ac',
                 '76a9149846b6b38ff713334ac19fe3cf851a1f98c07b0088ac',
                 'a914d37c4c809fe9840e7bfa77b86bd47163f6fb6c6087',
                 '76a914dcc535261a43835ca12352d0926ba06cf07cbe8388ac',
                 '76a91469724b96df46096cc95b1a6d408a4240ea80d85588ac',
                 '76a91458cddba2449285814dae43d4ed4a1c9998f3693e88ac',
                 '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                 '76a9146ffbe7c7d7bd01295eb1e371de9550339bdcf9fd88ac',
                 '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
                 '76a914dadf34cde9c774fdd6340cd2916a9b9c5d57cf4388ac',
                 'a914ea826cc1a3a981d048cd78b66711222bece8ebf287',
                 '76a91472a92e48c5ab72566959db1dbf1b8dce83afabb788ac',
                 '76a914378c3b416e77e01198c01ad215b8afd0bb72799488ac',
                 '76a914acdbf937b086ddaa970072a610daa8d10f14549a88ac',
                 '76a914104e67d912a7aab2a159bba141477e5867c04bfd88ac',
                 '76a9146d69b5cbe7c85d87628473c43620c0daa9a8102988ac',
                 '76a9144bb6f659b8dafd99527e0c0a3289f121b0a0209f88ac',
                 '76a914aed3f8a5add35a9ddaf0a07986c2b73a2202727d88ac',
                 '76a9148fa951904f6d0ebbc92dc29e761b9eb0a837545c88ac',
             ],
         },
     },
     coingeckoResponse: {
         bitcoin: {
             usd: 30000,
         },
         ecash: {
             usd: 0.0001,
         },
         ethereum: {
             usd: 2000,
         },
     },
     coingeckoPrices: [
         {
             fiat: 'usd',
             price: 0.0001,
             ticker: 'XEC',
         },
         {
             fiat: 'usd',
             price: 30000,
             ticker: 'BTC',
         },
         {
             fiat: 'usd',
             price: 2000,
             ticker: 'ETH',
         },
     ],
     tokenInfoMap: {
         dataType: 'Map',
         value: [
             [
                 'b76878b29eff39c8c28aaed7d18a166c20057c43beeb90b630264470983c984a',
                 {
                     tokenTicker: 'eAfrica',
                     tokenName: 'eAfrica Token',
                     url: 'https://chat.whatsapp.com/BJDUldMxnNm23KAFRE4diq',
                     decimals: 2,
                     hash: '',
                 },
             ],
             [
                 'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
                 {
                     tokenTicker: 'CRD',
                     tokenName: 'Credo In Unum Deo',
                     url: 'https://crd.network/token',
                     decimals: 4,
                     data: {},
                     authPubkey:
                         '0334b744e6338ad438c92900c0ed1869c3fd2c0f35a4a9b97a88447b6e2b145f10',
                 },
             ],
             [
                 'aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1',
                 {
                     tokenTicker: 'CACHET',
                     tokenName: 'Cachet',
                     url: 'https://cashtab.com/',
                     decimals: 2,
                     hash: '',
                 },
             ],
             [
                 '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
                 {
                     tokenTicker: 'DVV',
                     tokenName: 'Delta Variant Variants',
                     url: 'https://cashtabapp.com/',
                     decimals: 0,
                     hash: '',
                 },
             ],
             [
                 '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
                 {
                     tokenTicker: 'WDT',
                     tokenName:
                         'Test Token With Exceptionally Long Name For CSS And Style Revisions',
                     url: 'https://www.ImpossiblyLongWebsiteDidYouThinkWebDevWouldBeFun.org',
                     decimals: 7,
                     hash: '85b591c15c9f49531e39fcfeb2a5a26b2bd0f7c018fb9cd71b5d92dfb732d5cc',
                 },
             ],
             [
                 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
                 {
                     tokenTicker: 'GRP',
                     tokenName: 'GRUMPY',
                     url: 'https://bit.ly/GrumpyDoc',
                     decimals: 2,
                     hash: '',
                 },
             ],
             [
                 '010114b9bbe776def1a512ad1e96a4a06ec4c34fc79bcb5d908845f5102f6b0f',
                 {
                     tokenTicker: 'Lolly',
                     tokenName: 'LOLLY',
                     url: 'https://cashtab.com/',
                     decimals: 8,
                     hash: '',
                 },
             ],
             [
                 '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
                 {
                     tokenTicker: 'BUX',
                     tokenName: 'Badger Universal Token',
                     url: 'https://bux.digital',
                     decimals: 4,
                     hash: '',
                 },
             ],
             [
                 'aebcae9afe88d61d8b8ed7b8c83c7c2a555583bf8f8591c94a2c9eb82f34816c',
                 {
                     tokenTicker: 'GORB',
                     tokenName: 'Gorbeious',
                     url: 'gorbeious.cash',
                     decimals: 0,
                     hash: '',
                 },
             ],
         ],
     },
     outputScriptInfoMap: {
         dataType: 'Map',
         value: [
             [
                 '76a914231f7087937684790d1049294f3aef9cfb7b05dd88ac',
                 {
                     emoji: '🐳',
                     balanceSats: '01000000000000',
                     utxos: [
                         {
                             value: '1000000000000',
                         },
                     ],
                 },
             ],
             [
                 '76a9147c09e7cf1b2c40d4e08057e47bda9cabcdfd208588ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a914a520c86a08366941cd90d22e11ac1c7eefa2db3788ac',
                 {
                     emoji: 'πŸ¦€',
                     balanceSats: '010000000000',
                     utxos: [
                         {
                             value: '10000000000',
                         },
                     ],
                 },
             ],
             [
                 '76a91412934a7a99b69a60c3b99f991cd79d257104f5a688ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a914d7fc1d156d8ec4384623bb8ceb135df93f2bd93188ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a9142cc3608fe629c4f402e511878982bc01bde3445d88ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 'a9145aafaadba9ff909067a640e5e2a46b756aeaf71387',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a914d95a60cea21479569e6b1ad39416c8fbc97323c588ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a914453c8c15aee05fe5a027d4bf5681cd0bc682c0b788ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a914f93029e7593327c5b864ea6896ecfda4fffb6ab888ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a914957b59a2bfa17ea7fc234e532b263169b6d34aa988ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a9147d432e8ccc646fe6c52e36c285bce2b75f0f500b88ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a9144fb74b44c66ab529428a943131f236c80d99b82088ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a914821407ac2993f8684227004f4086082f3f801da788ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a91430f16ad77116a4b9e7f337743e35271323d63e0d88ac',
                 {
                     emoji: '',
                     balanceSats: 10000,
                     utxos: [
                         {
                             value: 10000,
                         },
                     ],
                 },
             ],
             [
                 '76a914eeae0fea781c26c93879523ba5a47c244c768ece88ac',
                 {
                     emoji: '',
                     balanceSats: 10000,
                     utxos: [
                         {
                             value: 10000,
                         },
                     ],
                 },
             ],
             [
                 '76a9147276ae7693883fa1165628e298899d8ee9248e7c88ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a914dee50f576362377dd2f031453c0bb09009acaf8188ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a9140b7d35fda03544a08e65464d54cfae4257eb6db788ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a9149846b6b38ff713334ac19fe3cf851a1f98c07b0088ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 'a914d37c4c809fe9840e7bfa77b86bd47163f6fb6c6087',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a914dcc535261a43835ca12352d0926ba06cf07cbe8388ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a91469724b96df46096cc95b1a6d408a4240ea80d85588ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a91458cddba2449285814dae43d4ed4a1c9998f3693e88ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a9146ffbe7c7d7bd01295eb1e371de9550339bdcf9fd88ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a914dadf34cde9c774fdd6340cd2916a9b9c5d57cf4388ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 'a914ea826cc1a3a981d048cd78b66711222bece8ebf287',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a91472a92e48c5ab72566959db1dbf1b8dce83afabb788ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a914378c3b416e77e01198c01ad215b8afd0bb72799488ac',
                 {
                     emoji: '',
                     balanceSats: 10000,
                     utxos: [
                         {
                             value: 10000,
                         },
                     ],
                 },
             ],
             [
                 '76a914acdbf937b086ddaa970072a610daa8d10f14549a88ac',
                 {
                     emoji: '',
                     balanceSats: 10000,
                     utxos: [
                         {
                             value: 10000,
                         },
                     ],
                 },
             ],
             [
                 '76a914104e67d912a7aab2a159bba141477e5867c04bfd88ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a9146d69b5cbe7c85d87628473c43620c0daa9a8102988ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a9144bb6f659b8dafd99527e0c0a3289f121b0a0209f88ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a914aed3f8a5add35a9ddaf0a07986c2b73a2202727d88ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
             [
                 '76a9148fa951904f6d0ebbc92dc29e761b9eb0a837545c88ac',
                 {
                     emoji: '',
                     balanceSats: '010000',
                     utxos: [
                         {
                             value: '10000',
                         },
                     ],
                 },
             ],
         ],
     },
     blockSummaryTgMsgs: [
         'πŸ“¦<a href="https://explorer.e.cash/block/0000000000000000000000000000000000000000000000000000000000000000">819346</a> | 27 txs | unknown, ...863u\n⏰ 20,654 blocks until eCash halving\nπŸ’°$63 to <a href="https://explorer.e.cash/address/ecash:qrpkjsd0fjxd7m332mmlu9px6pwkzaufpcn2u7jcwt">qrp...cwt</a>\n1 XEC = $0.0001\n1 BTC = $30,000\n1 ETH = $2,000\n\n<b>1 new eToken created</b>\nπŸ§ͺ<a href="https://explorer.e.cash/tx/010114b9bbe776def1a512ad1e96a4a06ec4c34fc79bcb5d908845f5102f6b0f">LOLLY</a> (Lolly) <a href="https://cashtab.com/">[doc]</a>\n\n<a href="https://cashtab.com/">Cashtab</a>\n<b>3</b> <a href="https://explorer.e.cash/tx/aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1">CACHET</a> rewards\n<b>2</b> new users received <b>84 XEC</b>\n\n2 txs sent 10.2000 <a href="https://explorer.e.cash/tx/cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145">Credo In Unum Deo (CRD)</a>\n1 tx sent 100.00 <a href="https://explorer.e.cash/tx/aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1">Cachet (CACHET)</a>\n1 tx sent 55 <a href="https://explorer.e.cash/tx/98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48">Delta Variant Variants (DVV)</a>\n1 tx sent 10.9876543 <a href="https://explorer.e.cash/tx/7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d">Test Token With Exceptionally Long Name For CSS And Style Revisions (WDT)</a>\n1 tx sent 5,000,000.00 <a href="https://explorer.e.cash/tx/fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa">GRUMPY (GRP)</a>\n1 tx sent 356.6918 <a href="https://explorer.e.cash/tx/7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5">Badger Universal Token (BUX)</a>\n\n<b>1 eToken burn tx</b>\nπŸ”₯qp9...et0 <a href="https://explorer.e.cash/tx/6b139007a0649f99a1a099c7c924716ee1920f74ea83111f6426854d4c3c3c79">burned</a> 1.00 <a href="https://explorer.e.cash/tx/fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa">GRP</a> \n\n<b>9 app txs</b>\nβš›οΈ<a href="https://explorer.e.cash/tx/d5be7a4b483f9fdbbe3bf46cfafdd0100d5dbeee0b972f4dabc8ae9d9962fa55">CashFusion:</a> Fused $1k from 64 inputs into 63 outputs\n❓<a href="https://explorer.e.cash/tx/b5782d3a3b55e5ee9e4330a969c2891042ae05fafab7dc05cd14da63e7242f8e">unknown:</a> 0x663ddd99990bcd9699...\n❓<a href="https://explorer.e.cash/tx/9094e1aab7ac73c680bf66e78cc8311831b3d813e608bff1e07b1854855fc0f1">unknown:</a> =:ETH.ETH:0xa9aaF30F65955C69c16B3345B51D426D9B88Ba87:841321:tr:0\nπŸͺ‚<a href="https://explorer.e.cash/tx/7a0d6ae3384e293183478f681f51a77ef4c71f29957199364bb9ba4d8e1938be">Airdrop:</a> qru...jys airdropped $5 to 13 holders of <a href="https://explorer.e.cash/tx/b76878b29eff39c8c28aaed7d18a166c20057c43beeb90b630264470983c984a">eAfrica</a>|Stay with us, eCash Africa is the next big community in the African cryptosphere. \nπŸ–‹<a href="https://explorer.e.cash/tx/d02d94a1a520877c60d1e3026c3e85f8995d48d7b90140f83e24ede592c30306">Cashtab Msg, $1 for $0.0005:</a> I like eCash\nπŸ”<a href="https://explorer.e.cash/tx/1083da7ead4779fbab5c5e8291bb7a37abaf4f97f5ff99ee654759b2eaee445b">Cashtab Encrypted:</a> qq9...fgx sent an encrypted message and $0.002 to qzv...fed\nπŸ‘Ύ<a href="https://explorer.e.cash/tx/22135bb69435023a84c80b1b93b31fc8898c3507eaa70569ed038f32d59599a9">Alias (beta):</a> doge2\n🀳<a href="https://explorer.e.cash/tx/ad44bf5e214ab71bb60a2eee165f368c139cd49c2380c3352f0a4fffc746b36a">SWaP:</a> Signal|SLP Atomic Swap|<a href="https://explorer.e.cash/tx/aebcae9afe88d61d8b8ed7b8c83c7c2a555583bf8f8591c94a2c9eb82f34816c">GORB</a>|SELL for 159,883.54 XEC|Min trade: 0 XEC\nπŸ—ž<a href="https://explorer.e.cash/tx/a8c348539a1470b28b9f99693994b918b475634352994dddce80ad544e871b3a">memo:</a> Reply to memo|<a href="https://explorer.e.cash/tx/eae5710aba50a0a22b266ddbb445e05b7348d15c88cbc2e012a91a09bec3861a">memo</a>|Twitter keeps turning their API on and off. Sometimes it works, sometimes it doesn\'t. Feature to create tweets from memo may work again at some point.\n\n<b>3 eCash txs</b>',
         'πŸ’Έ<a href="https://explorer.e.cash/tx/4f33c81d95641eb0f80e793dc96c58a2438f9bb1f18750d8fb3b56c28cd25035">$584k for $0.0003</a> 🐳 Binance ➑️ itself\nπŸ’Έ<a href="https://explorer.e.cash/tx/f5d4c112cfd22701226ba050cacfacc3aff570964c6196f67e326fc3224300a2">$107k for $0.003</a> qp7...sr4 ➑️ πŸ¦€qzj...ksg\nπŸ’Έ<a href="https://explorer.e.cash/tx/413b57617d2c497b137d31c53151fee595415ec273ef7a111160da8093147ed8">$0.0005 for $0.0005</a>',
     ],
     blockSummaryTgMsgsApiFailure: [
         'πŸ“¦<a href="https://explorer.e.cash/block/0000000000000000000000000000000000000000000000000000000000000000">819346</a> | 27 txs | unknown, ...863u\n⏰ 20,654 blocks until eCash halving\nπŸ’°625k XEC to <a href="https://explorer.e.cash/address/ecash:qrpkjsd0fjxd7m332mmlu9px6pwkzaufpcn2u7jcwt">qrp...cwt</a>\n\n<b>9 app txs</b>\nβš›οΈ<a href="https://explorer.e.cash/tx/d5be7a4b483f9fdbbe3bf46cfafdd0100d5dbeee0b972f4dabc8ae9d9962fa55">CashFusion:</a> Fused 13M XEC from 64 inputs into 63 outputs\n❓<a href="https://explorer.e.cash/tx/b5782d3a3b55e5ee9e4330a969c2891042ae05fafab7dc05cd14da63e7242f8e">unknown:</a> 0x663ddd99990bcd9699...\n❓<a href="https://explorer.e.cash/tx/9094e1aab7ac73c680bf66e78cc8311831b3d813e608bff1e07b1854855fc0f1">unknown:</a> =:ETH.ETH:0xa9aaF30F65955C69c16B3345B51D426D9B88Ba87:841321:tr:0\nπŸͺ‚<a href="https://explorer.e.cash/tx/7a0d6ae3384e293183478f681f51a77ef4c71f29957199364bb9ba4d8e1938be">Airdrop:</a> qru...jys airdropped 45k XEC to 13 holders of <a href="https://explorer.e.cash/tx/b76878b29eff39c8c28aaed7d18a166c20057c43beeb90b630264470983c984a">b76...84a</a>|Stay with us, eCash Africa is the next big community in the African cryptosphere. \nπŸ–‹<a href="https://explorer.e.cash/tx/d02d94a1a520877c60d1e3026c3e85f8995d48d7b90140f83e24ede592c30306">Cashtab Msg, 10k XEC for 4.79 XEC:</a> I like eCash\nπŸ”<a href="https://explorer.e.cash/tx/1083da7ead4779fbab5c5e8291bb7a37abaf4f97f5ff99ee654759b2eaee445b">Cashtab Encrypted:</a> qq9...fgx sent an encrypted message and 20 XEC to qzv...fed\nπŸ‘Ύ<a href="https://explorer.e.cash/tx/22135bb69435023a84c80b1b93b31fc8898c3507eaa70569ed038f32d59599a9">Alias (beta):</a> doge2\n🀳<a href="https://explorer.e.cash/tx/ad44bf5e214ab71bb60a2eee165f368c139cd49c2380c3352f0a4fffc746b36a">SWaP:</a> Signal|SLP Atomic Swap|<a href="https://explorer.e.cash/tx/aebcae9afe88d61d8b8ed7b8c83c7c2a555583bf8f8591c94a2c9eb82f34816c">Unknown Token</a>|SELL for 159,883.54 XEC|Min trade: 0 XEC\nπŸ—ž<a href="https://explorer.e.cash/tx/a8c348539a1470b28b9f99693994b918b475634352994dddce80ad544e871b3a">memo:</a> Reply to memo|<a href="https://explorer.e.cash/tx/eae5710aba50a0a22b266ddbb445e05b7348d15c88cbc2e012a91a09bec3861a">memo</a>|Twitter keeps turning their API on and off. Sometimes it works, sometimes it doesn\'t. Feature to create tweets from memo may work again at some point.\n\n<b>17 eCash txs</b>\nπŸ’Έ<a href="https://explorer.e.cash/tx/4f33c81d95641eb0f80e793dc96c58a2438f9bb1f18750d8fb3b56c28cd25035">6B XEC for 2.6 XEC</a>\nπŸ’Έ<a href="https://explorer.e.cash/tx/f5d4c112cfd22701226ba050cacfacc3aff570964c6196f67e326fc3224300a2">1B XEC for 29 XEC</a>\nπŸ’Έ<a href="https://explorer.e.cash/tx/d8fe456c89357c23ac6d240fe9319ce9ba393c9c3833631046a265ca7c8349e6">42 XEC for 2.19 XEC</a>\nπŸ’Έ<a href="https://explorer.e.cash/tx/083b7862bae48e78549ccf63833896f5f4f5bdef5c380a108fa99cdb64261fa3">42 XEC for 2.19 XEC</a>\nπŸ’Έ<a href="https://explorer.e.cash/tx/45ec66bc2440d2f94fa2c645e20a44f6fab7c397053ce77a95484c6053104cdc">31 XEC for 24 XEC</a>\nπŸ’Έ<a href="https://explorer.e.cash/tx/004e018dd98520aa722ee76c608771dd578a044f38103a8298f25e6ffbc7c3ba">5.46 XEC for 4.81 XEC</a>\nπŸ’Έ<a href="https://explorer.e.cash/tx/0110cd886ecd2d9570e98b7501cd039f4e5352d69659a46f1a49cc19c1869701">5.46 XEC for 4.81 XEC</a>\nπŸ’Έ<a href="https://explorer.e.cash/tx/327101f6f3b740280a6e9fbd8edc41f4f0500633672975a5974a4147c94016a5">5.46 XEC for 4.81 XEC</a>\nπŸ’Έ<a href="https://explorer.e.cash/tx/aa13c6f214ff58f36ed5e108a7f36d8f98729c50186b27a53b989c7f36fbf517">5.46 XEC for 4.81 XEC</a>\nπŸ’Έ<a href="https://explorer.e.cash/tx/6ffcc83e76226bd32821cc6862ce9b363b22594247a4e73ccf3701b0023592b2">5.46 XEC for 11 XEC</a>\nπŸ’Έ<a href="https://explorer.e.cash/tx/fb70df00c07749082756054522d3f08691fd9caccd0e0abf736df23d22845a6e">5.46 XEC for 11 XEC</a>\nπŸ’Έ<a href="https://explorer.e.cash/tx/25345b0bf921a2a9080c647768ba440bbe84499f4c7773fba8a1b03e88ae7fe7">5.46 XEC for 11 XEC</a>\n...and <a href="https://explorer.e.cash/block/0000000000000000000000000000000000000000000000000000000000000000">5 more</a>',
     ],
 };
 
 export default mockedBlock;
diff --git a/apps/ecash-herald/test/mocks/telegramBotMock.ts b/apps/ecash-herald/test/mocks/telegramBotMock.ts
index 07c0fc831..65e793966 100644
--- a/apps/ecash-herald/test/mocks/telegramBotMock.ts
+++ b/apps/ecash-herald/test/mocks/telegramBotMock.ts
@@ -1,47 +1,47 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 /* Mock node-telegram-bot-api TelegramBot instance
  * Supports sendMessage function
  */
 import { SendMessageOptions } from 'node-telegram-bot-api';
 export const mockChannelId = '-1001999999999';
 
 interface SendMessageResponse {
     success: boolean;
     channelId: string;
     msg: string;
     options: SendMessageOptions;
 }
 
-export interface MockTelegramBot {
+export interface MockTelegramBotInterface {
     messageSent: boolean;
     errors: { [key: string]: string | undefined };
     sendMessage: (
         channelId: string,
         msg: string,
         options: SendMessageOptions,
     ) => SendMessageResponse;
     setExpectedError: (method: string, error: string) => void;
 }
 
-export class MockTelegramBot implements MockTelegramBot {
-    constructor() {
-        // Use self since it is not a reserved term in js
-        // Can access self from inside a method and still get the class
-        const self = this;
-        self.messageSent = false;
-        self.errors = {};
-        self.sendMessage = function (channelId, msg, options) {
-            if (!self.errors.sendMessage) {
-                self.messageSent = true;
-                return { success: true, channelId, msg, options };
-            }
-            throw new Error(self.errors.sendMessage);
-        };
-        self.setExpectedError = function (method, error) {
-            self.errors[method] = error;
-        };
+export class MockTelegramBot implements MockTelegramBotInterface {
+    public messageSent = false;
+    public errors: { [key: string]: string | undefined } = {};
+    public sendMessage(
+        channelId: string,
+        msg: string,
+        options: SendMessageOptions,
+    ): SendMessageResponse {
+        if (!this.errors.sendMessage) {
+            this.messageSent = true;
+            return { success: true, channelId, msg, options };
+        }
+        throw new Error(this.errors.sendMessage || 'Unknown error');
+    }
+
+    public setExpectedError(method: string, error: string): void {
+        this.errors[method] = error;
     }
 }
diff --git a/apps/ecash-herald/test/mocks/templates.ts b/apps/ecash-herald/test/mocks/templates.ts
index 42c8fc315..8ea0f6874 100644
--- a/apps/ecash-herald/test/mocks/templates.ts
+++ b/apps/ecash-herald/test/mocks/templates.ts
@@ -1,101 +1,101 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 import { FiatCode } from '../../config';
 import { CoinGeckoPrice } from '../../src/utils';
 
 interface TgStringFixture {
     dangerous: string;
     safe: string;
     noChangeExpected: string;
 }
 interface Templates {
     telegramHtmlStrings: TgStringFixture;
     addressPreviews: { address: string; preview: string; sliceSize: number }[];
     mockCoingeckoPrices: CoinGeckoPrice[];
 }
-const templates = {
+const templates: Templates = {
     telegramHtmlStrings: {
         dangerous: '<b>Try to hack the format</b> ${true && <i>yes</i>}',
         safe: '&lt;b&gt;Try to hack the format&lt;/b&gt; ${true &amp;&amp; &lt;i&gt;yes&lt;/i&gt;}',
         noChangeExpected:
             'Just a normal sentence with punctuation and things, but none of the forbidden characters.',
     },
     addressPreviews: [
         {
             address: 'ecash:qqf76scx4s8yayz80n6r3wcvuqdnypw5dvt38lr8up',
             preview: 'qqf...8up',
             sliceSize: 3,
         },
         {
             address: 'ecash:qpp66yg3dsp0fx3w8gl9zw6nwkwf587pqcduy5jp3z',
             preview: 'qpp...p3z',
             sliceSize: 3,
         },
         {
             address: 'ecash:qq7uq470gu0afsffkveesckges366wrcrssvngy7gu',
             preview: 'qq7...7gu',
             sliceSize: 3,
         },
         {
             address: 'ecash:qqf76scx4s8yayz80n6r3wcvuqdnypw5dvt38lr8up',
             preview: 'qqf76s...8lr8up',
             sliceSize: 6,
         },
         {
             address: 'ecash:qpp66yg3dsp0fx3w8gl9zw6nwkwf587pqcduy5jp3z',
             preview: 'qpp66y...y5jp3z',
             sliceSize: 6,
         },
         {
             address: 'ecash:qq7uq470gu0afsffkveesckges366wrcrssvngy7gu',
             preview: 'qq7uq4...ngy7gu',
             sliceSize: 6,
         },
         {
             address: 'ecash:qq7uq470gu0afsffkveesckges366wrcrssvngy7gu',
             preview: 'qq...gu',
             sliceSize: 2,
         },
         {
             address: 'ecash:qqf76scx4s8yayz80n6r3wcvuqdnypw5dvt38lr8up',
             preview: 'qqf76...lr8up',
             sliceSize: 5,
         },
         {
             address: 'ecash:qq337uy8jdmgg7gdzpyjjne6a7w0k7c9m5m5gnpx4u',
             preview: 'Binance',
             sliceSize: 3,
         },
         {
             address: 'ecash:qq580luw0dkypdlrply9ulk3rht6nrqfugvgm9le8a',
             preview: 'Coinex 1',
             sliceSize: 3,
         },
         {
             address: 'ecash:qqv2vqz6he83x9pczvt552fuxnvhevlt6ugrqqa7w5',
             preview: 'Coinex 2',
             sliceSize: 3,
         },
     ],
     mockCoingeckoPrices: [
         {
             fiat: 'usd' as FiatCode,
             price: 0.00003,
             ticker: 'XEC',
         },
         {
             fiat: 'usd' as FiatCode,
             price: 28044.64857505,
             ticker: 'BTC',
         },
         {
             fiat: 'usd' as FiatCode,
             price: 1900.73166438,
             ticker: 'ETH',
         },
     ],
 };
 
 export default templates;
diff --git a/apps/ecash-herald/test/parse.test.ts b/apps/ecash-herald/test/parse.test.ts
index 5f5b4cec7..c768f7bd3 100644
--- a/apps/ecash-herald/test/parse.test.ts
+++ b/apps/ecash-herald/test/parse.test.ts
@@ -1,588 +1,588 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 import assert from 'assert';
 import opReturn from '../constants/op_return';
 import unrevivedBlock from './mocks/block';
 import minersJson, { KnownMiners } from '../constants/miners';
 import minerTestFixtures from './fixtures/miners';
 import stakerTestFixtures from './fixtures/stakers';
 import invalidatedBlocksTestFixtures from './fixtures/invalidatedBlocks';
 import { jsonReviver } from '../src/utils';
 import memoFixtures from './mocks/memo';
 import { consumeNextPush } from 'ecash-script';
 import { MockChronikClient } from '../../../modules/mock-chronik-client';
 import { TxOutput } from 'chronik-client';
 import { caching } from 'cache-manager';
 import { StoredMock } from '../src/events';
 import {
     parseBlockTxs,
     getStakerFromCoinbaseTx,
     getMinerFromCoinbaseTx,
     parseMemoOutputScript,
     getBlockTgMessage,
     parseOpReturn,
     getSwapTgMsg,
     getAirdropTgMsg,
     getEncryptedCashtabMsg,
     parseMultipushStack,
     parseSlpTwo,
     guessRejectReason,
     summarizeTxHistory,
 } from '../src/parse';
 import appTxSamples from './mocks/appTxSamples';
 import { dailyTxs, tokenInfoMap } from './mocks/dailyTxs';
 
 const {
     swaps,
     airdrops,
     encryptedCashtabMsgs,
     slp2PushVectors,
     slp2TxVectors,
     aliasRegistrations,
     cashtabMsgs,
     payButtonTxs,
     paywallTxs,
     authenticationTxs,
 } = appTxSamples;
 
 const block: StoredMock = JSON.parse(
     JSON.stringify(unrevivedBlock),
     jsonReviver,
 );
 const miners: KnownMiners = JSON.parse(JSON.stringify(minersJson), jsonReviver);
 
 describe('parse.js functions', function () {
     it('Parses the master test block', function () {
         const thisBlock = block;
         const {
             blockTxs,
             parsedBlock,
             coingeckoPrices,
             tokenInfoMap,
             outputScriptInfoMap,
             blockSummaryTgMsgs,
         } = thisBlock;
         assert.deepEqual(
             parseBlockTxs(parsedBlock.hash, parsedBlock.height, blockTxs),
             parsedBlock,
         );
         assert.deepEqual(
             getBlockTgMessage(
                 parsedBlock,
                 coingeckoPrices,
                 tokenInfoMap,
                 outputScriptInfoMap,
             ),
             blockSummaryTgMsgs,
         );
     });
     it('parseOpReturn handles all types of SWaP txs', function () {
         for (let i = 0; i < swaps.length; i += 1) {
             const { hex, stackArray, tokenId } = swaps[i];
             assert.deepEqual(parseOpReturn(hex), {
                 app: opReturn.knownApps.swap.app,
                 msg: '',
                 stackArray,
                 tokenId,
             });
         }
     });
     it('getSwapTgMsg handles all types of SWaP txs', function () {
         for (let i = 0; i < swaps.length; i += 1) {
             const { stackArray, msg, tokenInfo } = swaps[i];
             const result = getSwapTgMsg(stackArray, tokenInfo);
             assert.strictEqual(result, msg);
         }
     });
     it('parseOpReturn handles alias registration txs', function () {
         for (let i = 0; i < aliasRegistrations.length; i += 1) {
             const { hex, stackArray, msg } = aliasRegistrations[i];
             assert.deepEqual(parseOpReturn(hex), {
                 app: opReturn.knownApps.alias.app,
                 msg,
                 stackArray,
                 tokenId: false,
             });
         }
     });
     it('parseOpReturn handles Cashtab Msgs', function () {
         for (let i = 0; i < cashtabMsgs.length; i += 1) {
             const { hex, stackArray, msg } = cashtabMsgs[i];
             assert.deepEqual(parseOpReturn(hex), {
                 app: opReturn.knownApps.cashtabMsg.app,
                 msg,
                 stackArray,
                 tokenId: false,
             });
         }
     });
     it('parseOpReturn handles PayButton txs', function () {
         for (let i = 0; i < payButtonTxs.length; i += 1) {
             const { hex, stackArray, msg } = payButtonTxs[i];
             assert.deepEqual(parseOpReturn(hex), {
                 app: opReturn.knownApps.payButton.app,
                 msg,
                 stackArray,
                 tokenId: false,
             });
         }
     });
     it('parseOpReturn handles airdrop txs with and without a cashtab msg', function () {
         for (let i = 0; i < airdrops.length; i += 1) {
             const { hex, stackArray, tokenId } = airdrops[i];
             assert.deepEqual(parseOpReturn(hex), {
                 app: opReturn.knownApps.airdrop.app,
                 msg: '',
                 stackArray,
                 tokenId,
             });
         }
     });
     it('getAirdropMsg handles airdrop txs with and without a cashtab msg', function () {
         for (let i = 0; i < airdrops.length; i += 1) {
             const {
                 stackArray,
                 airdropSendingAddress,
                 airdropRecipientsKeyValueArray,
                 msg,
                 msgApiFailure,
                 tokenInfo,
                 coingeckoPrices,
             } = airdrops[i];
             const xecReceivingOutputs = new Map(airdropRecipientsKeyValueArray);
             let totalSatsSent = 0;
             for (const satoshis of xecReceivingOutputs.values()) {
                 totalSatsSent += satoshis;
             }
             const result = getAirdropTgMsg(
                 stackArray,
                 airdropSendingAddress,
                 xecReceivingOutputs,
                 totalSatsSent,
                 tokenInfo,
                 coingeckoPrices,
             );
             const resultApiFailure = getAirdropTgMsg(
                 stackArray,
                 airdropSendingAddress,
                 xecReceivingOutputs,
                 totalSatsSent,
                 false,
                 false,
             );
             assert.strictEqual(result, msg);
             assert.strictEqual(resultApiFailure, msgApiFailure);
         }
     });
     it('parseOpReturn handles encrypted cashtab msg txs', function () {
         for (let i = 0; i < encryptedCashtabMsgs.length; i += 1) {
             const { hex, stackArray } = encryptedCashtabMsgs[i];
             assert.deepEqual(parseOpReturn(hex), {
                 app: opReturn.knownApps.cashtabMsgEncrypted.app,
                 msg: '',
                 stackArray,
                 tokenId: false,
             });
         }
     });
     it('parseOpReturn handles paywall payment txs', function () {
         for (let i = 0; i < paywallTxs.length; i += 1) {
             const { hex, stackArray, msg } = paywallTxs[i];
             assert.deepEqual(parseOpReturn(hex), {
                 app: opReturn.knownApps.paywall.app,
                 msg: msg,
                 stackArray,
                 tokenId: false,
             });
         }
     });
     it('getEncryptedCashtabMsg handles encrypted cashtab msg txs with and without price info', function () {
         for (let i = 0; i < encryptedCashtabMsgs.length; i += 1) {
             const {
                 sendingAddress,
                 xecReceivingOutputsKeyValueArray,
                 msg,
                 msgApiFailure,
                 coingeckoPrices,
             } = encryptedCashtabMsgs[i];
 
             const xecReceivingOutputs = new Map(
                 xecReceivingOutputsKeyValueArray,
             );
             let totalSatsSent = 0;
             for (const satoshis of xecReceivingOutputs.values()) {
                 totalSatsSent += satoshis;
             }
             const result = getEncryptedCashtabMsg(
                 sendingAddress,
                 xecReceivingOutputs,
                 totalSatsSent,
                 coingeckoPrices,
             );
             const resultApiFailure = getEncryptedCashtabMsg(
                 sendingAddress,
                 xecReceivingOutputs,
                 totalSatsSent,
                 false,
             );
             assert.strictEqual(result, msg);
             assert.strictEqual(resultApiFailure, msgApiFailure);
         }
     });
     it('parseOpReturn handles slp2 txs', function () {
         for (let i = 0; i < slp2TxVectors.length; i += 1) {
             const { hex, msg } = slp2TxVectors[i];
             assert.deepEqual(parseOpReturn(hex), {
                 app: 'EMPP',
                 msg,
             });
         }
     });
     it('parseOpReturn handles authentication txs', function () {
         for (let i = 0; i < authenticationTxs.length; i += 1) {
             const { hex, stackArray, msg } = authenticationTxs[i];
             assert.deepEqual(parseOpReturn(hex), {
                 app: opReturn.knownApps.authentication.app,
                 msg: msg,
                 stackArray,
                 tokenId: false,
             });
         }
     });
     it('parseMultipushStack handles a range of observed slp2 empp pushes', function () {
         for (let i = 0; i < slp2TxVectors.length; i += 1) {
             const { emppStackArray, msg } = slp2TxVectors[i];
             assert.deepEqual(parseMultipushStack(emppStackArray), {
                 app: 'EMPP',
                 msg,
             });
         }
     });
     it('parseSlpTwo handles a range of observed slp2 empp pushes', function () {
         for (let i = 0; i < slp2PushVectors.length; i += 1) {
             const { push, msg } = slp2PushVectors[i];
 
             assert.strictEqual(parseSlpTwo(push.slice(8)), msg);
         }
     });
     it('parseOpReturn recognizes legacy Cash Fusion prefix', function () {
         assert.deepEqual(
             parseOpReturn(
                 '0446555a0020771c2fa0d402fe15ba0aa2e98660facf4a8ab6801b5baf3c0b08ced685dd85ed',
             ),
             {
                 app: opReturn.knownApps.fusionLegacy.app,
                 msg: '',
                 tokenId: false,
                 stackArray: [
                     '46555a00',
                     '771c2fa0d402fe15ba0aa2e98660facf4a8ab6801b5baf3c0b08ced685dd85ed',
                 ],
             },
         );
     });
     it(`parseMemoOutputScript correctly parses all tested memo actions in memo.js`, function () {
         memoFixtures.map(memoTestObj => {
             const { outputScript, msg } = memoTestObj;
             // Get array of pushes
-            let stack = { remainingHex: outputScript.slice(2) };
-            let stackArray = [];
+            const stack = { remainingHex: outputScript.slice(2) };
+            const stackArray = [];
             while (stack.remainingHex.length > 0) {
                 stackArray.push(consumeNextPush(stack).data);
             }
             assert.deepEqual(parseMemoOutputScript(stackArray), {
                 app: opReturn.memo.app,
                 msg,
             });
         });
     });
     it('getStakerFromCoinbaseTx parses miner for all test vectors', function () {
         for (let i = 0; i < stakerTestFixtures.length; i += 1) {
             const { coinbaseTx, staker } = stakerTestFixtures[i];
 
             assert.deepEqual(
                 getStakerFromCoinbaseTx(
                     coinbaseTx.block.height,
                     coinbaseTx.outputs as TxOutput[],
                 ),
                 staker,
             );
         }
     });
     it('getMinerFromCoinbaseTx parses miner for all test vectors', function () {
         for (let i = 0; i < minerTestFixtures.length; i += 1) {
             const { parsed, coinbaseHex, payoutOutputScript } =
                 minerTestFixtures[i];
             // Minimally mock the coinbase tx
             const inputScript = coinbaseHex;
             const outputs = [
                 { outputScript: payoutOutputScript },
             ] as TxOutput[];
 
             assert.strictEqual(
                 getMinerFromCoinbaseTx(inputScript, outputs, miners),
                 parsed,
             );
         }
     });
     it('guessRejectReason returns the expected guess for all test vectors', async function () {
         for (let i = 0; i < invalidatedBlocksTestFixtures.length; i += 1) {
             const {
                 height,
                 coinbaseData,
                 expectedRejectReason,
                 expectedCacheData,
                 mockedBlock,
             } = invalidatedBlocksTestFixtures[i];
 
             const mockedChronik = new MockChronikClient();
             mockedChronik.mockedResponses.block = mockedBlock;
 
             const testMemoryCache = await caching('memory', {
                 max: 100,
                 ttl: 60,
             });
             testMemoryCache.set(`${height}`, expectedCacheData);
 
             assert.strictEqual(
                 await guessRejectReason(
                     mockedChronik,
                     height,
                     coinbaseData,
                     testMemoryCache,
                 ),
                 expectedRejectReason,
             );
         }
     });
     it('summarizeTxHistory summarizes a collection of txs across multiple blocks including fiat prices', function () {
         const mockUtcNewDayTimestampSeconds = 1728950400;
         assert.deepEqual(
             summarizeTxHistory(
                 mockUtcNewDayTimestampSeconds,
                 dailyTxs,
                 tokenInfoMap,
                 {
                     usd: 0.00003487,
                     usd_market_cap: 689047177.8128564,
                     usd_24h_vol: 5957332.9687223025,
                     usd_24h_change: -0.3973642442197056,
                 },
             ),
             [
                 '<b>15 Oct 2024</b>\n' +
                     'πŸ“¦57,430 blocks\n' +
                     '➑️30 txs\n' +
                     '\n' +
                     'πŸ“‰<b>1 XEC = $0.00003487</b> <i>(-0.40%)</i>\n' +
                     'Trading volume: $5,957,333\n' +
                     'Market cap: $689,047,178\n' +
                     '\n' +
                     '<b><i>⛏️3 miners found blocks</i></b>\n' +
                     '<u>Top 3</u>\n' +
                     '1. Mining-Dutch, 1 <i>(0%)</i>\n' +
                     '2. solopool.org, 1 <i>(0%)</i>\n' +
                     '3. ViaBTC, 1 <i>(0%)</i>\n' +
                     '\n' +
                     '<b><i>πŸ’°3 stakers earned $33</i></b>\n' +
                     '<u>Top 3</u>\n' +
                     '1. <a href="https://explorer.e.cash/address/ecash:qzs8hq2pj4hu5j09fdr5uhha3986h2mthvfp7362nu">qzs...2nu</a>, 1 <i>(0%)</i>\n' +
                     '2. <a href="https://explorer.e.cash/address/ecash:qr42c8c04tqndscfrdnl0rzterg0qdaegyjzt8egyg">qr4...gyg</a>, 1 <i>(0%)</i>\n' +
                     '3. <a href="https://explorer.e.cash/address/ecash:qqvhatumna957qu0je78dnc9pc7c7hu89crkq6k0cd">qqv...0cd</a>, 1 <i>(0%)</i>\n' +
                     '\n' +
                     '<a href="https://cashtab.com/">Cashtab</a>\n' +
                     '🎁 <b>1</b> new user received <b>42 XEC</b>\n' +
                     '🎟 <b>1</b> <a href="https://explorer.e.cash/tx/aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1">CACHET</a> reward\n' +
                     '\n' +
                     'πŸ›πŸͺ™ <b><i>3 Agora token txs from 3 tokens</i></b>\n' +
                     'πŸ’°Buy, 🏷List, ❌Cancel\n' +
                     '<a href="https://explorer.e.cash/tx/aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1">Cachet</a> (CACHET): πŸ’°\n' +
                     '<a href="https://explorer.e.cash/tx/20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8">Vespene Gas</a> (VSP): ❌\n' +
                     '<a href="https://explorer.e.cash/tx/01d63c4f4cb496829a6743f7b1805d086ea3877a1dd34b3f92ffba2c9c99f896">Bull</a> (BULL): 🏷\n' +
                     '\nπŸ›πŸ–Ό <b><i>3 Agora NFT txs from 2 NFTs in 2 collections</i></b>\n' +
                     'πŸ’°Buy, 🏷List, ❌Cancel\n' +
                     '<a href="https://explorer.e.cash/tx/78efa5177e99bf05b48948ac7e23e6cc2255764e52ccf7092afb979a766dee2c">xolosArmyPOP</a> (RMZPOP): πŸ’°\n' +
                     '<a href="https://explorer.e.cash/tx/0fb781a98fffb980b1c9c609f62b29783c348e74aa7ea3908dcf7f46388ab316">Flags</a> (FLAGS): 🏷❌\n' +
                     '\n' +
                     'πŸͺ™ <b><i>8 token txs from 2 tokens</i></b>\n' +
                     '<a href="https://explorer.e.cash/tx/04009a8be347f21a1122964c3226b99c36a9bd755c5a450a53848471a2466103">Perpetua</a> (PRP): πŸ§ͺ➑️πŸ”₯πŸ”¨\n' +
                     '<a href="https://explorer.e.cash/tx/20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8">Vespene Gas</a> (VSP): ➑️\n' +
                     '\n' +
                     'πŸ–Ό <b><i>2 NFT txs from 2 NFTs in 2 collections</i></b>\n' +
                     '<a href="https://explorer.e.cash/tx/8fd3f14abd2b176a1d4bd5136542cd2a7ba3df0e11947dd19326c9d1cd81ae09">Xoloitzcuintli NFT Cigar Collection.</a> (RMZsmoke): πŸ§ͺ\n' +
                     '<a href="https://explorer.e.cash/tx/78efa5177e99bf05b48948ac7e23e6cc2255764e52ccf7092afb979a766dee2c">xolosArmyPOP</a> (RMZPOP): ➑️\n' +
                     '\n' +
                     'πŸ–Ό <b><i>1 NFT mint</i></b>\n' +
                     'πŸ”’ <b><i>1 new fixed-supply token</i></b>\n' +
                     'πŸ”¨ <b><i>1 new variable-supply token</i></b>\n' +
                     'πŸ—» <b><i>1 ALP tx</i></b>\n' +
                     '🧩 <b><i>1 Mint Vault tx</i></b>\n' +
                     '❌ <b><i>1 invalid token tx</i></b>\n' +
                     '\n' +
                     'πŸ“± <b><i>8 app txs</i></b>\n' +
                     'πŸ–‹ <b>1</b> <a href="https://www.ecashchat.com/">Article/Reply tx</a>\n' +
                     'βš›οΈ <b>1</b> CashFusion\n' +
                     'πŸ›’ <b>1</b> PayButton tx\n' +
                     'πŸͺ‚ <b>1</b> Airdrop\n' +
                     '✏️ <b>1</b> Cashtab Msg\n' +
                     'πŸ’¬ <b>1</b> <a href="https://www.ecashchat.com/">eCashChat tx</a>\n' +
                     'πŸ”“ <b>1</b> eCashChat Auth\n' +
                     'πŸ’Έ <b>1</b> Paywall tx\n' +
                     '\n' +
                     '🏦 <b><i>Binance</i></b>\n' +
                     '<b>1</b> withdrawal, $1',
             ],
         );
     });
     it('summarizeTxHistory summarizes a collection of txs across multiple blocks including fiat prices with no token cache info', function () {
         const mockUtcNewDayTimestampSeconds = 1728950400;
         assert.deepEqual(
             summarizeTxHistory(
                 mockUtcNewDayTimestampSeconds,
                 dailyTxs,
                 // we can't get any token cache info
                 new Map(),
                 {
                     usd: 0.00003487,
                     usd_market_cap: 689047177.8128564,
                     usd_24h_vol: 5957332.9687223025,
                     usd_24h_change: -0.3973642442197056,
                 },
             ),
             [
                 '<b>15 Oct 2024</b>\n' +
                     'πŸ“¦57,430 blocks\n' +
                     '➑️30 txs\n' +
                     '\n' +
                     'πŸ“‰<b>1 XEC = $0.00003487</b> <i>(-0.40%)</i>\n' +
                     'Trading volume: $5,957,333\n' +
                     'Market cap: $689,047,178\n' +
                     '\n' +
                     '<b><i>⛏️3 miners found blocks</i></b>\n' +
                     '<u>Top 3</u>\n' +
                     '1. Mining-Dutch, 1 <i>(0%)</i>\n' +
                     '2. solopool.org, 1 <i>(0%)</i>\n' +
                     '3. ViaBTC, 1 <i>(0%)</i>\n' +
                     '\n' +
                     '<b><i>πŸ’°3 stakers earned $33</i></b>\n' +
                     '<u>Top 3</u>\n' +
                     '1. <a href="https://explorer.e.cash/address/ecash:qzs8hq2pj4hu5j09fdr5uhha3986h2mthvfp7362nu">qzs...2nu</a>, 1 <i>(0%)</i>\n' +
                     '2. <a href="https://explorer.e.cash/address/ecash:qr42c8c04tqndscfrdnl0rzterg0qdaegyjzt8egyg">qr4...gyg</a>, 1 <i>(0%)</i>\n' +
                     '3. <a href="https://explorer.e.cash/address/ecash:qqvhatumna957qu0je78dnc9pc7c7hu89crkq6k0cd">qqv...0cd</a>, 1 <i>(0%)</i>\n' +
                     '\n' +
                     '<a href="https://cashtab.com/">Cashtab</a>\n' +
                     '🎁 <b>1</b> new user received <b>42 XEC</b>\n' +
                     '🎟 <b>1</b> <a href="https://explorer.e.cash/tx/aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1">CACHET</a> reward\n' +
                     '\n' +
                     'πŸ›πŸͺ™ <b><i>3 Agora token txs from 3 tokens</i></b>\n' +
                     'πŸ’°Buy, 🏷List, ❌Cancel\n' +
                     '<a href="https://explorer.e.cash/tx/aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1">aed...cb1</a>: πŸ’°\n' +
                     '<a href="https://explorer.e.cash/tx/20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8">20a...6f8</a>: ❌\n' +
                     '<a href="https://explorer.e.cash/tx/01d63c4f4cb496829a6743f7b1805d086ea3877a1dd34b3f92ffba2c9c99f896">01d...896</a>: 🏷\n' +
                     '\nπŸ›πŸ–Ό <b><i>3 Agora NFT txs from 2 NFTs in 2 collections</i></b>\n' +
                     'πŸ’°Buy, 🏷List, ❌Cancel\n' +
                     '<a href="https://explorer.e.cash/tx/78efa5177e99bf05b48948ac7e23e6cc2255764e52ccf7092afb979a766dee2c">78e...e2c</a>: πŸ’°\n' +
                     '<a href="https://explorer.e.cash/tx/0fb781a98fffb980b1c9c609f62b29783c348e74aa7ea3908dcf7f46388ab316">0fb...316</a>: 🏷❌\n' +
                     '\n' +
                     'πŸͺ™ <b><i>8 token txs from 2 tokens</i></b>\n' +
                     '<a href="https://explorer.e.cash/tx/04009a8be347f21a1122964c3226b99c36a9bd755c5a450a53848471a2466103">040...103</a>: πŸ§ͺ➑️πŸ”₯πŸ”¨\n' +
                     '<a href="https://explorer.e.cash/tx/20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8">20a...6f8</a>: ➑️\n' +
                     '\n' +
                     'πŸ–Ό <b><i>2 NFT txs from 2 NFTs in 2 collections</i></b>\n' +
                     '<a href="https://explorer.e.cash/tx/8fd3f14abd2b176a1d4bd5136542cd2a7ba3df0e11947dd19326c9d1cd81ae09">8fd...e09</a>: πŸ§ͺ\n' +
                     '<a href="https://explorer.e.cash/tx/78efa5177e99bf05b48948ac7e23e6cc2255764e52ccf7092afb979a766dee2c">78e...e2c</a>: ➑️\n' +
                     '\n' +
                     'πŸ–Ό <b><i>1 NFT mint</i></b>\n' +
                     'πŸ”’ <b><i>1 new fixed-supply token</i></b>\n' +
                     'πŸ”¨ <b><i>1 new variable-supply token</i></b>\n' +
                     'πŸ—» <b><i>1 ALP tx</i></b>\n' +
                     '🧩 <b><i>1 Mint Vault tx</i></b>\n' +
                     '❌ <b><i>1 invalid token tx</i></b>\n' +
                     '\n' +
                     'πŸ“± <b><i>8 app txs</i></b>\n' +
                     'πŸ–‹ <b>1</b> <a href="https://www.ecashchat.com/">Article/Reply tx</a>\n' +
                     'βš›οΈ <b>1</b> CashFusion\n' +
                     'πŸ›’ <b>1</b> PayButton tx\n' +
                     'πŸͺ‚ <b>1</b> Airdrop\n' +
                     '✏️ <b>1</b> Cashtab Msg\n' +
                     'πŸ’¬ <b>1</b> <a href="https://www.ecashchat.com/">eCashChat tx</a>\n' +
                     'πŸ”“ <b>1</b> eCashChat Auth\n' +
                     'πŸ’Έ <b>1</b> Paywall tx\n' +
                     '\n' +
                     '🏦 <b><i>Binance</i></b>\n' +
                     '<b>1</b> withdrawal, $1',
             ],
         );
     });
     it('summarizeTxHistory summarizes a collection of txs across multiple blocks without fiat price', function () {
         const mockUtcNewDayTimestampSeconds = 1728950400;
         assert.deepEqual(
             summarizeTxHistory(
                 mockUtcNewDayTimestampSeconds,
                 dailyTxs,
                 tokenInfoMap,
             ),
             [
                 '<b>15 Oct 2024</b>\n' +
                     'πŸ“¦57,430 blocks\n' +
                     '➑️30 txs\n' +
                     '\n' +
                     '<b><i>⛏️3 miners found blocks</i></b>\n' +
                     '<u>Top 3</u>\n' +
                     '1. Mining-Dutch, 1 <i>(0%)</i>\n' +
                     '2. solopool.org, 1 <i>(0%)</i>\n' +
                     '3. ViaBTC, 1 <i>(0%)</i>\n' +
                     '\n' +
                     '<b><i>πŸ’°3 stakers earned 937,620 XEC</i></b>\n' +
                     '<u>Top 3</u>\n' +
                     '1. <a href="https://explorer.e.cash/address/ecash:qzs8hq2pj4hu5j09fdr5uhha3986h2mthvfp7362nu">qzs...2nu</a>, 1 <i>(0%)</i>\n' +
                     '2. <a href="https://explorer.e.cash/address/ecash:qr42c8c04tqndscfrdnl0rzterg0qdaegyjzt8egyg">qr4...gyg</a>, 1 <i>(0%)</i>\n' +
                     '3. <a href="https://explorer.e.cash/address/ecash:qqvhatumna957qu0je78dnc9pc7c7hu89crkq6k0cd">qqv...0cd</a>, 1 <i>(0%)</i>\n' +
                     '\n' +
                     '<a href="https://cashtab.com/">Cashtab</a>\n' +
                     '🎁 <b>1</b> new user received <b>42 XEC</b>\n' +
                     '🎟 <b>1</b> <a href="https://explorer.e.cash/tx/aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1">CACHET</a> reward\n' +
                     '\n' +
                     'πŸ›πŸͺ™ <b><i>3 Agora token txs from 3 tokens</i></b>\n' +
                     'πŸ’°Buy, 🏷List, ❌Cancel\n' +
                     '<a href="https://explorer.e.cash/tx/aed861a31b96934b88c0252ede135cb9700d7649f69191235087a3030e553cb1">Cachet</a> (CACHET): πŸ’°\n' +
                     '<a href="https://explorer.e.cash/tx/20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8">Vespene Gas</a> (VSP): ❌\n' +
                     '<a href="https://explorer.e.cash/tx/01d63c4f4cb496829a6743f7b1805d086ea3877a1dd34b3f92ffba2c9c99f896">Bull</a> (BULL): 🏷\n' +
                     '\nπŸ›πŸ–Ό <b><i>3 Agora NFT txs from 2 NFTs in 2 collections</i></b>\n' +
                     'πŸ’°Buy, 🏷List, ❌Cancel\n' +
                     '<a href="https://explorer.e.cash/tx/78efa5177e99bf05b48948ac7e23e6cc2255764e52ccf7092afb979a766dee2c">xolosArmyPOP</a> (RMZPOP): πŸ’°\n' +
                     '<a href="https://explorer.e.cash/tx/0fb781a98fffb980b1c9c609f62b29783c348e74aa7ea3908dcf7f46388ab316">Flags</a> (FLAGS): 🏷❌\n' +
                     '\n' +
                     'πŸͺ™ <b><i>8 token txs from 2 tokens</i></b>\n' +
                     '<a href="https://explorer.e.cash/tx/04009a8be347f21a1122964c3226b99c36a9bd755c5a450a53848471a2466103">Perpetua</a> (PRP): πŸ§ͺ➑️πŸ”₯πŸ”¨\n' +
                     '<a href="https://explorer.e.cash/tx/20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8">Vespene Gas</a> (VSP): ➑️\n' +
                     '\n' +
                     'πŸ–Ό <b><i>2 NFT txs from 2 NFTs in 2 collections</i></b>\n' +
                     '<a href="https://explorer.e.cash/tx/8fd3f14abd2b176a1d4bd5136542cd2a7ba3df0e11947dd19326c9d1cd81ae09">Xoloitzcuintli NFT Cigar Collection.</a> (RMZsmoke): πŸ§ͺ\n' +
                     '<a href="https://explorer.e.cash/tx/78efa5177e99bf05b48948ac7e23e6cc2255764e52ccf7092afb979a766dee2c">xolosArmyPOP</a> (RMZPOP): ➑️\n' +
                     '\n' +
                     'πŸ–Ό <b><i>1 NFT mint</i></b>\n' +
                     'πŸ”’ <b><i>1 new fixed-supply token</i></b>\n' +
                     'πŸ”¨ <b><i>1 new variable-supply token</i></b>\n' +
                     'πŸ—» <b><i>1 ALP tx</i></b>\n' +
                     '🧩 <b><i>1 Mint Vault tx</i></b>\n' +
                     '❌ <b><i>1 invalid token tx</i></b>\n' +
                     '\n' +
                     'πŸ“± <b><i>8 app txs</i></b>\n' +
                     'πŸ–‹ <b>1</b> <a href="https://www.ecashchat.com/">Article/Reply tx</a>\n' +
                     'βš›οΈ <b>1</b> CashFusion\n' +
                     'πŸ›’ <b>1</b> PayButton tx\n' +
                     'πŸͺ‚ <b>1</b> Airdrop\n' +
                     '✏️ <b>1</b> Cashtab Msg\n' +
                     'πŸ’¬ <b>1</b> <a href="https://www.ecashchat.com/">eCashChat tx</a>\n' +
                     'πŸ”“ <b>1</b> eCashChat Auth\n' +
                     'πŸ’Έ <b>1</b> Paywall tx\n' +
                     '\n' +
                     '🏦 <b><i>Binance</i></b>\n' +
                     '<b>1</b> withdrawal, 19,720 XEC',
             ],
         );
     });
 });
diff --git a/apps/ecash-herald/test/utils.test.ts b/apps/ecash-herald/test/utils.test.ts
index 138cbb145..8b9a514d0 100644
--- a/apps/ecash-herald/test/utils.test.ts
+++ b/apps/ecash-herald/test/utils.test.ts
@@ -1,442 +1,442 @@
 // Copyright (c) 2023 The Bitcoin developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 import assert from 'assert';
 import BigNumber from 'bignumber.js';
 import axios from 'axios';
 import MockAdapter from 'axios-mock-adapter';
 import config, { FiatCode, HeraldPriceApi } from '../config';
 import {
     returnAddressPreview,
     getCoingeckoPrices,
     formatPrice,
     jsonReplacer,
     jsonReviver,
     mapToKeyValueArray,
     formatXecAmount,
     satsToFormattedValue,
     getEmojiFromBalanceSats,
     bigNumberAmountToLocaleString,
     containsOnlyPrintableAscii,
 } from '../src/utils';
 import templates from './mocks/templates';
 const { addressPreviews, mockCoingeckoPrices } = templates;
 
 describe('ecash-telegram-bot utils.js functions', function () {
     it('returnAddressPreview converts a valid ecash: address into an abbreviated preview at various slice sizes', function () {
         for (let i = 0; i < addressPreviews.length; i += 1) {
             const { address, preview, sliceSize } = addressPreviews[i];
             assert.strictEqual(
                 returnAddressPreview(address, sliceSize),
                 preview,
             );
         }
     });
     it('getCoingeckoPrices returns object of expected shape for config API call', async function () {
         // onNoMatch: 'throwException' helps to debug if mock is not being used
         const mock = new MockAdapter(axios, { onNoMatch: 'throwException' });
 
         const mockResult = {
             bitcoin: { usd: 28044.64857505 },
             ecash: { usd: 0.00003113 },
             ethereum: { usd: 1900.73166438 },
         };
 
         // Mock a successful API request
         mock.onGet().reply(200, mockResult);
 
         // Expected value will include ticker information
         const expectedCoingeckoPrices = [
             {
                 fiat: 'usd',
                 price: 0.00003113,
                 ticker: 'XEC',
             },
             {
                 fiat: 'usd',
                 price: 28044.64857505,
                 ticker: 'BTC',
             },
             {
                 fiat: 'usd',
                 price: 1900.73166438,
                 ticker: 'ETH',
             },
         ];
         assert.deepEqual(await getCoingeckoPrices(config.priceApi), {
             coingeckoResponse: mockResult,
             coingeckoPrices: expectedCoingeckoPrices,
         });
     });
     it('getCoingeckoPrices returns object of expected shape for API call of custom config', async function () {
         const apiConfig: HeraldPriceApi = {
             apiBase: 'https://api.coingecko.com/api/v3/simple/price',
             cryptos: [
                 { coingeckoSlug: 'ecash', ticker: 'XEC' },
                 { coingeckoSlug: 'monero', ticker: 'XMR' },
                 { coingeckoSlug: 'solana', ticker: 'SOL' },
             ],
             fiat: 'eur',
             precision: 8,
         };
 
         // onNoMatch: 'throwException' helps to debug if mock is not being used
         const mock = new MockAdapter(axios, { onNoMatch: 'throwException' });
 
         const mockResult = {
             ecash: { eur: 0.00003113 },
             monero: { eur: 107.64857505 },
             solana: { eur: 22.73166438 },
         };
 
         // Mock a successful API request
         mock.onGet().reply(200, mockResult);
 
         // Expected value will include ticker information
         const expectedCoingeckoPrices = [
             {
                 fiat: 'eur' as FiatCode,
                 price: 0.00003113,
                 ticker: 'XEC',
             },
             {
                 fiat: 'eur' as FiatCode,
                 price: 107.64857505,
                 ticker: 'XMR',
             },
             {
                 fiat: 'eur' as FiatCode,
                 price: 22.73166438,
                 ticker: 'SOL',
             },
         ];
         assert.deepEqual(await getCoingeckoPrices(apiConfig), {
             coingeckoResponse: mockResult,
             coingeckoPrices: expectedCoingeckoPrices,
         });
     });
     it('getCoingeckoPrices returns false if API returns error response', async function () {
         // onNoMatch: 'throwException' helps to debug if mock is not being used
         const mock = new MockAdapter(axios, { onNoMatch: 'throwException' });
 
         const mockResult = {};
 
         // Mock an API error
         mock.onGet().reply(500, mockResult);
 
         assert.deepEqual(await getCoingeckoPrices(config.priceApi), false);
     });
     it('getCoingeckoPrices returns false if API returns object of unexpected shape', async function () {
         // onNoMatch: 'throwException' helps to debug if mock is not being used
         const mock = new MockAdapter(axios, { onNoMatch: 'throwException' });
 
         const mockResult = {
             bitcoin: { usd: 28044.64857505 },
             ecash: { usd: 0.00003113 },
             monero: { usd: 153.21055216 },
         };
 
         // Mock a successful API request that returns data of unexpected shape
         mock.onGet().reply(200, mockResult);
 
         assert.deepEqual(await getCoingeckoPrices(config.priceApi), false);
     });
     it('getCoingeckoPrices returns false if API response is not of type object', async function () {
         // onNoMatch: 'throwException' helps to debug if mock is not being used
         const mock = new MockAdapter(axios, { onNoMatch: 'throwException' });
 
         const mockResult = 'a string for some reason';
 
         // Mock a successful API request that returns data of unexpected shape
         mock.onGet().reply(200, mockResult);
 
         assert.deepEqual(await getCoingeckoPrices(config.priceApi), false);
     });
     it('formatPrice correctly formats a USD price greater than $10 and less than $100', function () {
         assert.strictEqual(formatPrice(10.55303, 'usd'), `$10.55`);
     });
     it('formatPrice correctly formats a USD price greater than $1', function () {
         assert.strictEqual(formatPrice(1.52303, 'usd'), `$1.52`);
     });
     it('formatPrice correctly formats a USD price less than $1', function () {
         assert.strictEqual(formatPrice(0.000035123, 'usd'), `$0.00003512`);
     });
     it('formatPrice correctly formats a EUR price less than €1', function () {
         assert.strictEqual(formatPrice(0.000035123, 'eur'), `€0.00003512`);
     });
     it('formatPrice correctly formats a GBP price greater than 100', function () {
         assert.strictEqual(formatPrice(1523.134239, 'gbp'), `Β£1,523`);
     });
     it('formatPrice correctly formats a JPY price greater than Β₯100', function () {
         assert.strictEqual(formatPrice(100000.999923422, 'jpy'), `Β₯100,001`);
     });
     it('formatPrice omits a currency symbol if it cannot find it', function () {
         assert.strictEqual(
             formatPrice(100000.999923422, 'cad' as FiatCode),
             `100,001`,
         );
     });
     it('formatXecAmount returns a string with 2 decimal places if XEC amount < 10', function () {
         assert.strictEqual(formatXecAmount(9.99), `9.99 XEC`);
     });
     it('formatXecAmount returns a string with no decimal places if XEC amount < 10 and round number', function () {
         assert.strictEqual(formatXecAmount(9), `9 XEC`);
     });
     it('formatXecAmount returns a string with no decimal places if 10 <= XEC amount < 100', function () {
         assert.strictEqual(formatXecAmount(12.51), `13 XEC`);
     });
     it('formatXecAmount returns a string with no decimal places if 100 < XEC amount <  1000', function () {
         assert.strictEqual(formatXecAmount(125), `125 XEC`);
     });
     it('formatXecAmount returns a thousands string with no decimal places if 1000 < XEC amount < 1 million', function () {
         assert.strictEqual(formatXecAmount(1000), `1k XEC`);
     });
     it('formatXecAmount returns a rounded thousands string with no decimal places if 1000 < XEC amount < 1 million', function () {
         assert.strictEqual(formatXecAmount(555555.55), `556k XEC`);
     });
     it('formatXecAmount returns a string with no decimal places if XEC amount is 1 trillion', function () {
         assert.strictEqual(formatXecAmount(1000000000000), `1T XEC`);
     });
     it('formatXecAmount returns a rounded thousands string with no decimal places if 1000 < XEC amount < 1 million', function () {
         assert.strictEqual(formatXecAmount(555555.55), `556k XEC`);
     });
     it('formatXecAmount returns a rounded millions string with no decimal places if 1M < XEC amount < 1B', function () {
         assert.strictEqual(formatXecAmount(555555555.55), `556M XEC`);
     });
     it('formatXecAmount returns a rounded billions string with no decimal places if 1B < XEC amount < 1T', function () {
         assert.strictEqual(formatXecAmount(555555555555.55), `556B XEC`);
     });
     it('formatXecAmount returns a rounded trillions string with no decimal places if XEC amount > 1T', function () {
         assert.strictEqual(formatXecAmount(55555555555555.55), `56T XEC`);
     });
     it('formatXecAmount returns a rounded trillions string with no decimal places if XEC amount > 1T', function () {
         assert.strictEqual(formatXecAmount(19999999999999.99), `20T XEC`);
     });
     it('formatXecAmount returns a trillions string with no decimal places for max possible XEC amount', function () {
         assert.strictEqual(formatXecAmount(21000000000000), `21T XEC`);
     });
     it('satsToFormattedValue returns a 6-decimal formatted fiat amount if total fiat value is less than $0.00001', function () {
         assert.strictEqual(
             satsToFormattedValue(10, mockCoingeckoPrices),
             `$0.000003`,
         );
     });
     it('satsToFormattedValue returns a 5-decimal formatted fiat amount if total fiat value is less than $0.0001', function () {
         assert.strictEqual(
             satsToFormattedValue(100, mockCoingeckoPrices),
             `$0.00003`,
         );
     });
     it('satsToFormattedValue returns a 4-decimal formatted fiat amount if total fiat value is less than $0.001', function () {
         assert.strictEqual(
             satsToFormattedValue(1000, mockCoingeckoPrices),
             `$0.0003`,
         );
     });
     it('satsToFormattedValue returns a 3-decimal formatted fiat amount if total fiat value is less than $0.01', function () {
         assert.strictEqual(
             satsToFormattedValue(10000, mockCoingeckoPrices),
             `$0.003`,
         );
     });
     it('satsToFormattedValue returns a 2-decimal formatted fiat amount if total fiat value is less than $1', function () {
         assert.strictEqual(
             satsToFormattedValue(1000000, mockCoingeckoPrices),
             `$0.30`,
         );
     });
     it('satsToFormattedValue returns a formatted fiat amount if total fiat value is less than $10', function () {
         assert.strictEqual(
             satsToFormattedValue(10000000, mockCoingeckoPrices),
             '$3',
         );
     });
     it('satsToFormattedValue returns a formatted fiat amount if $100 < total fiat value < $1k', function () {
         assert.strictEqual(
             satsToFormattedValue(1234567890, mockCoingeckoPrices),
             '$370',
         );
     });
     it('satsToFormattedValue returns a formatted fiat amount if $1k < total fiat value < $1M', function () {
         assert.strictEqual(
             satsToFormattedValue(55555555555, mockCoingeckoPrices),
             '$17k',
         );
     });
     it('satsToFormattedValue returns a formatted fiat amount of $1M if $1M < total fiat value < $1B', function () {
         assert.strictEqual(
             satsToFormattedValue(3367973856209, mockCoingeckoPrices),
             '$1M',
         );
     });
     it('satsToFormattedValue returns a formatted fiat amount if $1M < total fiat value < $1B', function () {
         assert.strictEqual(
             satsToFormattedValue(55555555555555, mockCoingeckoPrices),
             '$17M',
         );
     });
     it('satsToFormattedValue returns a formatted fiat amount if  total fiat value > $1B', function () {
         assert.strictEqual(
             satsToFormattedValue(21000000000000000, mockCoingeckoPrices),
             '$6B',
         );
     });
     it('satsToFormattedValue returns a formatted fiat amount if Β£1M < total fiat value < Β£1B', function () {
         const gbpPrices = [
             {
                 fiat: 'gbp' as FiatCode,
                 price: 0.00003,
                 ticker: 'XEC',
             },
         ];
         assert.strictEqual(
             satsToFormattedValue(55555555555555, gbpPrices),
             'Β£17M',
         );
     });
     it('satsToFormattedValue returns a formatted XEC amount if coingeckoPrices is false', function () {
         assert.strictEqual(
             satsToFormattedValue(55555555555555, false),
             '556B XEC',
         );
     });
     it('satsToFormattedValue returns a USD amount with 7 decimal places if fiat qty is less than 0.000001', function () {
         assert.strictEqual(
             satsToFormattedValue(1, mockCoingeckoPrices),
             '$0.0000003',
         );
     });
     it('jsonReplacer and jsonReviver can encode and decode a Map to and from JSON', function () {
         const map = new Map([
             [1, 'one'],
             [2, 'two'],
             [3, 'three'],
         ]);
 
         const jsonText = JSON.stringify(map, jsonReplacer);
         const roundTrip = JSON.parse(jsonText, jsonReviver);
 
         assert.deepEqual(map, roundTrip);
     });
     it('jsonReplacer and jsonReviver can encode and decode Map containing a BigNumber', function () {
         const bigNumberMap = new Map([
             [
                 '76a9144c1efd024f560e4e1aaf4b62416cd1e82fbed24f88ac',
                 new BigNumber(36),
             ],
             [
                 '76a9144c1efd024f560e4e1aaf4b62416cd1e82fbed24f88ac',
                 new BigNumber(72),
             ],
         ]);
 
         const jsonText = JSON.stringify(bigNumberMap, jsonReplacer);
         const roundTrip = JSON.parse(jsonText, jsonReviver);
 
         assert.deepEqual(bigNumberMap, roundTrip);
     });
     it('jsonReplacer and jsonReviver can encode and decode a Set to and from JSON', function () {
         const set = new Set(['one', 'two', 'three']);
 
         const jsonText = JSON.stringify(set, jsonReplacer);
         const roundTrip = JSON.parse(jsonText, jsonReviver);
 
         assert.deepEqual(set, roundTrip);
     });
     it('jsonReplacer and jsonReviver can encode and decode an object including a Set and a Map to and from JSON', async function () {
         const map = new Map([
             [1, 'one'],
             [2, 'two'],
             [3, 'three'],
         ]);
         const set = new Set(['one', 'two', 'three']);
 
         const jsonText = JSON.stringify({ map, set }, jsonReplacer);
         const roundTrip = JSON.parse(jsonText, jsonReviver);
 
         assert.deepEqual({ map, set }, roundTrip);
     });
     it('mapToKeyValueArray converts a map to a key value array and back to the same map', function () {
         const map = new Map([
             [1, 'one'],
             [2, 'two'],
             [3, 'three'],
         ]);
 
         const kvArray = mapToKeyValueArray(map);
 
         const roundTrip = new Map(kvArray);
 
         assert.deepEqual(map, roundTrip);
     });
     it('getEmojiFromBalanceSats provides all correct threshold emojis', function () {
         const { whaleSats, emojis } = config;
         const names = Object.keys(whaleSats);
         for (let i = 0; i < names.length; i += 1) {
             // Really bad types in the config as app was written without ts
             // TODO fixme
-            // @ts-ignore
+            // @ts-expect-error config object developed before typescript implementation
             const balanceSats = whaleSats[names[i]];
             assert.strictEqual(
                 getEmojiFromBalanceSats(balanceSats),
-                // @ts-ignore
+                // @ts-expect-error config object developed before typescript implementation
                 emojis[names[i]],
             );
         }
     });
     it('bigNumberAmountToLocaleString correctly formats a token send amount with no decimal places', async function () {
         const tokenSendAmountString = '1000000';
         const decimals = 0;
 
         assert.strictEqual(
             bigNumberAmountToLocaleString(tokenSendAmountString, decimals),
             '1,000,000',
         );
     });
     it('bigNumberAmountToLocaleString correctly formats a token send amount with 1 decimal place', async function () {
         const tokenSendAmountString = '10000000000000001';
         const decimals = 1;
 
         assert.strictEqual(
             bigNumberAmountToLocaleString(tokenSendAmountString, decimals),
             '1,000,000,000,000,000.1',
         );
     });
     it('bigNumberAmountToLocaleString correctly formats a token send amount with 9 decimal places', async function () {
         const tokenSendAmountString = '123456789123456789';
         const decimals = 9;
 
         assert.strictEqual(
             bigNumberAmountToLocaleString(tokenSendAmountString, decimals),
             '123,456,789.123456789',
         );
     });
     it('containsOnlyPrintableAscii correctly identifies a hex string containing only ascii ranged values as probably ascii', async function () {
         const hexString =
             '3d3a4554482e4554483a3078613961614633304636353935354336396331364233333435423531443432364439423838426138373a3834313332313a74723a30';
 
         assert.strictEqual(containsOnlyPrintableAscii(hexString), true);
     });
     it('containsOnlyPrintableAscii recognizes a string of odd length is probably not ascii', async function () {
         const hexString =
             '3d3a4554482e4554483a3078613961614633304636353935354336396331364233333435423531443432364439423838426138373a3834313332313a74723a3';
 
         assert.strictEqual(containsOnlyPrintableAscii(hexString), false);
     });
     it('containsOnlyPrintableAscii recognizes a string containing characters out of ascii range is probably not ascii', async function () {
         const hexString = '663ddd99990bcd969994ec2288a2a86dc532e1a8';
 
         assert.strictEqual(containsOnlyPrintableAscii(hexString), false);
     });
     it('containsOnlyPrintableAscii returns false for a string that contains all valid ascii characters but also a control character < 32', async function () {
         const hexString = '1f663ddd99990bcd969994ec2288a2a86dc532e1a8';
 
         assert.strictEqual(containsOnlyPrintableAscii(hexString), false);
     });
     it('containsOnlyPrintableAscii returns false for a string that contains all valid ascii characters but also a control character > 126', async function () {
         const hexString = '7f663ddd99990bcd969994ec2288a2a86dc532e1a8';
 
         assert.strictEqual(containsOnlyPrintableAscii(hexString), false);
     });
 });