Skip to content
This repository was archived by the owner on Jul 15, 2025. It is now read-only.

Conversation

aum-deriv
Copy link
Contributor

@aum-deriv aum-deriv commented Mar 11, 2025

Summary by Sourcery

Subscribes to a stream of stake proposals based on the selected trade parameters and updates the UI with the received data. This includes fetching proposal data, handling loading and error states, and updating the payout values for the trade buttons.

New Features:

  • Introduces a hook to subscribe to a stream of stake proposals based on trade parameters.
  • Updates the trade buttons with payout information received from the proposal stream.
  • Adds a new API endpoint for streaming proposal data.
  • Implements error handling for the proposal stream, updating the UI to reflect error states and reconnection attempts.
  • Adds contract details to the proposal response
Screen.Recording.2025-03-14.at.12.03.43.PM.mov

Summary by Sourcery

Subscribes to a stream of stake proposals based on the selected trade parameters and updates the UI with the received data, including payout values for the trade buttons. It also handles loading and error states, and includes contract details in the proposal response.

New Features:

  • Introduces a hook to subscribe to a stream of stake proposals based on trade parameters.
  • Updates the trade buttons with payout information received from the proposal stream.
  • Adds a new API endpoint for streaming proposal data.
  • Implements error handling for the proposal stream, updating the UI to reflect error states and reconnection attempts.
  • Adds contract details to the proposal response

Copy link

sourcery-ai bot commented Mar 11, 2025

Reviewer's Guide by Sourcery

This pull request implements a stream of stake proposals based on the selected trade parameters and updates the UI with the received data. It introduces a new hook, useProposalStream, to manage the proposal subscription and updates the trade buttons with payout information from the proposal stream. The pull request also includes contract details in the proposal response and refactors stake validation logic.

Sequence diagram for proposal stream subscription

sequenceDiagram
    participant User
    participant TradeFormController
    participant useProposalStream
    participant subscribeToProposalStream
    participant Server

    User->>TradeFormController: Selects trade parameters
    TradeFormController->>useProposalStream: Passes proposalParams, isLoggedIn, account_uuid
    useProposalStream->>subscribeToProposalStream: Subscribes to proposal stream with params
    activate Server
    Server-->>subscribeToProposalStream: Sends proposal data
    deactivate Server
    subscribeToProposalStream-->>useProposalStream: Returns proposal data
    useProposalStream-->>TradeFormController: Updates proposalData state
    TradeFormController->>TradeFormController: Updates button states with payout information
Loading

File-Level Changes

Change Details Files
Implements a hook to subscribe to a stream of stake proposals based on trade parameters.
  • Introduces useProposalStream hook to manage the proposal subscription.
  • Adds ProposalRequest, ProposalData, ContractDetails, and ProposalVariant interfaces for proposal data types.
  • Updates subscribeToProposalStream to use a new API endpoint and include defined values in the parameters.
  • Modifies TradeFormController to use the useProposalStream hook and update button states based on the received proposal data.
src/screens/TradePage/components/TradeFormController.tsx
src/api/services/proposal/types.ts
src/hooks/proposal/useProposal.ts
src/api/services/proposal/proposal-sse.ts
Updates the trade buttons with payout information received from the proposal stream.
  • Modifies TradeFormController to update button states with payout information from the proposal data.
  • Handles loading and error states for the trade buttons based on the proposal stream status.
  • Uses payout values from productConfig when proposal data is not available.
src/screens/TradePage/components/TradeFormController.tsx
Adds contract details to the proposal response.
  • Introduces ContractDetails interface to represent contract details in the proposal response.
  • Adds contract_details property to the ProposalVariant interface.
src/api/services/proposal/types.ts
Refactors stake validation logic.
  • Removes validateStakeAmount function.
  • Updates useStakeField hook to use stake values directly from productConfig.
src/utils/__tests__/stake.test.ts
src/components/Stake/hooks/useStakeField.ts
src/utils/stake.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!
  • Generate a plan of action for an issue: Comment @sourcery-ai plan on
    an issue to generate a plan of action for it.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

github-actions bot commented Mar 11, 2025

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails

Scanned Manifest Files

Copy link

cloudflare-workers-and-pages bot commented Mar 11, 2025

Deploying champion-trader with  Cloudflare Pages  Cloudflare Pages

Latest commit: 8a55f22
Status: ✅  Deploy successful!
Preview URL: https://8fa3ec07.champion-trader.pages.dev
Branch Preview URL: https://aum-grwt-5204-stake-proposal.champion-trader.pages.dev

View logs

Copy link

@devloai devloai bot left a comment

Choose a reason for hiding this comment

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

I've completed a review of the stake proposal stream implementation. The code introduces a well-structured SSE connection for real-time proposal data, following the project's patterns. I've identified several areas for improvement including type inconsistencies, potential bugs in state management, and opportunities to enhance error handling and reconnection logic. Overall, the implementation is solid but would benefit from addressing these issues before merging. Feel free to provide any feedback or instructions for future reviews or tasks related to this repository.

duration_unit: string;
/** Whether equals option is allowed */
allow_equals: boolean;
/** Stake amount */
Copy link

Choose a reason for hiding this comment

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

The type for allow_equals in the interface is a boolean, but it's being converted to a string in the params on line 70. This could cause type confusion. Consider either making the interface parameter a string or handling the conversion more explicitly in the hook.

setLoading(true);
setError(null);

const cleanup = createSSEConnection<ProposalStreamResponse>({
Copy link

Choose a reason for hiding this comment

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

When a connection is established, loading state isn't explicitly reset if there are no messages received. Consider adding a timeout to set loading to false after a certain period if no message is received, to prevent the UI from showing a loading state indefinitely.

}

const data = JSON.parse(jsonString) as ContractPriceResponse;
const data = JSON.parse(jsonString) as T;
Copy link

Choose a reason for hiding this comment

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

The generic type T is correctly applied to the function signature, but there's no runtime type validation here. Consider adding a validation step or schema checking to ensure the parsed data matches the expected type structure, especially for critical data like contract proposals.

// Reset loading states when duration or trade type changes
// Update button states based on proposal stream data
useEffect(() => {
if (data) {
Copy link

Choose a reason for hiding this comment

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

This effect doesn't properly handle the case where the variants array might not include all possible button types. Consider adding a fallback that sets error states for buttons that don't have corresponding variants in the response data.

jest.clearAllMocks();
(createSSEConnection as jest.Mock).mockReturnValue(mockCleanup);
});

Copy link

Choose a reason for hiding this comment

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

The test verifies that the hook is called with correct parameters, but it doesn't test the automatic reconnection behavior when the network fails. Consider adding a test that simulates a network failure and checks if the connection is reestablished correctly.

if (loading) {
// Set loading state for all buttons without referencing previous state directly
setButtonStates((prev) => {
const newState = { ...prev };
Copy link

Choose a reason for hiding this comment

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

You're creating a new state object with newState = { ...prev } but then modifying it directly in the forEach loop. This mutative approach could lead to subtle bugs. Consider using a more immutable pattern:

setButtonStates((prev) => {
    const newState = {};
    tradeTypeConfigs[trade_type].buttons.forEach((button) => {
        newState[button.actionName] = {
            ...prev[button.actionName],
            loading: false,
            error: {
                error: error instanceof Error ? error.message : String(error),
            } as WebSocketError,
        };
    });
    return { ...prev, ...newState };
});

account: null;
transaction: null;
}

Copy link

Choose a reason for hiding this comment

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

The pricing_tick_id field appears as required in the response type, but it's marked as optional in the request type on line 9. This mismatch could cause confusion. Consider either making it consistent in both places or documenting when/why it might be optional in the request but always present in the response.


useEffect(() => {
// Skip connection if essential parameters are missing
if (!params.product_id || !params.instrument_id || !params.stake) {
Copy link

Choose a reason for hiding this comment

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

The hook doesn't handle reconnection attempts for network issues. The createSSEConnection function has reconnection logic built in, but the state in this hook doesn't reflect reconnection attempts. Consider adding a reconnecting state that users of this hook can display to users.

@aum-deriv aum-deriv force-pushed the aum/GRWT-5204/stake-proposal-stream branch from 9a1f1a2 to acb5839 Compare March 11, 2025 13:33
@aum-deriv aum-deriv closed this Mar 12, 2025
@aum-deriv aum-deriv force-pushed the aum/GRWT-5204/stake-proposal-stream branch from acb5839 to da9c314 Compare March 12, 2025 08:16
@aum-deriv aum-deriv reopened this Mar 12, 2025
Copy link

devloai bot commented Mar 12, 2025

Unable to perform a code review. You have run out of credits 😔

@aum-deriv
Copy link
Contributor Author

@sourcery-ai summary

@aum-deriv aum-deriv marked this pull request as ready for review March 14, 2025 08:08
@aum-deriv aum-deriv changed the title [draft] Aum / GRWT-5204 / stake proposal stream Aum / GRWT-5204 / stake proposal stream Mar 14, 2025
Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @aum-deriv - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Consider adding a cancellation mechanism to the useProposalStream hook to prevent memory leaks when the component unmounts.
  • The parseDuration function could be improved by using a more robust regular expression or a dedicated library for parsing duration strings.
Here's what I looked at during the review
  • 🟢 General issues: all looks good
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟡 Complexity: 1 issue found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

payout: prevStates[button.actionName]?.payout || 0,
reconnecting: false,
};
});
Copy link

Choose a reason for hiding this comment

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

issue (complexity): Consider extracting the button state update logic into a helper function to avoid duplicated loops over config.buttons in multiple useEffect blocks, improving code maintainability and readability by centralizing state management..

Consider extracting and centralizing the button state update logic into a helper or custom hook so that you can remove the duplicated loops over config.buttons in multiple useEffect blocks. For example, you could define a helper that returns the initial or updated states and then call it from your effects.

Create a helper:

const getButtonStates = (
  buttons: any[],
  prevStates: ButtonStates = {},
  overrides: Partial<ButtonState> = {}
): ButtonStates =>
  buttons.reduce((acc, button) => {
    acc[button.actionName] = {
      loading: overrides.loading ?? false,
      error: null,
      payout: prevStates[button.actionName]?.payout || 0,
      reconnecting: false,
      ...overrides,
    };
    return acc;
  }, {} as ButtonStates);

Usage in your effects:

// In the trade_type update effect:
useEffect(() => {
  setButtonStates(getButtonStates(config.buttons, buttonStates));
}, [trade_type, config.buttons]);

// In the proposal update effect:
useEffect(() => {
  if (!isLoggedIn || !account_uuid) return;

  if (!proposalData && !proposalError) {
    setButtonStates(getButtonStates(config.buttons, buttonStates, { loading: true }));
    return;
  }

  if (proposalData) {
    const updatedStates: ButtonStates = {};
    config.buttons.forEach((button: any) => {
      const variantType = button.actionName === "buy_rise" ? "rise" : "fall";
      const variant = proposalData.data.variants.find(
        (v: any) => v.variant === variantType
      );
      updatedStates[button.actionName] = {
        loading: false,
        error: null,
        payout: variant ? Number(variant.contract_details.payout) : 0,
        reconnecting: false,
      };
    });
    setButtonStates(updatedStates);
  }

  if (proposalError) {
    setButtonStates((prevStates) =>
      getButtonStates(config.buttons, prevStates, {
        loading: false,
        reconnecting: true,
        error: proposalError instanceof Error ? { error: proposalError.message } : proposalError,
      })
    );
  }
}, [proposalData, proposalError, trade_type, isLoggedIn, account_uuid, config.buttons]);

This refactoring reduces duplication and helps isolate the button state logic, making the code more maintainable while keeping all features intact.

@aum-deriv
Copy link
Contributor Author

@sourcery summary

@shafin-deriv shafin-deriv merged commit 1cd718d into master Mar 17, 2025
3 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants