Skip to content

Prevent 'pending' from being saved as a sweep transaction hash in the Claim record #97

@phertyameen

Description

@phertyameen

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:

  1. Mark account as CLAIMED
  2. Call sweepsService.executeSweep()
  3. Immediately create a Claim record using whatever executeSweep() returned
  4. 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

  • ClaimRedemptionProvider validates that sweepResult.txHash is a 64-character hex string before creating the Claim record
  • If the hash fails validation, the claim is treated as a failure, account status is rolled back and an error is thrown
  • The string 'pending' and any non-hex value can never be saved to sweepTxHash
  • A unit test covers the case where executeSweep() returns an invalid hash
  • The sweepTxHash column length and constraints are reviewed and documented in the PR description

Metadata

Metadata

Assignees

No one assigned

    Labels

    criticalVery important for the project to function.nestjsBackend frameworktypescriptPrograming language

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions