Transaction list shows clawback wrapper hashes instead of custody addresses
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.rsand thetransaction_coinsview provide the raw p2 puzzle hash.crates/sage/src/endpoints/data.rs::transaction_coinencodes it directly.crates/sage/src/utils/conversions.rs::address_kindlabels it as owned heuristically.src/components/TransactionListView.tsxandTransactionColumns.tsxdisplay and allow copying it.src/lib/exportTransactions.tsexports 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
Ownonly whenis_custody_p2_puzzle_hashconfirms 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
Ownmerely because it exists inp2_puzzles. - Existing burn, launcher, and offer address classifications remain intact.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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