UNPKG

@cashu/cashu-ts

Version:

cashu library for communicating with a cashu mint

1,297 lines (1,189 loc) 274 kB
import { WeierstrassPoint } from '@noble/curves/abstract/weierstrass.js'; /** * Immutable, non-negative integer amount value object. * * Internal representation is bigint. Use factory methods to instantiate. * * @example * * Amount.from('21'); // string * Amount.from(21); // number * Amount.from(21n); // bigint * Amount.zero(); * Amount.one(); */ export declare class Amount { private readonly value; private constructor(); /** * Parse/normalize supported inputs into an Amount. * * @throws If input is negative, or if a `number` input exceeds the safe integer limit, or if * input is not a finite integer. */ static from(input: AmountLike): Amount; static zero(): Amount; static one(): Amount; /** * Internal canonical value. */ toBigInt(): bigint; /** * Safe conversion to number. * * @throws If value exceeds Number.MAX_SAFE_INTEGER. */ toNumber(): number; /** * Unsafe conversion to number. Precision can be lost above MAX_SAFE_INTEGER. */ toNumberUnsafe(): number; /** * Canonical decimal representation for logs/JSON string mode. */ toString(): string; /** * Used by JSON.stringify() to convert Amount to string. */ toJSON(): string; add(other: AmountLike): Amount; subtract(other: AmountLike): Amount; multiplyBy(factor: AmountLike): Amount; divideBy(divisor: AmountLike): Amount; modulo(divisor: AmountLike): Amount; /** * Returns `ceil(this × numerator / denominator)` using integer arithmetic only. * * The default denominator of 100 makes common percentage calculations natural. Use a larger * denominator to express fractional percentages without floats. * * @example * * amount.ceilPercent(2); // ceil(2% of amount) * amount.ceilPercent(1, 200); // ceil(0.5% of amount) * amount.ceilPercent(15, 10); // ceil(1.5% of amount) * * @throws If numerator or denominator are not positive integers. */ ceilPercent(numerator: number, denominator?: number): Amount; /** * Returns `floor(this × numerator / denominator)` using integer arithmetic only. * * The natural complement to {@link Amount.ceilPercent} — use when you need the conservative lower * bound, e.g. "maximum spendable after reserving fees". * * @example * * amount.floorPercent(98); // floor(98% of amount) * amount.floorPercent(1, 200); // floor(0.5% of amount) * * @throws If numerator or denominator are not positive integers. */ floorPercent(numerator: number, denominator?: number): Amount; /** * Returns true if this amount is within the inclusive range [min, max]. * * @example * * msats.inRange(data.minSendable, data.maxSendable); * * @throws If min > max. */ inRange(min: AmountLike, max: AmountLike): boolean; /** * Clamps this amount to the inclusive range [min, max]. * * @example * * fee.clamp(MIN_FEE, tokenAmount); * invoiceAmount.clamp(Amount.from(minSendable), Amount.from(maxSendable)); * * @throws If min > max. */ clamp(min: AmountLike, max: AmountLike): Amount; /** * Returns `round(this × numerator / denominator)` using integer arithmetic only. * * Useful for proportional rescaling — currency conversion, capacity checks, partial fills — * without floating-point imprecision or overflow risk. * * Uses the identity: `round(a × b / c) = floor((2 × a × b + c) / (2 × c))` * * @example * * // Scale a 1000-sat amount down by a 3/4 ratio → 750 * Amount.from(1000).scaledBy(3, 4); * * // Proportional rescale: if neededAmount is too high, shrink estInvAmount to fit * estInvAmount.scaledBy(tokenAmount, neededAmount).subtract(1); * * @throws If numerator or denominator are zero or negative. */ scaledBy(numerator: AmountLike, denominator: AmountLike): Amount; /** * Whether this Amount can be safely converted to a number. */ isSafeNumber(): boolean; isZero(): boolean; equals(other: AmountLike): boolean; /** * Compares this Amount with another Amount. * * Defines the natural ordering of Amount values. Useful for sorting and ordering logic. * * @returns -1 if this < other, 0 if equal, 1 if this > other. */ compareTo(other: AmountLike): -1 | 0 | 1; lessThan(other: AmountLike): boolean; lessThanOrEqual(other: AmountLike): boolean; greaterThan(other: AmountLike): boolean; greaterThanOrEqual(other: AmountLike): boolean; static min(a: AmountLike, b: AmountLike): Amount; static max(a: AmountLike, b: AmountLike): Amount; static sum(values: Iterable<AmountLike>): Amount; /** * Tag this {@link Amount} with a currency unit, returning an {@link AmountWithUnit}. */ withUnit(unit: string): AmountWithUnit; } export declare class AmountError extends CTSError { constructor(message: string); } /** * All types that can be converted to an {@link Amount} value object. */ export declare type AmountLike = number | bigint | string | Amount; /** * Immutable {@link Amount} paired with a currency unit. * * Binary ops require matching units (throw {@link AmountWithUnitError} otherwise); scalar ops * preserve the unit. * * Lift via {@link Amount.withUnit} / {@link AmountWithUnit.from}, drop via * {@link AmountWithUnit.toAmount}. * * @example * * AmountWithUnit.from(100, 'sat'); * Amount.from(21).withUnit('sat'); */ export declare class AmountWithUnit { private readonly _amount; readonly unit: string; constructor(amount: Amount, unit: string); static from(value: AmountLike, unit: string): AmountWithUnit; static zero(unit: string): AmountWithUnit; static one(unit: string): AmountWithUnit; /** * Return the underlying unitless {@link Amount}, dropping the unit guard. */ toAmount(): Amount; toBigInt(): bigint; toNumber(): number; /** * Unit-bearing canonical form, e.g. `"[sat]: 100"`. Used by `String(x)`, template literals, * `console.log`, and any other string-coercion context. * * Leads with `[` (never a digit, sign, or decimal point) so that `parseInt(String(x))` / * `parseFloat(String(x))` return `NaN` even if the unit itself starts with digits — otherwise a * unit like `"9999sat"` would let `parseInt` silently extract `9999` from the unit and drop the * real amount. */ toString(): string; toJSON(): { amount: string; unit: string; }; /* Excluded from this release type: [Symbol.toPrimitive] */ isZero(): boolean; isSafeNumber(): boolean; private requireSameUnit; add(other: AmountWithUnit): AmountWithUnit; subtract(other: AmountWithUnit): AmountWithUnit; equals(other: AmountWithUnit): boolean; compareTo(other: AmountWithUnit): -1 | 0 | 1; lessThan(other: AmountWithUnit): boolean; lessThanOrEqual(other: AmountWithUnit): boolean; greaterThan(other: AmountWithUnit): boolean; greaterThanOrEqual(other: AmountWithUnit): boolean; inRange(min: AmountWithUnit, max: AmountWithUnit): boolean; clamp(min: AmountWithUnit, max: AmountWithUnit): AmountWithUnit; multiplyBy(factor: AmountLike): AmountWithUnit; divideBy(divisor: AmountLike): AmountWithUnit; modulo(divisor: AmountLike): AmountWithUnit; ceilPercent(numerator: number, denominator?: number): AmountWithUnit; floorPercent(numerator: number, denominator?: number): AmountWithUnit; scaledBy(numerator: AmountLike, denominator: AmountLike): AmountWithUnit; static min(a: AmountWithUnit, b: AmountWithUnit): AmountWithUnit; static max(a: AmountWithUnit, b: AmountWithUnit): AmountWithUnit; /** * Sum a unit-tagged iterable. * * - If `unit` is provided, every element must match it; the result has that unit. An empty iterable * returns `AmountWithUnit.zero(unit)`. * - If `unit` is omitted, the iterable must be non-empty; the unit is inferred from the first * element and every subsequent element must match. An empty iterable throws. * * @throws {AmountWithUnitError} On unit mismatch, or on empty iterable when `unit` is omitted. */ static sum(values: Iterable<AmountWithUnit>, unit?: string): AmountWithUnit; } export declare class AmountWithUnitError extends CTSError { constructor(message: string); } /** * Assert that a Secret is of the expected kind. * * @param allowed - NUT-10 Kind(s) allowed. * @param secret - The Proof secret. * @returns Parsed Secret if the kind matches. * @throws If secret kind is not as expected. */ export declare function assertSecretKind(allowed: SecretKind | SecretKind[], secret: Secret | string): Secret; /* Excluded from this release type: assertSigAllInputs */ /** * AuthManager. * * - Owns CAT lifecycle (stores, optional refresh via attached OIDCAuth) * - Mints and serves BATs (NUT-22) * - Validates DLEQs for BATs per NUT-12. * - Supplies serialized BATs for 'Blind-auth' and CAT for 'Clear-auth' */ export declare class AuthManager implements AuthProvider { private readonly mintUrl; private readonly req; private readonly logger; private info?; private lockChain?; private inflightRefresh?; private static readonly MIN_VALID_SECS; private oidc?; private tokens; private pool; private desiredPoolSize; private maxPerMint; private keychain?; constructor(mintUrl: string, opts?: AuthManagerOptions); /** * Attach an OIDCAuth instance so this manager can refresh CATs. Registers a listener to update * internal CAT/refresh state on new tokens. */ attachOIDC(oidc: OIDCAuth): this; get poolSize(): number; get poolTarget(): number; get activeAuthKeysetId(): string | undefined; get hasCAT(): boolean; getCAT(): string | undefined; setCAT(cat: string | undefined): void; /** * Ensure a valid CAT is available (refresh if expiring soon). Returns a token safe to send right * now, or undefined if unobtainable. */ ensureCAT(minValidSecs?: number): Promise<string | undefined>; private validForAtLeast; private updateFromOIDC; /** * Ensure there are enough BAT tokens (topping up if needed) * * @param minTokens Minimum tokens needed. */ ensure(minTokens: number): Promise<void>; /** * Gets a Blind Authentication Token (BAT) * * @param {method, path} to Call (not used in our implementation) * @returns The serialized BAT ready to insert into request header. */ getBlindAuthToken({ method, path, }: { method: 'GET' | 'POST'; path: string; }): Promise<string>; /** * Replace or merge the current BAT pool with previously persisted BATs. */ importPool(proofs: Proof[], mode?: 'replace' | 'merge'): void; /** * Return a deep-copied snapshot of the current BAT pool (full Proofs, including dleq). */ exportPool(): Proof[]; /** * Extract exp, seconds since epoch, from a JWT access token. */ private parseJwtExpSec; /** * Simple mutex lock - chains promises in order. */ private withLock; /** * Initialise mint info and auth keysets/keys as needed. */ private init; /** * Gets the BAT minting limit: lower of manager limit and Mint’s NUT-22 limit. */ private getBatMaxMint; private getActiveKeys; /** * Mint a batch of BATs using the current CAT if the endpoint is protected by NUT-21. */ private topUp; } export declare type AuthManagerOptions = { /** * Hard limit to target when minting BATs in one request. If omitted, we'll read * `nuts['22'].bat_max_mint` from the mint "/v1/info" endpoint. Values above the * `ABSOLUTE_MAX_PER_MINT` internal hard cap are clamped. */ maxPerMint?: number; /** * Desired BAT pool size. We’ll top-up to min(desiredPoolSize, maxPerMint) on demand. */ desiredPoolSize?: number; /** * Custom request fn (e.g. for tests or host env). */ request?: RequestFn; /** * Logger. */ logger?: Logger; }; export declare interface AuthProvider { getBlindAuthToken(input: { method: 'GET' | 'POST'; path: string; }): Promise<string>; ensure?(minTokens: number): Promise<void>; getCAT(): string | undefined; setCAT(cat: string | undefined): void; /** * Ensure a valid CAT is available, refreshing if expiring soon. Return a token that is safe to * send right now, or undefined if not obtainable. */ ensureCAT?(minValiditySec?: number): Promise<string | undefined>; } /** * Preview of a batched mint transaction created by prepareBatchMint. * * @remarks * Contains JSON-unsafe values (`bigint`, `Uint8Array`). Not intended for direct serialization. */ export declare interface BatchMintPreview<TQuote extends Pick<MintQuoteBaseResponse, 'quote' | 'pubkey'> = MintQuoteBaseResponse> { method: string; /** * Batch mint payload to be sent to the mint. */ payload: BatchMintRequest; /** * Blinding data required to construct proofs (consolidated across all quotes). */ outputData: OutputDataLike[]; /** * Keyset ID used to prepare the outputs. */ keysetId: string; /** * Mint Quote objects included in this batch. */ quotes: TQuote[]; } /** * Payload that needs to be sent to the mint when requesting a NUT-29 batched mint. */ export declare type BatchMintRequest = { /** * Array of Quote IDs received from the mint. */ quotes: string[]; /** * Array of amounts that shall be minted per quote id. */ quote_amounts: Amount[]; /** * Outputs (blinded messages) to be signed by the mint. */ outputs: SerializedBlindedMessage[]; /** * Optional. Signatures for the Public key the quote is locked to (NUT-20) (same order as quote * ids). If some quotes are unlocked null is expected. Can be omitted if all quotes are unlocked. */ signatures?: Array<string | null>; }; /* Excluded from this release type: bigIntStringify */ /** * Blind a secret message. * * @param secret A UTF-8 byte encoded string. * @param r Optional. Deterministic blinding scalar to use (eg: for testing / seeded) * @returns A RawBlindedMessage: {B_, r, secret} */ export declare function blindMessage(secret: Uint8Array, r?: bigint): RawBlindedMessage; export declare type BlindSignature = { C_: WeierstrassPoint<bigint>; id: string; }; /* Excluded from this release type: buildLegacyP2PKSigAllMessage */ /* Excluded from this release type: buildP2PKSigAllMessage */ export declare type CancellerLike = SubscriptionCanceller | Promise<SubscriptionCanceller>; /** * Enum for the state of a proof. */ export declare const CheckStateEnum: { readonly UNSPENT: "UNSPENT"; readonly PENDING: "PENDING"; readonly SPENT: "SPENT"; }; export declare type CheckStateEnum = (typeof CheckStateEnum)[keyof typeof CheckStateEnum]; /** * Payload that needs to be sent to the mint when checking for spendable proofs. */ export declare type CheckStatePayload = { /** * The Y = hash_to_curve(secret) of the proofs to be checked. */ Ys: string[]; }; /** * Response when checking proofs if they are spendable. Should not rely on this for receiving, since * it can be easily cheated. */ export declare type CheckStateResponse = { states: ProofState[]; }; export declare type CompleteMeltOptions = { preferAsync?: boolean; extraPayload?: Record<string, unknown>; }; /** * Computes the SHA-256 hash of a UTF-8 message string. * * @param message To hash (UTF-8 encoded before hashing). * @param asHex Optional: True returns a hex-encoded hash string; otherwise returns raw bytes. * @returns SHA-256 hash as raw bytes or hex string, depending on `asHex`. */ export declare function computeMessageDigest(message: string): Uint8Array; export declare function computeMessageDigest(message: string, asHex: false): Uint8Array; export declare function computeMessageDigest(message: string, asHex: true): string; /** * Outputs messages to the console based on the specified log level. * * Supports placeholder substitution in messages (e.g., `{key}`) using values from the optional * `context` object. Context keys not used in substitution are appended to the output as additional * data. Each log message is prefixed with the log level in square brackets (e.g., `[INFO]`). * * @example Const logger = new ConsoleLogger(LogLevel.DEBUG); logger.info('User {username} logged * in', { username: 'alice', ip: '127.0.0.1' }); // Output: [INFO] User alice logged in { ip: * "127.0.0.1" } */ export declare class ConsoleLogger implements Logger { private minLevel; constructor(minLevel?: LogLevel); private should; private method; private header; private flattenContext; private emit; error(msg: string, ctx?: Record<string, unknown>): void; warn(msg: string, ctx?: Record<string, unknown>): void; info(msg: string, ctx?: Record<string, unknown>): void; debug(msg: string, ctx?: Record<string, unknown>): void; trace(msg: string, ctx?: Record<string, unknown>): void; log(level: LogLevel, message: string, context?: Record<string, unknown>): void; } export declare function constructUnblindedSignature(blindSig: BlindSignature, r: bigint, secret: Uint8Array, key: WeierstrassPoint<bigint>): UnblindedSignature; /** * Usable counters in range is [start, start+count-1] * * @example // Start: 5, count: 3 => 5,6,7. */ export declare interface CounterRange { start: number; count: number; } export declare interface CounterSource { /** * Reserve n counters for a keyset. * * N may be 0. In that case the call MUST NOT mutate state and MUST return { start: currentNext, * count: 0 }, effectively a read only peek of the cursor. */ reserve(keysetId: string, n: number): Promise<CounterRange>; /** * Monotonic bump, ensure the next counter is at least minNext. */ advanceToAtLeast(keysetId: string, minNext: number): Promise<void>; /** * Optional introspection. */ snapshot?(): Promise<Record<string, number>>; /** * Optional hard set, useful for tests or migrations. */ setNext?(keysetId: string, next: number): Promise<void>; } /** * High-level helper to create a fully authenticated wallet session. * * @remarks * Like a dependency injector, it wires AuthManager->Mint->OIDCAuth->Wallet in the correct order. * Wallet is returned ready to use. * @param mintUrl URL of the mint to connect to. * @param options.authPool Optional. Desired BAT pool size and per-request mint cap. Both * desiredPoolSize and maxPerMint on the AuthManager will be set to this value. Defaults to 10. * @param options.oidc Optional. Options for OIDCAuth (scope, clientId, logger, etc.) * @returns {mint, auth, oidc, wallet} — hydrated, ready to use. * @throws If mint does not require authentication. */ export declare function createAuthWallet(mintUrl: string, options?: { authPool?: number; oidc?: OIDCAuthOptions; logger?: Logger; }): Promise<{ mint: Mint; auth: AuthManager; oidc: OIDCAuth; wallet: Wallet; }>; export declare function createBlindSignature(B_: WeierstrassPoint<bigint>, privateKey: Uint8Array, id: string): BlindSignature; /** * !!! WARNING !!! Not recommended for production use, due to non-constant time operations See: * https://github.com/cashubtc/cashu-crypto-ts/pull/2 for more details See: * https://en.wikipedia.org/wiki/Timing_attack for information about timing attacks. */ export declare const createDLEQProof: (B_: WeierstrassPoint<bigint>, a: Uint8Array) => DLEQ; /** * Create a shared in-memory {@link CounterSource}. * * Use this when multiple {@link Wallet} instances share the same seed and must allocate * deterministic outputs without overlapping counter ranges. Pass the returned source to each wallet * via the `counterSource` option. * * The source is memory-only — counters do not survive page reloads. Subscribe to * {@link WalletEvents.countersReserved | wallet.on.countersReserved} to persist counter state to * your own storage. * * @param initial - Optional seed values (`{ [keysetId]: nextCounter }`). */ export declare function createEphemeralCounterSource(initial?: Record<string, number>): CounterSource; /** * Create an HTLC hash/preimage pair. * * @param preimage - Optional. Preimage to use (Default: random preimage) * @returns Hash and preimage pair. * @throws If the preimage supplied is not a 64-char hex string. */ export declare function createHTLCHash(preimage?: string): { hash: string; preimage: string; }; /** * Create an HTLC secret. * * @remarks * Use `createHTLCHash()` for hash creation. * @param hash - The HTLC hash to add to Secret.data. * @param tags - Optional. Additional P2PK tags. */ export declare function createHTLCsecret(hash: string, tags?: string[][]): string; /** * Creates new mint keys. * * @param pow2height Number of powers of 2 to create (Max 65). * @param seed (Optional). Seed for key derivation. * @param options.expiry (optional) expiry of the keyset. * @param options.input_fee_ppk (optional) Input fee for keyset (in ppk) * @param options.unit (optional) the unit of the keyset. Default: sat. * @param options.versionByte (optional) version of the keyset ID. Default: 1. * @returns KeysetPair object. * @throws If keyset versionByte is not valid. */ export declare function createNewMintKeys(pow2height: IntRange<0, 65>, seed?: Uint8Array, options?: { expiry?: number; input_fee_ppk?: number; unit?: string; versionByte?: number; }): KeysetPair; /** * Create a P2PK secret. * * @param pubkey - The pubkey to add to Secret.data. * @param tags - Optional. Additional P2PK tags. * @throws If the sigflag is unrecognised. */ export declare function createP2PKsecret(pubkey: string, tags?: string[][]): string; /** * Creates a random blinded message. * * @remarks * The secret is a UTF-8 encoded 64-character lowercase hex string, generated from 32 random bytes * as recommended by NUT-00. * @returns A RawBlindedMessage: {B_, r, secret} */ export declare function createRandomRawBlindedMessage(): RawBlindedMessage; export declare function createRandomSecretKey(): Uint8Array<ArrayBufferLike>; /** * Create a NUT-10 well known secret. * * @param kind - The secret kind (P2PK, HTLC, etc) * @param pubkey - The pubkey to add to Secret.data. * @param tags - Optional. Additional P2PK tags. */ export declare function createSecret(kind: SecretKind, data: string, tags?: string[][]): string; /* Excluded from this release type: createSecretAndBlindingFactorDeriver */ /** * Base error for errors raised by cashu-ts itself. */ export declare class CTSError extends Error { readonly cause?: unknown; constructor(message: string, options?: { cause?: unknown; }); } /** * Decodes an encoded cashu payment request string into a {@link PaymentRequest}. */ export declare function decodePaymentRequest(paymentRequest: string): PaymentRequest_2; /* Excluded from this release type: dedupeP2PKPubkeys */ /** * @deprecated Use {@link deriveSecretAndBlindingFactor} to derive both values together. */ export declare const deriveBlindingFactor: (seed: Uint8Array, keysetId: string, counter: number) => Uint8Array; declare type DerivedSecretAndBlindingFactor = { blindingFactor: Uint8Array; secret: Uint8Array; }; /** * Returns the keyset id of a set of keys. * * @param keys Keys object to derive keyset id from. * @param options.expiry (optional) expiry of the keyset. * @param options.input_fee_ppk (optional) Input fee for keyset (in ppk) * @param options.unit (optional) the unit of the keyset. Default: sat. * @param options.versionByte (optional) version of the keyset ID. Default: 1. * @param options.isDeprecatedBase64 (optional) version of the keyset ID. Default: false. * @returns Keyset id of the keys. * @throws If keyset versionByte is not valid. */ export declare function deriveKeysetId(keys: Keys, options?: DeriveKeysetIdOptions): string; export declare type DeriveKeysetIdOptions = { expiry?: number; input_fee_ppk?: number; unit?: string; versionByte?: number; isDeprecatedBase64?: boolean; }; /** * Blind a sequence of public keys using ECDH derived tweaks, one tweak per slot. * * @remarks * Security note: "Ehex" must never be reused. Doing so would create linkability and leak privacy. * The only exception is for SIG_ALL proofs, as all secret tags must match. * * This is the Sender side API. * @param pubkeys Ordered SEC1 compressed pubkeys, [data, ...pubkeys, ...refund] * @param eBytes Optional. Fixed ephemeral secret key to use (eg for SIG_ALL / testing) * @returns Blinded pubkeys in the same order, and Ehex as SEC1 compressed hex, 33 bytes. * @throws If a blinded key is at infinity. */ export declare function deriveP2BKBlindedPubkeys(pubkeys: string[], eBytes?: Uint8Array): { blinded: string[]; Ehex: string; }; /** * Derive a blinded secret key per NUT-28. * * Unblinds the pubkey (P = P_ - r·G), verifies x-coord against the naturalPub x(P) == x(p·G), then * choose skStd = (p + rᵢ) mod n if parity(P) == parity(p·G), otherwise skNeg = (-p + rᵢ) mod n. * Returns skStd if no blindPubkey is provided. * * @remarks * Security note, this operates on long lived secrets. JavaScript BigInt arithmetic in a JIT is not * guaranteed constant time. Do not expose this function on a server that holds private keys. * @param privkey Unblinded private key (p), hex or bigint. * @param rBlind Blinding scalar (r), hex or bigint. * @param blindPubkey Optional. Blinded pubkey (P_) to match, 33 byte hex. * @param naturalPub Optional. Pubkey calculated from private key (P = p·G), 33 byte hex. * @returns Derived blinded secret key as 64 char hex. * @throws If inputs are out of range, or the derived key would be zero. */ export declare function deriveP2BKSecretKey(privkey: string | bigint, rBlind: string | bigint, blindPubkey?: Uint8Array, naturalPub?: Uint8Array): string | null; /** * Derive blinded secret keys that correspond to given P2BK blinded pubkeys. * * Pubkeys are processed in order, for a proof that is [data, ...pubkeys, ...refund]. Private key * order does not matter. * * @remarks * Security note, this operates on long lived secrets. JavaScript BigInt arithmetic in a JIT is not * guaranteed constant time. Do not expose this function on a server that holds private keys. * * This is the Receiver side API. * @param Ehex Ephemeral public key (E) as SEC1 hex. * @param privateKey Secret key or array of secret keys, hex. * @param blindPubKey Blinded public key or array of blinded public keys, hex. * @returns Array of derived secret keys as 64 char hex. */ export declare function deriveP2BKSecretKeys(Ehex: string, privateKey: string | string[], blindPubKey: string | string[]): string[]; /** * @deprecated Use {@link deriveSecretAndBlindingFactor} to derive both values together. */ export declare const deriveSecret: (seed: Uint8Array, keysetId: string, counter: number) => Uint8Array; /** * Derives the deterministic secret and blinding factor for one counter. * * @remarks * This is the preferred NUT-13 derivation API because deterministic output construction needs both * values for the same seed, keyset, and counter. For deprecated BIP-32 keysets, deriving both * values together is faster because it avoids repeating the shared path derivation common to the * secret and blinding factor. * * The function supports legacy base64 keyset IDs, deprecated hex keyset IDs with the `00` prefix, * and modern hex keyset IDs with the `01` prefix. * @param seed - Wallet seed used for deterministic derivation. * @param keysetId - Mint keyset ID that selects the derivation method. * @param counter - Deterministic counter for the output. * @returns The derived secret bytes and blinding factor bytes. * @throws {@link CTSError} If the keyset ID version is unsupported or if derivation produces an * invalid private key. */ export declare function deriveSecretAndBlindingFactor(seed: Uint8Array, keysetId: string, counter: number): { blindingFactor: Uint8Array; secret: Uint8Array; }; export declare function deserializeMintKeys(serializedMintKeys: SerializedMintKeys): RawMintKeys; /** * Deserializes proofs from JSON back into typed {@link Proof} objects, restoring `amount` as * `bigint` without silent precision loss. * * - Pass a `string[]` (individual proof JSON strings) when reading from NutZap proof tags or a * database. * - Pass a `string` (a JSON array) when reading from a single stored blob e.g. localStorage. * - Pass a `ProofLike[]` of already-parsed proof objects for legacy data or database rows. * * @example * * // NutZap proof tags * const proofs = deserializeProofs( * event.tags.filter((t) => t[0] === 'proof').map((t) => t[1]), * ); * * // localStorage — pass the raw string, no JSON.parse needed * const proofs = deserializeProofs(localStorage.getItem('proofs') ?? '[]'); */ export declare function deserializeProofs(json: string | string[] | ProofLike[]): Proof[]; export declare type DeviceStartResponse = { device_code: string; user_code: string; verification_uri: string; verification_uri_complete?: string; interval?: number; expires_in?: number; }; export declare type DigestInput = Uint8Array | string; export declare type DLEQ = { s: Uint8Array; e: Uint8Array; r?: bigint; }; export declare type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] extends N ? Acc[number] : Enumerate<N, [...Acc, Acc['length']]>; /** * Find the private key that can sign for a given compressed public key. * * @param pubkey Compressed SEC1 public key (33 bytes, hex-encoded) to match against. * @param privkeys One or more candidate private keys (hex-encoded). * @returns The matching private key hex string. * @throws If no candidate key derives to the expected pubkey. */ export declare function findSigningKey(pubkey: string, privkeys: string | string[]): string; /** * Get data field value from a secret. * * @param secret - The Proof secret. * @returns - SecretData.data. */ export declare function getDataField(secret: Secret | string): string; /** * Helper function to decode cashu tokens into an object. * * @param token An encoded cashu token (cashuB...) * @param keysets Array of full keyset ID strings, eg: from `KeyChain.getAllKeysetIds()` * @returns Cashu token object. */ export declare function getDecodedToken(tokenString: string, keysetIds: readonly string[]): Token; /** * Decodes a raw binary token (`craw` + `B` + CBOR) into a {@link Token}. */ export declare function getDecodedTokenBinary(bytes: Uint8Array): Token; /** * Encodes a {@link Token} as a cashu token string. */ export declare function getEncodedToken(token: Token, opts?: { removeDleq?: boolean; }): string; /** * Encodes a {@link Token} as a raw binary token (`craw` + `B` + CBOR). */ export declare function getEncodedTokenBinary(token: Token): Uint8Array; /** * Get preimage from a witness if present. * * @param witness From a Proof. * @returns Preimage if present. */ export declare function getHTLCWitnessPreimage(witness: Proof['witness']): string | undefined; /** * Response from mint at /info endpoint. */ export declare type GetInfoResponse = { name: string; pubkey: string; version: string; description?: string; description_long?: string; icon_url?: string; contact: MintContactInfo[]; nuts: { '4': { methods: SwapMethod[]; disabled: boolean; }; '5': { methods: SwapMethod[]; disabled: boolean; }; '7'?: { supported: boolean; }; '8'?: { supported: boolean; }; '9'?: { supported: boolean; }; '10'?: { supported: boolean; }; '11'?: { supported: boolean; }; '12'?: { supported: boolean; }; '14'?: { supported: boolean; }; '15'?: { methods: MPPMethod[]; }; '17'?: { supported: WebSocketSupport[]; }; '19'?: { ttl: number | null; cached_endpoints: Array<{ method: 'GET' | 'POST'; path: string; }>; }; '20'?: { supported: boolean; }; '21'?: { openid_discovery: string; client_id: string; protected_endpoints?: Array<{ method: 'GET' | 'POST'; path: string; }>; }; '22'?: { bat_max_mint: number; protected_endpoints: Array<{ method: 'GET' | 'POST'; path: string; }>; }; '29'?: Nut29Info; }; motd?: string; }; /** * Returns the amounts in the keyset sorted by the order specified. * * @param keyset To search in. * @param order Order to sort the amounts in. * @returns The amounts in the keyset sorted by the order specified. */ export declare function getKeysetAmounts(keyset: Keys, order?: 'asc' | 'desc'): Amount[]; export declare const getKeysetIdInt: (keysetId: string) => bigint; /** * NUT-02 Keysets API response (/v1/keysets) */ export declare type GetKeysetsResponse = { /** * Keysets. */ keysets: MintKeyset[]; }; /** * NUT-01 Keys API response (/v1/keys) */ export declare type GetKeysResponse = { /** * Keysets. */ keysets: MintKeys[]; }; /** * Returns the expected witness public keys from a NUT-11 P2PK secret. * * @remarks * Does not tell you the pathway (Locktime or Refund MultiSig), only the keys that CAN currently * sign. If no keys are returned, the proof is unlocked or expired with no refund path. * @param secretStr - The NUT-11 P2PK secret. * @returns Array of public keys or empty array. * @throws If the secret is malformed or not P2PK. */ export declare function getP2PKExpectedWitnessPubkeys(secretStr: string | Secret): string[]; /** * Returns the sigflag from a NUT-11 P2PK secret. * * @param secretStr - The NUT-11 P2PK secret. * @returns The sigflag (`'SIG_INPUTS'` or `'SIG_ALL'`). * @throws If secret is not P2PK, or if the sigflag tag contains an unrecognised value. */ export declare function getP2PKSigFlag(secretStr: string | Secret): SigFlag; /** * Gets witness signatures as an array. * * @param witness From Proof. * @returns Array of witness signatures. */ export declare function getP2PKWitnessSignatures(witness: Proof['witness']): string[]; export declare function getPubKeyFromPrivKey(privKey: Uint8Array): Uint8Array<ArrayBufferLike>; /** * Get the SecretData payload (second element) of a Secret. * * @param secret - The Proof secret. */ export declare function getSecretData(secret: Secret | string): SecretData; /** * Get the kind (first element) of a Secret. * * @param secret - The Proof secret. */ export declare function getSecretKind(secret: Secret | string): SecretKind; /** * Get the values of a tag by key, excluding the key itself. * * @param secret - The Proof secret. * @param key - Tag key to lookup. * @returns - Array of Tag values or undefined if not present. */ export declare function getTag(secret: Secret | string, key: string): string[] | undefined; /** * Get the first scalar value of a tag parsed as base-10 integer, or undefined. * * @param secret - The Proof secret. * @param key - Tag key to lookup. * @returns - Tag value as an integer, undefined if not present or invalid. */ export declare function getTagInt(secret: Secret | string, key: string): number | undefined; /** * Get all tags from a secret. * * @param secret - The Proof secret. * @returns - Array of tag arrays. */ export declare function getTags(secret: Secret | string): string[][]; /** * Get the first scalar value of a tag as a string, or undefined if missing. * * @param secret - The Proof secret. * @param key - Tag key to lookup. * @returns - Tag value or undefined if not present. */ export declare function getTagScalar(secret: Secret | string, key: string): string | undefined; /** * Returns the metadata of a cashu token. * * @param token An encoded cashu token (cashuB...) * @returns Token metadata. */ export declare function getTokenMetadata(token: string): TokenMetadata; /** * Returns the set of unique public keys that have produced a valid Schnorr signature for a given * message. * * @param signatures - The Schnorr signature(s) (hex-encoded). * @param message - The message to verify. * @param pubkeys - The Cashu P2PK public key(s) (hex-encoded, X-only or with 02/03 prefix) to * check. * @returns Array of public keys who validly signed, duplicates removed. */ export declare function getValidSigners(signatures: string[], message: string, pubkeys: string[]): string[]; /** * Checks if the provided amount is in the keyset. * * @param amount Amount to check. * @param keyset To search in. * @returns True if the amount is in the keyset, false otherwise. */ export declare function hasCorrespondingKey(amount: AmountLike, keyset: Keys): boolean; export declare function hash_e(pubkeys: Array<WeierstrassPoint<bigint>>): Uint8Array; export declare function hashToCurve(secret: Uint8Array): WeierstrassPoint<bigint>; /** * Minimal key carrier shape for low level helpers. * * Any type with Keyset `id` can be used, including MintKeyset, MintKeys, HasKeysetKeys, Keyset, * KeysetCache. */ export declare type HasKeysetId = { id: string; }; /** * Minimal key carrier shape for low level helpers. * * Any type with `id`, and `keys` can be used, including MintKeys, KeysetCache and Keyset. */ export declare type HasKeysetKeys = { id: string; keys: Keys; }; /** * Verifies a pubkey has signed a P2PK Proof. * * @param pubkey - The Cashu P2PK public key (hex-encoded, X-only or with 02/03 prefix). * @param proof - A Cashu proof. * @param message - Optional. The message that was signed (for SIG_ALL) * @returns True if one of the signatures is theirs, false otherwise. */ export declare function hasP2PKSignedProof(pubkey: string, proof: Proof, message?: string): boolean; /** * Check if a secret has a tag with the given key. * * @param secret - The Proof secret. * @param key - Tag key to lookup. * @returns - True if tag exists, False otherwise. */ export declare function hasTag(secret: Secret | string, key: string): boolean; /** * Checks that the proof has a valid DLEQ proof according to keyset `keys` * * @param proof The proof subject to verification. * @param keyset Object containing keyset keys (eg: Keyset, MintKeys, KeysetCache) * @param opts.require Default `true`. When `false`, a proof without a DLEQ payload returns `true` * (NUT-12 "MUST verify-if-present"). The default flips to `false` in v5.0. * @returns True if verification succeeded, false otherwise. * @throws Throws if the proof amount does not match any key in the provided keyset. */ export declare function hasValidDleq(proof: Proof, keyset: HasKeysetKeys, opts?: { require?: boolean; }): boolean; /* Excluded from this release type: hexToNumber */ /** * HTLC witness. */ export declare type HTLCWitness = { /** * Preimage. */ preimage: string; /** * An array of signatures in hex format. */ signatures?: string[]; }; /** * This error is thrown when a HTTP response is not 2XX nor a protocol error. */ export declare class HttpResponseError extends CTSError { status: number; constructor(message: string, status: number, options?: { cause?: unknown; }); } export declare function injectWebSocketImpl(ws: typeof WebSocket): void; export declare type IntRange<F extends number, T extends number> = Exclude<Enumerate<T>, Enumerate<F>>; /* Excluded from this release type: invoiceHasAmountInHRP */ /** * Verify HTLC spending conditions for a single input. * * @param proof - The Proof to check. * @param logger - Optional logger (default: NULL_LOGGER) * @param message - Optional. The message to sign (for SIG_ALL) * @returns True if spending conditions are satisfied, false otherwise. * @throws If verification is impossible. */ export declare function isHTLCSpendAuthorised(proof: Proof, logger?: Logger, message?: string): boolean; /* Excluded from this release type: isObj */ /* Excluded from this release type: isP2PKSigAll */ /** * Verify P2PK spending conditions for a single input. * * @param proof - The Proof to check. * @param logger - Optional logger (default: NULL_LOGGER) * @param message - Optional. The message to sign (for SIG_ALL) * @returns True if the witness threshold was reached, false otherwise. * @throws If verification is impossible. */ export declare function isP2PKSpendAuthorised(proof: Proof, logger?: Logger, message?: string): boolean; /* Excluded from this release type: isValidHex */ /* Excluded from this release type: joinUrls */ /** * BigInt-safe JSON parser/stringifier. * * @remarks * - Based on Crockford's JSON reference parser approach (recursive descent), adapted for BigInt. * - Does not touch the global `JSON` object. * - Stringifies BigInt as pure JSON numbers (no quotes, no `n`). * * Gotchas. * * - `s === JSONInt.stringify(JSONInt.parse(s))` is generally true for canonical JSON inputs. * - `o !== JSONInt.parse(JSONInt.stringify(o))` can happen because: * * - BigInt is stringified as an unquoted JSON number token (loss of JS type on parse). * - `undefined` values are dropped or become `null` in arrays, per JSON rules. * - Custom `toJSON`/replacer behavior can change output. * * There is no consistent way to preserve BigInt type through JSON today, so handling that case is * up to users. In Cashu-TS, we use the `Amount` VO to normalize numbers. */ export declare const JSONInt: JSONIntApi; export declare interface JSONIntApi { /** * Bigint aware JSON parser. * * @remarks * Returns `unknown`, so validate or cast the result to an application-specific type. * * Unquoted JSON number tokens are parsed to BigInt when outside the safe integer range, otherwise * to number. */ parse(source: string, reviver?: (this: unknown, key: string, value: unknown) => unknown, options?: { strict?: boolean; fallbackTo?: 'number' | 'string' | 'error'; }): unknown; /** * BigInt aware JSON stringify. * * @remarks * - BigInt is stringified as an unquoted JSON number token. * - Parsing the result may yield `number` or `bigint` depending on the value and parse options. * - Returns `undefined` for top-level values that JSON cannot represent, matching `JSON.stringify` * behavior. */ stringify(value: unknown, replacer?: ((this: unknown, key: string, value: unknown) => unknown) | ReadonlyArray<string | number>, space?: string | number): string | undefined; } export declare type JsonRpcReqParams = { kind: RpcSubKinds; filters: string[]; subId: string; }; /** * Manages all keysets for a Mint. Queries filter by the wallet's unit. * * @remarks * Stores keysets for every unit the mint exposes. Methods like `getKeysets()` and * `getCheap