Skip to content

feat(social-controllers): add the position-lifecycle stage of a trade - #9871

Draft
xavier-brochard wants to merge 1 commit into
mainfrom
xb/tsa-988-trade-lifecycle-action
Draft

feat(social-controllers): add the position-lifecycle stage of a trade#9871
xavier-brochard wants to merge 1 commit into
mainfrom
xb/tsa-988-trade-lifecycle-action

Conversation

@xavier-brochard

@xavier-brochard xavier-brochard commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Explanation

A trading position moves through four events: it is opened, added to, reduced, and closed. Trade['intent'] only distinguishes two of them — exit covers both a partial trim and a full close — so a consumer cannot tell a trader who sold 10% of a position from one who sold out. In MetaMask Mobile's social feed that surfaced as a real defect: both announced "closed", and the row switched to realized P&L on the strength of the same wrong boolean.

The social-api already had the information to settle this (it classifies each fill server-side, using a per-position isOpen flag), but nothing in this package's types carried it. This PR adds the two fields that do:

  • Trade['action']'opened' | 'added' | 'reduced' | 'closed', the fill's stage in its position's lifecycle. Deliberately asset-agnostic: a client may render only a direction for spot tokens while still needing the full value, because it is what decides whether a row shows realized or current P&L.
  • Position['isOpen'] — the API's own open/closed verdict. Stronger than a positionAmount === 0 check: it survives precision dust, and it distinguishes "no position" from "a position of size ~0". Perpetuals in particular retain a non-zero positionAmount after closing, so size alone cannot answer the question.

TradeAction is exported for consumers that branch on the value.

Both fields are optional, so this is not a breaking change. The social-api deploys independently of this package, so a response from a deployment that predates the fields must still validate — SocialService uses superstruct's permissive type(), and there is now a test pinning that a payload without them is accepted. Clients keep a local fallback that derives the stage from trade history for exactly this window.

References

  • Jira: TSA-988
  • Producer: va-mmcx-social-api PR adding TradeDto.action and PositionDto.isOpen
  • Consumer: MetaMask Mobile PR rendering the four stages in the social feed and position views

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

🤖 Generated with Claude Code

A position moves through four events: it is opened, added to, reduced,
and closed. `Trade['intent']` only distinguishes two — `exit` covers both
a partial trim and a full close — so a client could not tell a trader who
trimmed 10% from one who sold out, and social feeds announced "closed"
for both.

The social-api now classifies each fill and sends the result, so add the
two fields that carry it:

- `Trade['action']` — `opened` / `added` / `reduced` / `closed`, the
  fill's stage. Asset-agnostic, so clients that render only a direction
  for spot still get the value that decides whether a row realizes P&L.
- `Position['isOpen']` — the API's own open/closed verdict, which beats
  a `positionAmount === 0` check: it survives precision dust and
  distinguishes "no position" from "a position of size ~0".

Both are optional. The social-api ships independently of this package, so
a response from a deployment that predates them must still validate;
clients keep a local fallback that derives the stage from trade history.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant