import { type BitcoinApiConfig, type CasConfig, type DidBtcr2Api, type SignalDiscoveryMode } from '@did-btcr2/api'; import type { BroadcastOptions } from '@did-btcr2/method'; import { defaultConfigPath } from './paths.js'; import { type KeystoreProtectionLabel, type NetworkOption, type OutputFormat } from './types.js'; export { defaultConfigPath }; /** * Endpoint overrides provided via CLI flags, env vars, or config file. * These override the per-network defaults the SDK applies * (`DEFAULT_BITCOIN_NETWORK_CONFIG` in `@did-btcr2/api`). * * `config` and `profile` control config-file resolution and are only * meaningful when passed through the full merge chain. */ export type ConnectionOverrides = { btcRest?: string; btcRpcUrl?: string; btcRpcUser?: string; btcRpcPass?: string; /** IPFS HTTP gateway for CAS reads (read-only). */ casGateway?: string; /** IPFS HTTP RPC endpoint for a writable CAS (reads + writes). */ casRpcUrl?: string; /** Bitcoin REST/RPC request timeout in milliseconds (raw flag/env string). */ btcTimeout?: string; /** CAS request timeout in milliseconds (raw flag/env string; `0` disables). */ casTimeout?: string; /** Extra Bitcoin REST headers as raw `Key: Value` flag values (repeatable). */ btcRestHeader?: string[]; /** Bitcoin Core RPC wallet name for wallet-scoped RPCs. */ btcRpcWallet?: string; /** Extra Bitcoin Core RPC headers as raw `Key: Value` flag values (repeatable). */ btcRpcHeader?: string[]; /** Where beacon signals are read from (raw flag/env/profile string). */ btcSignalDiscovery?: string; /** CLI home root from `--home`. Colocates config.json + keystore.json (ADR 079). */ home?: string; config?: string; profile?: string; /** Keystore file path. Overrides the home default `/keystore.json`. */ keystore?: string; /** Path to a file holding the keystore passphrase (for unattended use). */ passphraseFile?: string; /** Signing key reference (URN, fingerprint prefix, or name) from `--signing-key`. */ signingKey?: string; }; /** * On-disk config file schema. * * @example * ```json * { * "profiles": { * "regtest": { * "btc": { * "rest": "http://localhost:3000", * "rpcUrl": "http://localhost:18443", * "rpcUser": "polaruser", * "rpcPass": "polarpass" * } * }, * "bitcoin": { * "btc": { "rest": "https://my-mempool/api" }, * "cas": { "gateway": "https://ipfs.io", "rpcUrl": "http://127.0.0.1:5001" } * } * } * } * ``` */ export type ConfigFile = { /** Schema version, stamped on every write for forward compatibility. */ schemaVersion?: number; /** Tool-wide defaults applied when not overridden by a flag or environment variable. */ defaults?: { profile?: string; network?: NetworkOption; output?: OutputFormat; }; profiles?: Record; /** Bitcoin Core wallet name for wallet-scoped RPCs. */ wallet?: string; /** Extra headers sent on Bitcoin Core RPC requests. */ rpcHeaders?: Record; /** * Where beacon signals are read from: `indexer` (Esplora, the default) or * `fullnode` (scan blocks over Bitcoin Core RPC). `fullnode` needs an * RPC-capable connection. */ signalDiscovery?: SignalDiscoveryMode; }; cas?: { /** IPFS HTTP gateway for CAS reads (read-only). */ gateway?: string; /** IPFS HTTP RPC endpoint for a writable CAS (reads + writes). */ rpcUrl?: string; /** Request timeout in milliseconds for CAS operations. Default 30000; `0` disables. */ timeoutMs?: number; }; /** Signing identity references. Never embeds key material; the secret lives in the keystore. */ identity?: { keystore?: string; default?: string; }; }>; }; /** Current config-file schema version, stamped on every write. */ export declare const CONFIG_SCHEMA_VERSION = 1; /** * Read-modify-write a config file, preserving unknown keys. Reads the raw JSON * (so keys outside {@link ConfigFile} survive a rewrite), applies `mutate`, * stamps the schema version, and writes atomically (file 0600, dir 0700). * * A file that exists but cannot be parsed makes {@link readConfigFile} throw, so * a write never starts from `{}` over a malformed-but-recoverable file and can * never clobber the other profiles and defaults it still holds. A genuinely * absent file (ENOENT) still starts from `{}`. */ export declare function writeConfigFile(path: string, mutate: (raw: Record) => void): void; /** * Writes a default config scaffold to `path`: schema version, a `text` output * default, and one empty profile per supported network. Shared by `config init` * and `btcr2 init` so the seeded config is identical. Writes atomically (file * 0600, dir 0700); the caller decides whether to overwrite an existing file. */ export declare function writeDefaultConfigFile(path: string): void; /** Reads the value at a dotted path (e.g. `profiles.regtest.btc.rest`). */ export declare function getConfigPath(config: Record, path: string): unknown; /** Sets the value at a dotted path, creating intermediate objects. */ export declare function setConfigPath(config: Record, path: string, value: unknown): void; /** Deletes the value at a dotted path. No-op if the path does not exist. */ export declare function unsetConfigPath(config: Record, path: string): void; /** * Factory function that creates a configured {@link DidBtcr2Api} instance. * * When `network` is provided, the returned API is wired to that network's * default Bitcoin endpoints (mempool.space for public networks, localhost * Polar for regtest). Optional `overrides` let callers replace individual * endpoints on top of the defaults. When `network` is omitted, no Bitcoin * or CAS is configured - suitable for offline operations like `create`. */ export type ApiFactory = (network?: NetworkOption, overrides?: ConnectionOverrides) => DidBtcr2Api; /** * Environment variable names consulted by {@link defaultApiFactory}. * * | Variable | Equivalent flag | * |-----------------------|--------------------| * | `BTCR2_BTC_REST` | `--btc-rest` | * | `BTCR2_BTC_RPC_URL` | `--btc-rpc-url` | * | `BTCR2_BTC_RPC_USER` | `--btc-rpc-user` | * | `BTCR2_BTC_RPC_PASS` | (no flag: never argv) | * | `BTCR2_CAS_GATEWAY` | `--cas-gateway` | * | `BTCR2_CAS_RPC_URL` | `--cas-rpc-url` | * | `BTCR2_BTC_TIMEOUT` | `--btc-timeout` | * | `BTCR2_CAS_TIMEOUT` | `--cas-timeout` | * | `BTCR2_FEE_RATE` | `--fee-rate` | * | `BTCR2_BTC_SIGNAL_DISCOVERY` | `--btc-signal-discovery` | */ export declare const ENV_VARS: { readonly BTC_REST: "BTCR2_BTC_REST"; readonly BTC_RPC_URL: "BTCR2_BTC_RPC_URL"; readonly BTC_RPC_USER: "BTCR2_BTC_RPC_USER"; readonly BTC_RPC_PASS: "BTCR2_BTC_RPC_PASS"; readonly CAS_GATEWAY: "BTCR2_CAS_GATEWAY"; readonly CAS_RPC_URL: "BTCR2_CAS_RPC_URL"; readonly BTC_TIMEOUT: "BTCR2_BTC_TIMEOUT"; readonly CAS_TIMEOUT: "BTCR2_CAS_TIMEOUT"; readonly FEE_RATE: "BTCR2_FEE_RATE"; readonly BTC_SIGNAL_DISCOVERY: "BTCR2_BTC_SIGNAL_DISCOVERY"; }; /** * Reads {@link ConnectionOverrides} from environment variables. * Only defined (non-empty) values are included. */ export declare function readEnvOverrides(): ConnectionOverrides; /** * Reads and JSON-parses a config file without applying the schema-version * ceiling check. Returns `undefined` only for a genuinely absent file (ENOENT). * Any other read failure, and any JSON parse failure, throws a {@link CLIError} * that names the file. Used by `config validate`, which reports a newer-than- * supported `schemaVersion` as a finding rather than aborting on it. */ export declare function parseConfigFileRaw(path: string): Record | undefined; /** * Reads and parses a config file. Returns `undefined` only when the file is * genuinely absent (ENOENT), so callers can safely treat "no file" as "use * defaults". Any other read failure, and any JSON parse failure, throws a * {@link CLIError} that names the file, rather than silently degrading to the * public network defaults. A file written by a newer CLI (higher `schemaVersion`) * is also refused. */ export declare function readConfigFile(path: string): ConfigFile | undefined; /** * Extracts {@link ConnectionOverrides} from a named profile in a * {@link ConfigFile}. Returns an empty object if the profile does not exist. */ export declare function profileToOverrides(config: ConfigFile, profileName: string): ConnectionOverrides; /** * Resolves the active profile name and the network it targets, shared by * {@link resolveDefaultNetwork} and {@link resolveConnectionConfig} so the two * can never disagree about which profile is active or which network it means. * * The active profile name is the explicit `--profile` flag, else the config * file's `defaults.profile`. The network is the profile's own `network` field * when set to a supported value, else the profile name itself when it is a * network name (the historical convention). A profile that declares no network * and is not named after one yields `network: undefined`. */ export declare function resolveActiveProfile(file: ConfigFile | undefined, overrides?: ConnectionOverrides): { name: string | undefined; network: NetworkOption | undefined; }; /** * Resolves the default Bitcoin network for offline identifier creation when no * `--network` flag is given. Resolution order: the config file's * `defaults.network`, then the active profile's network (its explicit `network` * field, else its network-derived name), then `regtest` as the development * fallback. Generation itself is offline; this only fixes which network the * identifier encodes. */ export declare function resolveDefaultNetwork(overrides?: ConnectionOverrides): NetworkOption; /** * The network recorded at `defaults.network` in the config file, validated, or * `undefined` when the file is absent, malformed, or the value is unset/unknown. * Unlike {@link resolveDefaultNetwork} this consults ONLY the raw * `defaults.network` (no profile fallback, no regtest default), so `quickstart` * can distinguish "the operator set a default" from "there is none yet" before * it writes (ADR 083). Never throws: a malformed config is surfaced loudly by * the write path, so this pre-write read stays quiet. */ export declare function readConfiguredDefaultNetwork(overrides?: ConnectionOverrides): NetworkOption | undefined; /** * Persists `defaults.network` idempotently and returns the resolved network, * the shared network-recording step behind `btcr2 init -n` and `btcr2 quickstart` * (ADR 083). Writes when `explicit` (an explicit `-n`) is given, or when a * `fallback` is given and the raw config has no `defaults.network` yet. Keyed on * the **raw** file value (not {@link resolveDefaultNetwork}, which never returns * undefined), so a defaulted re-run never clobbers a network the operator set * earlier. When neither condition writes, the existing default is returned * unchanged. Assumes `configPath` names a parseable config (the caller has just * scaffolded one, or an existing one that a malformed-JSON read surfaces loudly). */ export declare function persistDefaultNetwork(configPath: string, opts: { explicit?: NetworkOption; fallback?: NetworkOption; overrides?: ConnectionOverrides; }): { network: NetworkOption; wrote: boolean; }; /** * Validates an explicit network string against {@link SUPPORTED_NETWORKS}, * returning it typed as a {@link NetworkOption} or throwing a {@link CLIError}. * Shared by the `-n/--network` flags on `init` and `quickstart` (ADR 083). */ export declare function assertSupportedNetwork(value: string): NetworkOption; /** * Reports a coherence conflict between the network a `create` run is about to * encode and the network the active profile declares, so the CLI can warn * instead of silently minting an identifier on one network while wiring * endpoints for another. Returns `undefined` when the active profile declares * no network or agrees with the one being encoded. */ export declare function profileNetworkMismatch(network: NetworkOption, overrides?: ConnectionOverrides): { profile: string; declared: NetworkOption; } | undefined; /** * Resolves the effective output format: the `-o/--output` flag, then the * `BTCR2_OUTPUT` environment variable, then the config file's `defaults.output`, * then `'text'`. A malformed config never blocks output resolution (the command's * own read path surfaces it); output format falls back to `'text'` instead. */ export declare function resolveOutputFormat(options: { output?: string; config?: string; home?: string; }): OutputFormat; /** * Resolves the Bitcoin and CAS connection config for a network by merging, * in precedence order, CLI flags, environment variables, and the config-file * profile on top of the per-network defaults (handled by `BitcoinConnection`). * * Returns an empty config when no network is given, since offline operations * (create, key management) need no connection. * * When no `--profile` is given, the network name is used as the profile key * (e.g. a regtest DID auto-selects the `"regtest"` profile). */ export declare function resolveConnectionConfig(network?: NetworkOption, overrides?: ConnectionOverrides): { btc?: BitcoinApiConfig; cas?: CasConfig; }; /** * Parses repeatable `Key: Value` header flag values into a header map. Returns * `undefined` for an empty list. Throws a {@link CLIError} for an entry missing a * colon or with an empty key. */ export declare function parseHeaderList(list?: string[], flagName?: string): Record | undefined; /** Environment variable naming a file whose contents are the Bitcoin Core RPC password. */ export declare const ENV_RPC_PASS_FILE = "BTCR2_BTC_RPC_PASS_FILE"; /** * Resolves an RPC-password secret reference to its literal value: `env:` * reads the named environment variable, `file:` reads the file, and any * other value is returned as-is. A trailing newline is trimmed from file/env * sources so a secret written by `echo` matches an inline value (ADR 077). */ export declare function resolveSecretRef(value?: string): string | undefined; /** * Resolves the beacon {@link BroadcastOptions} for an update/deactivate from the * fee-rate and change-address knobs, following the CLI precedence chain. * * - Fee rate: `--fee-rate` flag, then `BTCR2_FEE_RATE`, then profile * `btc.feeRate`. A positive sats/vByte value wrapped in a `StaticFeeEstimator`. * - Change address: `--change-address` flag, then profile `btc.changeAddress` * (no env, since a change address is DID/network-specific). Validated against * the DID network by the beacon at broadcast time. * * Returns `undefined` when neither is set, so the SDK defaults (5 sat/vB, change * back to the beacon address) still apply. */ export declare function resolveBroadcastOptions(network: NetworkOption, overrides: ConnectionOverrides | undefined, flags: { feeRate?: string; changeAddress?: string; }): BroadcastOptions | undefined; /** Which precedence layer a resolved value came from. */ export type Provenance = 'flag' | 'env' | 'file' | 'default'; /** A resolved value paired with the layer it came from. */ export interface EffectiveEntry { value: string | number | undefined; source: Provenance; } /** * The resolved connection config with per-value provenance, the shape behind * `config effective`. Values are read through the real resolver (the constructed * api and {@link resolveConnectionConfig}) so they cannot drift from what a live * command would use; the `source` tag names the layer the merge selected. */ export interface EffectiveConfig { network: NetworkOption; profile: string | undefined; btc: { rest: EffectiveEntry; rpcUrl: EffectiveEntry; rpcUser: EffectiveEntry; rpcPass: EffectiveEntry; rpcWallet: EffectiveEntry; signalDiscovery: EffectiveEntry; timeoutMs: EffectiveEntry; }; cas: { gateway: EffectiveEntry; rpcUrl: EffectiveEntry; timeoutMs: EffectiveEntry; }; } /** * Resolves the effective connection config with provenance for `config effective`. * The btc values are read back from the constructed api (so SDK network defaults * are reflected), the cas and timeout values from {@link resolveConnectionConfig}, * and each `source` is derived by the same precedence order the merge uses. */ export declare function resolveEffectiveConfig(network: NetworkOption, overrides?: ConnectionOverrides): EffectiveConfig; /** One endpoint reachability check produced by `config doctor`. */ export interface DoctorCheck { endpoint: 'btc-rest' | 'btc-rpc' | 'cas'; target: string; ok: boolean; detail?: string; } /** Result of `config doctor`: per-endpoint reachability and any coherence warning. */ export interface DoctorReport { checks: DoctorCheck[]; coherence?: { profile: string; declared: NetworkOption; encoding: NetworkOption; }; } /** * Probes reachability of the resolved endpoints for `config doctor`: a * lightweight REST call against btc-rest, a `getblockchaininfo` against btc-rpc * when configured, and a reachability check against the resolved CAS. Also * surfaces the profile/network coherence warning. Reads and touches the network; * never writes. */ export declare function runDoctor(network: NetworkOption, overrides?: ConnectionOverrides): Promise; /** * Default {@link ApiFactory} backed by network defaults from * `@did-btcr2/bitcoin` (mempool.space for public networks, localhost for * regtest). Keystore-free: suitable for offline `create` and read-only * `resolve`, which never need a signing identity. * * Override precedence (highest wins): * CLI flags -> env vars -> config file profile -> network defaults. */ export declare function defaultApiFactory(network?: NetworkOption, overrides?: ConnectionOverrides): DidBtcr2Api; /** * The protection mode of the resolved keystore, read without decrypting or * prompting: `encrypted`, `dev` (plaintext), or `absent`. Used by `keystore * status`, `config path`, and the mainnet guard. */ export declare function resolveKeystoreProtection(overrides?: ConnectionOverrides): KeystoreProtectionLabel; /** * Hard-refuses using an unencrypted dev keystore for a mainnet operation (ADR * 080). A plaintext key must never sign or seal a `bitcoin` did:btcr2; the check * reads only the keystore's protection header, so it never decrypts or prompts. * A no-op for every other network and for encrypted/absent keystores. */ export declare function assertKeystoreAllowedForNetwork(network: NetworkOption, overrides?: ConnectionOverrides): void; /** * Resolves the keystore file path: the `--keystore` flag, else the active * profile's `identity.keystore`, else the default `/keystore.json` (ADR * 079). The flag always wins over the profile default and never reads the config. * * A malformed config aborts loudly by default so a keystore-mutating command * never silently reads or writes the wrong store. Pass `lenient: true` only for * diagnostic/recovery commands (`config path`, `keystore status`) that must still * report a path instead of crashing on the very config you ran them to fix; those * fall back to the home default when the profile identity cannot be read. */ export declare function resolveKeystorePath(overrides?: ConnectionOverrides, options?: { lenient?: boolean; }): string; /** * Resolves the signing-key reference for update/deactivate: the `--signing-key` * flag, else the active profile's `identity.default`, else `undefined` (letting * the KMS fall back to its active key). The flag always wins over the profile * default, consistent with the flag -> profile precedence used elsewhere. */ export declare function resolveSigningKeyRef(overrides?: ConnectionOverrides): string | undefined; /** * Keystore-aware {@link ApiFactory} for commands that need a signing identity * (key management, update, deactivate). Identical to {@link defaultApiFactory} * for Bitcoin and CAS, plus an injected keystore-backed KeyManager. Offline key * commands (no network) still get the keystore. */ export declare function keystoreApiFactory(network?: NetworkOption, overrides?: ConnectionOverrides): DidBtcr2Api; /** * Extracts and validates the Bitcoin network from a DID string. * * Decodes the DID via {@link Identifier.decode}, then checks that the * embedded network is one of the supported values. * * @param did A `did:btcr2:...` identifier string. * @returns The validated {@link NetworkOption}. * @throws {CLIError} If the network is unsupported. */ export declare function deriveNetwork(did: string): NetworkOption; //# sourceMappingURL=config.d.ts.map