Skip to content

feat(activity): open a transaction's details from any activity row - #1417

Open
bmc08gt wants to merge 1 commit into
code/cashfrom
feat/transaction-details
Open

feat(activity): open a transaction's details from any activity row#1417
bmc08gt wants to merge 1 commit into
code/cashfrom
feat/transaction-details

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

An activity row states what moved and when, and nothing else. Tapping one did nothing, so the exchange rate, the token quantity, the fee, and the settlement state had nowhere to be read, and a sent cash link could only be cancelled from the row's own swipe action.

Rows in the wallet preview, the token-info preview and the full activity history now push AppRoute.Sheets.TransactionDetails(messageId), which draws the same entry as a screen: heading and avatar, the signed amount, and a receipt of the values a row has no space for. Figma node 9708:105260.

How it resolves

TransactionDetailsMapper shares TransactionItemMapper's reading of the metadata — counterparty, avatar, direction — so a row and the screen it opens cannot disagree about what the entry was. What it adds is the kind stated in the user's own voice, the receipt values, and the two actions.

ResolvedTransaction carries the drawn state and the action targets in one emission. Cancelling needs IndirectlySentCrypto.creator; opening the conversation needs the user id plus the profile. Neither belongs in a UI model, and opening three flows on one id invites them to disagree.

The screen reads through MessageDao.observeMessageById, so cancelling a cash link from the app bar redraws the screen once the update lands rather than leaving a stale "Pending".

AvatarSlot moves out of ActivityFeedRow into TransactionAvatarImage, parameterised by size, so the screen opens on the same avatar that was tapped rather than a second rendering of it. Its defaults are the row's geometry unchanged.

Where the ViewModel lives

TransactionDetailsViewModel sits in :features:transactions, not beside the mapper. Cancelling goes through TokenCoordinator, and :shared:transaction-history depending on :shared:tokens closes a cycle through chat.

Two receipt rows are unreachable from real data

Neither the message metadata nor the notification carries a withdrawal destination or a deposit source — IndirectlySentCrypto.creator is a gift-card vault, not an account — so account is always null and the To/From row never renders. A legacy buy/sell records only the mint that moved, so its subtitle has no counterpart mint to name, and PaidCrypto carries a pool id with no name. Both are built and left in place for when the server sends them.

The token quantity is an estimate. estimatedTokenAmountIn prices against the mint's current supply, so on a historical entry it says what that value is worth now, not what it bought then.

An activity row states what moved and when, and nothing else. Tapping one did
nothing, so the exchange rate, the token quantity, the fee, and the settlement
state had nowhere to be read, and a sent cash link could only be cancelled from
the row's own swipe action.

Rows in the wallet preview, the token-info preview and the full activity history
now push `AppRoute.Sheets.TransactionDetails(messageId)`, which draws the same
entry as a screen: heading and avatar, the signed amount, and a receipt of the
values a row has no space for.

`TransactionDetailsMapper` shares `TransactionItemMapper`'s reading of the
metadata (counterparty, avatar, direction), so a row and the screen it opens
cannot disagree about what the entry was. What it adds is the kind stated in the
user's own voice, the receipt values, and the two actions. `ResolvedTransaction`
carries the drawn state and the action targets in one emission: cancelling needs
`IndirectlySentCrypto.creator`, and opening the conversation needs the user id
plus the profile, neither of which belongs in a UI model.

The screen reads through `MessageDao.observeMessageById`, so cancelling a cash
link from the app bar redraws the screen once the update lands rather than
leaving a stale "Pending".

`TransactionDetailsViewModel` lives in `:features:transactions` rather than
beside the mapper: cancelling goes through `TokenCoordinator`, and
`:shared:transaction-history` depending on `:shared:tokens` closes a cycle
through chat.

Two receipt rows are built but unreachable from real data. Neither the message
metadata nor the notification carries a withdrawal destination or a deposit
source, so `account` is always null and the To/From row never renders; and a
legacy buy/sell records only the mint that moved, so its subtitle has no
counterpart mint to name. Both are left in place for when the server sends them.

The token quantity is an estimate: `estimatedTokenAmountIn` prices against the
mint's current supply, so on a historical entry it says what that value is worth
now, not what it bought then.
@bmc08gt bmc08gt self-assigned this Sep 4, 2026
@github-actions github-actions Bot added type: feature New functionality area: payments Payments, transfers, intents, billing area: tokens Token accounts, balances, token info and removed type: feature New functionality labels Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: payments Payments, transfers, intents, billing area: tokens Token accounts, balances, token info

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant