feat: add changeAmount and effectiveFee to finalized melt operations#91
feat: add changeAmount and effectiveFee to finalized melt operations#91Provokke wants to merge 2 commits intocashubtc:masterfrom
Conversation
🦋 Changeset detectedLatest commit: a2b9ad8 The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Pull request overview
This PR enhances melt operations by adding settlement amount tracking. After a melt operation completes, the system now records the actual change received and effective fee paid, rather than just the initially estimated fee reserve. This provides accurate accounting of what was actually spent versus what was reserved.
Changes:
- Added
changeAmountandeffectiveFeefields toFinalizedMeltOperationto track actual settlement amounts - Updated
MeltMethodHandler.finalize()to returnFinalizeResultcontaining settlement amounts instead of void - Modified
MeltBolt11Handlerto calculate settlement amounts from mint responses and propagate them through execution, finalization, and recovery flows
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/core/operations/melt/MeltOperation.ts | Added changeAmount and effectiveFee fields to FinalizedMeltOperation interface with documentation |
| packages/core/operations/melt/MeltMethodHandler.ts | Added FinalizeResult interface and updated finalize method signature to return settlement data |
| packages/core/operations/melt/MeltOperationService.ts | Updated finalize method to return FinalizeResult and populate settlement amounts from handler results |
| packages/core/infra/handlers/MeltBolt11Handler.ts | Added calculateSettlementAmounts helper and updated execute, finalize, and recovery methods to compute and return settlement amounts |
| packages/core/infra/handlers/MeltBolt11Handler.utils.ts | Updated buildPaidResult to accept and include changeAmount and effectiveFee parameters |
| packages/core/test/unit/MeltOperationService.test.ts | Added makeFinalizedOp helper, updated mocks to return settlement amounts, and added assertions to verify settlement amount tracking |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| changeAmount: finalizedOp.changeAmount, | ||
| effectiveFee: finalizedOp.effectiveFee, |
There was a problem hiding this comment.
For backward compatibility with operations finalized before this PR, consider adding fallback values: changeAmount: finalizedOp.changeAmount ?? 0, effectiveFee: finalizedOp.effectiveFee ?? (finalizedOp as any).fee_reserve ?? 0. This ensures the return value always matches FinalizeResult even if the stored operation lacks these fields.
| changeAmount: finalizedOp.changeAmount, | |
| effectiveFee: finalizedOp.effectiveFee, | |
| // Fallbacks for backward compatibility with operations finalized before changeAmount/effectiveFee were added | |
| changeAmount: finalizedOp.changeAmount ?? 0, | |
| effectiveFee: finalizedOp.effectiveFee ?? (finalizedOp as any).fee_reserve ?? 0, |
| */ | ||
| changeAmount: number; | ||
|
|
||
| /** | ||
| * Actual fee impact after settlement. | ||
| * Calculated as: inputAmount - amount - changeAmount | ||
| * (total input proofs value - melt amount - change returned) | ||
| * This represents the actual cost paid for the melt, which may differ from fee_reserve. | ||
| */ | ||
| effectiveFee: number; |
There was a problem hiding this comment.
The FinalizedMeltOperation interface now requires changeAmount and effectiveFee fields (non-optional). Existing finalized operations in storage from before this change will not have these fields. Consider either: (1) making these fields optional with changeAmount?: number, (2) adding a data migration to populate these fields for existing operations, or (3) adding fallback values when reading from storage. Without one of these approaches, loading pre-existing finalized operations will fail or have undefined values that violate the type contract.
| */ | |
| changeAmount: number; | |
| /** | |
| * Actual fee impact after settlement. | |
| * Calculated as: inputAmount - amount - changeAmount | |
| * (total input proofs value - melt amount - change returned) | |
| * This represents the actual cost paid for the melt, which may differ from fee_reserve. | |
| */ | |
| effectiveFee: number; | |
| * | |
| * Optional for backward compatibility with finalized operations | |
| * persisted before this field was introduced. | |
| */ | |
| changeAmount?: number; | |
| /** | |
| * Actual fee impact after settlement. | |
| * Calculated as: inputAmount - amount - changeAmount | |
| * (total input proofs value - melt amount - change returned) | |
| * This represents the actual cost paid for the melt, which may differ from fee_reserve. | |
| * | |
| * Optional for backward compatibility with finalized operations | |
| * persisted before this field was introduced. | |
| */ | |
| effectiveFee?: number; |
Egge21M
left a comment
There was a problem hiding this comment.
Thank you for tackling this issue! The approach looks mostly great to me, however as Copilot pointed out already, old MeltOperation rows will not have this data.
Unfortunately how much change was generated is not part of the old FinalizedMeltOperation so re-calculating the new keys for the old data is not possible. Therefore this PR needs a strategy on how to deal with the old data.
Additionally this PR changed the MeltOperation model, so the storage adapters need to be adjusted accordingly.
No description provided.