New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@bitcoinerlab/discovery

Package Overview
Dependencies
Maintainers
0
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@bitcoinerlab/discovery - npm Package Compare versions

Comparing version 1.2.2 to 1.2.3

13

dist/deriveData.d.ts
/// <reference types="node" />
import memoizee from 'memoizee';
import { NetworkId, Descriptor, Account, DescriptorIndex, DiscoveryData, TxStatus, DescriptorData, TxAttribution, TxId, TxData } from './types';
import { NetworkId, Descriptor, Account, DescriptorIndex, DiscoveryData, TxStatus, DescriptorData, TxAttribution, TxId, TxData, TxWithOrder, TxoMap } from './types';
import { Transaction, Network } from 'bitcoinjs-lib';

@@ -12,2 +12,3 @@ export declare function canonicalize(descriptorOrDescriptors: Array<Descriptor> | Descriptor, network: Network): string | string[];

deriveUtxosAndBalanceByOutput: (networkId: NetworkId, txMap: Record<TxId, TxData>, descriptorMap: Record<Descriptor, DescriptorData>, descriptor: Descriptor, index: DescriptorIndex, txStatus: TxStatus) => {
txoMap: TxoMap;
stxos: string[];

@@ -20,2 +21,3 @@ utxos: string[];

utxos: string[];
txoMap: TxoMap;
balance: number;

@@ -45,3 +47,10 @@ };

deriveHistory: (withAttributions: boolean, networkId: NetworkId, txMap: Record<TxId, TxData>, descriptorMap: Record<Descriptor, DescriptorData>, descriptorOrDescriptors: Array<Descriptor> | Descriptor, txStatus: TxStatus) => TxData[] | TxAttribution[];
transactionFromHex: typeof Transaction.fromHex & memoizee.Memoized<typeof Transaction.fromHex>;
transactionFromHex: ((txHex: string) => {
tx: Transaction;
txId: string;
}) & memoizee.Memoized<(txHex: string) => {
tx: Transaction;
txId: string;
}>;
compareTxOrder: <TA extends TxWithOrder, TB extends TxWithOrder>(txWithOrderA: TA, txWithOrderB: TB) => number;
};

179

dist/deriveData.js

@@ -71,2 +71,59 @@ "use strict";

function deriveDataFactory({ descriptorsCacheSize = 0, outputsPerDescriptorCacheSize = 0 }) {
/**
* Compares two transactions based on their blockHeight and input dependencies.
* Can be used as callback in Array.sort function to sort from old to new.
*
* @param txWithOrderA - The first transaction data to compare.
* @param txWithOrderB - The second transaction data to compare.
*
*
* txWithOrderA and txWithOrderB should contain the `blockHeight` (use 0 if
* in the mempool) and either `tx` (`Transaction` type) or `txHex` (the
* hexadecimal representation of the transaction)
*
* @returns < 0 if txWithOrderA is older than txWithOrderB, > 01 if txWithOrderA is newer than txWithOrderB, and 0 if undecided.
*/
function compareTxOrder(txWithOrderA, txWithOrderB) {
// txWithOrderA is in mempool and txWithOrderB no, so txWithOrderA is newer
if (txWithOrderA.blockHeight === 0 && txWithOrderB.blockHeight !== 0)
return 1;
// txWithOrderB is in mempool and txWithOrderA no, so txWithOrderB is newer
if (txWithOrderB.blockHeight === 0 && txWithOrderA.blockHeight !== 0)
return -1;
// If blockHeight is different and none are in the mempool, sort by blockHeight
if (txWithOrderA.blockHeight !== txWithOrderB.blockHeight)
return txWithOrderA.blockHeight - txWithOrderB.blockHeight;
// If blockHeight is the same, check input dependencies
let txA = txWithOrderA.tx;
let txIdA;
if (!txA) {
if (!txWithOrderA.txHex)
throw new Error('Pass tx or txHex');
const { tx, txId } = transactionFromHex(txWithOrderA.txHex);
txA = tx;
txIdA = txId;
}
let txB = txWithOrderB.tx;
let txIdB;
if (!txB) {
if (!txWithOrderB.txHex)
throw new Error('Pass tx or txHex');
const { tx, txId } = transactionFromHex(txWithOrderB.txHex);
txB = tx;
txIdB = txId;
}
//getHash is slow, try to avoid it if we can use a cached getId:
const txHashB = txIdB ? hex2RevBuf(txIdB) : txB.getHash();
// txA is newer because it uses an input from txB
for (const Ainput of txA.ins)
if (Ainput.hash.equals(txHashB))
return 1;
//getHash is slow, try to avoid it if we can use a cached getId:
const txHashA = txIdA ? hex2RevBuf(txIdA) : txA.getHash();
// txB is newer because it uses an input from txA
for (const Binput of txB.ins)
if (Binput.hash.equals(txHashA))
return -1;
return 0; // Cannot decide, keep the original order
}
const deriveScriptPubKeyFactory = (0, memoizee_1.default)((networkId) => (0, memoizee_1.default)((descriptor) => (0, memoizee_1.default)((index) => {

@@ -85,13 +142,14 @@ const network = (0, networks_1.getNetwork)(networkId);

const deriveScriptPubKey = (networkId, descriptor, index) => deriveScriptPubKeyFactory(networkId)(descriptor)(index);
const coreDeriveTxosByOutput = (networkId, descriptor, index, txDataArray, txStatus) => {
const coreDeriveTxosByOutput = (networkId, descriptor, index, txWithOrderArray, txStatus) => {
const scriptPubKey = deriveScriptPubKey(networkId, descriptor, index);
const txoMap = {};
//All prev outputs (spent or unspent) sent to this output descriptor:
const allPrevOutputs = [];
//all outputs in txDataArray which have been spent.
//all outputs in txWithOrderArray which have been spent.
//May be outputs NOT snt to thil output descriptor:
const spendingTxIdByOutput = {}; //Means: Utxo was spent in txId
//Note that txDataArray cannot be assumed to be in correct order. See:
//Note that txWithOrderArray cannot be assumed to be in correct order if
//in the same block and if one does not depend on the other. See:
//https://github.com/Blockstream/esplora/issues/165#issuecomment-1584471718
//TODO: but we should guarantee same order always so use txId as second order criteria? - probably not needed?
for (const txData of txDataArray) {
for (const txData of txWithOrderArray) {
if (txStatus === types_1.TxStatus.ALL ||

@@ -103,10 +161,5 @@ (txStatus === types_1.TxStatus.IRREVERSIBLE && txData.irreversible) ||

throw new Error(`txHex not yet retrieved for an element of ${descriptor}, ${index}`);
const tx = transactionFromHex(txHex);
const txId = tx.getId();
for (let vin = 0; vin < tx.ins.length; vin++) {
const input = tx.ins[vin];
if (!input)
throw new Error(`Error: invalid input for ${txId}:${vin}`);
//Note we create a new Buffer since reverse() mutates the Buffer
const prevTxId = Buffer.from(input.hash).reverse().toString('hex');
const { tx, txId } = transactionFromHex(txHex);
for (const [vin, input] of tx.ins.entries()) {
const prevTxId = buf2RevHex(input.hash);
const prevVout = input.index;

@@ -116,9 +169,7 @@ const prevUtxo = `${prevTxId}:${prevVout}`;

}
for (let vout = 0; vout < tx.outs.length; vout++) {
const outputScript = tx.outs[vout]?.script;
if (!outputScript)
throw new Error(`Error: invalid output script for ${txId}:${vout}`);
if (outputScript.equals(scriptPubKey)) {
const outputKey = `${txId}:${vout}`;
allPrevOutputs.push(outputKey);
for (const [vout, output] of tx.outs.entries()) {
if (output.script.equals(scriptPubKey)) {
const txo = `${txId}:${vout}`;
allPrevOutputs.push(txo);
txoMap[txo] = `${descriptor}~${index}`;
}

@@ -133,3 +184,3 @@ }

.map(txo => `${txo}:${spendingTxIdByOutput[txo]}`);
return { utxos, stxos };
return { utxos, stxos, txoMap };
};

@@ -139,4 +190,4 @@ const deriveUtxosAndBalanceByOutputFactory = (0, memoizee_1.default)((networkId) => (0, memoizee_1.default)((txStatus) => (0, memoizee_1.default)((descriptor) => (0, memoizee_1.default)((index) => {

// coreDeriveTxosByOutput shares all params wrt the parent
// function except for additional param txDataArray.
// As soon as txDataArray in coreDeriveTxosByOutput changes,
// function except for additional param txWithOrderArray.
// As soon as txWithOrderArray in coreDeriveTxosByOutput changes,
// it will resets its memory.

@@ -148,7 +199,10 @@ const deriveTxosByOutput = (0, memoizee_1.default)(coreDeriveTxosByOutput, {

let lastStxos = null;
let lastTxoMap = null;
let lastBalance;
return (0, memoizee_1.default)((txMap, descriptorMap) => {
const txDataArray = deriveTxDataArray(txMap, descriptorMap, descriptor, index);
let { utxos, stxos } = deriveTxosByOutput(networkId, descriptor, index, txDataArray, txStatus);
const txWithOrderArray = deriveTxDataArray(txMap, descriptorMap, descriptor, index);
let { utxos, stxos, txoMap } = deriveTxosByOutput(networkId, descriptor, index, txWithOrderArray, txStatus);
let balance;
if (lastTxoMap && (0, shallow_equal_1.shallowEqualObjects)(lastTxoMap, txoMap))
txoMap = lastTxoMap;
if (lastStxos && (0, shallow_equal_1.shallowEqualArrays)(lastStxos, stxos))

@@ -162,6 +216,7 @@ stxos = lastStxos;

balance = coreDeriveUtxosBalance(txMap, utxos);
lastTxoMap = txoMap;
lastUtxos = utxos;
lastStxos = stxos;
lastBalance = balance;
return { stxos, utxos, balance };
return { txoMap, stxos, utxos, balance };
}, { max: 1 });

@@ -182,4 +237,4 @@ }, { primitive: true, max: outputsPerDescriptorCacheSize }), { primitive: true, max: descriptorsCacheSize }), { primitive: true } //unbounded cache (no max setting) since Search Space is small

const txIds = range[index]?.txIds || [];
const txDataArray = coreDeriveTxDataArray(txIds, txMap);
return txDataArray;
const txWithOrderArray = coreDeriveTxDataArray(txIds, txMap);
return txWithOrderArray;
});

@@ -206,6 +261,5 @@ }, { primitive: true, max: outputsPerDescriptorCacheSize }), { primitive: true, max: descriptorsCacheSize });

throw new Error(`Error: txHex not found`);
const tx = transactionFromHex(txHex);
const txId = tx.getId();
const { tx, txId } = transactionFromHex(txHex);
const ins = tx.ins.map(input => {
const prevTxId = Buffer.from(input.hash).reverse().toString('hex');
const prevTxId = buf2RevHex(input.hash);
const prevVout = input.index;

@@ -220,3 +274,3 @@ const prevTxo = `${prevTxId}:${prevVout}`;

throw new Error(`txHex not set for ${prevTxId}`);
const prevTx = transactionFromHex(prevTxHex);
const { tx: prevTx } = transactionFromHex(prevTxHex);
const value = prevTx.outs[prevVout]?.value;

@@ -288,6 +342,7 @@ if (value === undefined)

txData.blockHeight !== 0));
const sortedHistory = txHistory.sort(compareTxOrder);
if (withAttributions)
return deriveAttributions(txHistory, networkId, txMap, descriptorMap, descriptor, txStatus);
return deriveAttributions(sortedHistory, networkId, txMap, descriptorMap, descriptor, txStatus);
else
return txHistory;
return sortedHistory;
});

@@ -327,16 +382,6 @@ }, {

//Note that we cannot guarantee to keep correct order to txs
//that belong to the same blockHeight
//TODO: but we should guarantee same order always so use txId as second order criteria? - probably not needed?
const sortedHistory = dedupedHistory.sort((txDataA, txDataB) => {
if (txDataA.blockHeight === 0 && txDataB.blockHeight === 0) {
return 0; // Both are in mempool, keep their relative order unchanged
}
if (txDataA.blockHeight === 0) {
return 1; // txDataA is in mempool, so it should come after txDataB
}
if (txDataB.blockHeight === 0) {
return -1; // txDataB is in mempool, so it should come after txDataA
}
return txDataA.blockHeight - txDataB.blockHeight; // Regular ascending order sort
});
//that belong to the same blockHeight except when one of the txs depends
//on the other.
//See https://github.com/Blockstream/esplora/issues/165#issuecomment-1584471718
const sortedHistory = dedupedHistory.sort(compareTxOrder);
if (withAttributions)

@@ -357,2 +402,3 @@ return deriveAttributions(sortedHistory, networkId, txMap, descriptorMap, descriptorOrDescriptors, txStatus);

const stxos = [];
const txoMap = {};
const descriptorArray = Array.isArray(descriptorOrDescriptors)

@@ -367,5 +413,6 @@ ? descriptorOrDescriptors

const index = indexStr === 'non-ranged' ? indexStr : Number(indexStr);
const { utxos: utxosByO, stxos: stxosByO } = deriveUtxosAndBalanceByOutput(networkId, txMap, descriptorMap, descriptor, index, txStatus);
const { utxos: utxosByO, stxos: stxosByO, txoMap: txoMapByO } = deriveUtxosAndBalanceByOutput(networkId, txMap, descriptorMap, descriptor, index, txStatus);
utxos.push(...utxosByO);
stxos.push(...stxosByO);
Object.assign(txoMap, txoMapByO);
});

@@ -377,3 +424,3 @@ }

const dedupedStxos = [...new Set(stxos)];
return { utxos: dedupedUtxos, stxos: dedupedStxos };
return { utxos: dedupedUtxos, stxos: dedupedStxos, txoMap };
};

@@ -385,2 +432,3 @@ //unbound memoizee wrt TxStatus is fine since it has a small Search Space

const deriveUtxosAndBalanceFactory = (0, memoizee_1.default)((networkId) => (0, memoizee_1.default)((txStatus) => (0, memoizee_1.default)((descriptorOrDescriptors) => {
let lastTxoMap = null;
let lastUtxos = null;

@@ -390,4 +438,6 @@ let lastStxos = null;

return (0, memoizee_1.default)((txMap, descriptorMap) => {
let { utxos, stxos } = coreDeriveTxos(networkId, descriptorMap, txMap, descriptorOrDescriptors, txStatus);
let { utxos, stxos, txoMap } = coreDeriveTxos(networkId, descriptorMap, txMap, descriptorOrDescriptors, txStatus);
let balance;
if (lastTxoMap && (0, shallow_equal_1.shallowEqualObjects)(lastTxoMap, txoMap))
txoMap = lastTxoMap;
if (lastStxos && (0, shallow_equal_1.shallowEqualArrays)(lastStxos, stxos))

@@ -401,6 +451,7 @@ stxos = lastStxos;

balance = coreDeriveUtxosBalance(txMap, utxos);
lastTxoMap = txoMap;
lastUtxos = utxos;
lastStxos = stxos;
lastBalance = balance;
return { stxos, utxos, balance };
return { stxos, utxos, txoMap, balance };
}, { max: 1 });

@@ -412,6 +463,23 @@ }, { primitive: true, max: descriptorsCacheSize } //potentially ininite search space. limit to 100 descriptorOrDescriptors per txStatus combination

const deriveUtxosAndBalance = (networkId, txMap, descriptorMap, descriptorOrDescriptors, txStatus) => deriveUtxosAndBalanceFactory(networkId)(txStatus)(descriptorOrDescriptors)(txMap, descriptorMap);
const transactionFromHex = (0, memoizee_1.default)(bitcoinjs_lib_1.Transaction.fromHex, {
const transactionFromHex = (0, memoizee_1.default)((txHex) => {
const tx = bitcoinjs_lib_1.Transaction.fromHex(txHex);
const txId = tx.getId();
return { tx, txId };
}, {
primitive: true,
max: 1000
});
const hex2RevBuf = (0, memoizee_1.default)((idOrHash) => {
return Buffer.from(idOrHash).reverse();
}, {
primitive: true,
max: 1000
});
const buf2RevHex = (0, memoizee_1.default)((idOrHash) => {
//Note we create a new Buffer since reverse() mutates the Buffer
return Buffer.from(idOrHash).reverse().toString('hex');
}, {
primitive: true,
max: 1000
});
const coreDeriveUtxosBalance = (txMap, utxos) => {

@@ -435,3 +503,3 @@ let balance = 0;

throw new Error(`txHex not yet retrieved for ${txId}`);
const tx = transactionFromHex(txHex);
const { tx } = transactionFromHex(txHex);
const output = tx.outs[vout];

@@ -536,5 +604,6 @@ if (!output)

deriveHistory,
transactionFromHex
transactionFromHex,
compareTxOrder
};
}
exports.deriveDataFactory = deriveDataFactory;

@@ -6,3 +6,3 @@ /// <reference types="node" />

import type { Explorer } from '@bitcoinerlab/explorer';
import { OutputCriteria, NetworkId, TxId, TxData, Descriptor, Account, DescriptorIndex, DiscoveryData, Utxo, TxStatus, Stxo, TxHex, TxAttribution } from './types';
import { OutputCriteria, NetworkId, TxId, TxData, Descriptor, Account, DescriptorIndex, DiscoveryData, Utxo, TxStatus, Stxo, TxHex, TxAttribution, TxWithOrder, TxoMap } from './types';
/**

@@ -369,2 +369,6 @@ * Creates and returns a Discovery class for discovering funds in a Bitcoin network

* eventually spent as stxos: Array<Stxo>
* Finally, it returns `txoMap`. `txoMap` maps all the txos (unspent or spent
* outputs) with their corresponding `indexedDescriptor: IndexedDescriptor`
* (see {@link IndexedDescriptor IndexedDescriptor})
*
*/

@@ -374,2 +378,3 @@ getUtxosAndBalance({ descriptor, index, descriptors, txStatus }: OutputCriteria): {

stxos: Array<Stxo>;
txoMap: TxoMap;
balance: number;

@@ -474,4 +479,7 @@ };

* object given the transaction
* ID (TxId) or a Unspent Transaction Output (Utxo). The transaction data is obtained by first getting
* the transaction hexadecimal representation using getTxHex() method.
* ID (TxId) or a Unspent Transaction Output (Utxo) or the hexadecimal
* representation of the transaction (it will then use memoization).
* The transaction data is obtained by first getting
* the transaction hexadecimal representation using getTxHex() method
* (unless the txHex was passed).
*

@@ -486,3 +494,3 @@ * Use this method for quick access to the Transaction object, which avoids the

*/
getTransaction({ txId, utxo }: {
getTransaction({ txId, txHex, utxo }: {
/**

@@ -493,2 +501,6 @@ * The transaction ID.

/**
* The transaction txHex.
*/
txHex?: TxId;
/**
* The UTXO.

@@ -499,2 +511,17 @@ */

/**
* Compares two transactions based on their blockHeight and input dependencies.
* Can be used as callback in Array.sort function to sort from old to new.
*
* @param txWithOrderA - The first transaction data to compare.
* @param txWithOrderB - The second transaction data to compare.
*
* txWithOrderA and txWithOrderB should contain the `blockHeight` (use 0 if
* in the mempool) and either `tx` (`Transaction` type) or `txHex` (the
* hexadecimal representation of the transaction)
*
* @returns < 0 if txWithOrderA is older than txWithOrderB, > 0 if
* txWithOrderA is newer than txWithOrderB, and 0 if undecided.
*/
compareTxOrder<TA extends TxWithOrder, TB extends TxWithOrder>(txWithOrderA: TA, txWithOrderB: TB): number;
/**
* Given an unspent tx output, this function retrieves its descriptor (if still unspent).

@@ -506,4 +533,2 @@ * Alternatively, pass a txo (any transaction output, which may have been

*
* This query can be quite slow so use wisely.
*
* Returns the descriptor (and index if ranged) or undefined if not found.

@@ -510,0 +535,0 @@ */

@@ -333,2 +333,6 @@ "use strict";

* eventually spent as stxos: Array<Stxo>
* Finally, it returns `txoMap`. `txoMap` maps all the txos (unspent or spent
* outputs) with their corresponding `indexedDescriptor: IndexedDescriptor`
* (see {@link IndexedDescriptor IndexedDescriptor})
*
*/

@@ -450,11 +454,11 @@ getUtxosAndBalance({ descriptor, index, descriptors, txStatus = types_1.TxStatus.ALL }) {

const txMap = __classPrivateFieldGet(this, _Discovery_discoveryData, "f")[networkId].txMap;
let txDataArray = [];
let txWithOrderArray = [];
if (descriptor &&
(typeof index !== 'undefined' || !descriptor.includes('*'))) {
const internalIndex = typeof index === 'number' ? index : 'non-ranged';
txDataArray = __classPrivateFieldGet(this, _Discovery_derivers, "f").deriveHistoryByOutput(withAttributions, networkId, txMap, descriptorMap, descriptorOrDescriptors, internalIndex, txStatus);
txWithOrderArray = __classPrivateFieldGet(this, _Discovery_derivers, "f").deriveHistoryByOutput(withAttributions, networkId, txMap, descriptorMap, descriptorOrDescriptors, internalIndex, txStatus);
}
else
txDataArray = __classPrivateFieldGet(this, _Discovery_derivers, "f").deriveHistory(withAttributions, networkId, txMap, descriptorMap, descriptorOrDescriptors, txStatus);
return txDataArray;
txWithOrderArray = __classPrivateFieldGet(this, _Discovery_derivers, "f").deriveHistory(withAttributions, networkId, txMap, descriptorMap, descriptorOrDescriptors, txStatus);
return txWithOrderArray;
}

@@ -486,4 +490,7 @@ /**

* object given the transaction
* ID (TxId) or a Unspent Transaction Output (Utxo). The transaction data is obtained by first getting
* the transaction hexadecimal representation using getTxHex() method.
* ID (TxId) or a Unspent Transaction Output (Utxo) or the hexadecimal
* representation of the transaction (it will then use memoization).
* The transaction data is obtained by first getting
* the transaction hexadecimal representation using getTxHex() method
* (unless the txHex was passed).
*

@@ -498,10 +505,28 @@ * Use this method for quick access to the Transaction object, which avoids the

*/
getTransaction({ txId, utxo }) {
const txHex = this.getTxHex({
...(utxo ? { utxo } : {}),
...(txId ? { txId } : {})
});
return __classPrivateFieldGet(this, _Discovery_derivers, "f").transactionFromHex(txHex);
getTransaction({ txId, txHex, utxo }) {
if (!txHex)
txHex = this.getTxHex({
...(utxo ? { utxo } : {}),
...(txId ? { txId } : {})
});
return __classPrivateFieldGet(this, _Discovery_derivers, "f").transactionFromHex(txHex).tx;
}
/**
* Compares two transactions based on their blockHeight and input dependencies.
* Can be used as callback in Array.sort function to sort from old to new.
*
* @param txWithOrderA - The first transaction data to compare.
* @param txWithOrderB - The second transaction data to compare.
*
* txWithOrderA and txWithOrderB should contain the `blockHeight` (use 0 if
* in the mempool) and either `tx` (`Transaction` type) or `txHex` (the
* hexadecimal representation of the transaction)
*
* @returns < 0 if txWithOrderA is older than txWithOrderB, > 0 if
* txWithOrderA is newer than txWithOrderB, and 0 if undecided.
*/
compareTxOrder(txWithOrderA, txWithOrderB) {
return __classPrivateFieldGet(this, _Discovery_derivers, "f").compareTxOrder(txWithOrderA, txWithOrderB);
}
/**
* Given an unspent tx output, this function retrieves its descriptor (if still unspent).

@@ -513,4 +538,2 @@ * Alternatively, pass a txo (any transaction output, which may have been

*
* This query can be quite slow so use wisely.
*
* Returns the descriptor (and index if ranged) or undefined if not found.

@@ -527,3 +550,5 @@ */

const split = txo.split(':');
if (split.length !== 2)
if (utxo && split.length !== 2)
throw new Error(`Error: invalid utxo: ${utxo}`);
if (!utxo && split.length !== 3)
throw new Error(`Error: invalid txo: ${txo}`);

@@ -539,57 +564,21 @@ const txId = split[0];

throw new Error(`Error: invalid txo: ${txo}`);
//const txHex = this.#discoveryData[networkId].txMap[txId]?.txHex;
//if (!txHex)
// throw new Error(
// `Error: txHex not found for ${txo} while looking for its descriptor.`
// );
const descriptorMap = __classPrivateFieldGet(this, _Discovery_discoveryData, "f")[networkId].descriptorMap;
const descriptors = __classPrivateFieldGet(this, _Discovery_derivers, "f").deriveUsedDescriptors(__classPrivateFieldGet(this, _Discovery_discoveryData, "f"), networkId);
let output;
descriptors.forEach(descriptor => {
const range = descriptorMap[descriptor]?.range ||
{};
Object.keys(range).forEach(indexStr => {
const isRanged = indexStr !== 'non-ranged';
const index = isRanged && Number(indexStr);
if (!txo)
throw new Error('txo not defined');
const { utxos, stxos } = this.getUtxosAndBalance({
descriptor,
...(isRanged ? { index: Number(indexStr) } : {})
});
if (utxo) {
if (utxos.includes(txo)) {
if (output)
throw new Error(`output {${descriptor}, ${index}} is already represented by {${output.descriptor}, ${output.index}} .`);
output = {
descriptor,
...(isRanged ? { index: Number(indexStr) } : {})
};
}
}
else {
//Descriptor txos (Unspent txos and Spent txos). Note that
//stxos have this format: `${txId}:${vout}:${recipientTxId}:${recipientVin}`
//so normalize to Utxo format:
const txoSet = new Set([
...utxos,
...stxos.map(stxo => {
const [txId, voutStr] = stxo.split(':');
if (txId === undefined || voutStr === undefined) {
throw new Error(`Undefined txId or vout for STXO: ${stxo}`);
}
return `${txId}:${voutStr}`;
})
]);
if (txoSet.has(txo)) {
if (output)
throw new Error(`output {${descriptor}, ${index}} is already represented by {${output.descriptor}, ${output.index}} .`);
output = {
descriptor,
...(isRanged ? { index: Number(indexStr) } : {})
};
}
}
});
});
const { txoMap } = this.getUtxosAndBalance({ descriptors });
const indexedDescriptor = txoMap[txo];
if (indexedDescriptor) {
const splitTxo = (str) => {
const lastIndex = str.lastIndexOf('~');
if (lastIndex === -1)
throw new Error(`Separator '~' not found in string`);
return [str.slice(0, lastIndex), str.slice(lastIndex + 1)];
};
const [descriptor, internalIndex] = splitTxo(indexedDescriptor);
output = {
descriptor,
...(internalIndex === 'non-ranged'
? {}
: { index: Number(internalIndex) })
};
}
return output;

@@ -613,4 +602,3 @@ }

const DETECT_RETRY_MAX = 20;
const tx = __classPrivateFieldGet(this, _Discovery_derivers, "f").transactionFromHex(txHex);
const txId = tx.getId();
const { txId } = __classPrivateFieldGet(this, _Discovery_derivers, "f").transactionFromHex(txHex);
await explorer.push(txHex);

@@ -664,4 +652,3 @@ //Now, make sure it made it to the mempool:

throw new Error('txData must contain complete txHex information');
const tx = __classPrivateFieldGet(this, _Discovery_derivers, "f").transactionFromHex(txHex);
const txId = tx.getId();
const { tx, txId } = __classPrivateFieldGet(this, _Discovery_derivers, "f").transactionFromHex(txHex);
const networkId = (0, networks_1.getNetworkId)(network);

@@ -668,0 +655,0 @@ __classPrivateFieldSet(this, _Discovery_discoveryData, (0, immer_1.produce)(__classPrivateFieldGet(this, _Discovery_discoveryData, "f"), discoveryData => {

import { DiscoveryFactory, DiscoveryInstance } from './discovery';
export { DiscoveryFactory, DiscoveryInstance };
export { OutputCriteria, TxStatus, Account, Utxo, Stxo, TxAttribution } from './types';
export { TxWithOrder, OutputCriteria, TxStatus, Account, TxoMap, Utxo, Stxo, IndexedDescriptor, TxAttribution } from './types';

@@ -0,1 +1,2 @@

import type { Transaction } from 'bitcoinjs-lib';
/**

@@ -52,2 +53,25 @@ * Versions the structure of the data model. This variable should to be

/**
* A string representing an indexed descriptor for ranged descriptors or a
* descriptor followed by a separator and the keyword "non-ranged".
*
* An `IndexedDescriptor` is a descriptor representation what must correspond to
* a single output.
*
* - If it is ranged, then add an integer after the separaror (a
* tilde "\~").
* - It it is non-ranged, add the string "non-ranged" after the tilde "\~".
*
* Examples:
* pkh([73c5da0a/44'/1'/0']tpubDC5FSnBiZDMmhiuCmWAYsLwgLYrrT9rAqvTySfuCCrgsWz8wxMXUS9Tb9iVMvcRbvFcAHGkMD5Kx8koh4GquNGNTfohfk7pgjhaPCdXpoba/0/*)\~12
* pkh([73c5da0a/44'/1'/0']tpubDC5FSnBiZDMmhiuCmWAYsLwgLYrrT9rAqvTySfuCCrgsWz8wxMXUS9Tb9iVMvcRbvFcAHGkMD5Kx8koh4GquNGNTfohfk7pgjhaPCdXpoba)\~non-ranged
*/
export type IndexedDescriptor = string;
/**
* a Txo is represented in a similar manner as a Utxo, that is,
* prevtxId:vout. Hovewer, we use a different type name to denote we're dealing
* here with tx outputs that may have been spent or not
*/
type Txo = string;
export type TxoMap = Record<Txo, IndexedDescriptor>;
/**
* Type definition for Transaction ID.

@@ -67,2 +91,7 @@ */

export type Stxo = string;
export type TxWithOrder = {
blockHeight: number;
tx?: Transaction;
txHex?: string;
};
/**

@@ -205,1 +234,2 @@ * Type definition for Transaction Information.

export type DiscoveryData = Record<NetworkId, NetworkData>;
export {};

@@ -5,3 +5,3 @@ {

"homepage": "https://github.com/bitcoinerlab/discovery",
"version": "1.2.2",
"version": "1.2.3",
"author": "Jose-Luis Landabaso",

@@ -8,0 +8,0 @@ "license": "MIT",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc