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.
Problem
The persisted operation repositories currently coerce missing amount fields to
0when hydrating rows for states that should already have prepared data.Examples in the pre-v4 number-based adapters:
and for melt operations:
This is valid for
initrows 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
fee,inputAmountfeeamount,fee_reserve,swap_fee,inputAmountSuggested fix
Keep
initrow hydration permissive for fields that are not expected yet, but fail fast for required fields once the state implies prepared data exists.For example:
Then use it only after the state check:
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.