Summary
When a claim is redeemed, ClaimRedemptionProvider creates a Claim database record using the txHash returned by SweepsService.executeSweep(). Because the sweep transaction is not yet fully implemented (Issue 18), executeSweep() currently returns the hardcoded string 'pending' as the transaction hash. This string gets saved to the sweepTxHash column of the claims table, making it impossible to distinguish a genuinely completed sweep from a failed or incomplete one by looking at the database. This issue ensures the Claim record is only ever created with a real, confirmed Stellar transaction hash.
Background: Why this matters for data integrity
The sweepTxHash column exists so that every completed claim can be independently verified on the Stellar blockchain. A transaction hash is a globally unique identifier, anyone can look it up on a Stellar explorer to confirm the payment happened. If 'pending' is stored there, that guarantee is broken. Support requests, audits, and reconciliation processes that rely on this column will silently produce wrong results.
The broader issue is that ClaimRedemptionProvider creates the Claim record before it has confirmed the sweep actually succeeded.
The current flow is:
- Mark account as CLAIMED
- Call sweepsService.executeSweep()
- Immediately create a Claim record using whatever executeSweep() returned
- Return success to the caller
Steps 2 and 3 assume executeSweep() only returns on success. But step 3 does not validate what it received - it trusts the return value blindly.
What the correct behavior should be
The Claim record should only be created after a real transaction hash is available and confirmed. A real transaction hash is a 64-character hex string. Before creating the Claim record, the code should verify that sweepResult.txHash looks like a real transaction hash and not a placeholder. If it does not, the claim should be treated as a failure and the account status should be rolled back, not persisted with a fake hash.
The relationship to Issue #92
Issue #92 wires up TransactionProvider and makes executeSweep() return a real hash. This issue is the defensive counterpart - it ensures ClaimRedemptionProvider validates what it receives rather than trusting it blindly. These two issues can be worked on in parallel but both must land for the claim flow to be considered complete.
What to consider when implementing
Think about what makes a transaction hash valid enough to save. A 64-character hex string is the minimum bar. But also consider: should the code verify the transaction actually landed on Stellar before saving the record? That would require a Horizon lookup, which adds latency but gives a stronger guarantee. At minimum, the string 'pending' and any other non-hex placeholder must be rejected before the record is written.
Also consider the sweepTxHash column length - it is currently defined as varchar(64). Stellar transaction hashes are exactly 64 hex characters, so this fits, but there is no room for anything else. If a future format changes or the column needs to store additional metadata, this will require a migration.
Where to look
- src/modules/claims/providers/claim-redemption.provider.ts: the redeemClaim() method where the Claim record is created
- src/modules/claims/entities/claim.entity.ts: the sweepTxHash column definition
- src/modules/sweeps/sweeps.service.ts: the executeSweep() return value
- src/modules/sweeps/interfaces/: the SweepResult interface that defines the return type shape
Acceptance Criteria
Summary
When a claim is redeemed, ClaimRedemptionProvider creates a Claim database record using the txHash returned by SweepsService.executeSweep(). Because the sweep transaction is not yet fully implemented (Issue 18), executeSweep() currently returns the hardcoded string 'pending' as the transaction hash. This string gets saved to the sweepTxHash column of the claims table, making it impossible to distinguish a genuinely completed sweep from a failed or incomplete one by looking at the database. This issue ensures the Claim record is only ever created with a real, confirmed Stellar transaction hash.
Background: Why this matters for data integrity
The sweepTxHash column exists so that every completed claim can be independently verified on the Stellar blockchain. A transaction hash is a globally unique identifier, anyone can look it up on a Stellar explorer to confirm the payment happened. If 'pending' is stored there, that guarantee is broken. Support requests, audits, and reconciliation processes that rely on this column will silently produce wrong results.
The broader issue is that ClaimRedemptionProvider creates the Claim record before it has confirmed the sweep actually succeeded.
The current flow is:
Steps 2 and 3 assume executeSweep() only returns on success. But step 3 does not validate what it received - it trusts the return value blindly.
What the correct behavior should be
The Claim record should only be created after a real transaction hash is available and confirmed. A real transaction hash is a 64-character hex string. Before creating the Claim record, the code should verify that sweepResult.txHash looks like a real transaction hash and not a placeholder. If it does not, the claim should be treated as a failure and the account status should be rolled back, not persisted with a fake hash.
The relationship to Issue #92
Issue #92 wires up TransactionProvider and makes executeSweep() return a real hash. This issue is the defensive counterpart - it ensures ClaimRedemptionProvider validates what it receives rather than trusting it blindly. These two issues can be worked on in parallel but both must land for the claim flow to be considered complete.
What to consider when implementing
Think about what makes a transaction hash valid enough to save. A 64-character hex string is the minimum bar. But also consider: should the code verify the transaction actually landed on Stellar before saving the record? That would require a Horizon lookup, which adds latency but gives a stronger guarantee. At minimum, the string 'pending' and any other non-hex placeholder must be rejected before the record is written.
Also consider the sweepTxHash column length - it is currently defined as varchar(64). Stellar transaction hashes are exactly 64 hex characters, so this fits, but there is no room for anything else. If a future format changes or the column needs to store additional metadata, this will require a migration.
Where to look
Acceptance Criteria