From 9db01ddb575867e5e68eed9c6c4dbb9255f75100 Mon Sep 17 00:00:00 2001 From: Mehran Aghabozorgi Date: Sun, 22 Dec 2024 15:27:38 -0800 Subject: [PATCH 1/9] Add doge network --- packages/networks/doge-esplora/.eslintignore | 1 + packages/networks/doge-esplora/README.md | 24 + .../doge-esplora/lib/DogeEsploraNetwork.ts | 232 +++++++ packages/networks/doge-esplora/lib/index.ts | 3 + packages/networks/doge-esplora/lib/types.ts | 81 +++ packages/networks/doge-esplora/package.json | 44 ++ packages/networks/doge-esplora/tests/.gitkeep | 0 .../tests/DogeEsploraNetwork.spec.ts | 577 ++++++++++++++++++ .../doge-esplora/tests/mocked/axios.mock.ts | 33 + .../networks/doge-esplora/tests/testData.ts | 339 ++++++++++ .../networks/doge-esplora/tsconfig.build.json | 11 + packages/networks/doge-esplora/tsconfig.json | 11 + .../networks/doge-esplora/vitest.config.ts | 18 + 13 files changed, 1374 insertions(+) create mode 100644 packages/networks/doge-esplora/.eslintignore create mode 100644 packages/networks/doge-esplora/README.md create mode 100644 packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts create mode 100644 packages/networks/doge-esplora/lib/index.ts create mode 100644 packages/networks/doge-esplora/lib/types.ts create mode 100644 packages/networks/doge-esplora/package.json create mode 100644 packages/networks/doge-esplora/tests/.gitkeep create mode 100644 packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts create mode 100644 packages/networks/doge-esplora/tests/mocked/axios.mock.ts create mode 100644 packages/networks/doge-esplora/tests/testData.ts create mode 100644 packages/networks/doge-esplora/tsconfig.build.json create mode 100644 packages/networks/doge-esplora/tsconfig.json create mode 100644 packages/networks/doge-esplora/vitest.config.ts diff --git a/packages/networks/doge-esplora/.eslintignore b/packages/networks/doge-esplora/.eslintignore new file mode 100644 index 00000000..1521c8b7 --- /dev/null +++ b/packages/networks/doge-esplora/.eslintignore @@ -0,0 +1 @@ +dist diff --git a/packages/networks/doge-esplora/README.md b/packages/networks/doge-esplora/README.md new file mode 100644 index 00000000..d69db8f7 --- /dev/null +++ b/packages/networks/doge-esplora/README.md @@ -0,0 +1,24 @@ +# @rosen-chains/doge-esplora + +## Table of contents + +- [Introduction](#introduction) +- [Installation](#installation) + +## Introduction + +A package to be used as network api provider for @rosen-chains/doge package + +## Installation + +npm: + +```sh +npm i @rosen-chains/doge-esplora +``` + +yarn: + +```sh +yarn add @rosen-chains/doge-esplora +``` diff --git a/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts b/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts new file mode 100644 index 00000000..ac542b8a --- /dev/null +++ b/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts @@ -0,0 +1,232 @@ +import { AbstractLogger } from '@rosen-bridge/abstract-logger'; +import { + AssetBalance, + BlockInfo, + FailedError, + NetworkError, + TokenInfo, + UnexpectedApiError, +} from '@rosen-chains/abstract-chain'; +import JsonBigInt from '@rosen-bridge/json-bigint'; +import { + AbstractDogeNetwork, + DogeTx, + DogeUtxo, + CONFIRMATION_TARGET, +} from '@rosen-chains/doge'; +import axios, { AxiosInstance } from 'axios'; +import { Psbt } from 'bitcoinjs-lib'; +import { + EsploraAddress, + EsploraBlock, + EsploraTx, + EsploraUtxo, + EsploraUtxoInfo, +} from './types'; +import BitcoinEsploraNetwork from '@rosen-chains/bitcoin-esplora'; + +class DogeEsploraNetwork extends BitcoinEsploraNetwork { + protected client: AxiosInstance; + private getSavedTransactionById: ( + txId: string + ) => Promise; + + constructor( + url: string, + getSavedTransactionById: (txId: string) => Promise, + logger?: AbstractLogger + ) { + super(url, logger); + this.client = axios.create({ + baseURL: url, + }); + this.getSavedTransactionById = getSavedTransactionById; + } + + /** + * gets confirmation for a transaction (returns -1 if tx is not mined or found) + * @param transactionId the transaction id (only supports real signed tx id) + * @returns the transaction confirmation + */ + getTxConfirmationSigned = async (transactionId: string): Promise => { + const currentHeight = await this.getHeight(); + let txHeight = -1; + try { + const txInfo = ( + await this.client.get(`/api/tx/${transactionId}`) + ).data; + this.logger.debug( + `requested 'tx' for txId [${transactionId}]. res: ${JsonBigInt.stringify( + txInfo + )}` + ); + if (txInfo.status.confirmed && txInfo.status.block_height) + txHeight = txInfo.status.block_height; + } catch (e: any) { + const baseError = `Failed to get confirmation for tx [${transactionId}] from Esplora: `; + if (e.response && e.response.status === 404) { + this.logger.debug(`tx [${transactionId}] is not found`); + return -1; + } else if (e.response) { + throw new FailedError(baseError + e.response.data); + } else if (e.request) { + throw new NetworkError(baseError + e.message); + } else { + throw new UnexpectedApiError(baseError + e.message); + } + } + if (txHeight === -1) return txHeight; + return currentHeight - txHeight; + }; + + /** + * gets confirmation for a transaction (returns -1 if tx is not mined or found) + * @param transactionId the transaction id (supports both real signed tx id and unsigned tx id) + * @returns the transaction confirmation (returns -1 if tx is not mined or found) + */ + getTxConfirmation = async (transactionId: string): Promise => { + let realTxId = transactionId; + try { + const realTx = await this.getSavedTransactionById(transactionId); + if (realTx) { + const firstInputId = `${realTx?.inputs[0].txId}.${realTx?.inputs[0].index}`; + const spentTx = await this.getSpentTransactionByInputId(firstInputId); + if (spentTx) { + const sameInputs = realTx.inputs.every( + (input, i) => + spentTx.inputs[i].txId === input.txId && + spentTx.inputs[i].index === input.index + ); + const sameOutputs = realTx.outputs.every( + (output, i) => + spentTx.outputs[i].scriptPubKey === output.scriptPubKey && + spentTx.outputs[i].value === output.value + ); + if (sameInputs && sameOutputs) { + realTxId = spentTx.id; + } + } + } + } catch (e) { + this.logger.debug(`tx [${transactionId}] is not found in DB`); + } + + return await this.getTxConfirmationSigned(realTxId); + }; + + // /** + // * gets a transaction (serialized in `DogeTx` format) + // * @param transactionId the transaction id + // * @param blockId the block id + // * @returns the transaction + // */ + // getTransaction = async ( + // transactionId: string, + // blockId: string + // ): Promise => { + // let txInfo: EsploraTx; + // try { + // txInfo = (await this.client.get(`/api/tx/${transactionId}`)) + // .data; + // this.logger.debug( + // `requested 'tx' for txId [${transactionId}]. res: ${JsonBigInt.stringify( + // txInfo + // )}` + // ); + // } catch (e: any) { + // const baseError = `Failed to get transaction [${transactionId}] from Esplora: `; + // if (e.response) { + // throw new FailedError(baseError + e.response.data); + // } else if (e.request) { + // throw new NetworkError(baseError + e.message); + // } else { + // throw new UnexpectedApiError(baseError + e.message); + // } + // } + // + // if (txInfo.status.block_hash !== blockId) + // throw new FailedError( + // `Tx [${transactionId}] doesn't belong to block [${blockId}]` + // ); + // + // const tx: DogeTx = { + // id: txInfo.txid, + // inputs: txInfo.vin.map((input) => ({ + // txId: input.txid, + // index: input.vout, + // scriptPubKey: input.prevout.scriptpubkey, + // })), + // outputs: txInfo.vout.map((output) => ({ + // scriptPubKey: output.scriptpubkey, + // value: BigInt(output.value), + // })), + // }; + // + // return tx; + // }; + + /** + * submits a transaction + * @param transaction the transaction + */ + submitTransaction = async (transaction: Psbt): Promise => { + await this.client.post(`/api/tx`, transaction.extractTransaction().toHex()); + }; + + /** + * gets current fee ratio of the network + * @returns + */ + getFeeRatio = async (): Promise => { + const target: number = CONFIRMATION_TARGET; + if (target > 25) + throw new UnexpectedApiError( + `Esplora does not support target [${CONFIRMATION_TARGET}] for fee estimation` + ); + + return this.client + .get>(`/api/fee-estimates`) + .then((res) => { + this.logger.debug( + `requested 'fee-estimates'. res: ${JsonBigInt.stringify(res.data)}` + ); + return res.data[CONFIRMATION_TARGET]; + }) + .catch((e) => { + const baseError = `Failed to fetch fee estimation from Esplora: `; + if (e.response) { + throw new FailedError(baseError + `${e.response.data}`); + } else if (e.request) { + throw new NetworkError(baseError + e.message); + } else { + throw new UnexpectedApiError(baseError + e.message); + } + }); + }; + + /** + * gets a transaction hex string + * @param txId the transaction id (only supports real signed tx id) + * @returns hex string of the transaction + */ + getTransactionHex = async (txId: string): Promise => { + return this.client + .get(`/api/tx/${txId}/hex`) + .then((res) => res.data); + }; + + getSpentTransactionByInputId = async ( + boxId: string + ): Promise => { + const [txId, index] = boxId.split('.'); + const box = ( + await this.client.get( + `/api/tx/${txId}/outspends/${index}` + ) + ).data; + if (!box.spent) return undefined; + return this.getTransaction(box.txid!, box.status!.block_hash!); + }; +} + +export default DogeEsploraNetwork; diff --git a/packages/networks/doge-esplora/lib/index.ts b/packages/networks/doge-esplora/lib/index.ts new file mode 100644 index 00000000..30cb768f --- /dev/null +++ b/packages/networks/doge-esplora/lib/index.ts @@ -0,0 +1,3 @@ +import DogeEsploraNetwork from './DogeEsploraNetwork'; + +export { DogeEsploraNetwork }; diff --git a/packages/networks/doge-esplora/lib/types.ts b/packages/networks/doge-esplora/lib/types.ts new file mode 100644 index 00000000..0a8185fb --- /dev/null +++ b/packages/networks/doge-esplora/lib/types.ts @@ -0,0 +1,81 @@ +export interface EsploraTx { + txid: string; + version: number; + locktime: number; + vin: Vin[]; + vout: Vout[]; + size: number; + weight: number; + fee: number; + status: Status; +} + +export interface Status { + confirmed: boolean; + block_height?: number; + block_hash?: string; + block_time?: number; +} + +export interface Vin { + txid: string; + vout: number; + prevout: Vout; + scriptsig: string; + scriptsig_asm: string; + is_coinbase: boolean; + sequence: number; +} + +export interface Vout { + scriptpubkey: string; + scriptpubkey_asm: string; + scriptpubkey_type: string; + scriptpubkey_address?: string; + value: number; +} + +export interface EsploraAddress { + address: string; + chain_stats: Stats; + mempool_stats: Stats; +} + +export interface Stats { + funded_txo_count: number; + funded_txo_sum: number; + spent_txo_count: number; + spent_txo_sum: number; + tx_count: number; +} + +export interface EsploraBlock { + id: string; + height: number; + version: number; + timestamp: number; + tx_count: number; + size: number; + weight: number; + merkle_root: string; + previousblockhash: string; + mediantime: number; + nonce: number; + bits: number; + difficulty: number; +} + +export interface EsploraUtxo { + txid: string; + vout: number; + status: Status; + value: number; + txHex: string; +} + +export interface EsploraUtxoInfo { + spent: boolean; + txid?: string; + vin?: number; + status?: Status; +} diff --git a/packages/networks/doge-esplora/package.json b/packages/networks/doge-esplora/package.json new file mode 100644 index 00000000..6f03ad8d --- /dev/null +++ b/packages/networks/doge-esplora/package.json @@ -0,0 +1,44 @@ +{ + "name": "@rosen-chains/doge-esplora", + "version": "0.1.0", + "description": "A package to be used as network api provider for @rosen-chains/doge package", + "repository": "https://github.com/rosen-bridge/rosen-chains", + "license": "GPL-3.0", + "author": "Mehran", + "type": "module", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc --build tsconfig.build.json", + "coverage": "npm run test -- --run --coverage", + "lint": "eslint --fix . && npm run prettify", + "prettify": "prettier --write . --ignore-path ./.gitignore", + "release": "npm run test -- --run && npm run build && npm publish --access public", + "test": "NODE_OPTIONS=--loader=extensionless vitest", + "type-check": "tsc --noEmit" + }, + "devDependencies": { + "@types/node": "^20.11.9", + "@typescript-eslint/eslint-plugin": "^6.19.1", + "@typescript-eslint/parser": "^6.19.1", + "@vitest/coverage-istanbul": "^1.2.2", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "extensionless": "^1.9.6", + "prettier": "^3.2.4", + "typescript": "^5.3.3", + "vitest": "^1.2.2" + }, + "engines": { + "node": ">=20.11.0" + }, + "dependencies": { + "@rosen-bridge/abstract-logger": "^2.0.1", + "@rosen-bridge/json-bigint": "^0.1.0", + "@rosen-chains/abstract-chain": "^11.0.3", + "@rosen-chains/doge": "^0.0.0", + "@rosen-chains/bitcoin-esplora": "^4.0.8", + "axios": "^1.6.7", + "bitcoinjs-lib": "^6.1.5" + } +} diff --git a/packages/networks/doge-esplora/tests/.gitkeep b/packages/networks/doge-esplora/tests/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts b/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts new file mode 100644 index 00000000..7dff9c01 --- /dev/null +++ b/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts @@ -0,0 +1,577 @@ +import { FailedError } from '@rosen-chains/abstract-chain'; +import DogeEsploraNetwork from '../lib/DogeEsploraNetwork'; +import { + mockAxiosGet, + mockAxiosGetToThrow, + resetAxiosMock, +} from './mocked/axios.mock'; +import * as testData from './testData'; +import { vi } from 'vitest'; + +describe('DogeEsploraNetwork', () => { + let network: DogeEsploraNetwork; + + beforeEach(() => { + resetAxiosMock(); + network = new DogeEsploraNetwork('esplora-url', async () => undefined); + }); + + describe('getHeight', () => { + /** + * @target `DogeEsploraNetwork.getHeight` should return block height successfully + * @dependencies + * @scenario + * - mock axios to return height + * - run test + * - check returned value + * @expected + * - it should be mocked block height + */ + it('should return block height successfully', async () => { + mockAxiosGet(testData.blockHeight); + + const result = await network.getHeight(); + + expect(result).toEqual(testData.blockHeight); + }); + }); + + describe('getTxConfirmation', () => { + /** + * @target `DogeEsploraNetwork.getTxConfirmation` should return tx confirmation successfully + * @dependencies + * @scenario + * - mock axios to return height + * - mock axios to return tx + * - run test + * - check returned value + * @expected + * - it should be mocked height minus mocked tx height + */ + it('should return tx confirmation successfully', async () => { + mockAxiosGet(testData.blockHeight); + mockAxiosGet(testData.txResponse); + + const result = await network.getTxConfirmation(testData.txId); + + expect(result).toEqual(testData.txConfirmation); + }); + + /** + * @target `DogeEsploraNetwork.getTxConfirmation` should return -1 + * when transaction is not found + * @dependencies + * @scenario + * - mock axios to return height + * - mock axios to throw not found error + * - run test + * - check returned value + * @expected + * - it should be -1 + */ + it('should return -1 when transaction is not found', async () => { + mockAxiosGet(testData.blockHeight); + mockAxiosGetToThrow({ + response: { + status: 404, + data: 'TestResponse: Transaction not found', + }, + }); + + const result = await network.getTxConfirmation(testData.txId); + + expect(result).toEqual(-1); + }); + + /** + * @target `DogeEsploraNetwork.getTxConfirmation` should return -1 + * when transaction is unconfirmed + * @dependencies + * @scenario + * - mock axios to return height + * - mock axios to return unconfirmed tx + * - run test + * - check returned value + * @expected + * - it should be -1 + */ + it('should return -1 when transaction is unconfirmed', async () => { + mockAxiosGet(testData.blockHeight); + mockAxiosGet(testData.unconfirmedTxResponse); + + const result = await network.getTxConfirmation(testData.txId); + + expect(result).toEqual(-1); + }); + + it('should call getTxConfirmationSigned with the correct tx id', async () => { + // Create a new instance of DogeEsploraNetwork with a custom getSavedTransactionById + const customNetwork = new DogeEsploraNetwork( + 'esplora-url', + async (txId) => { + if (txId === testData.unsignedTxId) { + return testData.dogeTx; + } + return undefined; + } + ); + + const getTxConfirmationSignedSpy = vi.spyOn( + customNetwork, + 'getTxConfirmationSigned' + ); + + // Mock getSpentTransactionByInputId to return a transaction when called with the correct input + const getSpentTransactionByInputIdSpy = vi + .spyOn(customNetwork, 'getSpentTransactionByInputId') + .mockResolvedValue(testData.dogeTx); + + mockAxiosGet(testData.blockHeight); + mockAxiosGet(testData.txResponse); + + const result = await customNetwork.getTxConfirmation( + testData.unsignedTxId + ); + + expect(getSpentTransactionByInputIdSpy).toHaveBeenCalledWith( + `${testData.dogeTx.inputs[0].txId}.${testData.dogeTx.inputs[0].index}` + ); + expect(getTxConfirmationSignedSpy).toHaveBeenCalledWith(testData.txId); + expect(result).toEqual(testData.txConfirmation); + + getTxConfirmationSignedSpy.mockRestore(); + getSpentTransactionByInputIdSpy.mockRestore(); + }); + }); + + describe('getAddressAssets', () => { + /** + * @target `DogeEsploraNetwork.getAddressAssets` should return address assets successfully + * @dependencies + * @scenario + * - mock axios to return address utxo info + * - run test + * - check returned value + * @expected + * - it should be expected DOGE balance with no tokens + */ + it('should return address assets successfully', async () => { + mockAxiosGet(testData.addressResponse); + + const result = await network.getAddressAssets(testData.lockAddress); + + expect(result).toEqual({ + nativeToken: testData.addressBalance, + tokens: [], + }); + }); + + /** + * @target `DogeEsploraNetwork.getAddressAssets` should return 0 balance + * when address has no DOGE + * @dependencies + * @scenario + * - mock axios to return address utxo info with zero balance + * - run test + * - check returned value + * @expected + * - it should be zero native tokens with no tokens + */ + it('should return 0 balance when address has no DOGE', async () => { + mockAxiosGet(testData.emptyAddressResponse); + + const result = await network.getAddressAssets(testData.lockAddress); + + expect(result).toEqual({ nativeToken: 0n, tokens: [] }); + }); + + /** + * @target `DogeEsploraNetwork.getAddressAssets` should return 0 balance + * when address has no history of transactions + * @dependencies + * @scenario + * - mock axios to return address utxo info with 0 transactions + * - run test + * - check returned value + * @expected + * - it should be zero native tokens with no tokens + */ + it('should return 0 balance when address has no history of transactions', async () => { + mockAxiosGet(testData.unusedAddressResponse); + + const result = await network.getAddressAssets(testData.lockAddress); + + expect(result).toEqual({ nativeToken: 0n, tokens: [] }); + }); + }); + + describe('getBlockTransactionIds', () => { + /** + * @target `DogeEsploraNetwork.getBlockTransactionIds` should return block tx ids successfully + * @dependencies + * @scenario + * - mock axios to return tx ids + * - run test + * - check returned value + * @expected + * - it should be mocked tx ids + */ + it('should return block tx ids successfully', async () => { + mockAxiosGet(testData.txIds); + + const result = await network.getBlockTransactionIds(testData.txId); + + expect(result).toEqual(testData.txIds); + }); + }); + + describe('getBlockInfo', () => { + /** + * @target `DogeEsploraNetwork.getBlockInfo` should return block info successfully + * @dependencies + * @scenario + * - mock axios to return block info + * - run test + * - check returned value + * @expected + * - it should be mocked block info + */ + it('should return block info successfully', async () => { + mockAxiosGet(testData.blockResponse); + + const result = await network.getBlockInfo(testData.blockHash); + + expect(result).toEqual(testData.blockInfo); + }); + }); + + describe('getTransaction', () => { + /** + * @target `DogeEsploraNetwork.getTransaction` should return transaction successfully + * @dependencies + * @scenario + * - mock axios to return transaction + * - run test + * - check returned value + * @expected + * - it should be mocked tx in DogeTx format + */ + it('should return transaction successfully', async () => { + mockAxiosGet(testData.txResponse); + + const result = await network.getTransaction( + testData.txId, + testData.txBlockHash + ); + + expect(result).toEqual(testData.dogeTx); + }); + + /** + * @target `DogeEsploraNetwork.getTransaction` should throw error when + * block id is not matched with tx block + * @dependencies + * @scenario + * - mock axios to return transaction + * - run test with wrong block hash and expect exception thrown + * @expected + * - it should throw FailedError + */ + it('should throw error when block id is not matched with tx block', async () => { + mockAxiosGet(testData.txResponse); + + await expect(async () => { + await network.getTransaction(testData.txId, testData.blockHash); + }).rejects.toThrow('FailedError'); + }); + }); + + describe('getAddressBoxes', () => { + /** + * @target `DogeEsploraNetwork.getAddressBoxes` should return address utxos successfully + * @dependencies + * @scenario + * - mock axios to return address utxo info + * - run test + * - check returned value + * @expected + * - it should be mocked utxos in DogeUtxo format + */ + it('should return address utxos successfully', async () => { + mockAxiosGet(testData.addressUtxoResponse); + + const result = await network.getAddressBoxes( + testData.lockAddress, + 0, + 100 + ); + + expect(result).toEqual(testData.addressUtxos); + }); + + /** + * @target `DogeEsploraNetwork.getAddressBoxes` should return empty list + * when no utxo is returned + * @dependencies + * @scenario + * - mock axios to return address utxo info with zero balance + * - run test + * - check returned value + * @expected + * - it should be empty list + */ + it('should return empty list when no utxo is returned', async () => { + mockAxiosGet([]); + + const result = await network.getAddressBoxes( + testData.lockAddress, + 0, + 100 + ); + + expect(result).toEqual([]); + }); + }); + + describe('isBoxUnspentAndValid', () => { + /** + * @target `DogeEsploraNetwork.isBoxUnspentAndValid` should return true when box is unspent + * @dependencies + * @scenario + * - mock axios to return tx outspends + * - run test with unspent box index + * - check returned value + * @expected + * - it should be true + */ + it('should return true when box is unspent', async () => { + mockAxiosGet(testData.txOutspendsResponse); + + const boxId = `${testData.txId}.${1}`; + const result = await network.isBoxUnspentAndValid(boxId); + + expect(result).toEqual(true); + }); + + /** + * @target `DogeEsploraNetwork.isBoxUnspentAndValid` should return false when + * box is spent + * @dependencies + * @scenario + * - mock axios to return tx outspends + * - run test with spent box index + * - check returned value + * @expected + * - it should be false + */ + it('should return false when box is spent', async () => { + mockAxiosGet(testData.txOutspendsResponse); + + const boxId = `${testData.txId}.${0}`; + const result = await network.isBoxUnspentAndValid(boxId); + + expect(result).toEqual(false); + }); + + /** + * @target `DogeEsploraNetwork.isBoxUnspentAndValid` should return false when + * tx is not found + * @dependencies + * @scenario + * - mock axios to throw not found error + * - run test + * - check returned value + * @expected + * - it should be false + */ + it('should return false when tx is not found', async () => { + mockAxiosGetToThrow({ + response: { + status: 404, + data: 'TestResponse: Transaction not found', + }, + }); + + const boxId = `${testData.txId}.${1}`; + const result = await network.isBoxUnspentAndValid(boxId); + + expect(result).toEqual(false); + }); + + /** + * @target `DogeEsploraNetwork.isBoxUnspentAndValid` should return false when + * box index is more than number of tx outputs + * @dependencies + * @scenario + * - mock axios to return tx outspends + * - run test with invalid box index + * - check returned value + * @expected + * - it should be false + */ + it('should return false when box index is more than number of tx outputs', async () => { + mockAxiosGet(testData.txOutspendsResponse); + + const boxId = `${testData.txId}.${3}`; + const result = await network.isBoxUnspentAndValid(boxId); + + expect(result).toEqual(false); + }); + }); + + describe('getUtxo', () => { + /** + * @target `DogeEsploraNetwork.getUtxo` should return utxo successfully + * @dependencies + * @scenario + * - mock axios to return transaction + * - run test + * - check returned value + * @expected + * - it should be mocked utxo + */ + it('should return utxo successfully', async () => { + mockAxiosGet(testData.txResponse); + + const boxId = `${testData.txId}.${0}`; + const result = await network.getUtxo(boxId); + + expect(result).toEqual(testData.utxo); + }); + + /** + * @target `DogeEsploraNetwork.getUtxo` should throw error when + * tx is not found + * @dependencies + * @scenario + * - mock axios to throw not found error + * - run test and expect exception thrown + * @expected + * - it should throw FailedError + */ + it('should throw error when tx is not found', async () => { + mockAxiosGetToThrow({ + response: { + status: 404, + data: 'TestResponse: Transaction not found', + }, + }); + + const boxId = `${testData.txId}.${0}`; + await expect(async () => { + await network.getUtxo(boxId); + }).rejects.toThrow('FailedError'); + }); + + /** + * @target `DogeEsploraNetwork.getUtxo` should throw error when + * box index is more than number of tx outputs + * @dependencies + * @scenario + * - mock axios to return transaction + * - run test expect exception thrown + * @expected + * - it should throw FailedError + */ + it('should throw error when box index is more than number of tx outputs', async () => { + mockAxiosGet(testData.txResponse); + + const boxId = `${testData.txId}.${3}`; + await expect(async () => { + await network.getUtxo(boxId); + }).rejects.toThrow('FailedError'); + }); + }); + + describe('getFeeRatio', () => { + /** + * @target `DogeEsploraNetwork.getFeeRatio` should return fee ratio successfully + * @dependencies + * @scenario + * - mock axios to return fee estimates + * - run test + * - check returned value + * @expected + * - it should be fee estimation for 6 confirmation + */ + it('should return fee ratio successfully', async () => { + mockAxiosGet(testData.feeEstimatesResponse); + + const result = await network.getFeeRatio(); + + expect(result).toEqual(testData.targetFeeEstimation); + }); + }); + + describe('getMempoolTxIds', () => { + /** + * @target `DogeEsploraNetwork.getMempoolTxIds` should return mempool tx ids successfully + * @dependencies + * @scenario + * - mock axios to return tx ids + * - run test + * - check returned value + * @expected + * - it should be mocked tx ids + */ + it('should return mempool tx ids successfully', async () => { + mockAxiosGet(testData.txIds); + + const result = await network.getMempoolTxIds(); + + expect(result).toEqual(testData.txIds); + }); + }); + + describe('getSpentTransactionByInputId', () => { + /** + * @target `DogeEsploraNetwork.getSpentTransactionByInputId` should return transaction + * when box is spent + * @dependencies + * @scenario + * - mock axios to return spent box info + * - mock getTransaction to return a transaction + * - run test + * - check returned value + * @expected + * - it should be the mocked transaction + */ + it('should return transaction when box is spent', async () => { + mockAxiosGet(testData.spentResult); + const getTransactionSpy = vi + .spyOn(network, 'getTransaction') + .mockResolvedValue(testData.dogeTx); + + const result = await network.getSpentTransactionByInputId( + testData.spentBoxId + ); + + expect(result).toEqual(testData.dogeTx); + expect(getTransactionSpy).toHaveBeenCalledWith( + testData.spentResult.txid, + testData.spentResult.status.block_hash + ); + }); + + /** + * @target `DogeEsploraNetwork.getSpentTransactionByInputId` should return undefined + * when box is unspent + * @dependencies + * @scenario + * - mock axios to return unspent box info + * - run test + * - check returned value + * @expected + * - it should be undefined + */ + it('should return undefined when box is unspent', async () => { + mockAxiosGet(testData.unspentResult); + + const result = await network.getSpentTransactionByInputId( + testData.unspentBoxId + ); + + expect(result).toBeUndefined(); + }); + }); +}); diff --git a/packages/networks/doge-esplora/tests/mocked/axios.mock.ts b/packages/networks/doge-esplora/tests/mocked/axios.mock.ts new file mode 100644 index 00000000..b380a8c4 --- /dev/null +++ b/packages/networks/doge-esplora/tests/mocked/axios.mock.ts @@ -0,0 +1,33 @@ +import axios from 'axios'; +import { vi } from 'vitest'; + +export const axiosInstance = { + get: vi.fn(), + post: vi.fn(), +}; + +/** + * mocks axios.get function + * @param result + */ +export const mockAxiosGet = (result: any) => { + axiosInstance.get.mockResolvedValueOnce({ + data: result, + }); +}; + +/** + * mocks axios.get function + * @param error + */ +export const mockAxiosGetToThrow = (error: any) => { + axiosInstance.get.mockRejectedValueOnce(error); +}; + +/** + * resets axios functions mocks and call counts + */ +export const resetAxiosMock = () => { + axiosInstance.get.mockReset(); + vi.spyOn(axios, 'create').mockReturnValue(axiosInstance as any); +}; diff --git a/packages/networks/doge-esplora/tests/testData.ts b/packages/networks/doge-esplora/tests/testData.ts new file mode 100644 index 00000000..8ddc5f24 --- /dev/null +++ b/packages/networks/doge-esplora/tests/testData.ts @@ -0,0 +1,339 @@ +export const lockAddress = 'DHTom1rFwsgAn5raKU1nok8E5MdQ4GBkAN'; +export const lockAddressPublicKey = + '76a914872b67c8270a9eaf5c2abf632af3dea989d2e37188ac'; + +export const blockHeight = 5434656; +export const blockHash = + 'e4dc98a8e1faabf2c210e487027f1380a39a83cc22d7d7e38592f0ac30e0e847'; +export const blockResponse = { + id: 'e4dc98a8e1faabf2c210e487027f1380a39a83cc22d7d7e38592f0ac30e0e847', + height: 5434656, + version: 6422788, + timestamp: 1729891705, + tx_count: 25, + size: 6970, + weight: 27880, + merkle_root: + '58e56706160fb162eb07de7b4101fe69a74070b1051c8413f785b7029423cc47', + previousblockhash: + '7e1c0b269757d346b2b30183904ce70051f3dbac41fba1c5b467899fa2645fee', + mediantime: 1729891559, + nonce: 0, + bits: 436250374, + difficulty: 25714365.745825343, +}; +export const blockInfo = { + hash: 'e4dc98a8e1faabf2c210e487027f1380a39a83cc22d7d7e38592f0ac30e0e847', + parentHash: + '7e1c0b269757d346b2b30183904ce70051f3dbac41fba1c5b467899fa2645fee', + height: 5434656, +}; + +export const txId = + 'd3d2b2dc24639e8d698071a49921b7b378c0a56cffcc0db3b42d5937a67389ab'; +export const txBlockHash = + '5b1c666ef6ba36cda85e7d1ced54d43e1dfd30b31a9f071279b70a470a08ae2c'; +export const txResponse = { + txid: 'd3d2b2dc24639e8d698071a49921b7b378c0a56cffcc0db3b42d5937a67389ab', + version: 2, + locktime: 0, + vin: [ + { + txid: '8597e2de38e3b1e69db9b8a80463e149317e91f904df5d6fa26b71b962f29e34', + vout: 2, + prevout: { + scriptpubkey: '76a914872b67c8270a9eaf5c2abf632af3dea989d2e37188ac', + scriptpubkey_asm: + 'OP_DUP OP_HASH160 OP_PUSHBYTES_20 872b67c8270a9eaf5c2abf632af3dea989d2e371 OP_EQUALVERIFY OP_CHECKSIG', + scriptpubkey_type: 'p2pkh', + scriptpubkey_address: 'DHTom1rFwsgAn5raKU1nok8E5MdQ4GBkAN', + value: 15534394312, + }, + scriptsig: + '47304402207e4cd2745243257f0749b4a41425c2075dfb199f47072bfbf7db14b02677a8ae02204682c5159737314f7c4ba0f7112876497171a7cee48dddf667dccd59cf8ae1280121022b9ed0a9139042921decc62603a4a07357b444da2e0bd6a96c27155117913037', + scriptsig_asm: + 'OP_PUSHBYTES_71 304402207e4cd2745243257f0749b4a41425c2075dfb199f47072bfbf7db14b02677a8ae02204682c5159737314f7c4ba0f7112876497171a7cee48dddf667dccd59cf8ae12801 OP_PUSHBYTES_33 022b9ed0a9139042921decc62603a4a07357b444da2e0bd6a96c27155117913037', + is_coinbase: false, + sequence: 4294967295, + }, + ], + vout: [ + { + scriptpubkey: + '6a33000000000005f5e10000000000009896802103e5bedab3f782ef17a73e9bdc41ee0e18c3ab477400f35bcf7caa54171db7ff36', + scriptpubkey_asm: + 'OP_RETURN OP_PUSHBYTES_51 000000000005f5e10000000000009896802103e5bedab3f782ef17a73e9bdc41ee0e18c3ab477400f35bcf7caa54171db7ff36', + scriptpubkey_type: 'op_return', + value: 0, + }, + { + scriptpubkey: 'a914d4c141068ab3a242aed5081a27ac3f10ad99ac9887', + scriptpubkey_asm: + 'OP_HASH160 OP_PUSHBYTES_20 d4c141068ab3a242aed5081a27ac3f10ad99ac98 OP_EQUAL', + scriptpubkey_type: 'p2sh', + scriptpubkey_address: 'ABqDRagXMAqcwxeqnvSZKGKBAqjFBiFcU4', + value: 1000000000, + }, + { + scriptpubkey: '76a914872b67c8270a9eaf5c2abf632af3dea989d2e37188ac', + scriptpubkey_asm: + 'OP_DUP OP_HASH160 OP_PUSHBYTES_20 872b67c8270a9eaf5c2abf632af3dea989d2e371 OP_EQUALVERIFY OP_CHECKSIG', + scriptpubkey_type: 'p2pkh', + scriptpubkey_address: 'DHTom1rFwsgAn5raKU1nok8E5MdQ4GBkAN', + value: 14494394312, + }, + ], + size: 285, + weight: 1140, + fee: 40000000, + status: { + confirmed: true, + block_height: 5425056, + block_hash: + '5b1c666ef6ba36cda85e7d1ced54d43e1dfd30b31a9f071279b70a470a08ae2c', + block_time: 1729287853, + }, +}; +export const txConfirmation = 9600; +export const dogeTx = { + id: 'd3d2b2dc24639e8d698071a49921b7b378c0a56cffcc0db3b42d5937a67389ab', + inputs: [ + { + txId: '8597e2de38e3b1e69db9b8a80463e149317e91f904df5d6fa26b71b962f29e34', + index: 2, + scriptPubKey: '76a914872b67c8270a9eaf5c2abf632af3dea989d2e37188ac', + }, + ], + outputs: [ + { + scriptPubKey: + '6a33000000000005f5e10000000000009896802103e5bedab3f782ef17a73e9bdc41ee0e18c3ab477400f35bcf7caa54171db7ff36', + value: 0n, + }, + { + scriptPubKey: 'a914d4c141068ab3a242aed5081a27ac3f10ad99ac9887', + value: 1000000000n, + }, + { + scriptPubKey: '76a914872b67c8270a9eaf5c2abf632af3dea989d2e37188ac', + value: 14494394312n, + }, + ], +}; +export const unconfirmedTxResponse = { + txid: 'd3d2b2dc24639e8d698071a49921b7b378c0a56cffcc0db3b42d5937a67389ab', + version: 2, + locktime: 0, + vin: [ + { + txid: '8597e2de38e3b1e69db9b8a80463e149317e91f904df5d6fa26b71b962f29e34', + vout: 2, + prevout: { + scriptpubkey: '76a914872b67c8270a9eaf5c2abf632af3dea989d2e37188ac', + scriptpubkey_asm: + 'OP_DUP OP_HASH160 OP_PUSHBYTES_20 872b67c8270a9eaf5c2abf632af3dea989d2e371 OP_EQUALVERIFY OP_CHECKSIG', + scriptpubkey_type: 'p2pkh', + scriptpubkey_address: 'DHTom1rFwsgAn5raKU1nok8E5MdQ4GBkAN', + value: 15534394312, + }, + scriptsig: + '47304402207e4cd2745243257f0749b4a41425c2075dfb199f47072bfbf7db14b02677a8ae02204682c5159737314f7c4ba0f7112876497171a7cee48dddf667dccd59cf8ae1280121022b9ed0a9139042921decc62603a4a07357b444da2e0bd6a96c27155117913037', + scriptsig_asm: + 'OP_PUSHBYTES_71 304402207e4cd2745243257f0749b4a41425c2075dfb199f47072bfbf7db14b02677a8ae02204682c5159737314f7c4ba0f7112876497171a7cee48dddf667dccd59cf8ae12801 OP_PUSHBYTES_33 022b9ed0a9139042921decc62603a4a07357b444da2e0bd6a96c27155117913037', + is_coinbase: false, + sequence: 4294967295, + }, + ], + vout: [ + { + scriptpubkey: + '6a33000000000005f5e10000000000009896802103e5bedab3f782ef17a73e9bdc41ee0e18c3ab477400f35bcf7caa54171db7ff36', + scriptpubkey_asm: + 'OP_RETURN OP_PUSHBYTES_51 000000000005f5e10000000000009896802103e5bedab3f782ef17a73e9bdc41ee0e18c3ab477400f35bcf7caa54171db7ff36', + scriptpubkey_type: 'op_return', + value: 0, + }, + { + scriptpubkey: 'a914d4c141068ab3a242aed5081a27ac3f10ad99ac9887', + scriptpubkey_asm: + 'OP_HASH160 OP_PUSHBYTES_20 d4c141068ab3a242aed5081a27ac3f10ad99ac98 OP_EQUAL', + scriptpubkey_type: 'p2sh', + scriptpubkey_address: 'ABqDRagXMAqcwxeqnvSZKGKBAqjFBiFcU4', + value: 1000000000, + }, + { + scriptpubkey: '76a914872b67c8270a9eaf5c2abf632af3dea989d2e37188ac', + scriptpubkey_asm: + 'OP_DUP OP_HASH160 OP_PUSHBYTES_20 872b67c8270a9eaf5c2abf632af3dea989d2e371 OP_EQUALVERIFY OP_CHECKSIG', + scriptpubkey_type: 'p2pkh', + scriptpubkey_address: 'DHTom1rFwsgAn5raKU1nok8E5MdQ4GBkAN', + value: 14494394312, + }, + ], + size: 285, + weight: 1140, + fee: 40000000, + status: { + confirmed: false, + }, +}; + +export const addressResponse = { + address: 'DHTom1rFwsgAn5raKU1nok8E5MdQ4GBkAN', + chain_stats: { + funded_txo_count: 14, + funded_txo_sum: 112731760184, + spent_txo_count: 6, + spent_txo_sum: 97187365872, + tx_count: 9, + }, + mempool_stats: { + funded_txo_count: 0, + funded_txo_sum: 0, + spent_txo_count: 0, + spent_txo_sum: 0, + tx_count: 0, + }, +}; +export const addressBalance = 15544394312n; +export const emptyAddressResponse = { + address: 'DHTom1rFwsgAn5raKU1nok8E5MdQ4GBkAN', + chain_stats: { + funded_txo_count: 1, + funded_txo_sum: 541840, + spent_txo_count: 1, + spent_txo_sum: 541840, + tx_count: 2, + }, + mempool_stats: { + funded_txo_count: 0, + funded_txo_sum: 0, + spent_txo_count: 0, + spent_txo_sum: 0, + tx_count: 0, + }, +}; +export const unusedAddressResponse = { + address: 'DHTom1rFwsgAn5raKU1nok8E5MdQ4GBkAN', + chain_stats: { + funded_txo_count: 0, + funded_txo_sum: 0, + spent_txo_count: 0, + spent_txo_sum: 0, + tx_count: 0, + }, + mempool_stats: { + funded_txo_count: 0, + funded_txo_sum: 0, + spent_txo_count: 0, + spent_txo_sum: 0, + tx_count: 0, + }, +}; + +export const txIds = [ + '716587ea99237f4e1bf6f959b3f8f4227f42c593a91356fa3fb5c49b310caa49', + 'd67242cb1be722aa50d6802a2d9f2ee9948836ec3d9278658f5a1573fcacc5aa', + 'be36bc00ea47873fb6067f779cb5bd988dddbf50193e2311a0773133083eea33', + '3432409bb4094739122e2f49c386ab4a86451a55ed95ebd19315fc048ff444e5', + 'baaacc564ace500045d1744a57aaccdb9b601e5b4f5c2c06bcd4af0ce5b99a10', + 'c6bf107d6226a71c5b64ea500f7169b9a546eeb0898311f9b8dcf44f096f4d7d', +]; + +export const addressUtxoResponse = [ + { + txid: 'bc9c558b21c86f955e07af14b73e82939731ca6ffd0b28c5b72436d76cee881f', + vout: 1, + status: { + confirmed: true, + block_height: 5427984, + block_hash: + 'fb7a521ddd47397ba421276bd298828527d7f1803eba7e530c1e336fef0f8c0d', + block_time: 1729471417, + }, + value: 900000000, + }, +]; +export const addressUtxos = [ + { + txId: 'bc9c558b21c86f955e07af14b73e82939731ca6ffd0b28c5b72436d76cee881f', + index: 1, + value: 900000000n, + }, +]; + +export const txOutspendsResponse = [ + { + spent: true, + txid: '57e186f988953145b8f20a71219839ed018715fcdc5fedec94874e1cbe532cc7', + vin: 3, + status: { + confirmed: true, + block_height: 828669, + block_hash: + '000000000000000000000cde53a239563c5a947d325c526bf140c7663b989b56', + block_time: 1706930825, + }, + }, + { + spent: false, + }, +]; + +export const utxo = { + txId: 'd3d2b2dc24639e8d698071a49921b7b378c0a56cffcc0db3b42d5937a67389ab', + index: 0, + value: 0n, +}; + +export const spentBoxId = + 'd3d2b2dc24639e8d698071a49921b7b378c0a56cffcc0db3b42d5937a67389ab.1'; +export const spentResult = { + spent: true, + txid: '79e657a92547e0a67ad4b0f04777ddb617745e6064b1d9393583619da59ae4c6', + vin: 0, + status: { + confirmed: true, + block_height: 5425068, + block_hash: + '2e21903ce31a5b77e9a0f56255a92955cb018504e0647b99211833ae721ae15f', + block_time: 1729288618, + }, +}; + +export const unsignedTxId = + '2e21903ce31a5b77e9a0f56255a92955cb018504e0647b99211833ae721ae15f'; +export const unspentBoxId = + 'd3d2b2dc24639e8d698071a49921b7b378c0a56cffcc0db3b42d5937a67389ab.0'; +export const unspentResult = { + spent: false, +}; + +export const feeEstimatesResponse = { + '1': 50271.918000000005, + '2': 50271.918000000005, + '3': 50271.918000000005, + '4': 50271.918000000005, + '5': 36171.68, + '6': 36171.68, + '7': 3011.257, + '8': 3011.257, + '9': 3011.257, + '10': 3011.257, + '11': 3011.257, + '12': 3011.257, + '13': 3011.257, + '14': 3011.257, + '15': 3011.257, + '16': 1002.715, + '17': 1002.715, + '18': 1002.715, + '19': 1002.715, + '20': 1002.715, + '21': 1002.715, + '22': 1002.715, + '23': 1002.715, + '24': 1002.715, + '25': 1002.715, +}; +export const targetFeeEstimation = 3011.257; diff --git a/packages/networks/doge-esplora/tsconfig.build.json b/packages/networks/doge-esplora/tsconfig.build.json new file mode 100644 index 00000000..0c2efa44 --- /dev/null +++ b/packages/networks/doge-esplora/tsconfig.build.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "./lib" + }, + "exclude": ["tests", "vitest.config.ts"], + "references": [ + { "path": "../../abstract-chain/tsconfig.build.json" }, + { "path": "../../chains/doge/tsconfig.build.json" } + ] +} diff --git a/packages/networks/doge-esplora/tsconfig.json b/packages/networks/doge-esplora/tsconfig.json new file mode 100644 index 00000000..8ffbd6ee --- /dev/null +++ b/packages/networks/doge-esplora/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist" + }, + "include": ["tests", "lib", "vitest.config.ts"], + "references": [ + { "path": "../../abstract-chain" }, + { "path": "../../chains/doge" } + ] +} diff --git a/packages/networks/doge-esplora/vitest.config.ts b/packages/networks/doge-esplora/vitest.config.ts new file mode 100644 index 00000000..b4289be9 --- /dev/null +++ b/packages/networks/doge-esplora/vitest.config.ts @@ -0,0 +1,18 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + coverage: { + all: true, + provider: 'istanbul', + reporter: 'cobertura', + }, + passWithNoTests: true, + poolOptions: { + threads: { + singleThread: true, + }, + }, + }, +}); From 8a99afaf24fa63f655c2fd763add729c0fb1d86e Mon Sep 17 00:00:00 2001 From: Mehran Aghabozorgi Date: Sun, 22 Dec 2024 15:30:29 -0800 Subject: [PATCH 2/9] Add doge network --- .gitignore | 1 + package-lock.json | 275 +++++++++++++++++++- packages/networks/doge-esplora/package.json | 2 +- 3 files changed, 274 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index a6b6c818..a986ea79 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ coverage # TypeScript cache *.tsbuildinfo +.vscode \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 5d55037a..faae5e4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3825,6 +3825,10 @@ "resolved": "packages/chains/doge", "link": true }, + "node_modules/@rosen-chains/doge-esplora": { + "resolved": "packages/networks/doge-esplora", + "link": true + }, "node_modules/@rosen-chains/ergo": { "resolved": "packages/chains/ergo", "link": true @@ -16513,7 +16517,7 @@ }, "packages/chains/doge": { "name": "@rosen-chains/doge", - "version": "0.0.0", + "version": "0.1.0", "license": "GPL-3.0", "dependencies": { "@rosen-bridge/abstract-logger": "^2.0.1", @@ -22338,14 +22342,13 @@ "packages/networks/doge-esplora": { "name": "@rosen-chains/doge-esplora", "version": "0.1.0", - "extraneous": true, "license": "GPL-3.0", "dependencies": { "@rosen-bridge/abstract-logger": "^2.0.1", "@rosen-bridge/json-bigint": "^0.1.0", "@rosen-chains/abstract-chain": "^11.0.3", "@rosen-chains/bitcoin-esplora": "^4.0.8", - "@rosen-chains/doge": "^0.0.0", + "@rosen-chains/doge": "^0.1.0", "axios": "^1.6.7", "bitcoinjs-lib": "^6.1.5" }, @@ -22365,6 +22368,272 @@ "node": ">=20.11.0" } }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/networks/doge-esplora/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "packages/networks/doge-esplora/node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "packages/networks/doge-esplora/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/networks/doge-esplora/node_modules/prettier": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "packages/networks/doge-esplora/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "packages/networks/doge-esplora/node_modules/typescript": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "packages/networks/ergo-explorer": { "name": "@rosen-chains/ergo-explorer-network", "version": "9.0.8", diff --git a/packages/networks/doge-esplora/package.json b/packages/networks/doge-esplora/package.json index 6f03ad8d..e6b2699f 100644 --- a/packages/networks/doge-esplora/package.json +++ b/packages/networks/doge-esplora/package.json @@ -36,7 +36,7 @@ "@rosen-bridge/abstract-logger": "^2.0.1", "@rosen-bridge/json-bigint": "^0.1.0", "@rosen-chains/abstract-chain": "^11.0.3", - "@rosen-chains/doge": "^0.0.0", + "@rosen-chains/doge": "^0.1.0", "@rosen-chains/bitcoin-esplora": "^4.0.8", "axios": "^1.6.7", "bitcoinjs-lib": "^6.1.5" From 10e36addb8108d1c891fc5d7a02ef1ae013dff6f Mon Sep 17 00:00:00 2001 From: Mehran Aghabozorgi Date: Tue, 24 Dec 2024 14:26:52 -0800 Subject: [PATCH 3/9] Separate doge esplora --- .../doge-esplora/lib/DogeEsploraNetwork.ts | 376 +++++++++++++++--- packages/networks/doge-esplora/package.json | 7 +- .../tests/DogeEsploraNetwork.spec.ts | 6 +- 3 files changed, 329 insertions(+), 60 deletions(-) diff --git a/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts b/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts index ac542b8a..5f705dcc 100644 --- a/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts +++ b/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts @@ -23,9 +23,8 @@ import { EsploraUtxo, EsploraUtxoInfo, } from './types'; -import BitcoinEsploraNetwork from '@rosen-chains/bitcoin-esplora'; -class DogeEsploraNetwork extends BitcoinEsploraNetwork { +class DogeEsploraNetwork extends AbstractDogeNetwork { protected client: AxiosInstance; private getSavedTransactionById: ( txId: string @@ -36,13 +35,33 @@ class DogeEsploraNetwork extends BitcoinEsploraNetwork { getSavedTransactionById: (txId: string) => Promise, logger?: AbstractLogger ) { - super(url, logger); + super(logger); this.client = axios.create({ baseURL: url, }); this.getSavedTransactionById = getSavedTransactionById; } + /** + * gets the blockchain height + * @returns the blockchain height + */ + getHeight = async (): Promise => { + return this.client + .get(`/api/blocks/tip/height`) + .then((res) => Number(res.data)) + .catch((e) => { + const baseError = `Failed to fetch current height from Esplora: `; + if (e.response) { + throw new FailedError(baseError + `${e.response.data}`); + } else if (e.request) { + throw new NetworkError(baseError + e.message); + } else { + throw new UnexpectedApiError(baseError + e.message); + } + }); + }; + /** * gets confirmation for a transaction (returns -1 if tx is not mined or found) * @param transactionId the transaction id (only supports real signed tx id) @@ -114,56 +133,151 @@ class DogeEsploraNetwork extends BitcoinEsploraNetwork { return await this.getTxConfirmationSigned(realTxId); }; - // /** - // * gets a transaction (serialized in `DogeTx` format) - // * @param transactionId the transaction id - // * @param blockId the block id - // * @returns the transaction - // */ - // getTransaction = async ( - // transactionId: string, - // blockId: string - // ): Promise => { - // let txInfo: EsploraTx; - // try { - // txInfo = (await this.client.get(`/api/tx/${transactionId}`)) - // .data; - // this.logger.debug( - // `requested 'tx' for txId [${transactionId}]. res: ${JsonBigInt.stringify( - // txInfo - // )}` - // ); - // } catch (e: any) { - // const baseError = `Failed to get transaction [${transactionId}] from Esplora: `; - // if (e.response) { - // throw new FailedError(baseError + e.response.data); - // } else if (e.request) { - // throw new NetworkError(baseError + e.message); - // } else { - // throw new UnexpectedApiError(baseError + e.message); - // } - // } - // - // if (txInfo.status.block_hash !== blockId) - // throw new FailedError( - // `Tx [${transactionId}] doesn't belong to block [${blockId}]` - // ); - // - // const tx: DogeTx = { - // id: txInfo.txid, - // inputs: txInfo.vin.map((input) => ({ - // txId: input.txid, - // index: input.vout, - // scriptPubKey: input.prevout.scriptpubkey, - // })), - // outputs: txInfo.vout.map((output) => ({ - // scriptPubKey: output.scriptpubkey, - // value: BigInt(output.value), - // })), - // }; - // - // return tx; - // }; + /** + * gets the amount of each asset in an address + * @param address the address + * @returns an object containing the amount of each asset + */ + getAddressAssets = async (address: string): Promise => { + let nativeToken = 0n; + const tokens: Array = []; + + return this.client + .get(`/api/address/${address}`) + .then((res) => { + this.logger.debug( + `requested 'address' for address [${address}]. res: ${JsonBigInt.stringify( + res.data + )}` + ); + const chainStat = res.data.chain_stats; + nativeToken = BigInt( + chainStat.funded_txo_sum - chainStat.spent_txo_sum + ); + return { nativeToken, tokens }; + }) + .catch((e) => { + const baseError = `Failed to get address [${address}] assets from Esplora: `; + if (e.response) { + throw new FailedError(baseError + e.response.data); + } else if (e.request) { + throw new NetworkError(baseError + e.message); + } else { + throw new UnexpectedApiError(baseError + e.message); + } + }); + }; + + /** + * gets id of all transactions in the given block + * @param blockId the block id + * @returns list of the transaction ids in the block + */ + getBlockTransactionIds = (blockId: string): Promise> => { + return this.client + .get>(`/api/block/${blockId}/txids`) + .then((res) => { + this.logger.debug( + `requested 'block/:hash/txids' for blockId [${blockId}]. received: ${JsonBigInt.stringify( + res.data + )}` + ); + return res.data; + }) + .catch((e) => { + const baseError = `Failed to get block [${blockId}] transaction ids from Esplora: `; + if (e.response) { + throw new FailedError(baseError + e.response.data); + } else if (e.request) { + throw new NetworkError(baseError + e.message); + } else { + throw new UnexpectedApiError(baseError + e.message); + } + }); + }; + + /** + * gets info of the given block + * @param blockId the block id + * @returns an object containing block info + */ + getBlockInfo = (blockId: string): Promise => { + return this.client + .get(`/api/block/${blockId}`) + .then((res) => { + this.logger.debug( + `requested 'block' for blockId [${blockId}]. res: ${JsonBigInt.stringify( + res.data + )}` + ); + const block = res.data; + return { + hash: block.id, + parentHash: block.previousblockhash, + height: Number(block.height), + }; + }) + .catch((e) => { + const baseError = `Failed to get block [${blockId}] info from Esplora: `; + if (e.response) { + throw new FailedError(baseError + e.response.data); + } else if (e.request) { + throw new NetworkError(baseError + e.message); + } else { + throw new UnexpectedApiError(baseError + e.message); + } + }); + }; + /** + * gets a transaction (serialized in `DogeTx` format) + * @param transactionId the transaction id + * @param blockId the block id + * @returns the transaction + */ + getTransaction = async ( + transactionId: string, + blockId: string + ): Promise => { + let txInfo: EsploraTx; + try { + txInfo = (await this.client.get(`/api/tx/${transactionId}`)) + .data; + this.logger.debug( + `requested 'tx' for txId [${transactionId}]. res: ${JsonBigInt.stringify( + txInfo + )}` + ); + } catch (e: any) { + const baseError = `Failed to get transaction [${transactionId}] from Esplora: `; + if (e.response) { + throw new FailedError(baseError + e.response.data); + } else if (e.request) { + throw new NetworkError(baseError + e.message); + } else { + throw new UnexpectedApiError(baseError + e.message); + } + } + + if (txInfo.status.block_hash !== blockId) + throw new FailedError( + `Tx [${transactionId}] doesn't belong to block [${blockId}]` + ); + + const tx: DogeTx = { + id: txInfo.txid, + inputs: txInfo.vin.map((input) => ({ + txId: input.txid, + index: input.vout, + scriptPubKey: input.prevout.scriptpubkey, + })), + outputs: txInfo.vout.map((output) => ({ + scriptPubKey: output.scriptpubkey, + value: BigInt(output.value), + })), + }; + + return tx; + }; /** * submits a transaction @@ -173,6 +287,137 @@ class DogeEsploraNetwork extends BitcoinEsploraNetwork { await this.client.post(`/api/tx`, transaction.extractTransaction().toHex()); }; + /** + * gets confirmed and unspent boxes of an address + * @param address the address + * @param offset + * @param limit + * @returns list of boxes + */ + getAddressBoxes = async ( + address: string, + offset: number, + limit: number + ): Promise> => { + const boxes = await this.client + .get>(`/api/address/${address}/utxo`) + .then((res) => { + this.logger.debug( + `requested 'address/:address/utxo' for address [${address}]. res: ${JsonBigInt.stringify( + res.data + )}` + ); + return res.data.map((utxo) => ({ + txId: utxo.txid, + index: utxo.vout, + value: BigInt(utxo.value), + })); + }) + .catch((e) => { + const baseError = `Failed to get address [${address}] Utxos from Esplora: `; + if (e.response) { + throw new FailedError(baseError + e.response.data); + } else if (e.request) { + throw new NetworkError(baseError + e.message); + } else { + throw new UnexpectedApiError(baseError + e.message); + } + }); + // sort boxes to keep consistency between calls + boxes.sort((a, b) => { + if (a.txId < b.txId) return -1; + else if (a.txId === b.txId && a.index < b.index) return -1; + else if (a.txId === b.txId && a.index === b.index) return 0; + else return 1; + }); + return boxes.slice(offset, offset + limit); + }; + + /** + * checks if a box is still unspent and valid + * @param boxId the box id (txId + . + index) + * @returns true if the box is unspent and valid + */ + isBoxUnspentAndValid = async (boxId: string): Promise => { + const [txId, index] = boxId.split('.'); + let utxosInfo: Array; + + try { + utxosInfo = ( + await this.client.get>( + `/api/tx/${txId}/outspends` + ) + ).data; + this.logger.debug( + `requested 'tx/:txid/outspends' for tx [${txId}]. res: ${JsonBigInt.stringify( + utxosInfo + )}` + ); + } catch (e: any) { + const baseError = `Failed to get tx [${txId}] Utxos status from Esplora: `; + if (e.response && e.response.status === 404) { + this.logger.debug(`tx [${txId}] is not found`); + return false; + } else if (e.response) { + throw new FailedError(baseError + e.response.data); + } else if (e.request) { + throw new NetworkError(baseError + e.message); + } else { + throw new UnexpectedApiError(baseError + e.message); + } + } + + if (utxosInfo.length <= Number(index)) { + this.logger.debug( + `Utxo [${boxId}] is invalid: Transaction [${txId}] doesn't have index [${index}]` + ); + return false; + } + + const box = utxosInfo[Number(index)]; + if (!box.spent) return true; + this.logger.debug(`box [${boxId}] is spent in tx [${box.txid}]`); + return false; + }; + + /** + * gets an utxo from the network + * @param boxId the id of Utxo (txId + . + index) + * @returns the utxo + */ + getUtxo = async (boxId: string): Promise => { + const [txId, index] = boxId.split('.'); + let txInfo: EsploraTx; + + try { + txInfo = (await this.client.get(`/api/tx/${txId}`)).data; + this.logger.debug( + `requested 'tx' for tx [${txId}]. res: ${JsonBigInt.stringify(txInfo)}` + ); + } catch (e: any) { + const baseError = `Failed to get tx [${txId}] Utxos status from Esplora: `; + if (e.response) { + throw new FailedError(baseError + e.response.data); + } else if (e.request) { + throw new NetworkError(baseError + e.message); + } else { + throw new UnexpectedApiError(baseError + e.message); + } + } + + if (txInfo.vout.length <= Number(index)) { + throw new FailedError( + `Transaction [${txId}] doesn't have index [${index}]` + ); + } + + return { + txId: txId, + index: Number(index), + value: BigInt(txInfo.vout[Number(index)].value), + }; + }; + /** * gets current fee ratio of the network * @returns @@ -204,6 +449,31 @@ class DogeEsploraNetwork extends BitcoinEsploraNetwork { }); }; + /** + * gets id of transactions in mempool + * @returns + */ + getMempoolTxIds = async (): Promise> => { + return this.client + .get>(`/api/mempool/txids`) + .then((res) => { + this.logger.debug( + `requested 'mempool/txids'. received [${res.data.length}] txs` + ); + return res.data; + }) + .catch((e) => { + const baseError = `Failed to get mempool transaction ids from Esplora: `; + if (e.response) { + throw new FailedError(baseError + e.response.data); + } else if (e.request) { + throw new NetworkError(baseError + e.message); + } else { + throw new UnexpectedApiError(baseError + e.message); + } + }); + }; + /** * gets a transaction hex string * @param txId the transaction id (only supports real signed tx id) diff --git a/packages/networks/doge-esplora/package.json b/packages/networks/doge-esplora/package.json index e6b2699f..cd129d66 100644 --- a/packages/networks/doge-esplora/package.json +++ b/packages/networks/doge-esplora/package.json @@ -33,11 +33,10 @@ "node": ">=20.11.0" }, "dependencies": { - "@rosen-bridge/abstract-logger": "^2.0.1", + "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/json-bigint": "^0.1.0", - "@rosen-chains/abstract-chain": "^11.0.3", - "@rosen-chains/doge": "^0.1.0", - "@rosen-chains/bitcoin-esplora": "^4.0.8", + "@rosen-chains/abstract-chain": "^9.0.2", + "@rosen-chains/doge": "file:../../chains/doge", "axios": "^1.6.7", "bitcoinjs-lib": "^6.1.5" } diff --git a/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts b/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts index 7dff9c01..59ec7e0d 100644 --- a/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts +++ b/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts @@ -282,7 +282,7 @@ describe('DogeEsploraNetwork', () => { await expect(async () => { await network.getTransaction(testData.txId, testData.blockHash); - }).rejects.toThrow('FailedError'); + }).rejects.toThrow(FailedError); }); }); @@ -460,7 +460,7 @@ describe('DogeEsploraNetwork', () => { const boxId = `${testData.txId}.${0}`; await expect(async () => { await network.getUtxo(boxId); - }).rejects.toThrow('FailedError'); + }).rejects.toThrow(FailedError); }); /** @@ -479,7 +479,7 @@ describe('DogeEsploraNetwork', () => { const boxId = `${testData.txId}.${3}`; await expect(async () => { await network.getUtxo(boxId); - }).rejects.toThrow('FailedError'); + }).rejects.toThrow(FailedError); }); }); From 04bb2e15479aa36e3252cd10b79aa164e1cc6559 Mon Sep 17 00:00:00 2001 From: Mehran Aghabozorgi Date: Tue, 24 Dec 2024 14:32:31 -0800 Subject: [PATCH 4/9] Separate doge esplora --- packages/networks/doge-esplora/package.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/networks/doge-esplora/package.json b/packages/networks/doge-esplora/package.json index cd129d66..e6b2699f 100644 --- a/packages/networks/doge-esplora/package.json +++ b/packages/networks/doge-esplora/package.json @@ -33,10 +33,11 @@ "node": ">=20.11.0" }, "dependencies": { - "@rosen-bridge/abstract-logger": "^1.0.0", + "@rosen-bridge/abstract-logger": "^2.0.1", "@rosen-bridge/json-bigint": "^0.1.0", - "@rosen-chains/abstract-chain": "^9.0.2", - "@rosen-chains/doge": "file:../../chains/doge", + "@rosen-chains/abstract-chain": "^11.0.3", + "@rosen-chains/doge": "^0.1.0", + "@rosen-chains/bitcoin-esplora": "^4.0.8", "axios": "^1.6.7", "bitcoinjs-lib": "^6.1.5" } From 182f82c39d43ebb064eade841cdd84cdab07aeed Mon Sep 17 00:00:00 2001 From: Mehran Aghabozorgi Date: Sun, 19 Jan 2025 16:17:51 -0800 Subject: [PATCH 5/9] Fix package-lock --- package-lock.json | 1304 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1288 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0c134506..10d1ef98 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3466,6 +3466,18 @@ "node": ">=8" } }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "dev": true, @@ -4241,6 +4253,12 @@ "@rosen-clients/axios": "^0.1.0" } }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "license": "MIT", @@ -4856,6 +4874,18 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/aes-js": { "version": "4.0.0-beta.5", "license": "MIT" @@ -5908,6 +5938,12 @@ "devOptional": true, "license": "MIT" }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true + }, "node_modules/console-control-strings": { "version": "1.1.0", "license": "ISC", @@ -6194,6 +6230,15 @@ "node": ">=8" } }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "dev": true, @@ -7685,6 +7730,15 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "dev": true, @@ -9226,6 +9280,22 @@ "node": ">=4" } }, + "node_modules/local-pkg": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz", + "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==", + "dev": true, + "dependencies": { + "mlly": "^1.7.3", + "pkg-types": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/locate-path": { "version": "6.0.0", "dev": true, @@ -9872,6 +9942,24 @@ "version": "0.5.3", "license": "MIT" }, + "node_modules/mlly": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", + "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==", + "dev": true, + "dependencies": { + "acorn": "^8.14.0", + "pathe": "^2.0.1", + "pkg-types": "^1.3.0", + "ufo": "^1.5.4" + } + }, + "node_modules/mlly/node_modules/pathe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz", + "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==", + "dev": true + }, "node_modules/ms": { "version": "2.1.3", "license": "MIT" @@ -10658,6 +10746,23 @@ "node": ">=8" } }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/pkg-types/node_modules/pathe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz", + "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==", + "dev": true + }, "node_modules/postcss": { "version": "8.4.49", "dev": true, @@ -10745,6 +10850,32 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/promise": { "version": "7.3.1", "dev": true, @@ -10877,6 +11008,12 @@ "node": ">=0.10.0" } }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, "node_modules/read-pkg": { "version": "5.2.0", "dev": true, @@ -12125,6 +12262,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.1.tgz", + "integrity": "sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==", + "dev": true, + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true + }, "node_modules/supports-color": { "version": "7.2.0", "license": "MIT", @@ -12618,6 +12773,15 @@ "node": ">= 0.8.0" } }, + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/type-fest": { "version": "0.21.3", "dev": true, @@ -13020,6 +13184,12 @@ "node": "*" } }, + "node_modules/ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "dev": true + }, "node_modules/unbox-primitive": { "version": "1.0.2", "dev": true, @@ -16749,22 +16919,1124 @@ "node": ">=20.11.0" } }, - "packages/networks/ergo-explorer": { - "name": "@rosen-chains/ergo-explorer-network", - "version": "9.0.8", - "license": "CC0-1.0", - "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/type-utils": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "packages/networks/doge-esplora/node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.31.0.tgz", + "integrity": "sha512-9NrR4033uCbUBRgvLcBrJofa2KY9DzxL2UKZ1/4xA/mnTNyhZCWBuD8X3tPm1n4KxcgaraOYgrFKSgwjASfmlA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-android-arm64": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.31.0.tgz", + "integrity": "sha512-iBbODqT86YBFHajxxF8ebj2hwKm1k8PTBQSojSt3d1FFt1gN+xf4CowE47iN0vOSdnd+5ierMHBbu/rHc7nq5g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.31.0.tgz", + "integrity": "sha512-WHIZfXgVBX30SWuTMhlHPXTyN20AXrLH4TEeH/D0Bolvx9PjgZnn4H677PlSGvU6MKNsjCQJYczkpvBbrBnG6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-darwin-x64": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.31.0.tgz", + "integrity": "sha512-hrWL7uQacTEF8gdrQAqcDy9xllQ0w0zuL1wk1HV8wKGSGbKPVjVUv/DEwT2+Asabf8Dh/As+IvfdU+H8hhzrQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.31.0.tgz", + "integrity": "sha512-S2oCsZ4hJviG1QjPY1h6sVJLBI6ekBeAEssYKad1soRFv3SocsQCzX6cwnk6fID6UQQACTjeIMB+hyYrFacRew==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.31.0.tgz", + "integrity": "sha512-pCANqpynRS4Jirn4IKZH4tnm2+2CqCNLKD7gAdEjzdLGbH1iO0zouHz4mxqg0uEMpO030ejJ0aA6e1PJo2xrPA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.31.0.tgz", + "integrity": "sha512-0O8ViX+QcBd3ZmGlcFTnYXZKGbFu09EhgD27tgTdGnkcYXLat4KIsBBQeKLR2xZDCXdIBAlWLkiXE1+rJpCxFw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.31.0.tgz", + "integrity": "sha512-w5IzG0wTVv7B0/SwDnMYmbr2uERQp999q8FMkKG1I+j8hpPX2BYFjWe69xbhbP6J9h2gId/7ogesl9hwblFwwg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.31.0.tgz", + "integrity": "sha512-JyFFshbN5xwy6fulZ8B/8qOqENRmDdEkcIMF0Zz+RsfamEW+Zabl5jAb0IozP/8UKnJ7g2FtZZPEUIAlUSX8cA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.31.0.tgz", + "integrity": "sha512-kpQXQ0UPFeMPmPYksiBL9WS/BDiQEjRGMfklVIsA0Sng347H8W2iexch+IEwaR7OVSKtr2ZFxggt11zVIlZ25g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.31.0.tgz", + "integrity": "sha512-pMlxLjt60iQTzt9iBb3jZphFIl55a70wexvo8p+vVFK+7ifTRookdoXX3bOsRdmfD+OKnMozKO6XM4zR0sHRrQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.31.0.tgz", + "integrity": "sha512-D7TXT7I/uKEuWiRkEFbed1UUYZwcJDU4vZQdPTcepK7ecPhzKOYk4Er2YR4uHKme4qDeIh6N3XrLfpuM7vzRWQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.31.0.tgz", + "integrity": "sha512-wal2Tc8O5lMBtoePLBYRKj2CImUCJ4UNGJlLwspx7QApYny7K1cUYlzQ/4IGQBLmm+y0RS7dwc3TDO/pmcneTw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.31.0.tgz", + "integrity": "sha512-O1o5EUI0+RRMkK9wiTVpk2tyzXdXefHtRTIjBbmFREmNMy7pFeYXCFGbhKFwISA3UOExlo5GGUuuj3oMKdK6JQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.31.0.tgz", + "integrity": "sha512-zSoHl356vKnNxwOWnLd60ixHNPRBglxpv2g7q0Cd3Pmr561gf0HiAcUBRL3S1vPqRC17Zo2CX/9cPkqTIiai1g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.31.0.tgz", + "integrity": "sha512-ypB/HMtcSGhKUQNiFwqgdclWNRrAYDH8iMYH4etw/ZlGwiTVxBz2tDrGRrPlfZu6QjXwtd+C3Zib5pFqID97ZA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.31.0.tgz", + "integrity": "sha512-JuhN2xdI/m8Hr+aVO3vspO7OQfUFO6bKLIRTAy0U15vmWjnZDLrEgCZ2s6+scAYaQVpYSh9tZtRijApw9IXyMw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.31.0.tgz", + "integrity": "sha512-U1xZZXYkvdf5MIWmftU8wrM5PPXzyaY1nGCI4KI4BFfoZxHamsIe+BtnPLIvvPykvQWlVbqUXdLa4aJUuilwLQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "packages/networks/doge-esplora/node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.31.0.tgz", + "integrity": "sha512-ul8rnCsUumNln5YWwz0ted2ZHFhzhRRnkpBZ+YRuHoRAlUji9KChpOUOndY7uykrPEPXVbHLlsdo6v5yXo/TXw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "packages/networks/doge-esplora/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/networks/doge-esplora/node_modules/@vitest/coverage-istanbul": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/coverage-istanbul/-/coverage-istanbul-1.6.0.tgz", + "integrity": "sha512-h/BwpXehkkS0qsNCS00QxiupAqVkNi0WT19BR0dQvlge5oHghoSVLx63fABYFoKxVb7Ue7+k6V2KokmQ1zdMpg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-instrument": "^6.0.1", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.4", + "istanbul-reports": "^3.1.6", + "magicast": "^0.3.3", + "picocolors": "^1.0.0", + "test-exclude": "^6.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "1.6.0" + } + }, + "packages/networks/doge-esplora/node_modules/@vitest/expect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", + "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/networks/doge-esplora/node_modules/@vitest/runner": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz", + "integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==", + "dev": true, + "dependencies": { + "@vitest/utils": "1.6.0", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/networks/doge-esplora/node_modules/@vitest/snapshot": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz", + "integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==", + "dev": true, + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/networks/doge-esplora/node_modules/@vitest/spy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", + "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/networks/doge-esplora/node_modules/@vitest/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/networks/doge-esplora/node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "packages/networks/doge-esplora/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "packages/networks/doge-esplora/node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "packages/networks/doge-esplora/node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "packages/networks/doge-esplora/node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "packages/networks/doge-esplora/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "packages/networks/doge-esplora/node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "packages/networks/doge-esplora/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "packages/networks/doge-esplora/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/networks/doge-esplora/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "packages/networks/doge-esplora/node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "packages/networks/doge-esplora/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/networks/doge-esplora/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/networks/doge-esplora/node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "packages/networks/doge-esplora/node_modules/prettier": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "packages/networks/doge-esplora/node_modules/rollup": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.31.0.tgz", + "integrity": "sha512-9cCE8P4rZLx9+PjoyqHLs31V9a9Vpvfo4qNcs6JCiGWYhw2gijSetFbH6SSy1whnkgcefnUwr8sad7tgqsGvnw==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.31.0", + "@rollup/rollup-android-arm64": "4.31.0", + "@rollup/rollup-darwin-arm64": "4.31.0", + "@rollup/rollup-darwin-x64": "4.31.0", + "@rollup/rollup-freebsd-arm64": "4.31.0", + "@rollup/rollup-freebsd-x64": "4.31.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.31.0", + "@rollup/rollup-linux-arm-musleabihf": "4.31.0", + "@rollup/rollup-linux-arm64-gnu": "4.31.0", + "@rollup/rollup-linux-arm64-musl": "4.31.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.31.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.31.0", + "@rollup/rollup-linux-riscv64-gnu": "4.31.0", + "@rollup/rollup-linux-s390x-gnu": "4.31.0", + "@rollup/rollup-linux-x64-gnu": "4.31.0", + "@rollup/rollup-linux-x64-musl": "4.31.0", + "@rollup/rollup-win32-arm64-msvc": "4.31.0", + "@rollup/rollup-win32-ia32-msvc": "4.31.0", + "@rollup/rollup-win32-x64-msvc": "4.31.0", + "fsevents": "~2.3.2" + } + }, + "packages/networks/doge-esplora/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "packages/networks/doge-esplora/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/networks/doge-esplora/node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "packages/networks/doge-esplora/node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "packages/networks/doge-esplora/node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "packages/networks/doge-esplora/node_modules/tinypool": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", + "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "packages/networks/doge-esplora/node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "packages/networks/doge-esplora/node_modules/typescript": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "packages/networks/doge-esplora/node_modules/vite-node": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", + "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/networks/doge-esplora/node_modules/vite-node/node_modules/vite": { + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", + "dev": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "packages/networks/doge-esplora/node_modules/vitest": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz", + "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==", + "dev": true, + "dependencies": { + "@vitest/expect": "1.6.0", + "@vitest/runner": "1.6.0", + "@vitest/snapshot": "1.6.0", + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.3", + "vite": "^5.0.0", + "vite-node": "1.6.0", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.6.0", + "@vitest/ui": "1.6.0", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "packages/networks/doge-esplora/node_modules/vitest/node_modules/vite": { + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", + "dev": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "packages/networks/doge-esplora/node_modules/yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/networks/ergo-explorer": { + "name": "@rosen-chains/ergo-explorer-network", + "version": "9.0.8", + "license": "CC0-1.0", + "dependencies": { + "@rosen-bridge/abstract-logger": "^2.0.1", + "@rosen-bridge/json-bigint": "^0.1.0", + "@rosen-chains/abstract-chain": "^11.0.3", + "@rosen-chains/ergo": "^10.1.4", + "@rosen-clients/ergo-explorer": "^1.1.1", + "ergo-lib-wasm-nodejs": "^0.24.1", + "it-all": "^3.0.1" + }, + "devDependencies": { + "@types/node": "^20.11.9", + "@typescript-eslint/eslint-plugin": "^5.30.7", + "@typescript-eslint/parser": "^5.26.0", + "@vitest/coverage-istanbul": "^2.1.4", + "eslint": "^8.16.0", + "eslint-config-prettier": "^8.5.0", + "extensionless": "^1.9.6", + "prettier": "^2.7.1", + "typescript": "^5.0.4", + "vite-plugin-top-level-await": "^1.3.0", + "vite-plugin-wasm": "^3.2.2", + "vitest": "^2.1.4" }, "engines": { "node": ">=20.11.0" From 1c5874cc9eecb5b862391a7eec477e0791c2d8e6 Mon Sep 17 00:00:00 2001 From: Mehran Aghabozorgi Date: Sun, 19 Jan 2025 16:30:06 -0800 Subject: [PATCH 6/9] Add changeset --- .changeset/mean-cows-pump.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/mean-cows-pump.md diff --git a/.changeset/mean-cows-pump.md b/.changeset/mean-cows-pump.md new file mode 100644 index 00000000..5f8f2bb3 --- /dev/null +++ b/.changeset/mean-cows-pump.md @@ -0,0 +1,5 @@ +--- +'@rosen-chains/doge-esplora': major +--- + +Esplora network for Doge From 67a72c4d422883438b5856fa6e46e44063294729 Mon Sep 17 00:00:00 2001 From: Mehran Aghabozorgi Date: Sat, 1 Feb 2025 12:57:38 -0800 Subject: [PATCH 7/9] Improve test coverage --- package-lock.json | 1315 ++--------------- packages/chains/doge/package.json | 2 +- .../doge-esplora/lib/DogeEsploraNetwork.ts | 34 +- packages/networks/doge-esplora/package.json | 7 +- .../tests/DogeEsploraNetwork.spec.ts | 103 +- .../networks/doge-esplora/tests/testData.ts | 65 +- .../networks/doge-esplora/vitest.config.ts | 4 +- 7 files changed, 344 insertions(+), 1186 deletions(-) diff --git a/package-lock.json b/package-lock.json index 10d1ef98..9d1d91c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3466,18 +3466,6 @@ "node": ">=8" } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "dev": true, @@ -4253,12 +4241,6 @@ "@rosen-clients/axios": "^0.1.0" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "license": "MIT", @@ -4874,18 +4856,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/aes-js": { "version": "4.0.0-beta.5", "license": "MIT" @@ -5938,12 +5908,6 @@ "devOptional": true, "license": "MIT" }, - "node_modules/confbox": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", - "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", - "dev": true - }, "node_modules/console-control-strings": { "version": "1.1.0", "license": "ISC", @@ -6230,15 +6194,6 @@ "node": ">=8" } }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "dev": true, @@ -7730,15 +7685,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/get-intrinsic": { "version": "1.2.4", "dev": true, @@ -9280,22 +9226,6 @@ "node": ">=4" } }, - "node_modules/local-pkg": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz", - "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==", - "dev": true, - "dependencies": { - "mlly": "^1.7.3", - "pkg-types": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/locate-path": { "version": "6.0.0", "dev": true, @@ -9942,24 +9872,6 @@ "version": "0.5.3", "license": "MIT" }, - "node_modules/mlly": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", - "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==", - "dev": true, - "dependencies": { - "acorn": "^8.14.0", - "pathe": "^2.0.1", - "pkg-types": "^1.3.0", - "ufo": "^1.5.4" - } - }, - "node_modules/mlly/node_modules/pathe": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz", - "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==", - "dev": true - }, "node_modules/ms": { "version": "2.1.3", "license": "MIT" @@ -10746,23 +10658,6 @@ "node": ">=8" } }, - "node_modules/pkg-types": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", - "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", - "dev": true, - "dependencies": { - "confbox": "^0.1.8", - "mlly": "^1.7.4", - "pathe": "^2.0.1" - } - }, - "node_modules/pkg-types/node_modules/pathe": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz", - "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==", - "dev": true - }, "node_modules/postcss": { "version": "8.4.49", "dev": true, @@ -10850,32 +10745,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/promise": { "version": "7.3.1", "dev": true, @@ -11008,12 +10877,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, "node_modules/read-pkg": { "version": "5.2.0", "dev": true, @@ -12262,24 +12125,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-literal": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.1.tgz", - "integrity": "sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==", - "dev": true, - "dependencies": { - "js-tokens": "^9.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/strip-literal/node_modules/js-tokens": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", - "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", - "dev": true - }, "node_modules/supports-color": { "version": "7.2.0", "license": "MIT", @@ -12773,15 +12618,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/type-fest": { "version": "0.21.3", "dev": true, @@ -13184,12 +13020,6 @@ "node": "*" } }, - "node_modules/ufo": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", - "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", - "dev": true - }, "node_modules/unbox-primitive": { "version": "1.0.2", "dev": true, @@ -16898,7 +16728,6 @@ "@rosen-bridge/abstract-logger": "^2.0.1", "@rosen-bridge/json-bigint": "^0.1.0", "@rosen-chains/abstract-chain": "^11.0.3", - "@rosen-chains/bitcoin-esplora": "^4.0.8", "@rosen-chains/doge": "^0.1.0", "axios": "^1.6.7", "bitcoinjs-lib": "^6.1.5" @@ -16907,280 +16736,150 @@ "@types/node": "^20.11.9", "@typescript-eslint/eslint-plugin": "^6.19.1", "@typescript-eslint/parser": "^6.19.1", - "@vitest/coverage-istanbul": "^1.2.2", + "@vitest/coverage-istanbul": "^2.1.4", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "extensionless": "^1.9.6", "prettier": "^3.2.4", "typescript": "^5.3.3", - "vitest": "^1.2.2" + "vitest": "^2.1.4" }, "engines": { "node": ">=20.11.0" } }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.31.0.tgz", - "integrity": "sha512-9NrR4033uCbUBRgvLcBrJofa2KY9DzxL2UKZ1/4xA/mnTNyhZCWBuD8X3tPm1n4KxcgaraOYgrFKSgwjASfmlA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-android-arm64": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.31.0.tgz", - "integrity": "sha512-iBbODqT86YBFHajxxF8ebj2hwKm1k8PTBQSojSt3d1FFt1gN+xf4CowE47iN0vOSdnd+5ierMHBbu/rHc7nq5g==", - "cpu": [ - "arm64" - ], + "packages/networks/doge-esplora/node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", "dev": true, - "optional": true, - "os": [ - "android" - ] + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.31.0.tgz", - "integrity": "sha512-WHIZfXgVBX30SWuTMhlHPXTyN20AXrLH4TEeH/D0Bolvx9PjgZnn4H677PlSGvU6MKNsjCQJYczkpvBbrBnG6g==", - "cpu": [ - "arm64" - ], + "packages/networks/doge-esplora/node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, - "optional": true, - "os": [ - "darwin" - ] + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-darwin-x64": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.31.0.tgz", - "integrity": "sha512-hrWL7uQacTEF8gdrQAqcDy9xllQ0w0zuL1wk1HV8wKGSGbKPVjVUv/DEwT2+Asabf8Dh/As+IvfdU+H8hhzrQQ==", - "cpu": [ - "x64" - ], + "packages/networks/doge-esplora/node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, - "optional": true, - "os": [ - "darwin" - ] + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.31.0.tgz", - "integrity": "sha512-S2oCsZ4hJviG1QjPY1h6sVJLBI6ekBeAEssYKad1soRFv3SocsQCzX6cwnk6fID6UQQACTjeIMB+hyYrFacRew==", - "cpu": [ - "arm64" - ], + "packages/networks/doge-esplora/node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ] + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.31.0.tgz", - "integrity": "sha512-pCANqpynRS4Jirn4IKZH4tnm2+2CqCNLKD7gAdEjzdLGbH1iO0zouHz4mxqg0uEMpO030ejJ0aA6e1PJo2xrPA==", - "cpu": [ - "x64" - ], + "packages/networks/doge-esplora/node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ] + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.31.0.tgz", - "integrity": "sha512-0O8ViX+QcBd3ZmGlcFTnYXZKGbFu09EhgD27tgTdGnkcYXLat4KIsBBQeKLR2xZDCXdIBAlWLkiXE1+rJpCxFw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.31.0.tgz", - "integrity": "sha512-w5IzG0wTVv7B0/SwDnMYmbr2uERQp999q8FMkKG1I+j8hpPX2BYFjWe69xbhbP6J9h2gId/7ogesl9hwblFwwg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.31.0.tgz", - "integrity": "sha512-JyFFshbN5xwy6fulZ8B/8qOqENRmDdEkcIMF0Zz+RsfamEW+Zabl5jAb0IozP/8UKnJ7g2FtZZPEUIAlUSX8cA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.31.0.tgz", - "integrity": "sha512-kpQXQ0UPFeMPmPYksiBL9WS/BDiQEjRGMfklVIsA0Sng347H8W2iexch+IEwaR7OVSKtr2ZFxggt11zVIlZ25g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.31.0.tgz", - "integrity": "sha512-pMlxLjt60iQTzt9iBb3jZphFIl55a70wexvo8p+vVFK+7ifTRookdoXX3bOsRdmfD+OKnMozKO6XM4zR0sHRrQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.31.0.tgz", - "integrity": "sha512-D7TXT7I/uKEuWiRkEFbed1UUYZwcJDU4vZQdPTcepK7ecPhzKOYk4Er2YR4uHKme4qDeIh6N3XrLfpuM7vzRWQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.31.0.tgz", - "integrity": "sha512-wal2Tc8O5lMBtoePLBYRKj2CImUCJ4UNGJlLwspx7QApYny7K1cUYlzQ/4IGQBLmm+y0RS7dwc3TDO/pmcneTw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.31.0.tgz", - "integrity": "sha512-O1o5EUI0+RRMkK9wiTVpk2tyzXdXefHtRTIjBbmFREmNMy7pFeYXCFGbhKFwISA3UOExlo5GGUuuj3oMKdK6JQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.31.0.tgz", - "integrity": "sha512-zSoHl356vKnNxwOWnLd60ixHNPRBglxpv2g7q0Cd3Pmr561gf0HiAcUBRL3S1vPqRC17Zo2CX/9cPkqTIiai1g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.31.0.tgz", - "integrity": "sha512-ypB/HMtcSGhKUQNiFwqgdclWNRrAYDH8iMYH4etw/ZlGwiTVxBz2tDrGRrPlfZu6QjXwtd+C3Zib5pFqID97ZA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.31.0.tgz", - "integrity": "sha512-JuhN2xdI/m8Hr+aVO3vspO7OQfUFO6bKLIRTAy0U15vmWjnZDLrEgCZ2s6+scAYaQVpYSh9tZtRijApw9IXyMw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.31.0.tgz", - "integrity": "sha512-U1xZZXYkvdf5MIWmftU8wrM5PPXzyaY1nGCI4KI4BFfoZxHamsIe+BtnPLIvvPykvQWlVbqUXdLa4aJUuilwLQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "packages/networks/doge-esplora/node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.31.0.tgz", - "integrity": "sha512-ul8rnCsUumNln5YWwz0ted2ZHFhzhRRnkpBZ+YRuHoRAlUji9KChpOUOndY7uykrPEPXVbHLlsdo6v5yXo/TXw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "packages/networks/doge-esplora/node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", - "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "packages/networks/doge-esplora/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/type-utils": "6.21.0", - "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/types": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -17191,27 +16890,25 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" - }, "peerDependenciesMeta": { "typescript": { "optional": true } } }, - "packages/networks/doge-esplora/node_modules/@typescript-eslint/parser": { + "packages/networks/doge-esplora/node_modules/@typescript-eslint/utils": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", "@typescript-eslint/scope-manager": "6.21.0", "@typescript-eslint/types": "6.21.0", "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4" + "semver": "^7.5.4" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -17222,21 +16919,16 @@ }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } } }, - "packages/networks/doge-esplora/node_modules/@typescript-eslint/scope-manager": { + "packages/networks/doge-esplora/node_modules/@typescript-eslint/visitor-keys": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -17246,461 +16938,55 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "packages/networks/doge-esplora/node_modules/@typescript-eslint/type-utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", - "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "packages/networks/doge-esplora/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "balanced-match": "^1.0.0" } }, - "packages/networks/doge-esplora/node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "packages/networks/doge-esplora/node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" + "bin": { + "eslint-config-prettier": "bin/cli.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "packages/networks/doge-esplora/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "packages/networks/doge-esplora/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sponsors/isaacs" } }, - "packages/networks/doge-esplora/node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "packages/networks/doge-esplora/node_modules/prettier": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" + "bin": { + "prettier": "bin/prettier.cjs" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "packages/networks/doge-esplora/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "packages/networks/doge-esplora/node_modules/@vitest/coverage-istanbul": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/coverage-istanbul/-/coverage-istanbul-1.6.0.tgz", - "integrity": "sha512-h/BwpXehkkS0qsNCS00QxiupAqVkNi0WT19BR0dQvlge5oHghoSVLx63fABYFoKxVb7Ue7+k6V2KokmQ1zdMpg==", - "dev": true, - "dependencies": { - "debug": "^4.3.4", - "istanbul-lib-coverage": "^3.2.2", - "istanbul-lib-instrument": "^6.0.1", - "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^5.0.4", - "istanbul-reports": "^3.1.6", - "magicast": "^0.3.3", - "picocolors": "^1.0.0", - "test-exclude": "^6.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "vitest": "1.6.0" - } - }, - "packages/networks/doge-esplora/node_modules/@vitest/expect": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", - "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", - "dev": true, - "dependencies": { - "@vitest/spy": "1.6.0", - "@vitest/utils": "1.6.0", - "chai": "^4.3.10" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "packages/networks/doge-esplora/node_modules/@vitest/runner": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz", - "integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==", - "dev": true, - "dependencies": { - "@vitest/utils": "1.6.0", - "p-limit": "^5.0.0", - "pathe": "^1.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "packages/networks/doge-esplora/node_modules/@vitest/snapshot": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz", - "integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==", - "dev": true, - "dependencies": { - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "pretty-format": "^29.7.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "packages/networks/doge-esplora/node_modules/@vitest/spy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", - "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", - "dev": true, - "dependencies": { - "tinyspy": "^2.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "packages/networks/doge-esplora/node_modules/@vitest/utils": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", - "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", - "dev": true, - "dependencies": { - "diff-sequences": "^29.6.3", - "estree-walker": "^3.0.3", - "loupe": "^2.3.7", - "pretty-format": "^29.7.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "packages/networks/doge-esplora/node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "packages/networks/doge-esplora/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "packages/networks/doge-esplora/node_modules/chai": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", - "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "packages/networks/doge-esplora/node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, - "packages/networks/doge-esplora/node_modules/deep-eql": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", - "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "packages/networks/doge-esplora/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "packages/networks/doge-esplora/node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "packages/networks/doge-esplora/node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "packages/networks/doge-esplora/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "packages/networks/doge-esplora/node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "engines": { - "node": ">=16.17.0" - } - }, - "packages/networks/doge-esplora/node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.1" - } - }, - "packages/networks/doge-esplora/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "packages/networks/doge-esplora/node_modules/p-limit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", - "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "packages/networks/doge-esplora/node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "packages/networks/doge-esplora/node_modules/prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", - "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", - "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "packages/networks/doge-esplora/node_modules/rollup": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.31.0.tgz", - "integrity": "sha512-9cCE8P4rZLx9+PjoyqHLs31V9a9Vpvfo4qNcs6JCiGWYhw2gijSetFbH6SSy1whnkgcefnUwr8sad7tgqsGvnw==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.31.0", - "@rollup/rollup-android-arm64": "4.31.0", - "@rollup/rollup-darwin-arm64": "4.31.0", - "@rollup/rollup-darwin-x64": "4.31.0", - "@rollup/rollup-freebsd-arm64": "4.31.0", - "@rollup/rollup-freebsd-x64": "4.31.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.31.0", - "@rollup/rollup-linux-arm-musleabihf": "4.31.0", - "@rollup/rollup-linux-arm64-gnu": "4.31.0", - "@rollup/rollup-linux-arm64-musl": "4.31.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.31.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.31.0", - "@rollup/rollup-linux-riscv64-gnu": "4.31.0", - "@rollup/rollup-linux-s390x-gnu": "4.31.0", - "@rollup/rollup-linux-x64-gnu": "4.31.0", - "@rollup/rollup-linux-x64-musl": "4.31.0", - "@rollup/rollup-win32-arm64-msvc": "4.31.0", - "@rollup/rollup-win32-ia32-msvc": "4.31.0", - "@rollup/rollup-win32-x64-msvc": "4.31.0", - "fsevents": "~2.3.2" + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "packages/networks/doge-esplora/node_modules/semver": { @@ -17715,72 +17001,6 @@ "node": ">=10" } }, - "packages/networks/doge-esplora/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "packages/networks/doge-esplora/node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "packages/networks/doge-esplora/node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "packages/networks/doge-esplora/node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "packages/networks/doge-esplora/node_modules/tinypool": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", - "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "packages/networks/doge-esplora/node_modules/tinyspy": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", - "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, "packages/networks/doge-esplora/node_modules/typescript": { "version": "5.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", @@ -17794,223 +17014,6 @@ "node": ">=14.17" } }, - "packages/networks/doge-esplora/node_modules/vite-node": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", - "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==", - "dev": true, - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.4", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "vite": "^5.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "packages/networks/doge-esplora/node_modules/vite-node/node_modules/vite": { - "version": "5.4.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", - "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", - "dev": true, - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "packages/networks/doge-esplora/node_modules/vitest": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz", - "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==", - "dev": true, - "dependencies": { - "@vitest/expect": "1.6.0", - "@vitest/runner": "1.6.0", - "@vitest/snapshot": "1.6.0", - "@vitest/spy": "1.6.0", - "@vitest/utils": "1.6.0", - "acorn-walk": "^8.3.2", - "chai": "^4.3.10", - "debug": "^4.3.4", - "execa": "^8.0.1", - "local-pkg": "^0.5.0", - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "std-env": "^3.5.0", - "strip-literal": "^2.0.0", - "tinybench": "^2.5.1", - "tinypool": "^0.8.3", - "vite": "^5.0.0", - "vite-node": "1.6.0", - "why-is-node-running": "^2.2.2" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "1.6.0", - "@vitest/ui": "1.6.0", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "packages/networks/doge-esplora/node_modules/vitest/node_modules/vite": { - "version": "5.4.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", - "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", - "dev": true, - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "packages/networks/doge-esplora/node_modules/yocto-queue": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", - "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "packages/networks/ergo-explorer": { "name": "@rosen-chains/ergo-explorer-network", "version": "9.0.8", diff --git a/packages/chains/doge/package.json b/packages/chains/doge/package.json index 28994a4d..15288de7 100644 --- a/packages/chains/doge/package.json +++ b/packages/chains/doge/package.json @@ -4,7 +4,7 @@ "description": "this project contains doge chain for Rosen-bridge", "repository": "https://github.com/rosen-bridge/rosen-chains", "license": "GPL-3.0", - "author": "Mehran", + "author": "Rosen Team", "type": "module", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts b/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts index 5f705dcc..41bc8c45 100644 --- a/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts +++ b/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts @@ -67,7 +67,9 @@ class DogeEsploraNetwork extends AbstractDogeNetwork { * @param transactionId the transaction id (only supports real signed tx id) * @returns the transaction confirmation */ - getTxConfirmationSigned = async (transactionId: string): Promise => { + protected getTxConfirmationSigned = async ( + transactionId: string + ): Promise => { const currentHeight = await this.getHeight(); let txHeight = -1; try { @@ -108,8 +110,10 @@ class DogeEsploraNetwork extends AbstractDogeNetwork { try { const realTx = await this.getSavedTransactionById(transactionId); if (realTx) { - const firstInputId = `${realTx?.inputs[0].txId}.${realTx?.inputs[0].index}`; - const spentTx = await this.getSpentTransactionByInputId(firstInputId); + const spentTx = await this.getSpentTransactionByInputId( + realTx?.inputs[0].index, + realTx?.inputs[0].txId + ); if (spentTx) { const sameInputs = realTx.inputs.every( (input, i) => @@ -126,8 +130,10 @@ class DogeEsploraNetwork extends AbstractDogeNetwork { } } } - } catch (e) { - this.logger.debug(`tx [${transactionId}] is not found in DB`); + } catch (e: any) { + this.logger.debug( + `error while trying to see if the real transactionId differs from the input, will fallback to getTxConfirmationSigned: ${e.message}` + ); } return await this.getTxConfirmationSigned(realTxId); @@ -482,13 +488,23 @@ class DogeEsploraNetwork extends AbstractDogeNetwork { getTransactionHex = async (txId: string): Promise => { return this.client .get(`/api/tx/${txId}/hex`) - .then((res) => res.data); + .then((res) => res.data) + .catch((e) => { + const baseError = `Failed to get transaction [${txId}] hex from Esplora: `; + if (e.response) { + throw new FailedError(baseError + e.response.data); + } else if (e.request) { + throw new NetworkError(baseError + e.message); + } else { + throw new UnexpectedApiError(baseError + e.message); + } + }); }; - getSpentTransactionByInputId = async ( - boxId: string + protected getSpentTransactionByInputId = async ( + index: number, + txId: string ): Promise => { - const [txId, index] = boxId.split('.'); const box = ( await this.client.get( `/api/tx/${txId}/outspends/${index}` diff --git a/packages/networks/doge-esplora/package.json b/packages/networks/doge-esplora/package.json index e6b2699f..3a81b5bd 100644 --- a/packages/networks/doge-esplora/package.json +++ b/packages/networks/doge-esplora/package.json @@ -4,7 +4,7 @@ "description": "A package to be used as network api provider for @rosen-chains/doge package", "repository": "https://github.com/rosen-bridge/rosen-chains", "license": "GPL-3.0", - "author": "Mehran", + "author": "Rosen Team", "type": "module", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -21,13 +21,13 @@ "@types/node": "^20.11.9", "@typescript-eslint/eslint-plugin": "^6.19.1", "@typescript-eslint/parser": "^6.19.1", - "@vitest/coverage-istanbul": "^1.2.2", + "@vitest/coverage-istanbul": "^2.1.4", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "extensionless": "^1.9.6", "prettier": "^3.2.4", "typescript": "^5.3.3", - "vitest": "^1.2.2" + "vitest": "^2.1.4" }, "engines": { "node": ">=20.11.0" @@ -37,7 +37,6 @@ "@rosen-bridge/json-bigint": "^0.1.0", "@rosen-chains/abstract-chain": "^11.0.3", "@rosen-chains/doge": "^0.1.0", - "@rosen-chains/bitcoin-esplora": "^4.0.8", "axios": "^1.6.7", "bitcoinjs-lib": "^6.1.5" } diff --git a/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts b/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts index 59ec7e0d..eda65b9c 100644 --- a/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts +++ b/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts @@ -48,7 +48,7 @@ describe('DogeEsploraNetwork', () => { * @expected * - it should be mocked height minus mocked tx height */ - it('should return tx confirmation successfully', async () => { + it('should fetch confirmation using txId successfully', async () => { mockAxiosGet(testData.blockHeight); mockAxiosGet(testData.txResponse); @@ -104,7 +104,17 @@ describe('DogeEsploraNetwork', () => { expect(result).toEqual(-1); }); - it('should call getTxConfirmationSigned with the correct tx id', async () => { + /** + * @target `DogeEsploraNetwork.getTxConfirmation` should fetch confirmation using unsigned hash successfully + * @dependencies + * @scenario + * - create a new instance of DogeEsploraNetwork with a custom getSavedTransactionById + * - run test + * - check returned value + * @expected + * - it should fetch confirmation using unsigned hash successfully + */ + it('should fetch confirmation using unsigned hash successfully', async () => { // Create a new instance of DogeEsploraNetwork with a custom getSavedTransactionById const customNetwork = new DogeEsploraNetwork( 'esplora-url', @@ -117,13 +127,13 @@ describe('DogeEsploraNetwork', () => { ); const getTxConfirmationSignedSpy = vi.spyOn( - customNetwork, + customNetwork as any, 'getTxConfirmationSigned' ); // Mock getSpentTransactionByInputId to return a transaction when called with the correct input const getSpentTransactionByInputIdSpy = vi - .spyOn(customNetwork, 'getSpentTransactionByInputId') + .spyOn(customNetwork as any, 'getSpentTransactionByInputId') .mockResolvedValue(testData.dogeTx); mockAxiosGet(testData.blockHeight); @@ -134,13 +144,11 @@ describe('DogeEsploraNetwork', () => { ); expect(getSpentTransactionByInputIdSpy).toHaveBeenCalledWith( - `${testData.dogeTx.inputs[0].txId}.${testData.dogeTx.inputs[0].index}` + testData.dogeTx.inputs[0].index, + testData.dogeTx.inputs[0].txId ); expect(getTxConfirmationSignedSpy).toHaveBeenCalledWith(testData.txId); expect(result).toEqual(testData.txConfirmation); - - getTxConfirmationSignedSpy.mockRestore(); - getSpentTransactionByInputIdSpy.mockRestore(); }); }); @@ -331,6 +339,28 @@ describe('DogeEsploraNetwork', () => { expect(result).toEqual([]); }); + + /** + * @target `DogeEsploraNetwork.getAddressBoxes` should return sorted address utxos + * @dependencies + * @scenario + * - mock axios to return unsorted address utxo info + * - run test + * - check returned value is sorted by txId and index + * @expected + * - it should return utxos sorted first by txId and then by index + */ + it('should return sorted address utxos', async () => { + mockAxiosGet(testData.unsortedAddressUtxoResponse); + + const result = await network.getAddressBoxes( + testData.lockAddress, + 0, + 100 + ); + + expect(result).toEqual(testData.sortedAddressUtxos); + }); }); describe('isBoxUnspentAndValid', () => { @@ -542,8 +572,9 @@ describe('DogeEsploraNetwork', () => { .spyOn(network, 'getTransaction') .mockResolvedValue(testData.dogeTx); - const result = await network.getSpentTransactionByInputId( - testData.spentBoxId + const result = await (network as any).getSpentTransactionByInputId( + testData.spentIndex, + testData.spentTxId ); expect(result).toEqual(testData.dogeTx); @@ -567,11 +598,59 @@ describe('DogeEsploraNetwork', () => { it('should return undefined when box is unspent', async () => { mockAxiosGet(testData.unspentResult); - const result = await network.getSpentTransactionByInputId( - testData.unspentBoxId + const result = await (network as any).getSpentTransactionByInputId( + testData.unspentIndex, + testData.unspentTxId ); expect(result).toBeUndefined(); }); }); + + describe('getTransactionHex', () => { + /** + * @target `DogeEsploraNetwork.getTransactionHex` should return transaction hex successfully + * @dependencies + * @scenario + * - mock axios to return tx hex + * - run test + * - check returned value + * @expected + * - it should return the mocked tx hex + */ + it('should return transaction hex successfully', async () => { + const mockTxHex = + '020000000134292f961bb726fad6f54d904fe9177931493e46a8b8b99de6b1e338dee29785020000006a47304402207e4cd2745243257f0749b4a41425c2075dfb199f47072bfbf7db14b02677a8ae02204682c5159737314f7c4ba0f7112876497171a7cee48dddf667dccd59cf8ae1280121022b9ed0a9139042921decc62603a4a07357b444da2e0bd6a96c27155117913037ffffffff0300000000000000006a33000000000005f5e10000000000009896802103e5bedab3f782ef17a73e9bdc41ee0e18c3ab477400f35bcf7caa54171db7ff3600ca9a3b0000000017a914d4c141068ab3a242aed5081a27ac3f10ad99ac988788a4645600000000976a914872b67c8270a9eaf5c2abf632af3dea989d2e37188ac00000000'; + mockAxiosGet(mockTxHex); + + const result = await network.getTransactionHex(testData.txId); + + expect(result).toEqual(mockTxHex); + }); + + /** + * @target `DogeEsploraNetwork.getTransactionHex` should throw error when + * request fails + * @dependencies + * @scenario + * - mock axios to throw error + * - run test and expect exception thrown + * @expected + * - it should throw FailedError with appropriate message + */ + it('should throw error when request fails', async () => { + mockAxiosGetToThrow({ + response: { + status: 404, + data: 'Transaction not found', + }, + }); + + await expect(async () => { + await network.getTransactionHex(testData.txId); + }).rejects.toThrow( + `Failed to get transaction [${testData.txId}] hex from Esplora: Transaction not found` + ); + }); + }); }); diff --git a/packages/networks/doge-esplora/tests/testData.ts b/packages/networks/doge-esplora/tests/testData.ts index 8ddc5f24..04f3e832 100644 --- a/packages/networks/doge-esplora/tests/testData.ts +++ b/packages/networks/doge-esplora/tests/testData.ts @@ -286,8 +286,9 @@ export const utxo = { value: 0n, }; -export const spentBoxId = - 'd3d2b2dc24639e8d698071a49921b7b378c0a56cffcc0db3b42d5937a67389ab.1'; +export const spentTxId = + '79e657a92547e0a67ad4b0f04777ddb617745e6064b1d9393583619da59ae4c6'; +export const spentIndex = 1; export const spentResult = { spent: true, txid: '79e657a92547e0a67ad4b0f04777ddb617745e6064b1d9393583619da59ae4c6', @@ -305,6 +306,9 @@ export const unsignedTxId = '2e21903ce31a5b77e9a0f56255a92955cb018504e0647b99211833ae721ae15f'; export const unspentBoxId = 'd3d2b2dc24639e8d698071a49921b7b378c0a56cffcc0db3b42d5937a67389ab.0'; +export const unspentTxId = + 'd3d2b2dc24639e8d698071a49921b7b378c0a56cffcc0db3b42d5937a67389ab'; +export const unspentIndex = 0; export const unspentResult = { spent: false, }; @@ -337,3 +341,60 @@ export const feeEstimatesResponse = { '25': 1002.715, }; export const targetFeeEstimation = 3011.257; + +export const unsortedAddressUtxoResponse = [ + { + txid: 'cc9c558b21c86f955e07af14b73e82939731ca6ffd0b28c5b72436d76cee881f', + vout: 2, + status: { + confirmed: true, + block_height: 5427984, + block_hash: + 'fb7a521ddd47397ba421276bd298828527d7f1803eba7e530c1e336fef0f8c0d', + block_time: 1729471417, + }, + value: 800000000, + }, + { + txid: 'bc9c558b21c86f955e07af14b73e82939731ca6ffd0b28c5b72436d76cee881f', + vout: 1, + status: { + confirmed: true, + block_height: 5427984, + block_hash: + 'fb7a521ddd47397ba421276bd298828527d7f1803eba7e530c1e336fef0f8c0d', + block_time: 1729471417, + }, + value: 900000000, + }, + { + txid: 'cc9c558b21c86f955e07af14b73e82939731ca6ffd0b28c5b72436d76cee881f', + vout: 0, + status: { + confirmed: true, + block_height: 5427984, + block_hash: + 'fb7a521ddd47397ba421276bd298828527d7f1803eba7e530c1e336fef0f8c0d', + block_time: 1729471417, + }, + value: 700000000, + }, +]; + +export const sortedAddressUtxos = [ + { + txId: 'bc9c558b21c86f955e07af14b73e82939731ca6ffd0b28c5b72436d76cee881f', + index: 1, + value: 900000000n, + }, + { + txId: 'cc9c558b21c86f955e07af14b73e82939731ca6ffd0b28c5b72436d76cee881f', + index: 0, + value: 700000000n, + }, + { + txId: 'cc9c558b21c86f955e07af14b73e82939731ca6ffd0b28c5b72436d76cee881f', + index: 2, + value: 800000000n, + }, +]; diff --git a/packages/networks/doge-esplora/vitest.config.ts b/packages/networks/doge-esplora/vitest.config.ts index b4289be9..661cb841 100644 --- a/packages/networks/doge-esplora/vitest.config.ts +++ b/packages/networks/doge-esplora/vitest.config.ts @@ -10,8 +10,8 @@ export default defineConfig({ }, passWithNoTests: true, poolOptions: { - threads: { - singleThread: true, + forks: { + singleFork: true, }, }, }, From a99910e767321237f2b932808233f7a5a49e5df8 Mon Sep 17 00:00:00 2001 From: Mehran Aghabozorgi Date: Sat, 1 Feb 2025 13:04:44 -0800 Subject: [PATCH 8/9] Delete gitkeep --- packages/networks/doge-esplora/tests/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 packages/networks/doge-esplora/tests/.gitkeep diff --git a/packages/networks/doge-esplora/tests/.gitkeep b/packages/networks/doge-esplora/tests/.gitkeep deleted file mode 100644 index e69de29b..00000000 From 726f23f7338ad1ac028d4a302449ebc23f9a3b73 Mon Sep 17 00:00:00 2001 From: Mehran Aghabozorgi Date: Tue, 4 Feb 2025 17:37:38 -0800 Subject: [PATCH 9/9] Fix minor issues --- .../doge-esplora/lib/DogeEsploraNetwork.ts | 15 ++++++++++----- .../doge-esplora/tests/DogeEsploraNetwork.spec.ts | 6 ++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts b/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts index 41bc8c45..4f8b83a3 100644 --- a/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts +++ b/packages/networks/doge-esplora/lib/DogeEsploraNetwork.ts @@ -111,8 +111,8 @@ class DogeEsploraNetwork extends AbstractDogeNetwork { const realTx = await this.getSavedTransactionById(transactionId); if (realTx) { const spentTx = await this.getSpentTransactionByInputId( - realTx?.inputs[0].index, - realTx?.inputs[0].txId + realTx.inputs[0].index, + realTx.inputs[0].txId ); if (spentTx) { const sameInputs = realTx.inputs.every( @@ -131,9 +131,14 @@ class DogeEsploraNetwork extends AbstractDogeNetwork { } } } catch (e: any) { - this.logger.debug( - `error while trying to see if the real transactionId differs from the input, will fallback to getTxConfirmationSigned: ${e.message}` - ); + const baseError = `Failed to get confirmation for tx [${transactionId}] which was found in the database: `; + if (e.response) { + throw new FailedError(baseError + e.response.data); + } else if (e.request) { + throw new NetworkError(baseError + e.message); + } else { + throw new UnexpectedApiError(baseError + e.message); + } } return await this.getTxConfirmationSigned(realTxId); diff --git a/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts b/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts index eda65b9c..8ca38720 100644 --- a/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts +++ b/packages/networks/doge-esplora/tests/DogeEsploraNetwork.spec.ts @@ -636,7 +636,7 @@ describe('DogeEsploraNetwork', () => { * - mock axios to throw error * - run test and expect exception thrown * @expected - * - it should throw FailedError with appropriate message + * - it should throw FailedError */ it('should throw error when request fails', async () => { mockAxiosGetToThrow({ @@ -648,9 +648,7 @@ describe('DogeEsploraNetwork', () => { await expect(async () => { await network.getTransactionHex(testData.txId); - }).rejects.toThrow( - `Failed to get transaction [${testData.txId}] hex from Esplora: Transaction not found` - ); + }).rejects.toThrow(FailedError); }); }); });