Skip to content

Commit 6683f1b

Browse files
authored
Merge pull request #1 from bitcoinerlab/outputs
V1: Enhance Discovery API Usability and Documentation
2 parents 2c64233 + 6277842 commit 6683f1b

10 files changed

Lines changed: 1122 additions & 988 deletions

File tree

README.md

Lines changed: 81 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ The @bitcoinerlab/discovery library, written in TypeScript, provides a method fo
44

55
## Features
66

7-
- **Descriptor-Based Data Retrieval:** Retrieves UTXOs, transaction history, and balances for various sources: ranged descriptors, accounts (comprising internal & external descriptors), and addresses (a descriptor specialized for a specific index).
7+
- **Descriptor-Based Data Retrieval:** Retrieves transaction history for various sources, including: ranged descriptors, accounts (comprising internal & external descriptors), and addresses (a descriptor specialized for a specific index).
88

99
- **Transaction Status Filter:** Offers the ability to filter results by `TxStatus`: `ALL` (including transactions in the mempool), `CONFIRMED` (assuming one confirmation) and `IRREVERSIBLE` (for transactions with more than a user-defined number of confirmations).
1010

@@ -42,8 +42,7 @@ To get started, follow the steps below:
4242
host: 'electrum.blockstream.info',
4343
port: 60002,
4444
protocol: 'ssl', // 'ssl' and 'tcp' allowed
45-
network: networks.testnet // Specify the server's network; defaults to 'mainnet' if not specified
46-
45+
network: networks.testnet // Specify the server's network; defaults to networks.bitcoin (mainnet)
4746
});
4847
```
4948

@@ -52,62 +51,112 @@ To get started, follow the steps below:
5251
Please refer to the [Explorer documentation](https://github.com/bitcoinerlab/explorer) for more details.
5352

5453
3. **Create the Discovery Class**:
55-
After creating the explorer client instance, you can create the `Discovery` class, which you will use to query the Blockchain. The `Discovery` class is created using the `DiscoveryFactory` function, passing the previously created explorer instance.
54+
After creating the explorer client instance, you can create the `Discovery` class, which you will use to query the Blockchain. The `Discovery` class is created using the [`DiscoveryFactory` function](https://bitcoinerlab.com/modules/discovery/api/functions/DiscoveryFactory.html), passing the previously created explorer instance.
5655

5756
```typescript
5857
import { DiscoveryFactory } from '@bitcoinerlab/discovery';
59-
const { Discovery } = DiscoveryFactory(explorer); // where 'explorer' corresponds to
60-
// 'esploraExplorer' or 'electrumExplorer' above
58+
const { Discovery } = DiscoveryFactory(explorer, network);
59+
// where 'explorer' corresponds to 'esploraExplorer' or 'electrumExplorer' above
6160
await explorer.connect();
6261
const discovery = new Discovery();
62+
// Perform discovery operations...
6363
await explorer.close();
6464
```
6565

66-
The `Discovery` constructor accepts an optional object with two properties that are crucial for managing the application's memory usage:
66+
The [`Discovery` constructor](https://bitcoinerlab.com/modules/discovery/api/classes/_Internal_.Discovery.html#constructor), `new Discovery({ descriptorsCacheSize, outputsPerDescriptorCacheSize })`, accepts an optional object with two properties that are crucial for managing the application's memory usage:
6767

68-
- `expressionsCacheSize`: This property represents the cache size limit for descriptor expressions. The cache, implemented using memoizers, serves a dual purpose: it speeds up data queries by avoiding unnecessary recomputations, and it helps maintain immutability. Reaching the limit of the cache size may lead to a loss of immutability and the returned reference may change. This is not a critical issue, as the data is still correct, but it may trigger extra renders in the UI. The default value is 1000, and you can set it to 0 for unbounded caches.
69-
- `indicesPerExpressionCacheSize`: This property represents the cache size limit for indices per expression, related to the number of addresses in ranged descriptor expressions. Similar to the `expressionsCacheSize`, reaching the limit of this cache size may lead to the same immutability challenges. The default value is 10000, and you can set it to 0 for unbounded caches.
68+
- `descriptorsCacheSize`: This property represents the cache size limit for descriptor expressions. The cache, implemented using memoizers, serves a dual purpose: it speeds up data derivation by avoiding unnecessary recomputations, and it helps maintain immutability. Reaching the limit of the cache size may lead to a loss of immutability and the returned reference may change. This is not a critical issue, as the returned data is still correct, but it may trigger extra renders in the UI. The default value is `1000`, and you can set it to `0` for unbounded caches.
69+
- `outputsPerDescriptorCacheSize`: This property represents the cache size limit for indices per expression, related to the number of addresses in ranged descriptor expressions. Similar to the `descriptorsCacheSize`, reaching the limit of this cache size may lead to the same immutability challenges. The default value is `10000`, and you can set it to `0` for unbounded caches.
7070

71-
It is important to note that the default values for `expressionsCacheSize` and `indicesPerExpressionCacheSize` should be sufficient for most projects. However, if you expect to work with a large number of descriptor expressions or addresses, you may need to adjust these values accordingly. Conversely, for projects that require minimal resources, you may consider reducing these values to conserve memory.
71+
It's noteworthy that the default settings for `descriptorsCacheSize` and `outputsPerDescriptorCacheSize` are adequate for most use cases. Yet, for projects handling a large volume of descriptor expressions or addresses, increasing these limits may be necessary. On the flip side, if conserving memory is a priority, particularly for projects with minimal resource needs, consider lowering these values.
7272

7373
**Note**: The `connect` method must be run before starting any data queries to the blockchain, and the `close` method should be run after you have completed all necessary queries and no longer need to query the blockchain.
7474

75+
7576
4. **Using the Discovery Methods**
76-
77-
Once you've instantiated the `Discovery` class, you can leverage its methods to interact with blockchain data.
7877

79-
For instance, if you want to fetch all the addresses from a ranged descriptor expression, execute:
78+
Once you've instantiated the `Discovery` class, you have access to [a variety of methods](https://bitcoinerlab.com/modules/discovery/api/classes/_Internal_.Discovery.html#fetch) to fetch and derive blockchain data from *Bitcoin Output Descriptors*.
8079

80+
Descriptor expressions are a simple language used to describe collections of Bitcoin output scripts. They enable the `Discovery` class to fetch detailed blockchain information about specific outputs. For more comprehensive insights into descriptor expressions, refer to the [BitcoinerLab descriptors module](https://bitcoinerlab.com/modules/descriptors).
81+
82+
To initiate (or update) the data retrieval process for addresses associated with a descriptor, whether ranged or fixed, execute [`fetch`](https://bitcoinerlab.com/modules/discovery/api/classes/_Internal_.Discovery.html#fetch):
83+
8184
```typescript
82-
await discovery.discover({ expressions, network, gapLimit: 3 });
83-
const { utxos, balance } = discovery.getUtxos({ expressions, network });
85+
await discovery.fetch({ descriptor });
8486
```
87+
This method retrieves all associated outputs for a given descriptor. If the descriptor is ranged, you can also specify an index to target a specific output within that range. When dealing with multiple descriptors, use the `descriptors` parameter with an array of strings. See the [`fetch` API documentation](https://bitcoinerlab.com/modules/discovery/api/classes/_Internal_.Discovery.html#fetch) for detailed usage.
8588

86-
In this context, the term `expressions` can be a single string or an array of strings. These expressions represent [descriptor expressions](https://bitcoinerlab.com/modules/descriptors). If an expression is ranged, it will retrieve all the related `scriptPubKeys`. Subsequently, you can obtain the UTXOs and balance for that particular expression using the subsequent line.
87-
88-
Other beneficial methods include:
89+
**Note**: To ensure accurate data computations, fetch descriptor data (using the query above) before employing methods like `getUtxos`, `getBalance`, or others described below. An error will alert you when attempting to derive data from descriptors that have not been previously fetched. This ensures you do not compute data based on incomplete information. If you are unsure whether a descriptor has been previously fetched or need to ensure that the data is up-to-date, use [`whenFetched`](https://bitcoinerlab.com/modules/discovery/api/classes/_Internal_.Discovery.html#whenFetched):
90+
91+
```typescript
92+
const fetchStatus = discovery.whenFetched({ descriptor });
93+
if (fetchStatus === undefined) {
94+
// The descriptor has not been fetched.
95+
} else {
96+
const secondsSinceFetched = (Date.now() - fetchStatus.timeFetched * 1000) / 1000;
97+
if (secondsSinceFetched > SOME_TIME_THRESHOLD) {
98+
// The descriptor data is outdated and may need to be fetched again.
99+
}
100+
}
101+
```
102+
103+
If fetch status is verified or known, proceed directly to the data derivation methods:
89104

90-
- **Getting the Next Index**:
91-
If you're dealing with ranged descriptor expressions and want to determine the next available (unused) index, use:
105+
- **Deriving UTXOs**:
106+
Use [`getUtxos`](https://bitcoinerlab.com/modules/discovery/api/classes/_Internal_.Discovery.html#getUtxos) to derive all unspent transaction outputs (UTXOs) from the fetched data:
92107
```typescript
93-
const index = discovery.getNextIndex({ expression, network });
108+
const { utxos } = discovery.getUtxos({ descriptor });
94109
```
95-
96-
- **Fetching ScriptPubKeys by UTXO**:
97-
This method is essential post-discovery. For a given UTXO, it yields all possible `scriptPubKeys` and related data that can consume the specified UTXO. It's worth noting that this method returns an array since multiple valid descriptor expressions might refer to the same output.
110+
111+
- **Calculating Balance**:
112+
Use [`getBalance`](https://bitcoinerlab.com/modules/discovery/api/classes/_Internal_.Discovery.html#getBalance) to calculate the total balance from the fetched data:
98113
```typescript
99-
discovery.getScriptPubKeysByUtxo({ utxo, network });
100-
// This yields: Array<{ expression, index, vout, txHex }>
114+
const { balance } = discovery.getBalance({ descriptor });
101115
```
102-
This function is particularly useful when crafting a transaction capable of expending the UTXO, especially when paired with the @bitcoinerlab/descriptors library.
103-
104-
- **Reviewing Transaction History**:
105-
To inspect all transactions associated with a specific descriptor expression (or an array of them), use:
116+
117+
Other methods to derive or calculate data include:
118+
119+
- **Determining the Next Index**:
120+
For ranged descriptor expressions, determine the next unused index:
121+
```typescript
122+
const index = discovery.getNextIndex({ descriptor });
123+
```
124+
See the [`getNextIndex` API documentation](https://bitcoinerlab.com/modules/discovery/api/classes/_Internal_.Discovery.html#getNextIndex) for detailed usage.
125+
126+
- **Identifying Descriptors by UTXO**:
127+
Find the descriptor that corresponds to a specific UTXO using [`getDescriptor`](https://bitcoinerlab.com/modules/discovery/api/classes/_Internal_.Discovery.html#getDescriptor):
128+
```typescript
129+
const descriptorData = discovery.getDescriptor({ utxo });
130+
// Returns: { descriptor, index? }, with 'index' provided for ranged descriptors.
131+
```
132+
This is particularly useful for transaction preparation when you need to instantiate a `new Output({ descriptor })` using the descriptor associated with the UTXO, as facilitated by the [@bitcoinerlab/descriptors](https://bitcoinerlab.com/modules/descriptors) library.
133+
134+
- **Accessing Transaction History**:
135+
Access all transactions associated with a specific descriptor expression (or an array of them):
136+
```typescript
137+
const history = discovery.getHistory({ descriptors });
138+
```
139+
Refer to the [`getHistory` API](https://bitcoinerlab.com/modules/discovery/api/classes/_Internal_.Discovery.html#getHistory) for the details.
140+
141+
- **Fetching Standard Accounts**:
142+
The [`fetchStandardAccounts`](https://bitcoinerlab.com/modules/discovery/api/classes/_Internal_.Discovery.html#fetchStandardAccounts) method is a helper that automates the common task of retrieving or updating standard accounts (pkh, sh(wpkh), wpkh) associated with a master node. This method saves developers time and eliminates repetitive coding tasks.
143+
144+
Efficiently retrieve wallet accounts with:
106145
```typescript
107-
const history = discovery.getHistory({ expressions, network });
146+
await discovery.fetchStandardAccounts({
147+
masterNode,
148+
gapLimit: 20, // The default gap limit
149+
onAccountUsed: (account) => {
150+
// Optional: Trigger app updates when an account with transactions is found.
151+
},
152+
onAccountChecking: (account) => {
153+
// Optional: Implement app-specific logic when the check for an account begins.
154+
}
155+
});
108156
```
157+
Implement the `onAccountUsed` and `onAccountChecking` callbacks as needed for your app's functionality, such as UI updates or logging.
109158

110-
For a comprehensive rundown of all available methods and their descriptions, please consult [the API documentation](https://bitcoinerlab.com/modules/discovery/api/classes/_Internal_.Discovery.html).
159+
The methods listed above are only a part of all the `Discovery` class's functionality. For a complete overview of all available methods and their usage, refer to [the API documentation](https://bitcoinerlab.com/modules/discovery/api/classes/_Internal_.Discovery.html).
111160

112161
## API Documentation
113162

package-lock.json

Lines changed: 24 additions & 27 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@bitcoinerlab/discovery",
33
"description": "A TypeScript library for retrieving Bitcoin funds from ranged descriptors, leveraging @bitcoinerlab/explorer for standardized access to multiple blockchain explorers.",
44
"homepage": "https://github.com/bitcoinerlab/discovery",
5-
"version": "0.1.0",
5+
"version": "1.0.0",
66
"author": "Jose-Luis Landabaso",
77
"license": "MIT",
88
"prettier": "@bitcoinerlab/configs/prettierConfig.json",
@@ -43,7 +43,7 @@
4343
"dist"
4444
],
4545
"dependencies": {
46-
"@bitcoinerlab/descriptors": "^1.0.2",
46+
"@bitcoinerlab/descriptors": "^2.0.1",
4747
"@bitcoinerlab/explorer": "^0.1.0",
4848
"@bitcoinerlab/secp256k1": "^1.0.5",
4949
"@types/memoizee": "^0.4.8",

0 commit comments

Comments
 (0)