Skip to content

Implement mobile feed functionality in mobile-client - #431

Merged
frankinkfnd merged 18 commits into
mainfrom
mario/mobile-client-feed
Jul 28, 2026
Merged

Implement mobile feed functionality in mobile-client#431
frankinkfnd merged 18 commits into
mainfrom
mario/mobile-client-feed

Conversation

@marioinkfnd

@marioinkfnd marioinkfnd commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

This pull request introduces the global trade feed API to the mobile client, enabling fetching, filtering, and paginating public trade feed data. The main changes include implementing the getFeed method in MobileClient, defining new client and server types for feed data, adding data mapping utilities, and expanding error codes. It also refactors the query methods for improved type safety and consistency.

Global Feed API Implementation

  • Added the getFeed method to MobileClient, allowing clients to fetch pages of the global trade feed with optional filtering and pagination. (F8a701d8L135R177)
  • Defined new client-side types: MobileFeedMargin, MobileFeedTrade, MobileFeedPage, and GetMobileFeedParams in clientTypes.ts, describing the shape of feed data and request parameters. (Fc5f57eaL45R112, Fc5f57eaL163R163)
  • Added server-side request/response types for the feed (feed entry in MobileServerPublicQueryRequestByType) and updated discriminant types.

Data Mapping Utilities

  • Implemented mapMobileFeedPage, mapMobileFeedTrade, and mapMobileFeedMargin in dataMappers.ts to convert server-side feed data to client-side representations. (Ff4aa0bdL96R96)

Error Handling

  • Added new mobile error codes for feed-specific errors: INVALID_FEED_FILTER and INVALID_FEED_CURSOR in mobileErrorCodes.ts.

Type Safety and Query Refactoring

  • Refactored publicQuery and query methods in MobileClient to use discriminated union types for request/response, improving type safety and consistency. (F8a701d8L340R367)

Testing

  • Added an end-to-end test suite for the feed API in feed.test.ts, covering fetching, filtering, pagination, and error handling.

- Add mapping functions for server-side feed data to client-side representations, including `mapMobileFeedMargin`, `mapMobileFeedTrade`, and `mapMobileFeedPage`.
- Introduce `getFeed` method in `MobileClient` to fetch and map a page of global trade feed data.
- Define new types for feed-related data structures, including `MobileFeedMargin`, `MobileFeedTrade`, and `MobileFeedPage`.
- Update error codes to include feed-specific errors for improved error handling.
- Enhance server-side types to support feed queries and responses.

This update enhances the mobile-client's capabilities to handle trade feed data effectively.
- Update the MobileFeedMargin type to use an interface instead of a type alias for improved clarity and consistency.
- Enhance documentation to clarify the behavior of estimatedLeverage in relation to cross and isolated modes.

This change streamlines the type definition and improves the understanding of margin behavior in feed trades.
- Rename `filledAtMillis` to `filledAt` in the MobileFeedTrade interface for clarity and consistency.
- Update the mapping function to reflect this change, ensuring the filled time is accurately represented as a non-negative safe integer in tests.

This refactor improves the readability and maintainability of the code related to mobile feed trades.
- Simplify test cases by removing unnecessary parameters and conditions, enhancing readability.
- Eliminate the `getFeedOrSkip` utility function to streamline test logic.
- Update assertions to ensure proper validation of feed responses.

This refactor improves the clarity and maintainability of the feed test suite.
…uery methods

- Bump version in package.json to 0.27.0.
- Refactor publicQuery and query methods in MobileClient to improve type safety by using specific response types based on request type.
- Introduce new types for public and signed query responses to enhance clarity and maintainability of the code.

This update enhances the mobile-client's type safety and improves the overall structure of query handling.
@marioinkfnd
marioinkfnd marked this pull request as ready for review July 23, 2026 19:19

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@marioinkfnd
marioinkfnd requested a review from frankinkfnd July 23, 2026 19:19
Comment thread packages/mobile-client/package.json Outdated
Comment thread packages/mobile-client/src/MobileClient.ts Outdated
Comment thread packages/mobile-client/src/types/serverModelTypes.ts Outdated
Comment thread packages/mobile-client/src/types/serverModelTypes.ts Outdated
Comment thread packages/mobile-client/src/types/serverModelTypes.ts Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we now have MobileServerPublicQueryResponseByType, etc., why do we still need MobileServerPublicQueryType / MobileServerSuccessResponse?

Just to clarify - engine defines the server query params + response types, then builds EngineServerQueryRequestByType, and EngineServerQueryRequest / EngineServerQueryRequestType is derived based on that. Is this structure possible for mobile?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, done — it's now the engine structure with matching names.

Engine

flowchart TD
    subgraph ENGINE["engine-client — single query endpoint"]
        EP["per-query param interfaces<br/>(EngineServerMarketPriceQueryParams, ...)"] --> ERBT["EngineServerQueryRequestByType<br/>source of truth<br/>(param-less = Record&lt;string, never&gt;)"]
        ERBT -- "keyof" --> ERT["EngineServerQueryRequestType"]
        ERBT -- "{ type: T } &amp; RequestByType[T]" --> ER["EngineServerQueryRequest&lt;T&gt;"]
        ERES["per-query response interfaces<br/>(EngineServerMarketPriceResponse, ...)"] --> ERESBT["EngineServerQueryResponseByType<br/>(raw payloads)"]
        ERESBT -- "{ status: 'success', data: ResponseByType[T] }<br/>payload NESTED under data" --> ESR["EngineServerQuerySuccessResponse&lt;T&gt;"]
    end
Loading

Mobile

flowchart TD
    subgraph PUB["mobile-client — public_query endpoint"]
        MRBT["MobileServerPublicQueryRequestByType<br/>source of truth"]
        MRBT -- "keyof" --> MRT["MobileServerPublicQueryRequestType"]
        MRBT -- "{ type: T } &amp; RequestByType[T]" --> MR["MobileServerPublicQueryRequest&lt;T&gt;"]
        MRES["per-query payload interfaces<br/>(MobileServerFeedResponse, ...)"] --> MRESBT["MobileServerPublicQueryResponseByType<br/>(raw payloads)"]
    end

    subgraph SIG["mobile-client — signed query endpoint"]
        SRBT["MobileServerSignedQueryRequestByType<br/>all Record&lt;string, never&gt;<br/>(caller identified by signature)"]
        SRBT -- "keyof" --> SRT["MobileServerSignedQueryRequestType"]
        SINNER["MobileSignedInner<br/>+ signature / sender / nonce"] --> SREQ["MobileSignedRequest<br/>(wire request = signed envelope)"]
        SRES["per-query payload interfaces<br/>(MobileServerSelfIdentityResponse, ...)"] --> SRESBT["MobileServerSignedQueryResponseByType<br/>(raw payloads)"]
    end

    ENV["MobileServerSuccessResponse<br/>{ status: 'success' }<br/>shared base envelope"]
    MRESBT --> MSR["MobileServerPublicQuerySuccessResponse&lt;T&gt;"]
    ENV -- "envelope &amp; ResponseByType[T]<br/>payload INLINED next to status" --> MSR
    SRESBT --> SSR["MobileServerSignedQuerySuccessResponse&lt;T&gt;"]
    ENV -- "envelope &amp; ResponseByType[T]" --> SSR
    ENV -- "returned as-is (no payload)" --> EXEC["execute routes<br/>(claim_username, register_expo_token, ...)"]
Loading
  • MobileServerPublicQueryRequestByType is the source of truth (renamed from ParamsByType), and MobileServerPublicQueryRequestType / MobileServerPublicQueryRequest<T> are derived from it via keyof — exactly like engine.
  • *ResponseByType now holds raw payloads (like EngineServerQueryResponseByType) and the full response is derived: MobileServer*QuerySuccessResponse<T> = MobileServerSuccessResponse & ResponseByType[T].
  • MobileServerSuccessResponse is no longer a per-query wrapper — just the bare { status: 'success' } envelope. It exists because mobile inlines payloads next to status (no data key), and the executes return it as-is.
  • Signed queries got the same treatment (MobileServerSignedQueryRequestByType with empty objects, like engine's param-less queries).

Only structural diffs left, all forced by the API: payload inlined instead of nested under data, two parallel chains because public_query / signed query are separate endpoints, and on the signed route the wire request is the signed envelope rather than { type } & params.

…truction

- Streamline the creation of the MobileServerFeedRequest by directly assigning parameters instead of using conditional spreading.
- This change enhances code readability and maintainability by reducing complexity in the request body setup.
- Replace the MobileFeedPositionDirection type with BalanceSide for improved clarity and consistency in representing trade directions.
- Enhance documentation to clarify the meaning of the direction property in the context of feed trades.

This change streamlines the type definition and improves the understanding of position directions in mobile feed trades.
…r clarity

- Introduce MobileFeedPositionDirection type as an alias for BalanceSide to maintain consistency in trade direction representation.
- Update MobileFeedPosition interface to utilize the new MobileFeedPositionDirection type, improving code clarity and documentation.

This change streamlines the type definition and enhances the understanding of position directions in mobile feed trades.
- Rename MobileFeedPosition to MobileFeedTradePosition to better reflect its purpose in trade contexts.
- Update related types and interfaces, including MobileFeedPositionDirection and MobileFeedPositionEffect, to align with the new naming convention.
- This refactor enhances code clarity and consistency in representing trade-related data structures within the mobile client.
- Change MobileServerFeedMargin from a type alias to an interface for better structure and readability.
- Update documentation to clarify the behavior of estimated_leverage in relation to cross and isolated modes, ensuring accurate representation of margin data.

This refactor enhances the understanding of margin behavior in feed trades.
…safety

- Rename response types in MobileClient from `MobileServerPublicQueryResponseByType` and `MobileServerSignedQueryResponseByType` to `MobileServerPublicQuerySuccessResponse` and `MobileServerSignedQuerySuccessResponse` for consistency.
- Update the `MobileServerSuccessResponse` type to an interface for better structure.
- Enhance documentation for various response types to clarify their payloads and improve understanding of the API's success responses.

This refactor enhances type safety and improves the overall clarity of the mobile client's query handling.
…stency

- Rename types related to public queries from `MobileServerPublicQueryParamsByType` and `MobileServerPublicQueryType` to `MobileServerPublicQueryRequestByType` and `MobileServerPublicQueryRequestType` for better alignment with their purpose.
- Update the `query` and `publicQuery` methods in MobileClient to utilize the new request types, enhancing type safety and clarity in request handling.
- Adjust related types in `serverQueryTypes` to maintain consistency across the codebase.

This refactor enhances the overall structure and readability of the mobile client's query handling.
Comment thread packages/mobile-client/src/types/serverBaseTypes.ts Outdated
Comment thread packages/mobile-client/src/types/serverBaseTypes.ts Outdated
username: string;
available: boolean;
}>;
export type MobileServerFeedRequest = MobileServerPublicQueryRequest<'feed'>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to export a type for these? It's a bit confusing as I would have thought the request params would be retrieved via MobileServerPublicQueryRequestByType

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleted all three. The call sites in MobileClient now annotate with the generic directly, e.g. const body: MobileServerPublicQueryRequest<'feed'>.

One thing I tried and backed out: giving publicQuery a MobileServerPublicQueryRequest<T> param. That type is an indexed access on a mapped type, which isn't an inference site, so T widened to the full union and every caller lost its response narrowing. It keeps the { type: T } & MobileServerPublicQueryRequestByType[T] intersection, with a comment saying why.

Comment thread packages/mobile-client/src/dataMappers.ts Outdated
Comment thread apps/e2e/src/mobile-client/feed.test.ts Outdated
…stency

- Introduce new types for mobile feed margin modes and trade position directions, enhancing type safety and clarity in the feed test.
- Update the MobileClient methods to utilize the new request types, ensuring better alignment with their intended purpose.
- Refactor related types in server types to maintain consistency across the codebase.

This refactor enhances the overall structure and readability of the mobile client's feed handling.
- Update the assertion in feed tests to check that estimatedLeverage is undefined for cross margin trades, improving clarity in test expectations.
- Simplify the mapping of server-side margin data in data mappers by directly assigning properties, enhancing readability and maintainability.

These changes improve the accuracy of tests and streamline the data mapping process for mobile feed trades.
@marioinkfnd
marioinkfnd requested a review from frankinkfnd July 27, 2026 12:56
@frankinkfnd

Copy link
Copy Markdown
Contributor

@marioinkfnd can you look at the test cancelling? seems like a timeout

…eries

- Adjusted the timeout setting in the feed tests to a longer duration as a temporary measure, acknowledging that unfiltered queries can exceed a minute and filtered ones take around 20 seconds. This change is a stopgap until backend optimizations are implemented.
@marioinkfnd

Copy link
Copy Markdown
Contributor Author

@marioinkfnd can you look at the test cancelling? seems like a timeout

I bumped timeout but it still seems like it takes too long. Should I keep it as it is or?

@frankinkfnd

Copy link
Copy Markdown
Contributor

There seems to be an error with the test:
image

but also, why are the feed tests so slow?
image

@marioinkfnd

marioinkfnd commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

There seems to be an error with the test: image

but also, why are the feed tests so slow? image

Screenshot 2026-07-28 at 17 02 05

@frankinkfnd

Copy link
Copy Markdown
Contributor

@marioinkfnd can you raise this to Jonathan as well as the query_public_feed issue?

Will publish this as it's not in prod

@frankinkfnd
frankinkfnd merged commit 139f5de into main Jul 28, 2026
1 of 2 checks passed
@frankinkfnd
frankinkfnd deleted the mario/mobile-client-feed branch July 28, 2026 17:23
@frankinkfnd

Copy link
Copy Markdown
Contributor

0.30.0

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.

2 participants