UNPKG

mock-chronik-client

Version:

Testing utility to mock the Chronik indexer client and support unit tests that need to mock chronik related API calls.

386 lines 15.2 kB
import { BatchSummaryRow, BatchUtxosRow, Block, TxHistoryPage, Tx, TokenInfo, BlockchainInfo, Utxo, TokenIdUtxos, ScriptRef, ScriptUtxo, ScriptUtxos, WsConfig, WsMsgClient, WsSubScriptClient, WsSubPluginClient } from 'chronik-client'; import * as ws from 'ws'; type MockAgoraOffer = Record<string, any>; /** * MockAgora stores set responses in this object */ interface MockAgoraMockResponses { /** Supported Agora methods in MockAgora */ offeredGroupTokenIds: string[] | Error; offeredFungibleTokenIds: string[] | Error; activeOffersByPubKey: { [key: string]: MockAgoraOffer[] | Error; }; activeOffersByGroupTokenId: { [key: string]: MockAgoraOffer[] | Error; }; activeOffersByTokenId: { [key: string]: MockAgoraOffer[] | Error; }; } export type AgoraQueryParamVariants = { type: 'TOKEN_ID'; tokenId: string; } | { type: 'GROUP_TOKEN_ID'; groupTokenId: string; } | { type: 'PUBKEY'; pubkeyHex: string; }; interface MockAgoraInterface { mockedResponses: MockAgoraMockResponses; /** Methods used to set expected responses */ setOfferedGroupTokenIds: (expectedResponse: string[] | Error) => void; setOfferedFungibleTokenIds: (expectedResponse: string[] | Error) => void; setActiveOffersByPubKey: (pubKey: string, expectedResponse: MockAgoraOffer[] | Error) => void; setActiveOffersByGroupTokenId: (groupTokenId: string, expectedResponse: MockAgoraOffer[] | Error) => void; setActiveOffersByTokenId: (tokenId: string, expectedResponse: MockAgoraOffer[] | Error) => void; /** Supported Agora methods */ offeredGroupTokenIds: () => void; offeredFungibleTokenIds: () => void; activeOffersByPubKey: (pubKey: string) => void; activeOffersByGroupTokenId: (groupTokenId: string) => void; activeOffersByTokenId: (tokenId: string) => void; subscribeWs: (ws: MockWsEndpoint, params: AgoraQueryParamVariants) => void; unsubscribeWs: (ws: MockWsEndpoint, params: AgoraQueryParamVariants) => void; } export declare const TOKEN_ID_PREFIX = "54"; export declare const PUBKEY_PREFIX = "50"; export declare const GROUP_TOKEN_ID_PREFIX = "47"; export declare const PLUGIN_NAME = "agora"; /** * MockAgora * Useful test mock for writing unit tests for functions that use the Agora * class from the ecash-agora library. Drop-in replacement for Agora object * to unit test functions that accept an intialized Agora object as a param. * In this way, can write unit tests without hitting an actual chronik API. * * Mock calls to chronik nodes indexed with the ecash-agora plugin * * See Cashtab and ecash-herald for implementation examples. * * Note: not all Agora methods are mocked, can be extended as needed */ export declare class MockAgora implements MockAgoraInterface { mockedResponses: MockAgoraMockResponses; constructor(); setOfferedGroupTokenIds: (expectedResponse: string[] | Error) => void; setOfferedFungibleTokenIds: (expectedResponse: string[] | Error) => void; setActiveOffersByPubKey: (pubKey: string, expectedResponse: MockAgoraOffer[] | Error) => void; setActiveOffersByGroupTokenId: (groupTokenId: string, expectedResponse: MockAgoraOffer[] | Error) => void; setActiveOffersByTokenId: (tokenId: string, expectedResponse: MockAgoraOffer[] | Error) => void; offeredGroupTokenIds: () => Promise<Error | string[]>; offeredFungibleTokenIds: () => Promise<Error | string[]>; activeOffersByPubKey: (pubKey: string) => Promise<Error | MockAgoraOffer[]>; activeOffersByGroupTokenId: (groupTokenId: string) => Promise<Error | MockAgoraOffer[]>; activeOffersByTokenId: (tokenId: string) => Promise<Error | MockAgoraOffer[]>; /** Subscribe to updates from the websocket for some params */ subscribeWs: (ws: MockWsEndpoint, params: AgoraQueryParamVariants) => void; /** Unsubscribe from updates from the websocket for some params */ unsubscribeWs: (ws: MockWsEndpoint, params: AgoraQueryParamVariants) => void; private _groupHex; private _throwOrReturnValue; } type AddressType = 'p2sh' | 'p2pkh'; /** * Object where we store expected the values we want to get when * we make ChronikClient calls */ interface MockChronikClientMockedResponses { block: { [key: string | number]: Block | Error; }; blockTxs: { [key: string | number]: { history: Tx[] | Error; }; }; tx: { [key: string | number]: Tx | Error; }; token: { [key: string | number]: TokenInfo | Error; }; broadcastTx: { [key: string | number]: { txid: string; } | Error; }; blockchainInfo: BlockchainInfo | Error | object; chronikInfo: { version: string; } | Error; script: { p2pkh: { [key: string | number]: { history: Tx[] | Error; utxos: ScriptUtxo[] | Error; }; }; p2sh: { [key: string | number]: { history: Tx[] | Error; utxos: ScriptUtxo[] | Error; }; }; }; address: { [key: string | number]: { history: Tx[] | Error; utxos: ScriptUtxo[] | Error; }; }; tokenId: { [key: string | number]: { history: Tx[] | Error; utxos: Utxo[] | Error; }; }; lokadId: { [key: string | number]: { history: Tx[] | Error; utxos: ScriptUtxo[] | Error; }; }; } /** * Object where we store "deeper" methods * ChronikClient API supports methods that take params * So, when we call chronik.address(address).utxos, we * want the utxos for that address * And we want to also be able to set and get utxos for * another address in the mock */ interface MockChronikClientMockedMethods { script: { p2pkh: { [key: string]: { history: (pageNumer?: number, pageSize?: number) => Promise<TxHistoryPage | Error>; utxos: () => Promise<ScriptUtxos | Error>; }; }; p2sh: { [key: string]: { history: (pageNumer?: number, pageSize?: number) => Promise<TxHistoryPage | Error>; utxos: () => Promise<ScriptUtxos | Error>; }; }; }; address: { [key: string]: { history: (pageNumer?: number, pageSize?: number) => Promise<TxHistoryPage | Error>; utxos: () => Promise<ScriptUtxos | Error>; }; }; tokenId: { [key: string]: { history: (pageNumer?: number, pageSize?: number) => Promise<TxHistoryPage | Error>; utxos: () => Promise<TokenIdUtxos | Error>; }; }; lokadId: { [key: string]: { history: (pageNumer?: number, pageSize?: number) => Promise<TxHistoryPage | Error>; }; }; } /** * MockChronikClient * Drop-in replacement for ChronikClient in unit tests * * See Cashtab, token-server, ecash-herald for implementation * * Can set expected return values to test ChronikClient functions * without hitting an API */ export declare class MockChronikClient { mockedResponses: MockChronikClientMockedResponses; mockedMethods: MockChronikClientMockedMethods; constructor(); block: (blockHashOrHeight: string | number) => Promise<Error | Block>; tx: (txid: string) => Promise<Error | Tx>; token: (tokenId: string) => Promise<Error | TokenInfo>; blockTxs: (hashOrHeight: number | string, pageNumber?: number, pageSize?: number) => Promise<TxHistoryPage>; broadcastTx: (txHex: string, _skipTokenChecks?: boolean) => Promise<Error | { txid: string; }>; broadcastTxs: (txsHex: string[], _skipTokenChecks?: boolean) => Promise<{ txids: string[]; }>; /** * Same mocked responses as broadcastTx; optional separate timeout/error behavior later. */ broadcastAndFinalizeTx: (txHex: string, _finalizationTimeoutSecs?: number, _skipTokenChecks?: boolean) => Promise<Error | { txid: string; }>; broadcastAndFinalizeTxs: (txsHex: string[], _finalizationTimeoutSecs?: number, _skipTokenChecks?: boolean) => Promise<{ txids: string[]; }>; blockchainInfo: () => Promise<object | Error | BlockchainInfo>; script: (type: AddressType, hash: string) => { history: (pageNumer?: number, pageSize?: number) => Promise<TxHistoryPage | Error>; utxos: () => Promise<ScriptUtxos | Error>; } | { history: (pageNumer?: number, pageSize?: number) => Promise<TxHistoryPage | Error>; utxos: () => Promise<ScriptUtxos | Error>; }; address: (address: string) => { history: (pageNumer?: number, pageSize?: number) => Promise<TxHistoryPage | Error>; utxos: () => Promise<ScriptUtxos | Error>; }; tokenId: (tokenId: string) => { history: (pageNumer?: number, pageSize?: number) => Promise<TxHistoryPage | Error>; utxos: () => Promise<TokenIdUtxos | Error>; }; lokadId: (lokadId: string) => { history: (pageNumer?: number, pageSize?: number) => Promise<TxHistoryPage | Error>; }; ws: (wsConfig: WsConfig) => MockWsEndpoint; setBlock: (hashOrHeight: string | number, block: Block | Error) => void; setTx: (txid: string, tx: Tx | Error) => void; setToken: (tokenId: string, token: TokenInfo | Error) => void; setBlockchainInfo: (blockchainInfo: BlockchainInfo | Error) => void; setChronikInfo: (versionInfo: { version: string; } | Error) => void; chronikInfo: () => Promise<Error | { version: string; }>; /** * Batch UTXOs: resolves each script from data set by {@link setUtxosByScript} * or {@link setUtxosByAddress} (p2pkh / p2sh only). Unknown scripts get empty * `utxos`. Row order matches the request. */ batchUtxos: (scripts: ScriptRef[]) => Promise<BatchUtxosRow[]>; /** * Batch history summary: uses the same mocked `history` arrays as * `setTxHistoryByScript` / `setTxHistoryByAddress` (p2pkh / p2sh only). * The head tx is `history[0]`, matching page 0 of {@link MockChronikClientMockedMethods.script.*.history}. */ batchSummary: (scripts: ScriptRef[]) => Promise<BatchSummaryRow[]>; setBroadcastTx: (rawTx: string, txidOrError: string | Error) => void; setTxHistoryByScript: (type: AddressType, hash: string, history: Tx[] | Error) => void; setTxHistoryByAddress: (address: string, history: Tx[] | Error) => void; setTxHistoryByTokenId: (tokenId: string, history: Tx[] | Error) => void; setTxHistoryByLokadId: (lokadId: string, history: Tx[] | Error) => void; setTxHistoryByBlock: (hashOrHeight: string | number, history: Tx[] | Error) => void; setUtxosByScript: (type: AddressType, hash: string, utxos: ScriptUtxo[] | Error) => void; setUtxosByAddress: (address: string, utxos: ScriptUtxo[] | Error) => void; setUtxosByTokenId: (tokenId: string, utxos: Utxo[] | Error) => void; plugin: () => string; private _proxyInterface; proxyInterface: {}; blocks: () => void; rawTx: () => void; private _setAddress; private _setTokenId; private _setLokadId; private _setScript; private _getScriptUtxos; private _getAddressUtxos; private _getTokenIdUtxos; private _batchUtxosRowForScript; /** Resolved tx-history array for p2pkh/p2sh batch helpers. */ private _txHistoryArrayForScript; private _getTxHistory; private _throwOrReturnValue; } interface WsSubscriptions { /** Subscriptions to scripts */ scripts: WsSubScriptClient[]; /** Subscriptions to tokens by tokenId */ tokens: string[]; /** Subscriptions to txids */ txids: string[]; /** Subscriptions to lokadIds */ lokadIds: string[]; /** Subscriptions to plugins */ plugins: WsSubPluginClient[]; /** Subscription to blocks */ blocks: boolean; } /** * Mock WsEndpoint for MockChronikClient. * Based on WsEndpoint in chronik-client. * We do not test network functionality * Useful for testing that methods are called as expected, * ws is opened and closed as expected, subscriptions are added * and removed as expected * * See Cashtab and token-server tests for implemented examples */ export declare class MockWsEndpoint { /** Fired when a message is sent from the WebSocket. */ onMessage?: (msg: WsMsgClient) => void; /** Fired when a connection has been (re)established. */ onConnect?: (e: ws.Event) => void; /** * Fired after a connection has been unexpectedly closed, and before a * reconnection attempt is made. Only fired if `autoReconnect` is true. */ onReconnect?: (e: ws.Event) => void; /** Fired when an error with the WebSocket occurs. */ onError?: (e: ws.ErrorEvent) => void; /** * Fired after a connection has been manually closed, or if `autoReconnect` * is false, if the WebSocket disconnects for any reason. */ onEnd?: (e: ws.Event) => void; /** Whether to automatically reconnect on disconnect, default true. */ autoReconnect: boolean; ws: ws.WebSocket | undefined; connected: Promise<ws.Event> | undefined; manuallyClosed: boolean; waitForOpenCalled: boolean; subs: WsSubscriptions; constructor(config: WsConfig); /** Wait for the WebSocket to be connected. */ waitForOpen(): Promise<void>; /** * Subscribe to block messages */ subscribeToBlocks(): void; /** * Unsubscribe from block messages */ unsubscribeFromBlocks(): void; /** * Subscribe to the given script type and payload. * For "p2pkh", `scriptPayload` is the 20 byte public key hash. */ subscribeToScript(type: AddressType, payload: string): void; /** Unsubscribe from the given script type and payload. */ unsubscribeFromScript(type: AddressType, payload: string): void; /** * Subscribe to an address * Method can be used for p2pkh or p2sh addresses */ subscribeToAddress(address: string): void; /** Unsubscribe from the given address */ unsubscribeFromAddress(address: string): void; /** Subscribe to a lokadId */ subscribeToLokadId(lokadId: string): void; /** Unsubscribe from the given lokadId */ unsubscribeFromLokadId(lokadId: string): void; /** Subscribe to a tokenId */ subscribeToTokenId(tokenId: string): void; /** Unsubscribe from the given tokenId */ unsubscribeFromTokenId(tokenId: string): void; /** Subscribe to a txid */ subscribeToTxid(txid: string): void; /** Unsubscribe from the given txid */ unsubscribeFromTxid(txid: string): void; /** Subscribe to a plugin */ subscribeToPlugin(pluginName: string, group: string): void; /** Unsubscribe from the given plugin */ unsubscribeFromPlugin(pluginName: string, group: string): void; /** * Close the WebSocket connection and prevent any future reconnection * attempts. */ close(): void; private _subUnsubBlocks; } export {}; //# sourceMappingURL=index.d.ts.map