Area: Payments / transactions list (Payments → Overview) + transfers API ·
The transactions list is the reconciliation surface, but a row is hard to read at a glance and one field isn't persisted at all. Four related gaps on the same surface:
1. Counterparty shows a wallet address, not a name, and for direct payments it isn't recorded
The "Counterparty" column renders transfer.destination / transfer.source (a raw wallet address, truncated, monospace) and ignores the counterpartyId the row already carries. So:
- A ramp transfer that has
counterpartyId (e.g. an off-ramp to a saved individual) shows the address, or "Unavailable" when destination is null, despite the id being present on GET /v1/payments/transfers/{id}.
- A direct/Pay transfer never persists the counterparty at all: the dashboard
createTransfer sends only {source, destination, token, amount, memo}, so counterpartyId is saved as null even when the user explicitly selected the payee. The link to who was paid is lost at write time. (This is the one data bug in this issue, not just display.)
2. No transaction Type in the row
The table shows a Direction column ("Inbound"/"Outbound") but no transaction Type. A plain transfer and an offramp both read "Outbound"; an onramp and an inbound transfer both read "Inbound", indistinguishable at a glance. A label helper (RAMP_TYPE_LABELS) already exists but isn't wired into the row.
3. Token is a raw mint for direct transfers (API side of the already-fixed UI issue)
In GET /v1/payments/transfers, token is a symbol for ramp rows (USDC) but the raw mint for direct transfers (4zMMC9…, the devnet USDC mint, which isn't in the SDK's well-known-token map). The dashboard was fixed to map the mint for display, but the API still returns the raw mint, so any other consumer inherits the inconsistency.
Reproduce
curl "$BASE/v1/payments/transfers?category=ramp" -H "Authorization: Bearer $KEY"
# token "USDC", counterpartyId present on detail
curl "$BASE/v1/payments/transfers?category=wallet" -H "Authorization: Bearer $KEY"
# token "4zMMC9…" (raw mint), counterpartyId null even for a Pay to a selected counterparty
Then open Payments → Overview: rows show an address (or "Unavailable") under Counterparty, "Outbound"/"Inbound" with no type, and (for direct transfers via the API) the raw mint.
Impact: the reconciliation surface is hard to scan and, for direct payments, can't answer "who did we pay" at all because the counterparty was never stored.
Suggested fix
- Persist
counterpartyId on direct/Pay transfers (include it in createTransfer).
- Resolve
counterpartyId to a display name in the Counterparty column; keep the address on hover (the table already uses truncate + tooltip for signatures).
- Add a Type column or badge using the existing
RAMP_TYPE_LABELS.
- Represent
token consistently across transfer types in the API (resolve the symbol server-side, including devnet mints), or add a resolved-symbol field alongside the mint.
Area: Payments / transactions list (Payments → Overview) + transfers API ·
The transactions list is the reconciliation surface, but a row is hard to read at a glance and one field isn't persisted at all. Four related gaps on the same surface:
1. Counterparty shows a wallet address, not a name, and for direct payments it isn't recorded
The "Counterparty" column renders
transfer.destination/transfer.source(a raw wallet address, truncated, monospace) and ignores thecounterpartyIdthe row already carries. So:counterpartyId(e.g. an off-ramp to a saved individual) shows the address, or "Unavailable" whendestinationis null, despite the id being present onGET /v1/payments/transfers/{id}.createTransfersends only{source, destination, token, amount, memo}, socounterpartyIdis saved asnulleven when the user explicitly selected the payee. The link to who was paid is lost at write time. (This is the one data bug in this issue, not just display.)2. No transaction Type in the row
The table shows a Direction column ("Inbound"/"Outbound") but no transaction Type. A plain
transferand anofframpboth read "Outbound"; anonrampand an inboundtransferboth read "Inbound", indistinguishable at a glance. A label helper (RAMP_TYPE_LABELS) already exists but isn't wired into the row.3. Token is a raw mint for direct transfers (API side of the already-fixed UI issue)
In
GET /v1/payments/transfers,tokenis a symbol for ramp rows (USDC) but the raw mint for direct transfers (4zMMC9…, the devnet USDC mint, which isn't in the SDK's well-known-token map). The dashboard was fixed to map the mint for display, but the API still returns the raw mint, so any other consumer inherits the inconsistency.Reproduce
Then open Payments → Overview: rows show an address (or "Unavailable") under Counterparty, "Outbound"/"Inbound" with no type, and (for direct transfers via the API) the raw mint.
Impact: the reconciliation surface is hard to scan and, for direct payments, can't answer "who did we pay" at all because the counterparty was never stored.
Suggested fix
counterpartyIdon direct/Pay transfers (include it increateTransfer).counterpartyIdto a display name in the Counterparty column; keep the address on hover (the table already uses truncate + tooltip for signatures).RAMP_TYPE_LABELS.tokenconsistently across transfer types in the API (resolve the symbol server-side, including devnet mints), or add a resolved-symbol field alongside the mint.