Skip to content

Repository hydration masks missing prepared operation amounts #156

@Egge21M

Description

@Egge21M

Problem

The persisted operation repositories currently coerce missing amount fields to 0 when hydrating rows for states that should already have prepared data.

Examples in the pre-v4 number-based adapters:

fee: row.fee ?? 0,
inputAmount: row.inputAmount ?? 0,

and for melt operations:

amount: row.amount ?? 0,
fee_reserve: row.fee_reserve ?? 0,
swap_fee: row.swap_fee ?? 0,
inputAmount: row.inputAmount ?? 0,

This is valid for init rows only because those rows have not been prepared yet. For prepared-or-later states, these fields are required by the operation model. Defaulting a missing value to zero can hide corrupted or partially written rows and rehydrate them as plausible operations with incorrect financial data.

Affected surfaces

  • Send operation repositories: fee, inputAmount
  • Receive operation repositories: fee
  • Melt operation repositories: amount, fee_reserve, swap_fee, inputAmount
  • Applies across persisted adapters, including SQLite-backed adapters and IndexedDB

Suggested fix

Keep init row hydration permissive for fields that are not expected yet, but fail fast for required fields once the state implies prepared data exists.

For example:

function requireNumber(value: number | null, field: string, operationId: string): number {
  if (value == null) {
    throw new Error(`Invalid operation row ${operationId}: missing ${field}`);
  }
  return value;
}

Then use it only after the state check:

if (row.state === 'init') {
  return { ...base, state: 'init' };
}

const preparedData = {
  fee: requireNumber(row.fee, 'fee', row.id),
  inputAmount: requireNumber(row.inputAmount, 'inputAmount', row.id),
};

Scope

This is a pre-existing repository invariant issue, not part of the cashu-ts v4 amount migration. Track it separately so the v4 migration does not grow in scope.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions