@did-btcr2/cli 0.18.1 → 0.19.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/README.md +7 -5
- package/dist/.tsbuildinfo +1 -1
- package/dist/cjs/index.js +37 -5
- package/dist/esm/src/cli.js +7 -1
- package/dist/esm/src/cli.js.map +1 -1
- package/dist/esm/src/config-schema.js +4 -0
- package/dist/esm/src/config-schema.js.map +1 -1
- package/dist/esm/src/config.js +31 -1
- package/dist/esm/src/config.js.map +1 -1
- package/dist/types/src/cli.d.ts.map +1 -1
- package/dist/types/src/config-schema.d.ts.map +1 -1
- package/dist/types/src/config.d.ts +13 -2
- package/dist/types/src/config.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +1 -1
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/cli.ts +7 -1
- package/src/config-schema.ts +18 -10
- package/src/config.ts +81 -35
- package/src/types.ts +23 -20
package/src/config-schema.ts
CHANGED
|
@@ -19,16 +19,17 @@ const CONFIG_SCHEMA: SchemaNode = {
|
|
|
19
19
|
'*' : {
|
|
20
20
|
network : 'enum:network',
|
|
21
21
|
btc : {
|
|
22
|
-
rest
|
|
23
|
-
rpcUrl
|
|
24
|
-
rpcUser
|
|
25
|
-
rpcPass
|
|
26
|
-
feeRate
|
|
27
|
-
changeAddress
|
|
28
|
-
timeoutMs
|
|
29
|
-
headers
|
|
30
|
-
wallet
|
|
31
|
-
rpcHeaders
|
|
22
|
+
rest : 'string',
|
|
23
|
+
rpcUrl : 'string',
|
|
24
|
+
rpcUser : 'string',
|
|
25
|
+
rpcPass : 'string',
|
|
26
|
+
feeRate : 'number',
|
|
27
|
+
changeAddress : 'string',
|
|
28
|
+
timeoutMs : 'number',
|
|
29
|
+
headers : 'object',
|
|
30
|
+
wallet : 'string',
|
|
31
|
+
rpcHeaders : 'object',
|
|
32
|
+
signalDiscovery : 'enum:signalDiscovery',
|
|
32
33
|
},
|
|
33
34
|
cas : {
|
|
34
35
|
gateway : 'string',
|
|
@@ -100,6 +101,13 @@ function assertLeafValue(kind: SchemaLeaf, dotted: string, value: unknown): void
|
|
|
100
101
|
{ path: dotted, value },
|
|
101
102
|
);
|
|
102
103
|
}
|
|
104
|
+
if (kind === 'enum:signalDiscovery' && value !== 'indexer' && value !== 'fullnode') {
|
|
105
|
+
throw new CLIError(
|
|
106
|
+
`Invalid value for ${dotted}: "${String(value)}". Expected "indexer" or "fullnode".`,
|
|
107
|
+
'INVALID_ARGUMENT_ERROR',
|
|
108
|
+
{ path: dotted, value },
|
|
109
|
+
);
|
|
110
|
+
}
|
|
103
111
|
if (kind === 'number' && typeof value !== 'number') {
|
|
104
112
|
throw new CLIError(
|
|
105
113
|
`Invalid value for ${dotted}: expected a number, got ${typeof value}. `
|
package/src/config.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createApi, DEFAULT_BITCOIN_NETWORK_CONFIG, DEFAULT_CAS_GATEWAY, Identifier, type BitcoinApiConfig, type CasConfig, type DidBtcr2Api } from '@did-btcr2/api';
|
|
1
|
+
import { createApi, DEFAULT_BITCOIN_NETWORK_CONFIG, DEFAULT_CAS_GATEWAY, Identifier, type BitcoinApiConfig, type CasConfig, type DidBtcr2Api, type SignalDiscoveryMode } from '@did-btcr2/api';
|
|
2
2
|
import type { KeyManager } from '@did-btcr2/key-manager';
|
|
3
3
|
import { StaticFeeEstimator } from '@did-btcr2/method';
|
|
4
4
|
import type { BroadcastOptions } from '@did-btcr2/method';
|
|
@@ -43,6 +43,8 @@ export type ConnectionOverrides = {
|
|
|
43
43
|
btcRpcWallet? : string;
|
|
44
44
|
/** Extra Bitcoin Core RPC headers as raw `Key: Value` flag values (repeatable). */
|
|
45
45
|
btcRpcHeader? : string[];
|
|
46
|
+
/** Where beacon signals are read from (raw flag/env/profile string). */
|
|
47
|
+
btcSignalDiscovery? : string;
|
|
46
48
|
/** CLI home root from `--home`. Colocates config.json + keystore.json (ADR 079). */
|
|
47
49
|
home? : string;
|
|
48
50
|
config? : string;
|
|
@@ -112,6 +114,12 @@ export type ConfigFile = {
|
|
|
112
114
|
wallet? : string;
|
|
113
115
|
/** Extra headers sent on Bitcoin Core RPC requests. */
|
|
114
116
|
rpcHeaders? : Record<string, string>;
|
|
117
|
+
/**
|
|
118
|
+
* Where beacon signals are read from: `indexer` (Esplora, the default) or
|
|
119
|
+
* `fullnode` (scan blocks over Bitcoin Core RPC). `fullnode` needs an
|
|
120
|
+
* RPC-capable connection.
|
|
121
|
+
*/
|
|
122
|
+
signalDiscovery? : SignalDiscoveryMode;
|
|
115
123
|
};
|
|
116
124
|
cas?: {
|
|
117
125
|
/** IPFS HTTP gateway for CAS reads (read-only). */
|
|
@@ -231,23 +239,25 @@ export type ApiFactory = (network?: NetworkOption, overrides?: ConnectionOverrid
|
|
|
231
239
|
* | `BTCR2_BTC_REST` | `--btc-rest` |
|
|
232
240
|
* | `BTCR2_BTC_RPC_URL` | `--btc-rpc-url` |
|
|
233
241
|
* | `BTCR2_BTC_RPC_USER` | `--btc-rpc-user` |
|
|
234
|
-
* | `BTCR2_BTC_RPC_PASS` |
|
|
242
|
+
* | `BTCR2_BTC_RPC_PASS` | (no flag: never argv) |
|
|
235
243
|
* | `BTCR2_CAS_GATEWAY` | `--cas-gateway` |
|
|
236
244
|
* | `BTCR2_CAS_RPC_URL` | `--cas-rpc-url` |
|
|
237
245
|
* | `BTCR2_BTC_TIMEOUT` | `--btc-timeout` |
|
|
238
246
|
* | `BTCR2_CAS_TIMEOUT` | `--cas-timeout` |
|
|
239
247
|
* | `BTCR2_FEE_RATE` | `--fee-rate` |
|
|
248
|
+
* | `BTCR2_BTC_SIGNAL_DISCOVERY` | `--btc-signal-discovery` |
|
|
240
249
|
*/
|
|
241
250
|
export const ENV_VARS = {
|
|
242
|
-
BTC_REST
|
|
243
|
-
BTC_RPC_URL
|
|
244
|
-
BTC_RPC_USER
|
|
245
|
-
BTC_RPC_PASS
|
|
246
|
-
CAS_GATEWAY
|
|
247
|
-
CAS_RPC_URL
|
|
248
|
-
BTC_TIMEOUT
|
|
249
|
-
CAS_TIMEOUT
|
|
250
|
-
FEE_RATE
|
|
251
|
+
BTC_REST : 'BTCR2_BTC_REST',
|
|
252
|
+
BTC_RPC_URL : 'BTCR2_BTC_RPC_URL',
|
|
253
|
+
BTC_RPC_USER : 'BTCR2_BTC_RPC_USER',
|
|
254
|
+
BTC_RPC_PASS : 'BTCR2_BTC_RPC_PASS',
|
|
255
|
+
CAS_GATEWAY : 'BTCR2_CAS_GATEWAY',
|
|
256
|
+
CAS_RPC_URL : 'BTCR2_CAS_RPC_URL',
|
|
257
|
+
BTC_TIMEOUT : 'BTCR2_BTC_TIMEOUT',
|
|
258
|
+
CAS_TIMEOUT : 'BTCR2_CAS_TIMEOUT',
|
|
259
|
+
FEE_RATE : 'BTCR2_FEE_RATE',
|
|
260
|
+
BTC_SIGNAL_DISCOVERY : 'BTCR2_BTC_SIGNAL_DISCOVERY',
|
|
251
261
|
} as const;
|
|
252
262
|
|
|
253
263
|
/**
|
|
@@ -257,12 +267,13 @@ export const ENV_VARS = {
|
|
|
257
267
|
export function readEnvOverrides(): ConnectionOverrides {
|
|
258
268
|
const env = (key: string): string | undefined => process.env[key] || undefined;
|
|
259
269
|
return {
|
|
260
|
-
btcRest
|
|
261
|
-
btcRpcUrl
|
|
262
|
-
btcRpcUser
|
|
263
|
-
btcRpcPass
|
|
264
|
-
casGateway
|
|
265
|
-
casRpcUrl
|
|
270
|
+
btcRest : env(ENV_VARS.BTC_REST),
|
|
271
|
+
btcRpcUrl : env(ENV_VARS.BTC_RPC_URL),
|
|
272
|
+
btcRpcUser : env(ENV_VARS.BTC_RPC_USER),
|
|
273
|
+
btcRpcPass : env(ENV_VARS.BTC_RPC_PASS),
|
|
274
|
+
casGateway : env(ENV_VARS.CAS_GATEWAY),
|
|
275
|
+
casRpcUrl : env(ENV_VARS.CAS_RPC_URL),
|
|
276
|
+
btcSignalDiscovery : env(ENV_VARS.BTC_SIGNAL_DISCOVERY),
|
|
266
277
|
};
|
|
267
278
|
}
|
|
268
279
|
|
|
@@ -343,12 +354,13 @@ export function profileToOverrides(
|
|
|
343
354
|
const profile = config.profiles?.[profileName];
|
|
344
355
|
if (!profile) return {};
|
|
345
356
|
return {
|
|
346
|
-
btcRest
|
|
347
|
-
btcRpcUrl
|
|
348
|
-
btcRpcUser
|
|
349
|
-
btcRpcPass
|
|
350
|
-
casGateway
|
|
351
|
-
casRpcUrl
|
|
357
|
+
btcRest : profile.btc?.rest,
|
|
358
|
+
btcRpcUrl : profile.btc?.rpcUrl,
|
|
359
|
+
btcRpcUser : profile.btc?.rpcUser,
|
|
360
|
+
btcRpcPass : profile.btc?.rpcPass,
|
|
361
|
+
casGateway : profile.cas?.gateway,
|
|
362
|
+
casRpcUrl : profile.cas?.rpcUrl,
|
|
363
|
+
btcSignalDiscovery : profile.btc?.signalDiscovery,
|
|
352
364
|
};
|
|
353
365
|
}
|
|
354
366
|
|
|
@@ -563,6 +575,27 @@ function resolveRpcUnit(
|
|
|
563
575
|
return undefined;
|
|
564
576
|
}
|
|
565
577
|
|
|
578
|
+
/** The accepted `--btc-signal-discovery` values, in help/error order. */
|
|
579
|
+
const SIGNAL_DISCOVERY_MODES: readonly SignalDiscoveryMode[] = ['indexer', 'fullnode'];
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Validates a beacon signal-discovery mode drawn from any precedence layer.
|
|
583
|
+
* A bad value is rejected here rather than passed to the SDK, so a typo in an
|
|
584
|
+
* env var or a profile fails with the same named-flag message as a bad flag.
|
|
585
|
+
*/
|
|
586
|
+
function resolveSignalDiscovery(value?: string): SignalDiscoveryMode | undefined {
|
|
587
|
+
const mode = blankToUndef(value);
|
|
588
|
+
if (mode === undefined) return undefined;
|
|
589
|
+
if (!SIGNAL_DISCOVERY_MODES.includes(mode as SignalDiscoveryMode)) {
|
|
590
|
+
throw new CLIError(
|
|
591
|
+
`Invalid --btc-signal-discovery value "${mode}". Expected ${SIGNAL_DISCOVERY_MODES.join(' or ')}.`,
|
|
592
|
+
'INVALID_ARGUMENT_ERROR',
|
|
593
|
+
{ value: mode },
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
return mode as SignalDiscoveryMode;
|
|
597
|
+
}
|
|
598
|
+
|
|
566
599
|
/**
|
|
567
600
|
* Resolves the Bitcoin and CAS connection config for a network by merging,
|
|
568
601
|
* in precedence order, CLI flags, environment variables, and the config-file
|
|
@@ -641,6 +674,14 @@ export function resolveConnectionConfig(
|
|
|
641
674
|
};
|
|
642
675
|
}
|
|
643
676
|
|
|
677
|
+
// Where beacon signals are read from. `fullnode` scans blocks over Bitcoin
|
|
678
|
+
// Core RPC and is rejected by BitcoinApi when the resolved connection has no
|
|
679
|
+
// RPC client, which includes the networks that carry no default RPC host.
|
|
680
|
+
const signalDiscovery = resolveSignalDiscovery(
|
|
681
|
+
pick(overrides?.btcSignalDiscovery, env.btcSignalDiscovery, fileOverrides.btcSignalDiscovery),
|
|
682
|
+
);
|
|
683
|
+
if (signalDiscovery) btc.signalDiscovery = signalDiscovery;
|
|
684
|
+
|
|
644
685
|
// Bitcoin request timeout. No default: honored only when explicitly set, so
|
|
645
686
|
// callers that rely on unbounded waits are unaffected (ADR 076).
|
|
646
687
|
const btcTimeout = resolveTimeout(overrides?.btcTimeout, process.env[ENV_VARS.BTC_TIMEOUT], profileBtc?.timeoutMs, '--btc-timeout', 1);
|
|
@@ -839,12 +880,13 @@ export interface EffectiveConfig {
|
|
|
839
880
|
network : NetworkOption;
|
|
840
881
|
profile : string | undefined;
|
|
841
882
|
btc : {
|
|
842
|
-
rest
|
|
843
|
-
rpcUrl
|
|
844
|
-
rpcUser
|
|
845
|
-
rpcPass
|
|
846
|
-
rpcWallet
|
|
847
|
-
|
|
883
|
+
rest : EffectiveEntry;
|
|
884
|
+
rpcUrl : EffectiveEntry;
|
|
885
|
+
rpcUser : EffectiveEntry;
|
|
886
|
+
rpcPass : EffectiveEntry;
|
|
887
|
+
rpcWallet : EffectiveEntry;
|
|
888
|
+
signalDiscovery : EffectiveEntry;
|
|
889
|
+
timeoutMs : EffectiveEntry;
|
|
848
890
|
};
|
|
849
891
|
cas : {
|
|
850
892
|
gateway : EffectiveEntry;
|
|
@@ -897,12 +939,16 @@ export function resolveEffectiveConfig(network: NetworkOption, overrides?: Conne
|
|
|
897
939
|
network,
|
|
898
940
|
profile : activeProfile,
|
|
899
941
|
btc : {
|
|
900
|
-
rest
|
|
901
|
-
rpcUrl
|
|
902
|
-
rpcUser
|
|
903
|
-
rpcPass
|
|
904
|
-
rpcWallet
|
|
905
|
-
|
|
942
|
+
rest : { value: restCfg.host, source: src(overrides?.btcRest, env.btcRest, fileOv.btcRest) },
|
|
943
|
+
rpcUrl : { value: rpcCfg?.host, source: rpcUnit?.url !== undefined ? rpcSrc : 'default' },
|
|
944
|
+
rpcUser : { value: rpcCfg?.username, source: rpcUnit?.user !== undefined ? rpcSrc : 'default' },
|
|
945
|
+
rpcPass : { value: rpcCfg?.password, source: rpcUnit?.pass !== undefined ? rpcSrc : (passFromFile ? 'env' : 'default') },
|
|
946
|
+
rpcWallet : { value: rpcCfg?.wallet, source: src(overrides?.btcRpcWallet, undefined, profileBtc?.wallet) },
|
|
947
|
+
// Read back from the constructed api, like the endpoints above, so the
|
|
948
|
+
// reported value is the mode a live command would actually resolve with
|
|
949
|
+
// (the SDK's `indexer` default included) rather than only an explicit setting.
|
|
950
|
+
signalDiscovery : { value: api.btc.signalDiscovery, source: src(overrides?.btcSignalDiscovery, env.btcSignalDiscovery, fileOv.btcSignalDiscovery) },
|
|
951
|
+
timeoutMs : { value: conn.btc?.timeoutMs, source: src(overrides?.btcTimeout, process.env[ENV_VARS.BTC_TIMEOUT], profileBtc?.timeoutMs) },
|
|
906
952
|
},
|
|
907
953
|
cas : {
|
|
908
954
|
gateway : { value: casGatewayVal, source: src(overrides?.casGateway, env.casGateway, fileOv.casGateway) },
|
package/src/types.ts
CHANGED
|
@@ -88,24 +88,27 @@ export type CommandResult =
|
|
|
88
88
|
| { action: 'profile-remove'; data: { profile: string } };
|
|
89
89
|
|
|
90
90
|
export interface GlobalOptions {
|
|
91
|
-
output
|
|
92
|
-
verbose
|
|
93
|
-
quiet
|
|
94
|
-
home?
|
|
95
|
-
config?
|
|
96
|
-
profile?
|
|
97
|
-
btcRest?
|
|
98
|
-
btcRpcUrl?
|
|
99
|
-
btcRpcUser?
|
|
100
|
-
btcRpcPass
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
91
|
+
output : OutputFormat;
|
|
92
|
+
verbose : boolean;
|
|
93
|
+
quiet : boolean;
|
|
94
|
+
home? : string;
|
|
95
|
+
config? : string;
|
|
96
|
+
profile? : string;
|
|
97
|
+
btcRest? : string;
|
|
98
|
+
btcRpcUrl? : string;
|
|
99
|
+
btcRpcUser? : string;
|
|
100
|
+
// No btcRpcPass: the RPC password is never accepted as a flag, so it cannot be
|
|
101
|
+
// parsed off argv. It reaches the connection from the environment, a pass file,
|
|
102
|
+
// or a profile secret reference instead (see the flag list in `cli.ts`).
|
|
103
|
+
casGateway? : string;
|
|
104
|
+
casRpcUrl? : string;
|
|
105
|
+
btcTimeout? : string;
|
|
106
|
+
casTimeout? : string;
|
|
107
|
+
btcRestHeader? : string[];
|
|
108
|
+
btcRpcWallet? : string;
|
|
109
|
+
btcRpcHeader? : string[];
|
|
110
|
+
btcSignalDiscovery? : string;
|
|
111
|
+
keystore? : string;
|
|
112
|
+
passphraseFile? : string;
|
|
113
|
+
signingKey? : string;
|
|
111
114
|
}
|