From ae5f756bd2b8827be2cb88246d256aaceb65d480 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 17:22:15 +0300 Subject: [PATCH 01/75] chore(eslint): turn off camelcase rule --- .eslintrc.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index 34f7205..deb4061 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -19,6 +19,8 @@ "linebreak-style": "error", "quotes": ["error", "double", { "avoidEscape": true }], "prefer-destructuring": "error", - "semi": "error" + "semi": "error", + "camelcase": "off", + "@typescript-eslint/camelcase": ["error", { "properties": "never" }] } } From c7f4a53dfa04e493dd2f0dd6313028cba298cefc Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 17:22:50 +0300 Subject: [PATCH 02/75] feat(rpc): add getBestBlockHash method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index 8d0688c..5027b27 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -42,4 +42,11 @@ export class RPCClient extends RESTClient { const response = await this.batch(body, uri); return this.fullResponse ? response : response.result; } + + /** + * @description Returns the hash of the best (tip) block in the longest blockchain. + */ + async getBestBlockHash() { + return this.rpc("getbestblockhash"); + } } From b2c89d87c54e697b42e58253f3e676764688b674 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 17:23:17 +0300 Subject: [PATCH 03/75] doc(readme): add getBestBlockHash example --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index fa4af3c..ae242ea 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,14 @@ const response = await client.batch([ ]); ``` +### Blockchain + +- [getBestBlockHash](https://bitcoin.org/en/developer-reference#getbestblockhash) + +```javascript +const hex = await client.getbestblockhash(); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 59bafcfbf40f0ddd4166cc2684d95b44c76b93f8 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 17:23:32 +0300 Subject: [PATCH 04/75] test(rpc): add getBestBlockHash --- test/rpc.spec.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 5cd3bb7..c87357d 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -112,4 +112,20 @@ suite("RPCClient", () => { const data = await client.rpc(method, params, wallet); assert.deepStrictEqual(data, result); }); + + suite("Blockchain", () => { + test(".getBestBlockHash()", async () => { + const request = { params: {}, method: "getbestblockhash", id, jsonrpc }; + const result = + "000000006e60e2ae7b464e4e38e061cb4aea9dafa605cc1d38d34601fdf77064"; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getBestBlockHash(); + assert.deepStrictEqual(data, result); + }); + }); }); From f387b05fb5a70c3ec702a8ea982b99e4febbb58f Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 17:42:24 +0300 Subject: [PATCH 05/75] feat(rpc): add getblock method --- src/rpc.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/rpc.ts b/src/rpc.ts index 5027b27..f21d2c6 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -14,6 +14,12 @@ export type JSONRPC = { params?: any; }; +export type Verbosity = { verbosity: 0 | 1 | 2 }; + +export type Blockhash = { blockhash: string }; + +export type GetBlockParams = Verbosity & Blockhash; + export class RPCClient extends RESTClient { wallet?: string; fullResponse?: boolean; @@ -46,7 +52,14 @@ export class RPCClient extends RESTClient { /** * @description Returns the hash of the best (tip) block in the longest blockchain. */ - async getBestBlockHash() { + async getbestblockhash() { return this.rpc("getbestblockhash"); } + + /** + * @description If verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'. If verbosity is 1, returns an Object with information about block . If verbosity is 2, returns an Object with information about block and information about each transaction. + */ + async getblock({ blockhash, verbosity = 1 }: GetBlockParams) { + return this.rpc("getblock", { blockhash, verbosity }); + } } From 796dac9ee8e16db5bd9d8a634ed7a9592c7b1315 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 17:42:42 +0300 Subject: [PATCH 06/75] doc(readme): add getblock example --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ae242ea..5e25e02 100644 --- a/README.md +++ b/README.md @@ -32,12 +32,21 @@ const response = await client.batch([ ### Blockchain -- [getBestBlockHash](https://bitcoin.org/en/developer-reference#getbestblockhash) +- [`getbestblockhash`](https://bitcoin.org/en/developer-reference#getbestblockhash) ```javascript const hex = await client.getbestblockhash(); ``` +- [`getblock`](https://bitcoin.org/en/developer-reference#getblock) + +```javascript +const blockhash = + "000000004182034f427d463b92162d35d0accef9ea0c5354a87e870ca1815b4c"; +const verbosity = 2; +const block = await client.getblock({ blockhash, verbosity }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 09aeae1a564129c4d4fe00650739a27b83e29bcf Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 17:43:06 +0300 Subject: [PATCH 07/75] test(rpc): add getblock --- test/rpc.spec.ts | 145 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 143 insertions(+), 2 deletions(-) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index c87357d..102de6e 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -114,7 +114,7 @@ suite("RPCClient", () => { }); suite("Blockchain", () => { - test(".getBestBlockHash()", async () => { + test(".getbestblockhash()", async () => { const request = { params: {}, method: "getbestblockhash", id, jsonrpc }; const result = "000000006e60e2ae7b464e4e38e061cb4aea9dafa605cc1d38d34601fdf77064"; @@ -124,7 +124,148 @@ suite("RPCClient", () => { .times(1) .basicAuth(auth) .reply(200, response); - const data = await client.getBestBlockHash(); + const data = await client.getbestblockhash(); + assert.deepStrictEqual(data, result); + }); + + test(".getblock()", async () => { + const blockhash = + "000000004182034f427d463b92162d35d0accef9ea0c5354a87e870ca1815b4c"; + const verbosity = 2; + const params = { blockhash, verbosity }; + const request = { params, method: "getblock", id, jsonrpc }; + const result = { + hash: + "000000004182034f427d463b92162d35d0accef9ea0c5354a87e870ca1815b4c", + confirmations: 3383, + strippedsize: 123950, + size: 178661, + weight: 550511, + height: 1580399, + version: 536870912, + versionHex: "20000000", + merkleroot: + "d3f3bb31c88119d341f9a5598a213655bc0168a83a9d9cb80ac4386485b3c0f5", + tx: [ + { + txid: + "6adb52bcfbc0f88378eed06783d5dbb3edd649f485c3fdc2f38e779e724f612a", + hash: + "2b1826bdd156e6f86248404da4f51febd58eaa8abdb85572302bb27af89a4089", + version: 1, + size: 197, + vsize: 170, + weight: 680, + locktime: 0, + vin: [ + { + coinbase: + "036f1d180459fe965d08f80000014b0700000c2f746573746e65747465722f", + sequence: 0 + } + ], + vout: [ + { + value: 0.53670882, + n: 0, + scriptPubKey: { + asm: + "OP_HASH160 b4316d69836fe185d3d4ca234e90a7a5ce6491ab OP_EQUAL", + hex: "a914b4316d69836fe185d3d4ca234e90a7a5ce6491ab87", + reqSigs: 1, + type: "scripthash", + addresses: ["2N9fzq66uZYQXp7uqrPBH6jKBhjrgTzpGCy"] + } + }, + { + value: 0, + n: 1, + scriptPubKey: { + asm: + "OP_RETURN aa21a9ed3116a1d2c6dc9cf601112589ce7d2334acd8a196fb02ceacddf6eed2bf4b72b5", + hex: + "6a24aa21a9ed3116a1d2c6dc9cf601112589ce7d2334acd8a196fb02ceacddf6eed2bf4b72b5", + type: "nulldata" + } + } + ], + hex: + "010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff1f036f1d180459fe965d08f80000014b0700000c2f746573746e65747465722f0000000002e2f332030000000017a914b4316d69836fe185d3d4ca234e90a7a5ce6491ab870000000000000000266a24aa21a9ed3116a1d2c6dc9cf601112589ce7d2334acd8a196fb02ceacddf6eed2bf4b72b50120000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + txid: + "5416f86c8d41840ff9c09d997372a7f140e78b765252583fb23f74e0992c6e71", + hash: + "5416f86c8d41840ff9c09d997372a7f140e78b765252583fb23f74e0992c6e71", + version: 1, + size: 226, + vsize: 226, + weight: 904, + locktime: 0, + vin: [ + { + txid: + "623145a17de90d190f3b2379672b3bb11f19f73b3be4c412cea1f60f9bbe7344", + vout: 1, + scriptSig: { + asm: + "304502210098a6a7a2329a7373ff838b3e816e8b48f94238dfbe08add7896ff95127ebfc310220541302168ae986ec6abbb0c5eea95f069621166fe841ba965ed6ea3bb351735c[ALL] 0396cfa148d2fc150d225262836aaf4ed98da771a9c2f6bc54da03d402d3f1a384", + hex: + "48304502210098a6a7a2329a7373ff838b3e816e8b48f94238dfbe08add7896ff95127ebfc310220541302168ae986ec6abbb0c5eea95f069621166fe841ba965ed6ea3bb351735c01210396cfa148d2fc150d225262836aaf4ed98da771a9c2f6bc54da03d402d3f1a384" + }, + sequence: 4294967295 + } + ], + vout: [ + { + value: 5e-8, + n: 0, + scriptPubKey: { + asm: + "OP_DUP OP_HASH160 ef6639af5e3f5beb577f327f09ec3b0708cb03f1 OP_EQUALVERIFY OP_CHECKSIG", + hex: "76a914ef6639af5e3f5beb577f327f09ec3b0708cb03f188ac", + reqSigs: 1, + type: "pubkeyhash", + addresses: ["n3LnFeCEuo6zcRS7kGuKx9URwnLXHaKonL"] + } + }, + { + value: 0.40164686, + n: 1, + scriptPubKey: { + asm: + "OP_DUP OP_HASH160 60ade08bbf58068ccbed250d4ee64c0a827745d3 OP_EQUALVERIFY OP_CHECKSIG", + hex: "76a91460ade08bbf58068ccbed250d4ee64c0a827745d388ac", + reqSigs: 1, + type: "pubkeyhash", + addresses: ["mpL9TfWHudvTkWPrtzwkcuD4mKoo7eXJo5"] + } + } + ], + hex: + "01000000014473be9b0ff6a1ce12c4e43b3bf7191fb13b2b6779233b0f190de97da1453162010000006b48304502210098a6a7a2329a7373ff838b3e816e8b48f94238dfbe08add7896ff95127ebfc310220541302168ae986ec6abbb0c5eea95f069621166fe841ba965ed6ea3bb351735c01210396cfa148d2fc150d225262836aaf4ed98da771a9c2f6bc54da03d402d3f1a384ffffffff0205000000000000001976a914ef6639af5e3f5beb577f327f09ec3b0708cb03f188ac4edd6402000000001976a91460ade08bbf58068ccbed250d4ee64c0a827745d388ac00000000" + } + ], + time: 1570176600, + mediantime: 1570170591, + nonce: 534459415, + bits: "1d00ffff", + difficulty: 1, + chainwork: + "00000000000000000000000000000000000000000000012b3c804ee0bb6e8fdf", + nTx: 469, + previousblockhash: + "000000006d7da16a58a4e56c790d1aeb4e08bce6dab68e03995f585b187551be", + nextblockhash: + "000000005104d2692a021f9b58932c3fa32ea15b97cbff2147e11ad24f9d49af" + }; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getblock({ blockhash, verbosity }); assert.deepStrictEqual(data, result); }); }); From c402ee8b34ce2783ef3618dc7e39bdc92bd3d99e Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 17:47:06 +0300 Subject: [PATCH 08/75] feat(rpc): add getblockchaininfo method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index f21d2c6..1ddd5b3 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -62,4 +62,11 @@ export class RPCClient extends RESTClient { async getblock({ blockhash, verbosity = 1 }: GetBlockParams) { return this.rpc("getblock", { blockhash, verbosity }); } + + /** + * @description Returns an object containing various state info regarding blockchain processing. + */ + async getblockchaininfo() { + return this.rpc("getblockchaininfo"); + } } From 18b139cb8f93a6e1d9f47ff48729409e70e2a877 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 17:47:21 +0300 Subject: [PATCH 09/75] doc(readme): add getblockchaininfo example --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 5e25e02..96165ee 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,12 @@ const verbosity = 2; const block = await client.getblock({ blockhash, verbosity }); ``` +- [`getblockchaininfo`](https://bitcoin.org/en/developer-reference#getblockchaininfo) + +```javascript +const info = await client.getblockchaininfo(); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 4b582034273a3e2e0773a5d925df44229bd509b2 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 17:47:40 +0300 Subject: [PATCH 10/75] test(rpc): add getblockchaininfo --- test/rpc.spec.ts | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 102de6e..19a193d 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -268,5 +268,55 @@ suite("RPCClient", () => { const data = await client.getblock({ blockhash, verbosity }); assert.deepStrictEqual(data, result); }); + + test(".getblockchaininfo()", async () => { + const request = { params: {}, method: "getblockchaininfo", id, jsonrpc }; + const result = { + chain: "test", + blocks: 1583781, + headers: 1583781, + bestblockhash: + "000000003572a2f04d0b30c644ae4281b37e9becde9fc8a17fb54253a1a07397", + difficulty: 1, + mediantime: 1571834687, + verificationprogress: 0.9999861133153368, + initialblockdownload: false, + chainwork: + "00000000000000000000000000000000000000000000012e44a73ad9f48c5bbb", + size_on_disk: 1004297599, + pruned: true, + pruneheight: 1566856, + automatic_pruning: true, + prune_target_size: 1073741824, + softforks: [ + { id: "bip34", version: 2, reject: { status: true } }, + { id: "bip66", version: 3, reject: { status: true } }, + { id: "bip65", version: 4, reject: { status: true } } + ], + bip9_softforks: { + csv: { + status: "active", + startTime: 1456790400, + timeout: 1493596800, + since: 770112 + }, + segwit: { + status: "active", + startTime: 1462060800, + timeout: 1493596800, + since: 834624 + } + }, + warnings: "Warning: unknown new rules activated (versionbit 28)" + }; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getblockchaininfo(); + assert.deepStrictEqual(data, result); + }); }); }); From bf7d58d7d8a7d17d2ff32e072fd1ed686144f5bf Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 17:51:33 +0300 Subject: [PATCH 11/75] feat(rpc): add getblockcount method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index 1ddd5b3..d4a174e 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -69,4 +69,11 @@ export class RPCClient extends RESTClient { async getblockchaininfo() { return this.rpc("getblockchaininfo"); } + + /** + * @description Returns the number of blocks in the longest blockchain. + */ + async getblockcount() { + return this.rpc("getblockcount"); + } } From 5b1f8b40e7e84384caa6663097f0e46ef392b109 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 17:51:49 +0300 Subject: [PATCH 12/75] doc(readme): add getblockcount example --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 96165ee..144d8bc 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,12 @@ const block = await client.getblock({ blockhash, verbosity }); const info = await client.getblockchaininfo(); ``` +- [`getblockcount`](https://bitcoin.org/en/developer-reference#getblockcount) + +```javascript +const count = await client.getblockcount(); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 3eece3f29b43f86cda1fdba243b1aac45065fe5c Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 17:52:12 +0300 Subject: [PATCH 13/75] test(rpc): add getblockcount --- test/rpc.spec.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 19a193d..ddc6d94 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -318,5 +318,18 @@ suite("RPCClient", () => { const data = await client.getblockchaininfo(); assert.deepStrictEqual(data, result); }); + + test(".getblockcount()", async () => { + const request = { params: {}, method: "getblockcount", id, jsonrpc }; + const result = 1583782; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getblockcount(); + assert.deepStrictEqual(data, result); + }); }); }); From 91f964d2f36758b816822e9a3c08ba96955494fd Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:02:33 +0300 Subject: [PATCH 14/75] feat(rpc): add getblockhash method --- src/rpc.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index d4a174e..7278a1f 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -16,6 +16,8 @@ export type JSONRPC = { export type Verbosity = { verbosity: 0 | 1 | 2 }; +export type Height = { height: number }; + export type Blockhash = { blockhash: string }; export type GetBlockParams = Verbosity & Blockhash; @@ -76,4 +78,11 @@ export class RPCClient extends RESTClient { async getblockcount() { return this.rpc("getblockcount"); } + + /** + * @description Returns hash of block in best-block-chain at height provided. + */ + async getblockhash({ height }: Height) { + return this.rpc("getblockhash", { height }); + } } From 4ce70d7e8ef5b1a23b723b61a7bf0c8f055f08be Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:02:55 +0300 Subject: [PATCH 15/75] doc(readme): add getblockhash example --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 144d8bc..b5a4010 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,13 @@ const info = await client.getblockchaininfo(); const count = await client.getblockcount(); ``` +- [`getblockhash`](https://bitcoin.org/en/developer-reference#getblockhash) + +```javascript +const height = 1583782; +const hash = await client.getblockhash({ height }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From a8168b88ff62d602a68099091b6dc21540de3859 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:03:17 +0300 Subject: [PATCH 16/75] test(rpc): add getblockhash --- test/rpc.spec.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index ddc6d94..15c1be2 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -1,4 +1,4 @@ -import { RPCClient } from "../."; +import { RPCClient, GetBlockParams } from "../."; import * as nock from "nock"; import * as assert from "assert"; @@ -132,7 +132,7 @@ suite("RPCClient", () => { const blockhash = "000000004182034f427d463b92162d35d0accef9ea0c5354a87e870ca1815b4c"; const verbosity = 2; - const params = { blockhash, verbosity }; + const params: GetBlockParams = { blockhash, verbosity }; const request = { params, method: "getblock", id, jsonrpc }; const result = { hash: @@ -265,7 +265,7 @@ suite("RPCClient", () => { .times(1) .basicAuth(auth) .reply(200, response); - const data = await client.getblock({ blockhash, verbosity }); + const data = await client.getblock(params); assert.deepStrictEqual(data, result); }); @@ -331,5 +331,21 @@ suite("RPCClient", () => { const data = await client.getblockcount(); assert.deepStrictEqual(data, result); }); + + test(".getblockhash()", async () => { + const height = 1583782; + const params = { height }; + const request = { params, method: "getblockhash", id, jsonrpc }; + const result = + "00000000a4991fe43933f0a0bde13b6b22b4308442453845903151004e9cc0a5"; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getblockhash(params); + assert.deepStrictEqual(data, result); + }); }); }); From 4e9d5ea370cd75cfb4cc95d10297a5c45784a582 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:12:14 +0300 Subject: [PATCH 17/75] feat(rpc): add getblockheader method --- src/rpc.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index 7278a1f..9387f40 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -22,6 +22,8 @@ export type Blockhash = { blockhash: string }; export type GetBlockParams = Verbosity & Blockhash; +export type GetBlockHeaderParams = Blockhash & { verbose: boolean }; + export class RPCClient extends RESTClient { wallet?: string; fullResponse?: boolean; @@ -85,4 +87,11 @@ export class RPCClient extends RESTClient { async getblockhash({ height }: Height) { return this.rpc("getblockhash", { height }); } + + /** + * @description If verbose is `false`, returns a string that is serialized, hex-encoded data for blockheader 'hash'. If verbose is `true`, returns an Object with information about blockheader . + */ + async getblockheader({ blockhash, verbose = true }: GetBlockHeaderParams) { + return this.rpc("getblockheader", { blockhash, verbose }); + } } From f163a03fe245cc9574adcf0d7e7bc5d45e913972 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:12:28 +0300 Subject: [PATCH 18/75] doc(reamde): add getblockheader example --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index b5a4010..3400862 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,15 @@ const height = 1583782; const hash = await client.getblockhash({ height }); ``` +- [`getblockheader`](https://bitcoin.org/en/developer-reference#getblockheader) + +```javascript +const blockhash = + "000000004182034f427d463b92162d35d0accef9ea0c5354a87e870ca1815b4c"; +const verbose = false; +const header = await client.getblockheader({ blockhash, verbose }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From c34712182119165bc7756196dcbbd7ab5978c623 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:12:45 +0300 Subject: [PATCH 19/75] test(rpc): add getblockheader --- test/rpc.spec.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 15c1be2..e1507ef 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -347,5 +347,23 @@ suite("RPCClient", () => { const data = await client.getblockhash(params); assert.deepStrictEqual(data, result); }); + + test(".getblockheader()", async () => { + const blockhash = + "000000004182034f427d463b92162d35d0accef9ea0c5354a87e870ca1815b4c"; + const verbose = false; + const params = { blockhash, verbose }; + const request = { params, method: "getblockheader", id, jsonrpc }; + const result = + "00000020be5175185b585f99038eb6dae6bc084eeb1a0d796ce5a4586aa17d6d00000000f5c0b3856438c40ab89c9d3aa86801bc5536218a59a5f941d31981c831bbf3d358fe965dffff001d1734db1f"; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getblockheader(params); + assert.deepStrictEqual(data, result); + }); }); }); From 9a0beed87e4a6281c4f294b1156564e282a40410 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:21:47 +0300 Subject: [PATCH 20/75] feat(rpc): add getblockstats method --- src/rpc.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index 9387f40..9fdf907 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -24,6 +24,11 @@ export type GetBlockParams = Verbosity & Blockhash; export type GetBlockHeaderParams = Blockhash & { verbose: boolean }; +export type GetBlockStatsParams = { + hash_or_height: string | number; + stats?: string[]; +}; + export class RPCClient extends RESTClient { wallet?: string; fullResponse?: boolean; @@ -94,4 +99,11 @@ export class RPCClient extends RESTClient { async getblockheader({ blockhash, verbose = true }: GetBlockHeaderParams) { return this.rpc("getblockheader", { blockhash, verbose }); } + + /** + * @description Compute per block statistics for a given window. + */ + async getblockstats({ hash_or_height, stats = [] }: GetBlockStatsParams) { + return this.rpc("getblockstats", { hash_or_height, stats }); + } } From cf27795253b0993a6689b1b6fd4857268f369ee1 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:22:05 +0300 Subject: [PATCH 21/75] doc(readme): add getblockstats example --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 3400862..c175efe 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,15 @@ const verbose = false; const header = await client.getblockheader({ blockhash, verbose }); ``` +- [`getblockstats`](https://bitcoin.org/en/developer-reference#getblockstats) + +```javascript +const hash_or_height = + "000000004182034f427d463b92162d35d0accef9ea0c5354a87e870ca1815b4c"; +const stats = ["txs", "time"]; +const info = await client.getblockstats({ hash_or_height, stats }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From d097852ed37dba7e647caa0fe7f906bce37b674a Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:22:28 +0300 Subject: [PATCH 22/75] test(rpc): add getblockstats --- test/rpc.spec.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index e1507ef..871588c 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -365,5 +365,22 @@ suite("RPCClient", () => { const data = await client.getblockheader(params); assert.deepStrictEqual(data, result); }); + + test(".getblockstats()", async () => { + const hash_or_height = + "000000004182034f427d463b92162d35d0accef9ea0c5354a87e870ca1815b4c"; + const stats = ["txs", "time"]; + const params = { hash_or_height, stats }; + const request = { params, method: "getblockstats", id, jsonrpc }; + const result = { time: 1570176600, txs: 469 }; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getblockstats(params); + assert.deepStrictEqual(data, result); + }); }); }); From ccb60a86ae6e68dbb38a9f12ef584d7338b74251 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:26:37 +0300 Subject: [PATCH 23/75] feat(rpc): add getchaintips method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index 9fdf907..2d315dd 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -106,4 +106,11 @@ export class RPCClient extends RESTClient { async getblockstats({ hash_or_height, stats = [] }: GetBlockStatsParams) { return this.rpc("getblockstats", { hash_or_height, stats }); } + + /** + * @description Return information about all known tips in the block tree, including the main chain as well as orphaned branches. + */ + async getchaintips() { + return this.rpc("getchaintips"); + } } From e5b24dbec45dd2a00a953ef7a1df7cefce1e0090 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:26:50 +0300 Subject: [PATCH 24/75] doc(readme): add getchaintips example --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index c175efe..58739f5 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,12 @@ const stats = ["txs", "time"]; const info = await client.getblockstats({ hash_or_height, stats }); ``` +- [`getchaintips`](https://bitcoin.org/en/developer-reference#getchaintips) + +```javascript +const tips = await client.getchaintips(); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 1a7da009de234df80111eb5322afb13a21d5ee7c Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:27:04 +0300 Subject: [PATCH 25/75] test(rpc): add getchaintips --- test/rpc.spec.ts | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 871588c..62ff29b 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -382,5 +382,47 @@ suite("RPCClient", () => { const data = await client.getblockstats(params); assert.deepStrictEqual(data, result); }); + + test(".getchaintips()", async () => { + const request = { params: {}, method: "getchaintips", id, jsonrpc }; + const result = [ + { + height: 1583784, + hash: + "0000000071434abcdf7b2a82fb3005a67fe9f458e542a586313f5a7dc671a0c9", + branchlen: 0, + status: "active" + }, + { + height: 1580960, + hash: + "000000006999656106c726515ccfc34d160a5fa299ddb6bb278598b2feefaa7e", + branchlen: 1, + status: "valid-fork" + }, + { + height: 1580787, + hash: + "0000000029515fe9800761af4c19a087525ad9f3a1e41c4d1b136993711c3f83", + branchlen: 1, + status: "valid-fork" + }, + { + height: 1414433, + hash: + "00000000210004840364b52bc5e455d888f164e4264a4fec06a514b67e9d5722", + branchlen: 23, + status: "headers-only" + } + ]; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getchaintips(); + assert.deepStrictEqual(data, result); + }); }); }); From 49e01dcf101ee83fdbb0171a9609d439dc5a6904 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:38:08 +0300 Subject: [PATCH 26/75] feat(rpc): add getchaintxstats method --- src/rpc.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index 2d315dd..13951f1 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -29,6 +29,11 @@ export type GetBlockStatsParams = { stats?: string[]; }; +export type GetChainTxStatsParams = { + nblocks?: number; + blockhash?: string; +}; + export class RPCClient extends RESTClient { wallet?: string; fullResponse?: boolean; @@ -113,4 +118,11 @@ export class RPCClient extends RESTClient { async getchaintips() { return this.rpc("getchaintips"); } + + /** + * @description Compute statistics about the total number and rate of transactions in the chain. + */ + async getchaintxstats({ nblocks, blockhash }: GetChainTxStatsParams) { + return this.rpc("getchaintxstats", { nblocks, blockhash }); + } } From 5df34f561a5daaaa8b0856497063f245b8f07614 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:38:41 +0300 Subject: [PATCH 27/75] doc(readme): add getchaintxstats example --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 58739f5..c6656f3 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,15 @@ const info = await client.getblockstats({ hash_or_height, stats }); const tips = await client.getchaintips(); ``` +- [`getchaintxstats`](https://bitcoin.org/en/developer-reference#getchaintxstats) + +```javascript +const nblocks = 2016; +const blockhash = + "000000004182034f427d463b92162d35d0accef9ea0c5354a87e870ca1815b4c"; +const data = await client.getchaintxstats({ nblocks, blockhash }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 3524f7a62a967f01d682dccb4044e0660ad69951 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:38:54 +0300 Subject: [PATCH 28/75] test(rpc): add getchaintxstats --- test/rpc.spec.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 62ff29b..d70de81 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -424,5 +424,31 @@ suite("RPCClient", () => { const data = await client.getchaintips(); assert.deepStrictEqual(data, result); }); + + test(".getchaintxstats()", async () => { + const nblocks = 2016; + const blockhash = + "000000004182034f427d463b92162d35d0accef9ea0c5354a87e870ca1815b4c"; + const params = { nblocks, blockhash }; + const request = { params, method: "getchaintxstats", id, jsonrpc }; + const result = { + time: 1570176600, + txcount: 52393515, + window_final_block_hash: + "000000004182034f427d463b92162d35d0accef9ea0c5354a87e870ca1815b4c", + window_block_count: 2016, + window_tx_count: 274713, + window_interval: 1731648, + txrate: 0.1586425185719038 + }; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getchaintxstats(params); + assert.deepStrictEqual(data, result); + }); }); }); From 0db657ede1cea23d4837291e29baf835412fc36d Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:41:44 +0300 Subject: [PATCH 29/75] feat(rpc): add getdifficulty method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index 13951f1..2f192d8 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -125,4 +125,11 @@ export class RPCClient extends RESTClient { async getchaintxstats({ nblocks, blockhash }: GetChainTxStatsParams) { return this.rpc("getchaintxstats", { nblocks, blockhash }); } + + /** + * @description Returns the proof-of-work difficulty as a multiple of the minimum difficulty. + */ + async getdifficulty() { + return this.rpc("getdifficulty"); + } } From 5b31929a1d5cf7ca31c534ce6008fa634b25bd3c Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:42:01 +0300 Subject: [PATCH 30/75] doc(readme): add getdifficulty example --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index c6656f3..974869b 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,12 @@ const blockhash = const data = await client.getchaintxstats({ nblocks, blockhash }); ``` +- [`getdifficulty`](https://bitcoin.org/en/developer-reference#getdifficulty) + +```javascript +const difficulty = await client.getdifficulty(); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 62c0ffc8560b745331b5c6d1c661bb8092e38f03 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:42:12 +0300 Subject: [PATCH 31/75] test(rpc): add getdifficulty --- test/rpc.spec.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index d70de81..eec14fe 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -450,5 +450,18 @@ suite("RPCClient", () => { const data = await client.getchaintxstats(params); assert.deepStrictEqual(data, result); }); + + test(".getdifficulty()", async () => { + const request = { params: {}, method: "getdifficulty", id, jsonrpc }; + const result = 1; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getdifficulty(); + assert.deepStrictEqual(data, result); + }); }); }); From 09a8937028132a9266faca269cb27957ba03d739 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:57:46 +0300 Subject: [PATCH 32/75] feat(rpc): add getmempoolancestors method --- src/rpc.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/rpc.ts b/src/rpc.ts index 2f192d8..c87b8fc 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -14,15 +14,19 @@ export type JSONRPC = { params?: any; }; -export type Verbosity = { verbosity: 0 | 1 | 2 }; +export type Verbosity = { verbosity?: 0 | 1 | 2 }; + +export type Verbose = { verbose?: boolean }; export type Height = { height: number }; export type Blockhash = { blockhash: string }; +export type TxId = { txid: string }; + export type GetBlockParams = Verbosity & Blockhash; -export type GetBlockHeaderParams = Blockhash & { verbose: boolean }; +export type GetBlockHeaderParams = Blockhash & Verbose; export type GetBlockStatsParams = { hash_or_height: string | number; @@ -34,6 +38,8 @@ export type GetChainTxStatsParams = { blockhash?: string; }; +export type GetMemPoolParams = TxId & Verbose; + export class RPCClient extends RESTClient { wallet?: string; fullResponse?: boolean; @@ -132,4 +138,11 @@ export class RPCClient extends RESTClient { async getdifficulty() { return this.rpc("getdifficulty"); } + + /** + * @description If txid is in the mempool, returns all in-mempool ancestors. + */ + async getmempoolancestors({ txid, verbose = false }: GetMemPoolParams) { + return this.rpc("getmempoolancestors", { txid, verbose }); + } } From a2528ef4195aa339657f798bffd6d7541faba2f7 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:58:05 +0300 Subject: [PATCH 33/75] doc(readme): add getmempoolancestors example --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 974869b..ebe9e70 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,14 @@ const data = await client.getchaintxstats({ nblocks, blockhash }); const difficulty = await client.getdifficulty(); ``` +- [`getmempoolancestors`](https://bitcoin.org/en/developer-reference#getmempoolancestors) + +```javascript +const verbose = true; +const txid = "3e128c38f35520d4121d582f15998b7f74b44f17aa650b4d60decf975e642b9a"; +const data = await client.getmempoolancestors({ txid, verbose }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From d411f8d1129992acd2e7c8dcb56c0f9e8825e8e8 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:58:28 +0300 Subject: [PATCH 34/75] test(rpc): add getmempoolancestors --- test/rpc.spec.ts | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index eec14fe..10fb2a5 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -463,5 +463,49 @@ suite("RPCClient", () => { const data = await client.getdifficulty(); assert.deepStrictEqual(data, result); }); + + test(".getmempoolancestors()", async () => { + const verbose = true; + const txid = + "3e128c38f35520d4121d582f15998b7f74b44f17aa650b4d60decf975e642b9a"; + const params = { verbose, txid }; + const request = { params, method: "getmempoolancestors", id, jsonrpc }; + const result = { + ff758ffd73729be8afae0d683547f7840bdaee75ad5e5c464fb621b2509c366b: { + fees: { + base: 0.00000208, + modified: 0.00000208, + ancestor: 0.00000208, + descendant: 0.00000349 + }, + size: 208, + fee: 0.00000208, + modifiedfee: 0.00000208, + time: 1571845913, + height: 1583786, + descendantcount: 2, + descendantsize: 349, + descendantfees: 349, + ancestorcount: 1, + ancestorsize: 208, + ancestorfees: 208, + wtxid: + "4ec7101b17a19ad11c6b738330303f9baa30c0aabc3e56ce8735d019fcff13e7", + depends: [], + spentby: [ + "3e128c38f35520d4121d582f15998b7f74b44f17aa650b4d60decf975e642b9a" + ], + "bip125-replaceable": true + } + }; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getmempoolancestors(params); + assert.deepStrictEqual(data, result); + }); }); }); From 90a73858d9d626911f65f8d02db5bf9adb007b8f Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:58:49 +0300 Subject: [PATCH 35/75] feat(rpc): add getmempooldescendants method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index c87b8fc..1980500 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -145,4 +145,11 @@ export class RPCClient extends RESTClient { async getmempoolancestors({ txid, verbose = false }: GetMemPoolParams) { return this.rpc("getmempoolancestors", { txid, verbose }); } + + /** + * @description If txid is in the mempool, returns all in-mempool descendants. + */ + async getmempooldescendants({ txid, verbose = false }: GetMemPoolParams) { + return this.rpc("getmempooldescendants", { txid, verbose }); + } } From b46fe26ef0687d8d5c685e49abbdcd6c68303f20 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:59:04 +0300 Subject: [PATCH 36/75] doc(readme): add getmempooldescendants example --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index ebe9e70..ac71a55 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,14 @@ const txid = "3e128c38f35520d4121d582f15998b7f74b44f17aa650b4d60decf975e642b9a"; const data = await client.getmempoolancestors({ txid, verbose }); ``` +- [`getmempooldescendants`](https://bitcoin.org/en/developer-reference#getmempooldescendants) + +```javascript +const verbose = true; +const txid = "ff758ffd73729be8afae0d683547f7840bdaee75ad5e5c464fb621b2509c366b"; +const data = await client.getmempooldescendants({ txid, verbose }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 63442371964edc6a619ea530735fe7cc1f41b4b3 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 18:59:24 +0300 Subject: [PATCH 37/75] test(rpc): add getmempooldescendants --- test/rpc.spec.ts | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 10fb2a5..7a4d272 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -507,5 +507,49 @@ suite("RPCClient", () => { const data = await client.getmempoolancestors(params); assert.deepStrictEqual(data, result); }); + + test(".getmempooldescendants()", async () => { + const verbose = true; + const txid = + "ff758ffd73729be8afae0d683547f7840bdaee75ad5e5c464fb621b2509c366b"; + const params = { verbose, txid }; + const request = { params, method: "getmempooldescendants", id, jsonrpc }; + const result = { + "3e128c38f35520d4121d582f15998b7f74b44f17aa650b4d60decf975e642b9a": { + fees: { + base: 0.00000141, + modified: 0.00000141, + ancestor: 0.00000349, + descendant: 0.00000141 + }, + size: 141, + fee: 0.00000141, + modifiedfee: 0.00000141, + time: 1571845933, + height: 1583786, + descendantcount: 1, + descendantsize: 141, + descendantfees: 141, + ancestorcount: 2, + ancestorsize: 349, + ancestorfees: 349, + wtxid: + "6a2704699b5935b96a9c008b21518e99990cf099a6977760d56aec350b2d9d66", + depends: [ + "ff758ffd73729be8afae0d683547f7840bdaee75ad5e5c464fb621b2509c366b" + ], + spentby: [], + "bip125-replaceable": true + } + }; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getmempooldescendants(params); + assert.deepStrictEqual(data, result); + }); }); }); From 43c0fbab7c1b0ee4051e18151a73ed7f99502228 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:04:03 +0300 Subject: [PATCH 38/75] feat(rpc): add getmempoolentry method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index 1980500..4ca5c61 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -152,4 +152,11 @@ export class RPCClient extends RESTClient { async getmempooldescendants({ txid, verbose = false }: GetMemPoolParams) { return this.rpc("getmempooldescendants", { txid, verbose }); } + + /** + * @description Returns mempool data for given transaction + */ + async getmempoolentry({ txid }: TxId) { + return this.rpc("getmempoolentry", { txid }); + } } From 61a816a4cf5716faa05119ddb814d01654ea1457 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:04:34 +0300 Subject: [PATCH 39/75] doc(readme): add getmempoolentry example --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index ac71a55..9f22eb3 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,13 @@ const txid = "ff758ffd73729be8afae0d683547f7840bdaee75ad5e5c464fb621b2509c366b"; const data = await client.getmempooldescendants({ txid, verbose }); ``` +- [`getmempoolentry`](https://bitcoin.org/en/developer-reference#getmempoolentry) + +```javascript +const txid = "0629e01f05088728b089715f247de82a160428c06d6c85484adab2aa66574ace"; +const data = await client.getmempoolentry({ txid }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 61d1bdbec7fa3cee26665bacd2eef55ed3374926 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:04:44 +0300 Subject: [PATCH 40/75] test(rpc): add getmempoolentry --- test/rpc.spec.ts | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 7a4d272..c85791c 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -551,5 +551,46 @@ suite("RPCClient", () => { const data = await client.getmempooldescendants(params); assert.deepStrictEqual(data, result); }); + + test(".getmempoolentry()", async () => { + const txid = + "0629e01f05088728b089715f247de82a160428c06d6c85484adab2aa66574ace"; + const params = { txid }; + const request = { params, method: "getmempoolentry", id, jsonrpc }; + const result = { + fees: { + base: 0.00000148, + modified: 0.00000148, + ancestor: 0.00000391, + descendant: 0.00000148 + }, + size: 146, + fee: 0.00000148, + modifiedfee: 0.00000148, + time: 1571846114, + height: 1583786, + descendantcount: 1, + descendantsize: 146, + descendantfees: 148, + ancestorcount: 2, + ancestorsize: 389, + ancestorfees: 391, + wtxid: + "cf5208ea2196816473a315504b5476fb4e75a16fb4584dda92093b72901bde08", + depends: [ + "f594f57099cd6e1c4d0697ad92795196a1774ea752d1bec481019abd3eef30ee" + ], + spentby: [], + "bip125-replaceable": false + }; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getmempoolentry(params); + assert.deepStrictEqual(data, result); + }); }); }); From d9cec3b45ddf9f7140d6c376d871a92d9e59d070 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:08:00 +0300 Subject: [PATCH 41/75] feat(rpc): add getmempoolinfo method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index 4ca5c61..d506f61 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -159,4 +159,11 @@ export class RPCClient extends RESTClient { async getmempoolentry({ txid }: TxId) { return this.rpc("getmempoolentry", { txid }); } + + /** + * @description Returns details on the active state of the TX memory pool. + */ + async getmempoolinfo() { + return this.rpc("getmempoolinfo"); + } } From 8c00182853d39a96d1684f14e6e42534c92ae905 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:08:11 +0300 Subject: [PATCH 42/75] doc(readme): add getmempoolinfo example --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 9f22eb3..8ed18e4 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,12 @@ const txid = "0629e01f05088728b089715f247de82a160428c06d6c85484adab2aa66574ace"; const data = await client.getmempoolentry({ txid }); ``` +- [`getmempoolinfo`](https://bitcoin.org/en/developer-reference#getmempoolinfo) + +```javascript +const info = await client.getmempoolinfo(); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 1db12db0110148448effd48ece5683303ebccbd1 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:08:38 +0300 Subject: [PATCH 43/75] test(rpc): add getmempoolinfo --- test/rpc.spec.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index c85791c..754b512 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -592,5 +592,25 @@ suite("RPCClient", () => { const data = await client.getmempoolentry(params); assert.deepStrictEqual(data, result); }); + + test(".getmempoolinfo()", async () => { + const request = { params: {}, method: "getmempoolinfo", id, jsonrpc }; + const result = { + size: 208, + bytes: 73712, + usage: 362416, + maxmempool: 300000000, + mempoolminfee: 0.00001, + minrelaytxfee: 0.00001 + }; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getmempoolinfo(); + assert.deepStrictEqual(data, result); + }); }); }); From 9e7e8906aabf259b8162bd5592a73fdf91809487 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:14:51 +0300 Subject: [PATCH 44/75] feat(rpc): add getrawmempool method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index d506f61..e242540 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -166,4 +166,11 @@ export class RPCClient extends RESTClient { async getmempoolinfo() { return this.rpc("getmempoolinfo"); } + + /** + * @description Returns all transaction ids in memory pool as a json array of string transaction ids. + */ + async getrawmempool({ verbose = false }: Verbose = {}) { + return this.rpc("getrawmempool", { verbose }); + } } From 47c006ee226973d16adc6630e6cdc3b1d4e0905c Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:15:09 +0300 Subject: [PATCH 45/75] doc(readme): add getrawmempool example --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 8ed18e4..6509b71 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,13 @@ const data = await client.getmempoolentry({ txid }); const info = await client.getmempoolinfo(); ``` +- [`getrawmempool`](https://bitcoin.org/en/developer-reference#getrawmempool) + +```javascript +const verbose = true; +const data = await client.getrawmempool({ verbose }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 2ff121f7f2be8404add8980fbb0a7189d9a41be3 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:15:27 +0300 Subject: [PATCH 46/75] test(rpc): add getrawmempool --- test/rpc.spec.ts | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 754b512..201c77b 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -612,5 +612,69 @@ suite("RPCClient", () => { const data = await client.getmempoolinfo(); assert.deepStrictEqual(data, result); }); + + test(".getrawmempool()", async () => { + const verbose = true; + const params = { verbose }; + const request = { params, method: "getrawmempool", id, jsonrpc }; + const result = { + "9d4e511e5138b90cf530e1b33e391bf2f04f68a6d5bec3218b03d353655e3769": { + fees: { + base: 0.00000543, + modified: 0.00000543, + ancestor: 0.00000543, + descendant: 0.00000543 + }, + size: 149, + fee: 0.00000543, + modifiedfee: 0.00000543, + time: 1571846917, + height: 1583787, + descendantcount: 1, + descendantsize: 149, + descendantfees: 543, + ancestorcount: 1, + ancestorsize: 149, + ancestorfees: 543, + wtxid: + "957c764cede26364705436977e087039f4a8fb9d68c51c9db9e2347dbd12a120", + depends: [], + spentby: [], + "bip125-replaceable": true + }, + "2275109000640d8e45ec8e23cf74ba8a82850bb5c01993972f1a40dd20fa9484": { + fees: { + base: 0.00016797, + modified: 0.00016797, + ancestor: 0.00016797, + descendant: 0.00016797 + }, + size: 166, + fee: 0.00016797, + modifiedfee: 0.00016797, + time: 1571846920, + height: 1583787, + descendantcount: 1, + descendantsize: 166, + descendantfees: 16797, + ancestorcount: 1, + ancestorsize: 166, + ancestorfees: 16797, + wtxid: + "7b05abb26d64d6c39d1f483a2cac992c3ebad77f9240fadeeee90649ffbc9092", + depends: [], + spentby: [], + "bip125-replaceable": false + } + }; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.getrawmempool(params); + assert.deepStrictEqual(data, result); + }); }); }); From 29a7105bb2de02eeaa3eaf503c39094ee24a6a42 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:24:04 +0300 Subject: [PATCH 47/75] feat(rpc): add gettxout method --- src/rpc.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index e242540..8ea4761 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -40,6 +40,11 @@ export type GetChainTxStatsParams = { export type GetMemPoolParams = TxId & Verbose; +export type GetTxOutParams = TxId & { + n: number; + include_mempool?: boolean; +}; + export class RPCClient extends RESTClient { wallet?: string; fullResponse?: boolean; @@ -173,4 +178,11 @@ export class RPCClient extends RESTClient { async getrawmempool({ verbose = false }: Verbose = {}) { return this.rpc("getrawmempool", { verbose }); } + + /** + * @description Returns details about an unspent transaction output. + */ + async gettxout({ txid, n, include_mempool = true }: GetTxOutParams) { + return this.rpc("gettxout", { txid, n, include_mempool }); + } } From d136f1c08186ec4778d4315d3da6e1646477b8b0 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:24:22 +0300 Subject: [PATCH 48/75] doc(readme): add gettxout example --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 6509b71..ef59712 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,15 @@ const verbose = true; const data = await client.getrawmempool({ verbose }); ``` +- [`gettxout`](https://bitcoin.org/en/developer-reference#gettxout) + +```javascript +const txid = "d2f6b1d1844e483ce350a4a22fbaef36c31ebe88730415b7408c1f34b834fab5"; +const n = 1; +const include_mempool = true; +const data = await client.gettxout({ txid, n, include_mempool }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 1210021c29ca8383b943433473b294ab70b8c583 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:24:43 +0300 Subject: [PATCH 49/75] test(rpc): add gettxout --- test/rpc.spec.ts | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 201c77b..a1eebbd 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -676,5 +676,36 @@ suite("RPCClient", () => { const data = await client.getrawmempool(params); assert.deepStrictEqual(data, result); }); + + test(".gettxout()", async () => { + const txid = + "d2f6b1d1844e483ce350a4a22fbaef36c31ebe88730415b7408c1f34b834fab5"; + const n = 1; + const include_mempool = true; + const params = { txid, n, include_mempool }; + const request = { params, method: "gettxout", id, jsonrpc }; + const result = { + bestblock: + "000000000000006b3157f2f7d8cda21be0204863c93521e9afa05615436deb71", + confirmations: 0, + value: 76.67255676, + scriptPubKey: { + asm: "OP_HASH160 f2420e17b443ea418ec4c6ac97affaafd48eca70 OP_EQUAL", + hex: "a914f2420e17b443ea418ec4c6ac97affaafd48eca7087", + reqSigs: 1, + type: "scripthash", + addresses: ["2NFLAeHuBzrMfqQHfCtnKErNJSF3fqysUhF"] + }, + coinbase: false + }; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.gettxout(params); + assert.deepStrictEqual(data, result); + }); }); }); From 6a03c60470919eb7dd58e336e256047dc1d8d01e Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:31:04 +0300 Subject: [PATCH 50/75] feat(rpc): add gettxoutproof method --- src/rpc.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index 8ea4761..fa9ccb1 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -45,6 +45,8 @@ export type GetTxOutParams = TxId & { include_mempool?: boolean; }; +export type GetTxOutProofParams = { txids: string[]; blockhash?: string }; + export class RPCClient extends RESTClient { wallet?: string; fullResponse?: boolean; @@ -185,4 +187,11 @@ export class RPCClient extends RESTClient { async gettxout({ txid, n, include_mempool = true }: GetTxOutParams) { return this.rpc("gettxout", { txid, n, include_mempool }); } + + /** + * @description Returns a hex-encoded proof that "txid" was included in a block. + */ + async gettxoutproof({ txids, blockhash }: GetTxOutProofParams) { + return this.rpc("gettxoutproof", { txids, blockhash }); + } } From f90a4d1c23295f39f33a4851a75db9d9ff58f56a Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:31:17 +0300 Subject: [PATCH 51/75] doc(readme): add gettxoutproof example --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index ef59712..9759fd1 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,17 @@ const include_mempool = true; const data = await client.gettxout({ txid, n, include_mempool }); ``` +- [`gettxoutproof`](https://bitcoin.org/en/developer-reference#gettxoutproof) + +```javascript +const txids = [ + "42e75d074cf5b836170d20fc09593245c65a3f07283a497c3350c4d109b38bb6" +]; +const blockhash = + "000000000000000000055bc30b762904ab996430603cafe846cc6adc82c4af1e"; +const data = await client.gettxoutproof({ txids, blockhash }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 4ae930d679a9bac27bf8fec52190548890c218f4 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 19:31:48 +0300 Subject: [PATCH 52/75] test(rpc): add gettxoutproof --- test/rpc.spec.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index a1eebbd..13ce64c 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -707,5 +707,25 @@ suite("RPCClient", () => { const data = await client.gettxout(params); assert.deepStrictEqual(data, result); }); + + test(".gettxoutproof()", async () => { + const txids = [ + "e50c4bf07ca16e5089bf8c4f4b4d12b4e6b2bb47b09d533ebaa395342c756b95" + ]; + const blockhash = + "000000005a9b7656024e9d1a2a0e559b91dcc5756048ce4904ba877686f0eecc"; + const params = { txids, blockhash }; + const request = { params, method: "gettxoutproof", id, jsonrpc }; + const result = + "00000020e798ee174759ba2eb4f57c8055eaadb903aeef74a407878265361d00000000005c70c7f197058b8ff6f06d9f144497d1801e057e06735a56b658ac78ff915516fa7ab05dffff001d32384563dd00000009eeeb7a022e70291fe3d8d5186615358d45107c10d71a212459b30fe73174494f956b752c3495a3ba3e539db047bbb2e6b4124d4b4f8cbf89506ea17cf04b0ce5864f91edb21f1918fb1031d5545c7b835fb82d8cdc87f1df76808c599bbcb4e372e0788a9ce2c9b2f1a07305b7bea5e1fca0b19f77d919e51e2e72e438c19df5a953ce7bad42e1c78372ad2df199a08c26153f7846f6cc95c4615572bc997b45803b803c49e6298dec1a9029c32addac44f2abbc8c496def1f47a6ff55d8f90901b66efccdea0dcb52c26d610c4f2ac0b1e699ee4606918ff9901c317919038a5a3f3cedf7d664a2891fe1e116dc52e9ca9166e4e8a6398b10072412ef3893693508204127c87c8c025dded104f34ceeb44958095571907e6787615929cbc8cd03ff0200"; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.gettxoutproof(params); + assert.deepStrictEqual(data, result); + }); }); }); From 044734ad002d9f5e274870f8497e92917c38ed40 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 20:09:03 +0300 Subject: [PATCH 53/75] feat(rpc): add gettxoutsetinfo method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index fa9ccb1..7a38077 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -194,4 +194,11 @@ export class RPCClient extends RESTClient { async gettxoutproof({ txids, blockhash }: GetTxOutProofParams) { return this.rpc("gettxoutproof", { txids, blockhash }); } + + /** + * @description Returns statistics about the unspent transaction output set. + */ + async gettxoutsetinfo() { + return this.rpc("gettxoutsetinfo"); + } } From 7fd169cb57e31e48776d80bb278c090ea4afc438 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 20:09:32 +0300 Subject: [PATCH 54/75] doc(readme): add gettxoutsetinfo example --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 9759fd1..5f2e41e 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,12 @@ const blockhash = const data = await client.gettxoutproof({ txids, blockhash }); ``` +- [`gettxoutsetinfo`](https://bitcoin.org/en/developer-reference#gettxoutsetinfo) + +```javascript +const info = await client.gettxoutsetinfo(); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 601d8f66c91dea049e87351a4330cac0c7cd9a77 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 20:09:49 +0300 Subject: [PATCH 55/75] test(rpc): add gettxoutsetinfo --- test/rpc.spec.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 13ce64c..5a91d31 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -727,5 +727,29 @@ suite("RPCClient", () => { const data = await client.gettxoutproof(params); assert.deepStrictEqual(data, result); }); + + test(".gettxoutsetinfo()", async () => { + const request = { params: {}, method: "gettxoutsetinfo", id, jsonrpc }; + const result = { + height: 1583793, + bestblock: + "00000000000000b332c067ccb2cb52aafac5b7de4bec01470b6c634449e6ebbc", + transactions: 8345507, + txouts: 22946232, + bogosize: 1722061178, + hash_serialized_2: + "9b4021d53da6689371aa734ef32fe502ed38a47870db2802c48c8cde0a5c191e", + disk_size: 1256916738, + total_amount: 20879513.30609612 + }; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.gettxoutsetinfo(); + assert.deepStrictEqual(data, result); + }); }); }); From b44a8cfc2471f0452aa1c0d1438fa5e731ac6a41 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 20:15:01 +0300 Subject: [PATCH 56/75] feat(rpc): add preciousblock method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index 7a38077..d2ba185 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -201,4 +201,11 @@ export class RPCClient extends RESTClient { async gettxoutsetinfo() { return this.rpc("gettxoutsetinfo"); } + + /** + * @description Treats a block as if it were received before others with the same work. + */ + async preciousblock({ blockhash }: Blockhash) { + return this.rpc("preciousblock", { blockhash }); + } } From b0d1b798b3ae60787563fc6c7cf5468d5297c4f5 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 20:15:15 +0300 Subject: [PATCH 57/75] doc(readme): add preciousblock example --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 5f2e41e..6f1c7ad 100644 --- a/README.md +++ b/README.md @@ -167,6 +167,14 @@ const data = await client.gettxoutproof({ txids, blockhash }); const info = await client.gettxoutsetinfo(); ``` +- [`preciousblock`](https://bitcoin.org/en/developer-reference#preciousblock) + +```javascript +const blockhash = + "00000000000000261a35cf378bf8fa1bf6ac87800d798ce2a11f581f562e92ba"; +const data = await client.preciousblock({ blockhash }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 4188b5d2e18fa8bad1952e578a5129b2dc71c98e Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 20:15:33 +0300 Subject: [PATCH 58/75] test(rpc): add preciousblock --- test/rpc.spec.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 5a91d31..9ca6e40 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -751,5 +751,21 @@ suite("RPCClient", () => { const data = await client.gettxoutsetinfo(); assert.deepStrictEqual(data, result); }); + + test(".preciousblock()", async () => { + const blockhash = + "00000000000000261a35cf378bf8fa1bf6ac87800d798ce2a11f581f562e92ba"; + const params = { blockhash }; + const request = { params, method: "preciousblock", id, jsonrpc }; + const result = null; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.preciousblock(params); + assert.deepStrictEqual(data, result); + }); }); }); From 0bbef0853215fda19fe13377d95c519a5a2e8409 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 20:54:01 +0300 Subject: [PATCH 59/75] feat(rpc): add pruneblockchain method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index d2ba185..e0df93a 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -208,4 +208,11 @@ export class RPCClient extends RESTClient { async preciousblock({ blockhash }: Blockhash) { return this.rpc("preciousblock", { blockhash }); } + + /** + * @description Prune the blockchain. + */ + async pruneblockchain({ height }: Height) { + return this.rpc("pruneblockchain", { height }); + } } From 67e59d59daa80336e7672876dc2143cfc0b1da8e Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 20:54:18 +0300 Subject: [PATCH 60/75] doc(readme): add pruneblockchain example --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 6f1c7ad..0a9c2d5 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,13 @@ const blockhash = const data = await client.preciousblock({ blockhash }); ``` +- [`pruneblockchain`](https://bitcoin.org/en/developer-reference#pruneblockchain) + +```javascript +const height = 1000; +const result = await client.pruneblockchain({ height }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From ff083b233994182d2504d02652dd8065ab954a09 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 20:54:29 +0300 Subject: [PATCH 61/75] test(rpc): add pruneblockchain --- test/rpc.spec.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 9ca6e40..58d8194 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -767,5 +767,20 @@ suite("RPCClient", () => { const data = await client.preciousblock(params); assert.deepStrictEqual(data, result); }); + + test(".pruneblockchain()", async () => { + const height = 1000; + const params = { height }; + const request = { params, method: "pruneblockchain", id, jsonrpc }; + const result = 1566856; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.pruneblockchain(params); + assert.deepStrictEqual(data, result); + }); }); }); From 1736d145d60eba10f7dbda74b782489c5bec0601 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 20:57:52 +0300 Subject: [PATCH 62/75] feat(rpc): add savemempool method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index e0df93a..c86cd43 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -215,4 +215,11 @@ export class RPCClient extends RESTClient { async pruneblockchain({ height }: Height) { return this.rpc("pruneblockchain", { height }); } + + /** + * @description Dumps the mempool to disk. It will fail until the previous dump is fully loaded. + */ + async savemempool() { + return this.rpc("savemempool"); + } } From a5eda9070b774fb144321d257bee42b11799e006 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 20:58:09 +0300 Subject: [PATCH 63/75] doc(readme): add savemempool example --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 0a9c2d5..9b8de97 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,12 @@ const height = 1000; const result = await client.pruneblockchain({ height }); ``` +- [`savemempool`](https://bitcoin.org/en/developer-reference#savemempool) + +```javascript +const result = await client.savemempool(); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 0eca4311303f4d80d8dc0ca9506b1b5e79ba9097 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 20:58:46 +0300 Subject: [PATCH 64/75] test(rpc): add savemempool --- test/rpc.spec.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 58d8194..83d9342 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -782,5 +782,18 @@ suite("RPCClient", () => { const data = await client.pruneblockchain(params); assert.deepStrictEqual(data, result); }); + + test(".savemempool()", async () => { + const request = { params: {}, method: "savemempool", id, jsonrpc }; + const result = null; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.savemempool(); + assert.deepStrictEqual(data, result); + }); }); }); From 27cb284675b550e29fa55875af94f3421fb35247 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 21:42:29 +0300 Subject: [PATCH 65/75] metadata: bump version to 1.1.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 80ae57b..0076ded 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "rpc-bitcoin", - "version": "1.0.0", + "version": "1.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b68ca86..151d7e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rpc-bitcoin", - "version": "1.0.0", + "version": "1.1.0", "description": "A TypeScript library to make RPC and HTTP REST requests to Bitcoin Core", "main": "build/index.js", "type": "module", From e7a991009d1c9c7491bfea0a6721e54fd72fce96 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 21:46:48 +0300 Subject: [PATCH 66/75] feat(rpc): add scantxoutset method --- src/rpc.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index c86cd43..d52f7ff 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -47,6 +47,18 @@ export type GetTxOutParams = TxId & { export type GetTxOutProofParams = { txids: string[]; blockhash?: string }; +export type Descriptor = + | string + | { + desc: string; + range: number | [number, number]; + }; + +export type ScanTxOutSetParams = { + action: "start" | "abort" | "status"; + scanobjects: Descriptor[]; +}; + export class RPCClient extends RESTClient { wallet?: string; fullResponse?: boolean; @@ -222,4 +234,11 @@ export class RPCClient extends RESTClient { async savemempool() { return this.rpc("savemempool"); } + + /** + * @description Scans the unspent transaction output set for entries that match certain output descriptors. + */ + async scantxoutset({ action, scanobjects }: ScanTxOutSetParams) { + return this.rpc("scantxoutset", { action, scanobjects }); + } } From 95905f2b708181344edd524650520cbd4a0ca0e8 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 21:47:34 +0300 Subject: [PATCH 67/75] doc(readme): add scantxoutset example --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 9b8de97..f898169 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,21 @@ const result = await client.pruneblockchain({ height }); const result = await client.savemempool(); ``` +- [`scantxoutset`](https://bitcoin.org/en/developer-reference#scantxoutset) + +```javascript +const action = "start"; +const scanobjects = [ + "addr(mxosQ4CvQR8ipfWdRktyB3u16tauEdamGc)", + { + desc: + "wpkh([d34db33f/84'/0'/0']tpubD6NzVbkrYhZ4YTN7usjEzYmfu4JKqnfp9RCbDmdKH78vTyuwgQat8vRw5cX1YaZZvFfQrkHrM2XsyfA8cZE1thA3guTBfTkKqbhCDpcKFLG/0/*)#8gfuh6ex", + range: [1, 3] + } +]; +const result = await client.scantxoutset({ action, scanobjects }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 191917392b9a2243485a862e9a05b3e712e1005a Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 21:48:31 +0300 Subject: [PATCH 68/75] test(rpc): add scantxoutset --- test/rpc.spec.ts | 62 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 83d9342..f64ff58 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -1,4 +1,9 @@ -import { RPCClient, GetBlockParams } from "../."; +import { + RPCClient, + GetBlockParams, + ScanTxOutSetParams, + Descriptor +} from "../."; import * as nock from "nock"; import * as assert from "assert"; @@ -795,5 +800,60 @@ suite("RPCClient", () => { const data = await client.savemempool(); assert.deepStrictEqual(data, result); }); + + test(".scantxoutset()", async () => { + const action = "start"; + const desc_1 = "addr(mxosQ4CvQR8ipfWdRktyB3u16tauEdamGc)"; + const desc_2: Descriptor = { + desc: + "wpkh([d34db33f/84'/0'/0']tpubD6NzVbkrYhZ4YTN7usjEzYmfu4JKqnfp9RCbDmdKH78vTyuwgQat8vRw5cX1YaZZvFfQrkHrM2XsyfA8cZE1thA3guTBfTkKqbhCDpcKFLG/0/*)#8gfuh6ex", + range: [1, 20] + }; + const scanobjects = [desc_1, desc_2]; + const params: ScanTxOutSetParams = { action, scanobjects }; + const request = { params, method: "scantxoutset", id, jsonrpc }; + const result = { + success: true, + searched_items: 22946468, + unspents: [ + { + txid: + "ab78587c07c039d1e55dc0efc959ba872693f98dce9e749a53582125e692f408", + vout: 1, + scriptPubKey: "76a914bdad1f4d02035b61fb1d237410e85d8402a1187d88ac", + desc: "addr(mxosQ4CvQR8ipfWdRktyB3u16tauEdamGc)#7ca3vlzt", + amount: 0.08745533, + height: 1583799 + }, + { + txid: + "ed6f71276d0624989e8d572c98386e35c646cdce062c73ae0a1f554887d41aa5", + vout: 1, + scriptPubKey: "76a914bdad1f4d02035b61fb1d237410e85d8402a1187d88ac", + desc: "addr(mxosQ4CvQR8ipfWdRktyB3u16tauEdamGc)#7ca3vlzt", + amount: 0, + height: 1352790 + }, + { + txid: + "801d5821586dd0dc10123b17d284983d6c835b8aa616e0ee828721c9073ba7ea", + vout: 1, + scriptPubKey: "76a914bdad1f4d02035b61fb1d237410e85d8402a1187d88ac", + desc: "addr(mxosQ4CvQR8ipfWdRktyB3u16tauEdamGc)#7ca3vlzt", + amount: 0, + height: 1326382 + } + ], + total_amount: 0.08745533 + }; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.scantxoutset(params); + assert.deepStrictEqual(data, result); + }); }); }); From f2e38096fec7b281a732a94c47e0d609f83f82a3 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 21:53:33 +0300 Subject: [PATCH 69/75] feat(rpc): add verifychain method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index d52f7ff..2a16451 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -241,4 +241,11 @@ export class RPCClient extends RESTClient { async scantxoutset({ action, scanobjects }: ScanTxOutSetParams) { return this.rpc("scantxoutset", { action, scanobjects }); } + + /** + * @description Verifies blockchain database. + */ + async verifychain({ checklevel = 3, nblocks = 6 } = {}) { + return this.rpc("verifychain", { checklevel, nblocks }); + } } From 0ab3925cef80cbcad977597e4cbab6dbae5d55f7 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 21:53:59 +0300 Subject: [PATCH 70/75] doc(readme): add verifychain example --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index f898169..5897bc8 100644 --- a/README.md +++ b/README.md @@ -203,6 +203,14 @@ const scanobjects = [ const result = await client.scantxoutset({ action, scanobjects }); ``` +- [`verifychain`](https://bitcoin.org/en/developer-reference#verifychain) + +```javascript +const checklevel = 1; +const nblocks = 10; +const result = await client.verifychain({ checklevel, nblocks }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 0ec01b3fd28338106262b4b83e75ca565b36b0c2 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 21:54:15 +0300 Subject: [PATCH 71/75] test(rpc): add verifychain --- test/rpc.spec.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index f64ff58..1d76b20 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -855,5 +855,21 @@ suite("RPCClient", () => { const data = await client.scantxoutset(params); assert.deepStrictEqual(data, result); }); + + test(".verifychain()", async () => { + const checklevel = 1; + const nblocks = 10; + const params = { checklevel, nblocks }; + const request = { params, method: "verifychain", id, jsonrpc }; + const result = true; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.verifychain(params); + assert.deepStrictEqual(data, result); + }); }); }); From cfc4630960b93def131b2455355c8d8fc7bc3b7e Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 22:00:51 +0300 Subject: [PATCH 72/75] feat(rpc): add verifytxoutproof method --- src/rpc.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc.ts b/src/rpc.ts index 2a16451..a60c625 100644 --- a/src/rpc.ts +++ b/src/rpc.ts @@ -248,4 +248,11 @@ export class RPCClient extends RESTClient { async verifychain({ checklevel = 3, nblocks = 6 } = {}) { return this.rpc("verifychain", { checklevel, nblocks }); } + + /** + * @description Verifies that a proof points to a transaction in a block, returning the transaction it commits to and throwing an RPC error if the block is not in our best chain. + */ + async verifytxoutproof({ proof }: { proof: string }) { + return this.rpc("verifytxoutproof", { proof }); + } } From 5c130331c8906a21e61ece51cc1f5c0829e73434 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 22:01:04 +0300 Subject: [PATCH 73/75] doc(readme): add verifytxoutproof example --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 5897bc8..aa86d18 100644 --- a/README.md +++ b/README.md @@ -211,6 +211,14 @@ const nblocks = 10; const result = await client.verifychain({ checklevel, nblocks }); ``` +- [`verifytxoutproof`](https://bitcoin.org/en/developer-reference#verifytxoutproof) + +```javascript +const proof = + "00000020ed07b12f0398e45fd403db11dbe894dc3301ce1a7725424e0b5e460c0000000066fca14db436f305aea37b3ae0f8b188cbf112dff3854c3d419f3ff3ebbc821f6c0c975dffff001d8fd5a7d2eb00000009e7acd3f605d1b957d684d9eeca9c472d803d90c0d17e29e5606f9b080b177a4abcd854622ad3900b5bc1ae71e99699a05eb972d46bd439c08eb7fbd20bba6494542222b2d1388f52c6d23ac12b32245ca47b02fc2f0a283a88aabca1f4db43ca8a4da8ffd7d9ae403b0c34ccbf14d2318c34fabb713c48f6d6490c6095250b6f08f26f020275d448dfb9967c62bedefaf29260021671a191f620f7783252788549b1e033dc815e2cd36ff204b398046f834643859f881a4d93b3fc5b91413a009c5069be274e1dcc675183ea2a989ef598422c0ed02e407aade8eaa6ef7ec1120ca4ffdef21b5fd26c4525a27c78cc38026b257f9d23f0d796603b1d3cbf539bdf87ccf9e81954f58e072d67eff2891339f203cbdec68bbbabbbbc0c070cceea03bf0a00"; +const result = await client.verifytxoutproof({ proof }); +``` + ## [HTTP REST](https://bitcoin.org/en/developer-reference#http-rest) ```javascript From 458cc8ccc601ddd13cd9c66d1122f14741b94f3a Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 22:01:33 +0300 Subject: [PATCH 74/75] test(rpc): add verifytxoutproof --- test/rpc.spec.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/rpc.spec.ts b/test/rpc.spec.ts index 1d76b20..60a5ede 100644 --- a/test/rpc.spec.ts +++ b/test/rpc.spec.ts @@ -871,5 +871,23 @@ suite("RPCClient", () => { const data = await client.verifychain(params); assert.deepStrictEqual(data, result); }); + + test(".verifytxoutproof()", async () => { + const proof = + "00000020ed07b12f0398e45fd403db11dbe894dc3301ce1a7725424e0b5e460c0000000066fca14db436f305aea37b3ae0f8b188cbf112dff3854c3d419f3ff3ebbc821f6c0c975dffff001d8fd5a7d2eb00000009e7acd3f605d1b957d684d9eeca9c472d803d90c0d17e29e5606f9b080b177a4abcd854622ad3900b5bc1ae71e99699a05eb972d46bd439c08eb7fbd20bba6494542222b2d1388f52c6d23ac12b32245ca47b02fc2f0a283a88aabca1f4db43ca8a4da8ffd7d9ae403b0c34ccbf14d2318c34fabb713c48f6d6490c6095250b6f08f26f020275d448dfb9967c62bedefaf29260021671a191f620f7783252788549b1e033dc815e2cd36ff204b398046f834643859f881a4d93b3fc5b91413a009c5069be274e1dcc675183ea2a989ef598422c0ed02e407aade8eaa6ef7ec1120ca4ffdef21b5fd26c4525a27c78cc38026b257f9d23f0d796603b1d3cbf539bdf87ccf9e81954f58e072d67eff2891339f203cbdec68bbbabbbbc0c070cceea03bf0a00"; + const params = { proof }; + const request = { params, method: "verifytxoutproof", id, jsonrpc }; + const result = [ + "6f0b2595600c49d6f6483c71bbfa348c31d214bfcc340c3b40aed9d7ffa84d8a" + ]; + const response = { result, error, id }; + nock(uri) + .post("/", request) + .times(1) + .basicAuth(auth) + .reply(200, response); + const data = await client.verifytxoutproof(params); + assert.deepStrictEqual(data, result); + }); }); }); From f9605dad3559018f42648fc55a0b2a62d3604c64 Mon Sep 17 00:00:00 2001 From: Sergey Bakulin Date: Wed, 23 Oct 2019 22:03:51 +0300 Subject: [PATCH 75/75] metadata: bump version to 1.2.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0076ded..e864916 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "rpc-bitcoin", - "version": "1.1.0", + "version": "1.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 151d7e3..643eada 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rpc-bitcoin", - "version": "1.1.0", + "version": "1.2.0", "description": "A TypeScript library to make RPC and HTTP REST requests to Bitcoin Core", "main": "build/index.js", "type": "module",