@did-btcr2/bitcoin 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/{bitcoin.browser.js → bitcoin.js} +39 -16
- package/dist/cjs/bitcoin.js.map +1 -0
- package/dist/cjs/client/rest/address.js +76 -0
- package/dist/cjs/client/rest/address.js.map +1 -0
- package/dist/cjs/client/rest/block.js +50 -0
- package/dist/cjs/client/rest/block.js.map +1 -0
- package/dist/cjs/client/rest/index.js +118 -0
- package/dist/cjs/client/rest/index.js.map +1 -0
- package/dist/cjs/client/rest/transaction.js +56 -0
- package/dist/cjs/client/rest/transaction.js.map +1 -0
- package/dist/cjs/client/rpc/index.js +394 -0
- package/dist/cjs/client/rpc/index.js.map +1 -0
- package/dist/cjs/client/rpc/interface.js.map +1 -0
- package/dist/cjs/client/rpc/json-rpc.js +78 -0
- package/dist/cjs/client/rpc/json-rpc.js.map +1 -0
- package/dist/cjs/client/utils.js +28 -0
- package/dist/cjs/client/utils.js.map +1 -0
- package/dist/cjs/constants.js +34 -13
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/errors.js +8 -0
- package/dist/cjs/errors.js.map +1 -1
- package/dist/cjs/index.js +15 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/types.js +2 -2
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/{bitcoin.browser.js → bitcoin.js} +39 -16
- package/dist/esm/bitcoin.js.map +1 -0
- package/dist/esm/client/rest/address.js +76 -0
- package/dist/esm/client/rest/address.js.map +1 -0
- package/dist/esm/client/rest/block.js +50 -0
- package/dist/esm/client/rest/block.js.map +1 -0
- package/dist/esm/client/rest/index.js +118 -0
- package/dist/esm/client/rest/index.js.map +1 -0
- package/dist/esm/client/rest/transaction.js +56 -0
- package/dist/esm/client/rest/transaction.js.map +1 -0
- package/dist/esm/client/rpc/index.js +394 -0
- package/dist/esm/client/rpc/index.js.map +1 -0
- package/dist/esm/client/rpc/interface.js.map +1 -0
- package/dist/esm/client/rpc/json-rpc.js +78 -0
- package/dist/esm/client/rpc/json-rpc.js.map +1 -0
- package/dist/esm/client/utils.js +28 -0
- package/dist/esm/client/utils.js.map +1 -0
- package/dist/esm/constants.js +34 -13
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/errors.js +8 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.js +15 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/types.js +2 -2
- package/dist/esm/types.js.map +1 -1
- package/dist/types/{bitcoin.browser.d.ts → bitcoin.d.ts} +23 -8
- package/dist/types/bitcoin.d.ts.map +1 -0
- package/dist/types/client/rest/address.d.ts +56 -0
- package/dist/types/client/rest/address.d.ts.map +1 -0
- package/dist/types/client/rest/block.d.ts +32 -0
- package/dist/types/client/rest/block.d.ts.map +1 -0
- package/dist/types/client/rest/index.d.ts +149 -0
- package/dist/types/client/rest/index.d.ts.map +1 -0
- package/dist/types/client/rest/transaction.d.ts +44 -0
- package/dist/types/client/rest/transaction.d.ts.map +1 -0
- package/dist/types/client/rpc/index.d.ts +276 -0
- package/dist/types/client/rpc/index.d.ts.map +1 -0
- package/dist/types/client/rpc/interface.d.ts +27 -0
- package/dist/types/client/rpc/interface.d.ts.map +1 -0
- package/dist/types/client/rpc/json-rpc.d.ts +24 -0
- package/dist/types/client/rpc/json-rpc.d.ts.map +1 -0
- package/dist/types/client/utils.d.ts +12 -0
- package/dist/types/client/utils.d.ts.map +1 -0
- package/dist/types/constants.d.ts +46 -13
- package/dist/types/constants.d.ts.map +1 -1
- package/dist/types/errors.d.ts +4 -0
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/index.d.ts +14 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/types.d.ts +8 -8
- package/dist/types/types.d.ts.map +1 -1
- package/package.json +9 -15
- package/src/{bitcoin.browser.ts → bitcoin.ts} +48 -16
- package/src/client/rest/address.ts +84 -0
- package/src/client/rest/block.ts +58 -0
- package/src/client/rest/index.ts +217 -0
- package/src/client/rest/transaction.ts +64 -0
- package/src/client/rpc/index.ts +479 -0
- package/src/client/rpc/interface.ts +58 -0
- package/src/client/rpc/json-rpc.ts +82 -0
- package/src/client/utils.ts +21 -0
- package/src/constants.ts +35 -14
- package/src/errors.ts +9 -0
- package/src/index.ts +14 -0
- package/src/types.ts +9 -9
- package/dist/cjs/bitcoin.browser.js.map +0 -1
- package/dist/cjs/bitcoin.node.js +0 -85
- package/dist/cjs/bitcoin.node.js.map +0 -1
- package/dist/cjs/index.browser.js +0 -10
- package/dist/cjs/index.browser.js.map +0 -1
- package/dist/cjs/index.node.js +0 -10
- package/dist/cjs/index.node.js.map +0 -1
- package/dist/cjs/interface.js.map +0 -1
- package/dist/cjs/rest-client.js +0 -294
- package/dist/cjs/rest-client.js.map +0 -1
- package/dist/cjs/rpc-client.js +0 -722
- package/dist/cjs/rpc-client.js.map +0 -1
- package/dist/esm/bitcoin.browser.js.map +0 -1
- package/dist/esm/bitcoin.node.js +0 -85
- package/dist/esm/bitcoin.node.js.map +0 -1
- package/dist/esm/index.browser.js +0 -10
- package/dist/esm/index.browser.js.map +0 -1
- package/dist/esm/index.node.js +0 -10
- package/dist/esm/index.node.js.map +0 -1
- package/dist/esm/interface.js.map +0 -1
- package/dist/esm/rest-client.js +0 -294
- package/dist/esm/rest-client.js.map +0 -1
- package/dist/esm/rpc-client.js +0 -722
- package/dist/esm/rpc-client.js.map +0 -1
- package/dist/types/bitcoin.browser.d.ts.map +0 -1
- package/dist/types/bitcoin.node.d.ts +0 -47
- package/dist/types/bitcoin.node.d.ts.map +0 -1
- package/dist/types/index.browser.d.ts +0 -9
- package/dist/types/index.browser.d.ts.map +0 -1
- package/dist/types/index.node.d.ts +0 -9
- package/dist/types/index.node.d.ts.map +0 -1
- package/dist/types/interface.d.ts +0 -86
- package/dist/types/interface.d.ts.map +0 -1
- package/dist/types/rest-client.d.ts +0 -273
- package/dist/types/rest-client.d.ts.map +0 -1
- package/dist/types/rpc-client.d.ts +0 -506
- package/dist/types/rpc-client.d.ts.map +0 -1
- package/src/bitcoin.node.ts +0 -121
- package/src/index.browser.ts +0 -9
- package/src/index.node.ts +0 -9
- package/src/interface.ts +0 -160
- package/src/rest-client.ts +0 -420
- package/src/rpc-client.ts +0 -888
- /package/dist/cjs/{interface.js → client/rpc/interface.js} +0 -0
- /package/dist/esm/{interface.js → client/rpc/interface.js} +0 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { MethodError, UnixTimestamp } from '@did-btcr2/common';
|
|
2
|
+
import { TxInPrevout } from '../../types.js';
|
|
3
|
+
import { BitcoinAddress } from './address.js';
|
|
4
|
+
import { BitcoinBlock } from './block.js';
|
|
5
|
+
import { BitcoinTransaction } from './transaction.js';
|
|
6
|
+
import { DEFAULT_BITCOIN_NETWORK_CONFIG } from '../../constants.js';
|
|
7
|
+
|
|
8
|
+
export type TransactionStatus = {
|
|
9
|
+
confirmed: boolean;
|
|
10
|
+
block_height: number;
|
|
11
|
+
block_hash: string;
|
|
12
|
+
block_time: UnixTimestamp;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export interface Vin {
|
|
16
|
+
txid: string;
|
|
17
|
+
vout: number;
|
|
18
|
+
prevout?: TxInPrevout;
|
|
19
|
+
scriptsig: string;
|
|
20
|
+
scriptsig_asm: string;
|
|
21
|
+
witness: string[];
|
|
22
|
+
is_coinbase: boolean;
|
|
23
|
+
sequence: number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export interface Vout {
|
|
27
|
+
scriptpubkey: string;
|
|
28
|
+
scriptpubkey_asm: string;
|
|
29
|
+
scriptpubkey_type: string;
|
|
30
|
+
scriptpubkey_address?: string;
|
|
31
|
+
value: number;
|
|
32
|
+
}
|
|
33
|
+
export interface ChainStats {
|
|
34
|
+
funded_txo_count: number;
|
|
35
|
+
funded_txo_sum: number;
|
|
36
|
+
spent_txo_count: number;
|
|
37
|
+
spent_txo_sum: number;
|
|
38
|
+
tx_count: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface MempoolStats {
|
|
42
|
+
funded_txo_count: number;
|
|
43
|
+
funded_txo_sum: number;
|
|
44
|
+
spent_txo_count: number;
|
|
45
|
+
spent_txo_sum: number;
|
|
46
|
+
tx_count: number;
|
|
47
|
+
}
|
|
48
|
+
export interface AddressInfo {
|
|
49
|
+
address: string;
|
|
50
|
+
chain_stats: ChainStats;
|
|
51
|
+
mempool_stats: MempoolStats;
|
|
52
|
+
}
|
|
53
|
+
export interface RawTransactionRest {
|
|
54
|
+
txid: string;
|
|
55
|
+
version: number;
|
|
56
|
+
locktime: number;
|
|
57
|
+
vin: Array<Vin>;
|
|
58
|
+
vout: Array<Vout>;
|
|
59
|
+
size: number;
|
|
60
|
+
weight: number;
|
|
61
|
+
fee: number;
|
|
62
|
+
status: TransactionStatus;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface AddressUtxo {
|
|
66
|
+
txid: string;
|
|
67
|
+
vout: number;
|
|
68
|
+
status: TransactionStatus;
|
|
69
|
+
value: number;
|
|
70
|
+
}
|
|
71
|
+
export interface RestClientConfigParams {
|
|
72
|
+
host: string;
|
|
73
|
+
headers?: { [key: string]: string };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export class RestClientConfig {
|
|
77
|
+
host: string;
|
|
78
|
+
headers?: { [key: string]: string };
|
|
79
|
+
constructor({ host, headers }: RestClientConfigParams) {
|
|
80
|
+
this.host = host;
|
|
81
|
+
this.headers = headers;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface RestApiCallParams {
|
|
86
|
+
path: string;
|
|
87
|
+
url?: string;
|
|
88
|
+
method?: string;
|
|
89
|
+
body?: any;
|
|
90
|
+
headers?: any;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export interface RestResponse extends Response {
|
|
94
|
+
[key: string]: any;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Implements a strongly-typed BitcoinRestClient to connect to remote bitcoin node via REST API.
|
|
99
|
+
* @class BitcoinRestClient
|
|
100
|
+
* @type {BitcoinRestClient}
|
|
101
|
+
*/
|
|
102
|
+
export class BitcoinRestClient {
|
|
103
|
+
/**
|
|
104
|
+
* The encapsulated {@link RestClientConfig} object.
|
|
105
|
+
* @private
|
|
106
|
+
* @type {RestClientConfig}
|
|
107
|
+
*/
|
|
108
|
+
private _config: RestClientConfig;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The api calls related to bitcoin transactions.
|
|
112
|
+
* @type {BitcoinTransaction}
|
|
113
|
+
*/
|
|
114
|
+
public transaction: BitcoinTransaction;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* The api calls related to bitcoin blocks.
|
|
118
|
+
* @type {BitcoinBlock}
|
|
119
|
+
*/
|
|
120
|
+
public block: BitcoinBlock;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The api calls related to bitcoin addresses.
|
|
124
|
+
* @type {BitcoinAddress}
|
|
125
|
+
*/
|
|
126
|
+
public address: BitcoinAddress;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The API call method that can be used to make requests to the REST API.
|
|
130
|
+
* @returns {Promise<any>} A promise resolving to the response data.
|
|
131
|
+
*/
|
|
132
|
+
public api: (params: RestApiCallParams) => Promise<any> = this.call;
|
|
133
|
+
|
|
134
|
+
constructor(config: RestClientConfig){
|
|
135
|
+
this._config = new RestClientConfig(config);
|
|
136
|
+
this.api = this.call.bind(this);
|
|
137
|
+
this.transaction = new BitcoinTransaction(this.api);
|
|
138
|
+
this.block = new BitcoinBlock(this.api);
|
|
139
|
+
this.address = new BitcoinAddress(this.api);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Get the configuration object.
|
|
144
|
+
* @private
|
|
145
|
+
*/
|
|
146
|
+
get config(): RestClientConfig {
|
|
147
|
+
const config = this._config;
|
|
148
|
+
return config;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Static method connects to a bitcoin node running a esplora REST API.
|
|
153
|
+
*
|
|
154
|
+
* @param {RestClientConfig} config The configuration object for the client (optional).
|
|
155
|
+
* @returns {BitcoinRestClient} A new {@link BitcoinRestClient} instance.
|
|
156
|
+
* @example
|
|
157
|
+
* ```
|
|
158
|
+
* const rest = BitcoinRestClient.connect();
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
public static connect(config?: RestClientConfig): BitcoinRestClient {
|
|
162
|
+
return new BitcoinRestClient(config ?? DEFAULT_BITCOIN_NETWORK_CONFIG.regtest.rest);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Make a REST API call to the configured Bitcoin node.
|
|
167
|
+
* @private
|
|
168
|
+
* @param {RestApiCallParams} params The parameters for the API call. See {@link RestApiCallParams} for details.
|
|
169
|
+
* @param {string} [params.path] The path to the API endpoint (required).
|
|
170
|
+
* @param {string} [params.url] The full URL to the API endpoint (optional).
|
|
171
|
+
* @param {string} [params.method] The HTTP method to use (default is 'GET').
|
|
172
|
+
* @param {any} [params.body] The body of the request (optional).
|
|
173
|
+
* @param {any} [params.headers] Additional headers to include in the request (optional).
|
|
174
|
+
* @returns {Promise<any>} A promise resolving to the response data.
|
|
175
|
+
*/
|
|
176
|
+
private async call({ path, url, method, body, headers }: RestApiCallParams): Promise<any> {
|
|
177
|
+
// Construct the URL if not provided
|
|
178
|
+
url ??= `${this.config.host.replaceEnd('/')}${path}`;
|
|
179
|
+
|
|
180
|
+
// Set the method to GET if not provided
|
|
181
|
+
method ??= 'GET';
|
|
182
|
+
|
|
183
|
+
// Construct the request options
|
|
184
|
+
const requestInit = {
|
|
185
|
+
method,
|
|
186
|
+
headers : headers ?? {
|
|
187
|
+
'Content-Type' : 'application/json',
|
|
188
|
+
...this.config.headers,
|
|
189
|
+
}
|
|
190
|
+
} as any;
|
|
191
|
+
|
|
192
|
+
// If the method is POST or PUT, add the body to the request
|
|
193
|
+
if(body) {
|
|
194
|
+
requestInit.body = JSON.is(body) ? JSON.stringify(body) : body;
|
|
195
|
+
requestInit.method = 'POST';
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Make the request
|
|
199
|
+
const response = await fetch(url, requestInit) as RestResponse;
|
|
200
|
+
|
|
201
|
+
// Check if the response is a text/plain response
|
|
202
|
+
const data = (response.headers.get('Content-Type') ?? 'json') === 'text/plain'
|
|
203
|
+
? await response.text()
|
|
204
|
+
: await response.json();
|
|
205
|
+
|
|
206
|
+
// Check if the response is ok (status in the range 200-299)
|
|
207
|
+
if (!response.ok) {
|
|
208
|
+
throw new MethodError(
|
|
209
|
+
`Request to ${url} failed: ${response.status} - ${response.statusText}`,
|
|
210
|
+
'FAILED_HTTP_REQUEST',
|
|
211
|
+
{ data, response }
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return data;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Bytes } from '@did-btcr2/common';
|
|
2
|
+
import { RawTransactionRest, RestApiCallParams } from './index.js';
|
|
3
|
+
|
|
4
|
+
export class BitcoinTransaction {
|
|
5
|
+
private api: (params: RestApiCallParams) => Promise<any>;
|
|
6
|
+
|
|
7
|
+
constructor(api: (params: RestApiCallParams) => Promise<any>) {
|
|
8
|
+
this.api = api;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Returns the transaction in JSON format.
|
|
13
|
+
* See {@link https://github.com/blockstream/esplora/blob/master/API.md#get-txtxid | Esplora GET /tx/:txid } for details.
|
|
14
|
+
* @param {string} txid The transaction id (required).
|
|
15
|
+
* @returns {GetRawTransaction} A promise resolving to data about a transaction in the form specified by verbosity.
|
|
16
|
+
*/
|
|
17
|
+
public async get(txid: string): Promise<RawTransactionRest> {
|
|
18
|
+
return await this.api({ path: `/tx/${txid}` });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Returns the transaction in JSON format.
|
|
23
|
+
* See {@link https://github.com/blockstream/esplora/blob/master/API.md#get-txtxid | Esplora GET /tx/:txid } for details.
|
|
24
|
+
* @param {string} txid The transaction id (required).
|
|
25
|
+
* @returns {GetRawTransaction} A promise resolving to data about a transaction in the form specified by verbosity.
|
|
26
|
+
*/
|
|
27
|
+
public async isConfirmed(txid: string): Promise<boolean> {
|
|
28
|
+
const tx = await this.get(txid);
|
|
29
|
+
return tx.status.confirmed;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Returns the raw transaction in hex or as binary data.
|
|
34
|
+
* See {@link https://github.com/blockstream/esplora/blob/master/API.md#get-txtxidhex | Esplora GET /tx/:txid/hex } and
|
|
35
|
+
* {@link https://github.com/blockstream/esplora/blob/master/API.md#get-txtxidraw | Esplora GET /tx/:txid/raw } for details.
|
|
36
|
+
* @param {string} txid The transaction id (required).
|
|
37
|
+
* @returns {Promise<RawTransactionRest | string>} A promise resolving to the raw transaction in the specified format.
|
|
38
|
+
*/
|
|
39
|
+
public async getHex(txid: string): Promise<string> {
|
|
40
|
+
return await this.api({ path: `/tx/${txid}/hex` });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Returns the raw transaction in hex or as binary data.
|
|
45
|
+
* See {@link https://github.com/blockstream/esplora/blob/master/API.md#get-txtxidhex | Esplora GET /tx/:txid/hex } and
|
|
46
|
+
* {@link https://github.com/blockstream/esplora/blob/master/API.md#get-txtxidraw | Esplora GET /tx/:txid/raw } for details.
|
|
47
|
+
* @param {string} txid The transaction id (required).
|
|
48
|
+
* @returns {Promise<RawTransactionRest | string>} A promise resolving to the raw transaction in the specified format.
|
|
49
|
+
*/
|
|
50
|
+
public async getRaw(txid: string): Promise<Bytes> {
|
|
51
|
+
return await this.api({ path: `/tx/${txid}/raw` });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Broadcast a raw transaction to the network. The transaction should be provided as hex in the request body. The txid
|
|
56
|
+
* will be returned on success.
|
|
57
|
+
* See {@link https://github.com/blockstream/esplora/blob/master/API.md#post-tx | Esplora POST /tx } for details.
|
|
58
|
+
* @param {string} tx The raw transaction in hex format (required).
|
|
59
|
+
* @returns {Promise<string>} The transaction id of the broadcasted transaction.
|
|
60
|
+
*/
|
|
61
|
+
public async send(tx: string): Promise<string> {
|
|
62
|
+
return await this.api({ path: '/tx', method: 'POST', body: tx, headers: { 'Content-Type': 'text/plain' } });
|
|
63
|
+
}
|
|
64
|
+
}
|