Skip to content

Commit

Permalink
Merge pull request #27 from LN-Zap/bitcoind
Browse files Browse the repository at this point in the history
Add support for bitcoind fee estimation source
  • Loading branch information
mrfelton authored Feb 13, 2024
2 parents 88f454c + 3810eb9 commit 2a283e1
Show file tree
Hide file tree
Showing 14 changed files with 505 additions and 192 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ npm-debug.log
.DS_Store

# Ignore IntelliJ IDEA settings
.idea/
.idea/

# Ignore local config files
config/local.*
49 changes: 22 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,38 +62,33 @@ In addition, you may need to adjust the settings of your Mempool or Esplora inst
## Configuration Options

This project uses the [`config`](https://www.npmjs.com/package/config) package for configuration. The configuration options are stored in `default.json` and `custom-environment-variables.json` in the `config` directory.
This project uses the [`config`](https://www.npmjs.com/package/config) package for configuration. The default configuration options are stored in [`config/default.json`](./config/default.json) and [`config/custom-environment-variables.json`](./config/custom-environment-variables.json). You can override these options by creating a `config/local.json` file or environment specific configuration files.

Here are the available configuration options:

- `server.port`: The port on which the server runs. Default is `3000`
- `server.baseUrl`: The base url port on which the server is accessible. Default is `http://localhost:3000`
- `esplora.baseUrl`: The base URL of the Esplora API instance to connect to. Default is `https://blockstream.info`
- `esplora.fallbacekBaseUrl`: The base URL of the Esplora API instance to fallback to if the primary instance is unavailable.
- `mempool.baseUrl`: The base URL of the Mempool instance to connect to. Default is `https://mempool.space`
- `mempool.fallbacekBaseUrl`: The base URL of the Mempool instance to fallback to if the primary instance is unavailable.
- `mempool.depth`: The number of blocks to use for mempool-based fee estimates. Default is `6`. Valid options are `1`, `3`, and `6`
- `settings.feeMultiplier`: The multiplier to apply to the fee estimates. Default is `1` (a conservative approach to ensure that the fee estimates are always slightly higher than the raw estimates)
- `cache.stdTTL`: The standard time to live in seconds for every generated cache element. Default is `15`
- `cache.checkperiod`: The period in seconds, used for the automatic delete check interval. Default is `20`

In addition to configuring the application through the config files, you can also override these options by setting the corresponding environment variables:

- `PORT`: Overrides `server.port`
- `BASE_URL`: Overrides `server.baseUrl`
- `ESPLORA_BASE_URL`: Overrides `esplora.baseUrl`
- `ESPLORA_FALLBACK_BASE_URL`: Overrides `esplora.fallbackBaseUrl`
- `MEMPOOL_BASE_URL`: Overrides `mempool.baseUrl`
- `MEMPOOL_FALLBACK_BASE_URL`: Overrides `mempool.fallbackBaseUrl`
- `MEMPOOL_DEPTH`: Overrides `mempool.depth`
- `FEE_MULTIPLIER`: Overrides `settings.feeMultiplier`
- `CACHE_STDTTL`: Overrides `cache.stdTTL`
- `CACHE_CHECKPERIOD`: Overrides `cache.checkperiod`
| Config Key | Description | Default Value | Environment Variable |
| --- | --- | --- | --- |
| `server.port` | The port on which the server runs | `3000` | `PORT` |
| `server.baseUrl` | The base url port on which the server is accessible | `http://localhost:3000` | `BASE_URL` |
| `esplora.baseUrl` | The base URL of the Esplora API instance to connect to | `https://blockstream.info` | `ESPLORA_BASE_URL` |
| `esplora.fallbacekBaseUrl` | The base URL of the Esplora API instance to fallback to if the primary instance is unavailable | - | `ESPLORA_FALLBACK_BASE_URL` |
| `mempool.baseUrl` | The base URL of the Mempool instance to connect to | `https://mempool.space` | `MEMPOOL_BASE_URL` |
| `mempool.fallbacekBaseUrl` | The base URL of the Mempool instance to fallback to if the primary instance is unavailable | - | `MEMPOOL_FALLBACK_BASE_URL` |
| `mempool.depth` | The number of blocks to use for mempool-based fee estimates | `6` | `MEMPOOL_DEPTH` |
| `bitcoind.baseUrl` | The base URL of the bitcoind instance to connect to | `http://localhost:8332` | `BITCOIND_BASE_URL` |
| `bitcoind.username` | The username to use for authenticating with the bitcoind instance | - | `BITCOIND_USERNAME` |
| `bitcoind.password` | The password to use for authenticating with the bitcoind instance | - | `BITCOIND_PASSWORD` |
| `bitcoind.confTargets` | The block targets to use for history-based fee estimates | `[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 144, 504, 1008]` | `BITCOIND_CONF_TARGETS` |
| `settings.timeout` | Timeout to use when fetching data (ms) | `5000` | `TIMEOUT` |
| `settings.feeMultiplier` | The multiplier to apply to the fee estimates | `1` | `FEE_MULTIPLIER` |
| `settings.feeMinimum` | The minimum fee (sat/vB) to use for fee estimates if we could not determine from a configured data source | `2` | `FEE_MINIMUM` |
| `cache.stdTTL` | The standard time to live in seconds for every generated cache element | `15` | `CACHE_STDTTL` |
| `cache.checkperiod` | The period in seconds, used for the automatic delete check interval | `20` | `CACHE_CHECKPERIOD` |

For example, to run the server on port 4000 and connect to a local Mempool instance, you can start the server like this:

```bash
PORT=4000 MEMPOOL_BASE_URL=localhost npm start
PORT=4000 MEMPOOL_BASE_URL=localhost bun start
```

## Development
Expand Down Expand Up @@ -126,8 +121,8 @@ Please ensure that Docker is installed and running on your machine before runnin

You can build a Docker image from the source and run it with the following scripts:

- `docker:build`: Builds a Docker image of the project. You can run this script with `npm run docker:build`.
- `docker:run`: Runs the Docker image. You can run this script with `npm run docker:run`.
- `docker:build`: Builds a Docker image of the project. You can run this script with `bun run docker:build`.
- `docker:run`: Runs the Docker image. You can run this script with `bun run docker:run`.

For example, to build and run the Docker image, you can use the following commands:

Expand Down
Binary file modified bun.lockb
Binary file not shown.
10 changes: 9 additions & 1 deletion config/custom-environment-variables.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"port": "PORT"
},
"settings": {
"feeMultiplier": "FEE_MULTIPLIER"
"timeout": "TIMEOUT",
"feeMultiplier": "FEE_MULTIPLIER",
"feeMinimum" : "FEE_MINIMUM"
},
"mempool": {
"baseUrl": "MEMPOOL_BASE_URL",
Expand All @@ -15,6 +17,12 @@
"baseUrl": "ESPLORA_BASE_URL",
"fallbackBaseUrl": "ESPLORA_FALLBACK_BASE_URL"
},
"bitcoind": {
"baseUrl": "BITCOIND_BASE_URL",
"username": "BITCOIND_USERNAME",
"password": "BITCOIND_PASSWORD",
"confTargets": "BITCOIND_CONF_TARGETS"
},
"cache": {
"stdTTL": "CACHE_STD_TTL",
"checkperiod": "CACHE_CHECKPERIOD"
Expand Down
12 changes: 10 additions & 2 deletions config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"port": 3000
},
"settings": {
"feeMultiplier": 1
"timeout": 5000,
"feeMultiplier": 1,
"feeMinimum": 2
},
"mempool": {
"baseUrl": "https://mempool.space",
Expand All @@ -15,8 +17,14 @@
"baseUrl": "https://blockstream.info",
"fallbackBaseUrl": null
},
"bitcoind": {
"baseUrl": null,
"username": null,
"password": null,
"confTargets": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 144, 504, 1008]
},
"cache": {
"stdTTL": 15,
"checkperiod": 20
}
}
}
7 changes: 7 additions & 0 deletions config/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"bitcoind": {
"baseUrl": "http://127.0.0.1:18445",
"username": "user",
"password": "pass"
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"author": "Tom Kirkpatrick <[email protected]> (https://twitter.com/mrfelton)",
"license": "MIT",
"dependencies": {
"bitcoind-rpc": "0.9.1",
"config": "3.3.9",
"hono": "3.11.12",
"node-cache": "5.1.2"
Expand Down
53 changes: 34 additions & 19 deletions src/custom.d.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,48 @@
// MempoolFeeEstimates represents the fee estimates for different transaction speeds.
type MempoolFeeEstimates = {
[key: string]: number | undefined;
fastestFee: number;
halfHourFee: number;
hourFee: number;
economyFee: number;
minimumFee: number;
};

type EsploraFeeEstimates = {
[key: number]: number;
[key: string]: number; // dynamic keys with number as value (sat/vb)
fastestFee: number; // fee for the fastest transaction speed (sat/vb)
halfHourFee: number; // fee for half an hour transaction speed (sat/vb)
hourFee: number; // fee for an hour transaction speed (sat/vb)
economyFee: number; // fee for economy transaction speed (sat/vb)
minimumFee: number; // minimum relay fee (sat/vb)
};

// FeeByBlockTarget represents the fee by block target.
type FeeByBlockTarget = {
[key: string]: number;
[key: string]: number; // fees by confirmation target
};

// Estimates represents the current block hash and fee by block target.
type Estimates = {
current_block_hash: string | null;
fee_by_block_target: FeeByBlockTarget;
current_block_hash: string | null; // current block hash
fee_by_block_target: FeeByBlockTarget; // fee by block target (in sat/kb)
};

// BlockTargetMapping represents the mapping of block targets.
type BlockTargetMapping = {
[key: number]: string;
[key: number]: string; // dynamic numeric keys with string as value
};

// SiteData represents the data of a site.
interface SiteData {
title: string,
subtitle: string,
children?: any
}
title: string, // title of the site
subtitle: string, // subtitle of the site
children?: any // children of the site (optional)
};

// ExpectedResponseType represents the expected response type for an http request.
type ExpectedResponseType = 'json' | 'text'; // can be either 'json' or 'text'

type ExpectedResponseType = 'json' | 'text';
// BatchRequest represents a bitcoind batch request response.
interface BitcoindRpcBatchResponse {
result?: EstimateSmartFeeResponse;
error?: any;
};

// EstimateSmartFeeResponse represents the response of the estimatesmarttee method.
interface EstimateSmartFeeResponse {
feerate?: number, // estimate fee rate in BTC/kB (only present if no errors were encountered)
errors?: [string], // errors encountered during processing (if there are any)
blocks?: number // block number where estimate was found
};
Loading

0 comments on commit 2a283e1

Please sign in to comment.