Skip to content

fix(activity): phrase in-chat payments as sends, not tips - #1332

Merged
bmc08gt merged 3 commits into
code/cashfrom
fix/in-chat-payment-history-labels
Aug 26, 2026
Merged

fix(activity): phrase in-chat payments as sends, not tips#1332
bmc08gt merged 3 commits into
code/cashfrom
fix/in-chat-payment-history-labels

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

A payment sent inside a chat showed up in the recipient's transaction history as
"Tip from ".

The send side is already correct. TipPaymentDelegate stamps
ChatMetadata.TipDmPayment.LocationTIPCARD for a tip card or deeplink,
CHAT for an in-chat send — and the server picks the activity verb from it, so a
tip arrives as "Tipped" and an in-chat send as "Sent". The bug is in
TransactionItemMapper.resolveTitle, which threw that verb away on the received
side and hardcoded title_activity_tipFrom for every ReceivedCrypto row.

It now reads the verb and phrases the row from it:

server verb sent received
Tipped Tipped Sally Tip from Sally
Sent Sent to Sally Received from Sally

title_activity_sentTo and title_activity_receivedFrom are new. The
substitution path, converts, and rows with no counterparty are untouched.

Analytics

The transfer events drew the line the other way: Sent Tip vs Sent Cash was
chosen by who the peer was, so a payment into a tip DM reported as a tip whether
it came from a tip card or the money button inside the thread. No data was lost,
since the event carried Origin: chat, but any count on Sent Tip that didn't
split on Origin read in-chat sends as tips.

The second commit draws the same line as the feed: only a tip card payment is a
tip. Every send from the chat screen is CHAT, so the branch collapses to
Sent Cash and Sent Tip is left to the tip card flow in TippingCoordinator.

That leaves Origin constant at Tipcard on every Sent Tip, so the third
commit drops the property and the TipOrigin.propertyValue mapping behind it.
TipOrigin itself stays — it still selects the payment's Location.

Net effect on the event stream:

payment before after
tip card / deeplink Sent Tip, Origin: Tipcard Sent Tip, no Origin
in-chat send to a tip peer Sent Tip, Origin: Chat Sent Cash
in-chat send to a contact Sent Cash unchanged

Existing queries that count Sent Tip without splitting on Origin will see the
in-chat volume move to Sent Cash from the release forward; historical events
keep their Origin values.

Known limit

The verb is the only signal available: activity/v1 models a peer payment as
plain directly_sent_crypto / received_crypto with no structured tip flag.
Matching an English prefix holds while the app ships no values-*
localizations. A localized feed would need the tip/send distinction promoted
into the notification metadata upstream.

Mirrors code-payments/code-ios-app#657.

The activity feed titled every received peer payment "Tip from <name>", so an
in-chat send showed up in the recipient's history as a tip.

The server already separates the two: it picks the verb from the payment's
`ChatMetadata.TipDmPayment.Location`, so a tip-card tip arrives as "Tipped" and
an in-chat send as "Sent". `resolveTitle` discarded that verb on the received
side and hardcoded the tip phrasing. Read it instead, and give a plain send its
own directional labels — "Sent to <name>" and "Received from <name>".

The verb is the only signal available: `activity/v1` models both as plain
sent/received crypto with no structured tip flag. Matching it holds while
`localized_text` is English-only; a localized feed would need the distinction
promoted into the notification metadata.
`Sent Tip` vs `Sent Cash` was chosen by who the peer was, so a payment into a tip
DM reported as a tip whether it came from a tip card or from the money button
inside the thread. No data was lost — the event carried `Origin: chat` — but any
count on `Sent Tip` that didn't split on `Origin` read in-chat sends as tips.

Draw the same line the activity feed now draws, from
`ChatMetadata.TipDmPayment.Location`: only a tip card payment is a tip. Every
send from the chat screen is `CHAT`, so the branch collapses to `Sent Cash` and
`Sent Tip` is left to the tip card flow in `TippingCoordinator`.

`SentTip.origin` is unchanged and now only ever reports `tipcard`. Removing the
property would break continuity of the existing series, so it stays.
`Sent Tip` now only fires for a tip card payment, so `Origin` is
constant at `Tipcard` and says nothing a Mixpanel query can use. Drop
the property and the `TipOrigin.propertyValue` mapping behind it;
`SentTip` becomes an object with no state.

`TipOrigin` itself stays — it still selects the payment's
`ChatMetadata.TipDmPayment.Location`, which is what the server reads to
pick the activity feed's verb.
@bmc08gt
bmc08gt merged commit 7a4c4d5 into code/cash Aug 26, 2026
3 checks passed
bmc08gt added a commit to code-payments/code-ios-app that referenced this pull request Aug 26, 2026
* fix: phrase in-chat payments as sends, not tips

The activity feed titled every received peer payment "Tip from <name>", so an
in-chat send showed up in the recipient's history as a tip.

The server already separates the two: it picks the verb from the payment's
`ChatMetadata.TipDmPayment.Location`, so a tip-card tip arrives as "Tipped" and
an in-chat send as "Sent". `ActivityRow.displayTitle` discarded that verb and
hardcoded the tip phrasing for both directions. Read it instead, and give a
plain send its own directional labels — "Sent to <name>" and "Received from
<name>". The switch moves into a static `peerTitle`, matching `swapTitle`'s
testable shape.

The verb is the only signal available: `activity/v1` models both as plain
sent/received crypto with no structured tip flag. Matching it holds while the
rendered title is English-only; a localized feed would need the distinction
promoted into the notification metadata.

Mirrors code-payments/code-android-app#1332.

* fix: report an in-chat send as Sent Cash, not Sent Tip

`Sent Tip` vs `Sent Cash` was chosen by who the peer was, so a payment into a tip
DM reported as a tip whether it came from a tip card or from the Send Cash action
inside the thread. No data was lost — the event carried `Origin: chat` — but any
count on `Sent Tip` that didn't split on `Origin` read in-chat sends as tips.

Draw the same line the activity feed now draws, from
`ChatMetadata.TipDmPayment.Location`: only a tip card payment is a tip. Both
flows submit through `SendAmountViewModel`, so the condition narrows to
`recipient.origin == .tipcard` and an in-chat send reports `Sent Cash` with no
origin.

`Origin` is unchanged and now only ever reports `tipcard`. Removing it would
break continuity of the existing series, so it stays.

* refactor(analytics): drop the Origin property from Sent Tip

`Sent Tip` now only fires for a tip card payment, so `Origin` is
constant at `Tipcard` and says nothing a Mixpanel query can use. Drop
the parameter, the `Property.origin` key, and the
`TipOrigin.analyticsValue` mapping behind it, along with the test that
pinned those values.

`TipOrigin` itself stays — it still selects the payment's
`ChatMetadata.TipDmPayment.Location`, which is what the server reads to
pick the activity feed's verb.
@bmc08gt
bmc08gt deleted the fix/in-chat-payment-history-labels branch August 27, 2026 15:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant