/** * Named wallets (profiles) and wallet selection, owned by the Node SDK. * * Each named wallet is a self-contained profile directory under * `{config_dir}/profiles//` with its own key, project keystore, and * non-secret `meta.json`; the reserved `default` wallet lives at the * config-dir root. This module is the one implementation of: * * - the SELECTION precedence chain (`resolveWalletSelection`), highest first: * 1. an explicit flag value (`--wallet ` / `--profile `) * 2. `RUN402_WALLET` / `RUN402_PROFILE` * 3. the nearest `.run402.local.json` / `.run402.json` binding, walking up * 4. the global default recorded by `wallets use` (base `config.json`) * 5. `default` * An env value that disagrees with a directory binding is a hard error * (`WALLET_SELECTION_CONFLICT`) unless the caller is the wallet-management * surface itself, which must keep working while selection is ambiguous. * - the MANAGEMENT verbs on `r.wallets` (`list`, `current`, `create`, `use`, * `rename`, `bind`, `unbind`, `import`, `remove`), which operate on explicit * named targets and are independent of the active selection. * * The CLI (`run402 wallets …`, the `--wallet` pre-resolution in `cli.mjs`) and * the MCP server consume these; neither adds a precedence rule of its own. * * A rejected name is a value we know nothing about — a private key pasted * into `RUN402_WALLET` is a demonstrated case — so every refusal routes the * value through `describeRejectedValue()`: a short typo shows in full, anything * secret-shaped is redacted. */ import { type WalletData } from "../../core-dist/wallet.js"; import { LocalError, type NextAction } from "../errors.js"; import type { Client } from "../kernel.js"; import { Wallets, type WalletCreateResult } from "../namespaces/wallets.js"; /** * The active profile's wallet, or null when there is none. A file that exists * but cannot be read as a wallet is `BAD_WALLET_FILE`, naming the file and * the way to recreate it, never the parser's own failure. */ export declare function readLocalWallet(): WalletData | null; /** Where the active wallet came from, highest precedence first. `config` is the global `wallets use` default. */ export type WalletSelectionSource = "flag" | "env" | "binding" | "config" | "default"; /** A flag value handed to the resolver, e.g. `{ flag: "--wallet", value: "kychon" }`; `value` undefined when the flag had none. */ export interface WalletFlag { flag: string; value: string | undefined; } export interface WalletSelection { name: string; source: WalletSelectionSource; /** The flag, env var, binding file, or `wallets use` that decided; null for the bare default. */ sourceDetail: string | null; } export interface ResolveWalletSelectionOptions { walletFlag?: WalletFlag | null; env?: Record; /** Directory the binding walk starts from. Default `process.cwd()`. */ cwd?: string; /** Skip the env-vs-binding conflict error (the wallet-management surface itself). */ allowConflict?: boolean; } /** * A wallet selection refused: bad name, env-vs-binding conflict, or a named * wallet that does not exist locally. A {@link LocalError} carrying `code`, * `hint`, and `details`, never exiting the process, so a caller mid-protocol * (the git remote helper) can report it on its own channel. */ export declare class WalletSelectionError extends LocalError { constructor({ code, message, hint, details }: { code: string; message: string; hint?: string; details?: unknown; }); } /** Nearest wallet binding walking up from `startDir` to the filesystem root. */ export declare function findWalletBinding(startDir: string): { wallet: string; file: string; } | null; /** * The one precedence chain. Pure: reads the environment it is handed, the * binding files above `cwd`, and the global default; never prompts, never * exits. Throws {@link WalletSelectionError}. */ export declare function resolveWalletSelection({ walletFlag, env, cwd, allowConflict, }?: ResolveWalletSelectionOptions): WalletSelection; /** * Fail closed when a non-default selection names a wallet that does not exist * locally. Throws {@link WalletSelectionError} `WALLET_NOT_FOUND`. */ export declare function assertWalletExists({ name, source }: Pick): void; /** The environment variable carrying the published selection's provenance. */ export declare const ACTIVE_WALLET_CONTEXT_ENV = "RUN402_ACTIVE_WALLET_JSON"; export interface ActiveWalletContext { name: string; source: WalletSelectionSource; sourceDetail: string | null; binding: { wallet: string; file: string; } | null; envName: string | null; diverged: boolean; } export interface SelectWalletOptions extends ResolveWalletSelectionOptions { /** Skip the fail-closed existence check (surfaces that create wallets). */ allowMissing?: boolean; } /** * Resolve, fail closed, and PUBLISH the selection to `env` so every core path * function resolves under it: `RUN402_WALLET` names the wallet and * `RUN402_ACTIVE_WALLET_JSON` carries how it was chosen (read back by * `r.wallets.current()`, since the env var alone no longer can say). Call * once per process, before any client reads a path. */ export declare function selectWallet(opts?: SelectWalletOptions): WalletSelection; /** The published selection context, or null when no surface published one. */ export declare function readActiveWalletContext(env?: Record): ActiveWalletContext | null; export type WalletRail = "x402" | "mpp" | "lightning"; export interface WalletDescriptor { local_label: string; server_label: string | null; address: string | null; address_short: string | null; rail: string | null; active: boolean; } export interface WalletWarning { code: string; message: string; hint: string; } export interface CurrentWalletResult { local_label: string; source: WalletSelectionSource | "unknown"; source_detail: string | null; address: string | null; server_label: string | null; configured: boolean; created: string | null; rail: string | null; faucet_used: boolean; path: string; next_actions?: NextAction[]; warnings: WalletWarning[]; } export interface CreatedWalletProfile { local_label: string; address: string; rail: WalletRail; created: true; /** The first next action's command, kept beside `next_actions` for plain readers. */ next: string; next_actions: NextAction[]; } export interface WalletBindResult { wallet: string; file: ".run402.json"; bound: true; safe_to_commit: true; note: string; binding: Record | null; warning?: string; } export interface WalletUnbindResult { file: ".run402.json"; unbound: boolean; removed: boolean; binding: Record | null; } /** Builds a client signing as another named wallet (the label push signs as its target). */ export type WalletClientFactory = (paths: { walletPath: string; keystorePath: string; }) => { wallet(address: string): { setLabel(label: string): Promise<{ ok: boolean; }>; }; }; /** * `r.wallets` on the Node entry: the isomorphic local-wallet and label verbs * plus the named-wallet (profile) management verbs. */ export declare class NodeWallets extends Wallets { #private; constructor(client: Client, opts?: { clientFor?: WalletClientFactory; }); /** Every local wallet, without loading any private key. */ list(): Promise; /** The active wallet: its name, how it was selected, and the local wallet file's facts. */ current(): Promise; /** * With no name: create the ACTIVE profile's wallet file (the isomorphic * behaviour). With a name: create a new named wallet (its key stays local) * on `rail` (default `x402`); `default` creates the root wallet. Refused on * the sandbox surface: it writes a private key. */ create(): Promise; create(name: string, opts?: { rail?: string; }): Promise; /** Set the global default wallet (`wallets use`). */ use(name: string): Promise<{ local_label: string; active: true; }>; /** Rename a wallet; renaming `default` moves it under `profiles/`. */ rename(oldName: string, newName: string): Promise<{ from: string; to: string; renamed: true; }>; /** Bind a directory (default cwd) to a wallet by writing its name into `./.run402.json`. */ bind(name?: string, opts?: { cwd?: string; }): Promise; /** Remove only the `wallet` key from `./.run402.json`; the file goes when nothing else is left in it. */ unbind(opts?: { cwd?: string; }): Promise; /** * Adopt an existing private key as a new named wallet. `privateKey` may be a * function, called only after the name checks pass, so a caller reading the * key from a file or stdin reads nothing for a refused name. Refused on the * sandbox surface: its input is a private key. */ import(name: string, privateKey: string | (() => string)): Promise<{ local_label: string; address: string; imported: true; }>; /** Delete a named wallet and its keys. Requires `{ confirm: true }`; `default` is protected. */ remove(name: string, opts?: { confirm?: boolean; }): Promise<{ local_label: string; removed: true; }>; } //# sourceMappingURL=wallets.d.ts.map