xch-dev / xch-dev/sage

Transaction list shows clawback wrapper hashes instead of custody addresses

Open
#879 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
59
Forks
34
Avg merge
4d 14h
Merged PRs (30d)
31

Description

Problem

The transaction list encodes the raw transaction_coins.p2_puzzle_hash as an address. For Clawback V2 coins this is the wrapper puzzle hash, not the sender or receiver custody puzzle hash.

The wrapper is then shown in the Transactions address column with copy-to-clipboard support and included in CSV exports. Reusing that value as a receive address can send funds into an existing clawback puzzle instead of a standard custody puzzle. This happened in practice: a later clawback used an older clawback wrapper hash as its receiver.

The backend also classifies every non-special Some(p2_puzzle_hash) as AddressKind::Own, without checking custody ownership.

Relevant code

  • crates/sage-database/src/tables/transactions.rs and the transaction_coins view provide the raw p2 puzzle hash.
  • crates/sage/src/endpoints/data.rs::transaction_coin encodes it directly.
  • crates/sage/src/utils/conversions.rs::address_kind labels it as owned heuristically.
  • src/components/TransactionListView.tsx and TransactionColumns.tsx display and allow copying it.
  • src/lib/exportTransactions.ts exports the same value to CSV.

The confirmation path already has the desired model via receiver_custody_p2_puzzle_hash() and is_custody_p2_puzzle_hash.

Expected behavior

Transaction history should show the relevant custody address, not a wrapped p2 puzzle hash:

  • Resolve Clawback V2 wrappers to their custody puzzle hash before encoding an address.
  • Show the receiver custody address for outgoing clawback transfers, with equivalent role-aware handling for other transaction directions.
  • Classify an address as Own only when is_custody_p2_puzzle_hash confirms it belongs to the current wallet.
  • Classify counterparty custody addresses as external.
  • Apply the same resolved address to confirmed transactions, pending transactions, and CSV exports.
  • Never expose clawback, option, or other wrapper puzzle hashes as reusable wallet receive addresses.

Acceptance criteria

  • Add regression coverage for a transaction containing a Clawback V2 p2 puzzle.
  • The transaction list and CSV contain the custody address, not the wrapper hash.
  • A wrapped p2 puzzle is never classified as Own merely because it exists in p2_puzzles.
  • Existing burn, launcher, and offer address classifications remain intact.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in crates/sage/src/endpoints/data.rs::transaction_coin and crates/sage/src/utils/conversions.rs::address_kind, using receiver_custody_p2_puzzle_hash() and is_custody_p2_puzzle_hash as the existing model. Trace the resolved value through TransactionListView.tsx, TransactionColumns.tsx, and src/lib/exportTransactions.ts, then add regression coverage for a Clawback V2 transaction. Done means confirmed and pending transactions, CSV exports, and address ownership classifications use custody addresses without changing burn, launcher, or offer behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, rust, typescript
Domain
backend, blockchain, databases, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.