@bitcoinerlab/discovery
Advanced tools
Comparing version
@@ -536,2 +536,13 @@ /// <reference types="node" /> | ||
}): Promise<void>; | ||
addTransaction({ txData, gapLimit }: { | ||
/** | ||
* The hexadecimal representation of the tx and its associated data. | ||
* `txData = { blockHeight: number; irreversible: boolean; txHex: TxHex; }`. | ||
*/ | ||
txData: TxData; | ||
/** | ||
* The gap limit for descriptor discovery. Defaults to 20. | ||
*/ | ||
gapLimit?: number; | ||
}): void; | ||
/** | ||
@@ -538,0 +549,0 @@ * Retrieves the Explorer instance. |
@@ -608,5 +608,3 @@ "use strict"; | ||
const txId = tx.getId(); | ||
const networkId = (0, networks_1.getNetworkId)(network); | ||
await explorer.push(txHex); | ||
const txData = { irreversible: false, blockHeight: 0, txHex }; | ||
//Now, make sure it made it to the mempool: | ||
@@ -621,2 +619,43 @@ let found = false; | ||
} | ||
const txData = { irreversible: false, blockHeight: 0, txHex }; | ||
this.addTransaction({ txData, gapLimit }); | ||
if (found === false) | ||
console.warn(`txId ${txId} was pushed. However, it was then not found in the mempool. It has been set as part of the discoveryData anyway.`); | ||
} | ||
/* | ||
* Given a transaction it updates the internal `discoveryData` state to | ||
* include it. | ||
* | ||
* This function is useful when a transaction affecting one of the | ||
* descriptors has been pushed to the blockchain by a third party. It allows | ||
* updating the internal representation without performing a more expensive | ||
* `fetch` operation. | ||
* | ||
* If the transaction was recently pushed to the blockchain, set | ||
* `txData.irreversible = false` and `txData.blockHeight = 0`. | ||
* | ||
* The transaction is represented by `txData`, where | ||
* `txData = { blockHeight: number; irreversible: boolean; txHex: TxHex; }`. | ||
* | ||
* It includes its hexadecimal representation `txHex`, its `blockHeight` | ||
* (zero if it's in the mempool), and whether it is `irreversible` or | ||
* not. `irreversible` is set by the Explorer, using the configuration parameter | ||
* `irrevConfThresh` (defaults to `IRREV_CONF_THRESH = 3`). It can be obtained | ||
* by calling explorer.fetchTxHistory(), for example. Set it to | ||
* `false` when it's been just pushed (which will be the typical use of this | ||
* function). | ||
* | ||
* The `gapLimit` parameter is essential for managing descriptor discovery. | ||
* When addint a transaction, there is a possibility the transaction is | ||
* adding new funds as change (for example). If the range for that index | ||
* does not exist yet, the `gapLimit` helps to update the descriptor | ||
* corresponding to a new UTXO for new indices within the gap limit. | ||
*/ | ||
addTransaction({ txData, gapLimit = DEFAULT_GAP_LIMIT }) { | ||
const txHex = txData.txHex; | ||
if (!txHex) | ||
throw new Error('txData must contain complete txHex information'); | ||
const tx = __classPrivateFieldGet(this, _Discovery_derivers, "f").transactionFromHex(txHex); | ||
const txId = tx.getId(); | ||
const networkId = (0, networks_1.getNetworkId)(network); | ||
__classPrivateFieldSet(this, _Discovery_discoveryData, (0, immer_1.produce)(__classPrivateFieldGet(this, _Discovery_discoveryData, "f"), discoveryData => { | ||
@@ -671,4 +710,2 @@ const txMap = discoveryData[networkId].txMap; | ||
}), "f"); | ||
if (found === false) | ||
console.warn(`txId ${txId} was pushed. However, it was then not found in the mempool. It has been set as part of the discoveryData anyway.`); | ||
} | ||
@@ -719,7 +756,7 @@ /** | ||
const descriptorMap = __classPrivateFieldGet(this, _Discovery_discoveryData, "f")[networkId].descriptorMap; | ||
const descriptors = __classPrivateFieldGet(this, _Discovery_derivers, "f").deriveUsedDescriptors(__classPrivateFieldGet(this, _Discovery_discoveryData, "f"), networkId); | ||
const descriptors = Object.keys(descriptorMap); | ||
for (const descriptor of descriptors) { | ||
const range = descriptorMap[descriptor]?.range || | ||
{}; | ||
let maxIndex = -1; | ||
let maxUsedIndex = -1; | ||
for (const indexStr of Object.keys(range)) { | ||
@@ -732,12 +769,12 @@ const index = indexStr === 'non-ranged' ? indexStr : Number(indexStr); | ||
if (typeof index === 'number') { | ||
if (maxIndex === 'non-ranged') | ||
throw new Error('maxIndex shoulnt be set as non-ranged'); | ||
if (index > maxIndex) | ||
maxIndex = index; | ||
if (maxUsedIndex === 'non-ranged') | ||
throw new Error('maxUsedIndex shoulnt be set as non-ranged'); | ||
if (index > maxUsedIndex && range[index]?.txIds.length) | ||
maxUsedIndex = index; | ||
} | ||
if (index === 'non-ranged') | ||
maxIndex = index; | ||
maxUsedIndex = index; | ||
} | ||
if (maxIndex !== 'non-ranged' && gapLimit) { | ||
for (let index = maxIndex + 1; index < maxIndex + 1 + gapLimit; index++) { | ||
if (maxUsedIndex !== 'non-ranged' && gapLimit) { | ||
for (let index = maxUsedIndex + 1; index < maxUsedIndex + 1 + gapLimit; index++) { | ||
if (scriptPubKey.equals(__classPrivateFieldGet(this, _Discovery_derivers, "f").deriveScriptPubKey(networkId, descriptor, index) //This will be very fast (uses memoization) | ||
@@ -797,2 +834,5 @@ )) { | ||
if (!outputData) { | ||
//If it has not been set already, search for other descriptor expressions | ||
//in case the same scriptPubKey already exists and throw if this is the | ||
//case | ||
__classPrivateFieldGet(this, _Discovery_instances, "m", _Discovery_ensureScriptPubKeyUniqueness).call(this, { networkId, scriptPubKey }); | ||
@@ -799,0 +839,0 @@ range[internalIndex] = { txIds: [], fetching: true, timeFetched: 0 }; |
@@ -5,3 +5,3 @@ { | ||
"homepage": "https://github.com/bitcoinerlab/discovery", | ||
"version": "1.2.1", | ||
"version": "1.2.2", | ||
"author": "Jose-Luis Landabaso", | ||
@@ -8,0 +8,0 @@ "license": "MIT", |
142537
1.93%2444
2.13%