Skip to content

ENG-2072, ENG-2073: Update margin + update SL/TP#21

Merged
petar-omni merged 2 commits intomainfrom
feat/misc
Apr 3, 2026
Merged

ENG-2072, ENG-2073: Update margin + update SL/TP#21
petar-omni merged 2 commits intomainfrom
feat/misc

Conversation

@petar-omni
Copy link
Copy Markdown
Collaborator

@petar-omni petar-omni commented Apr 3, 2026

Summary by CodeRabbit

  • New Features

    • Added "Adjust Margin" feature for isolated margin positions, allowing users to add or remove margin with real-time liquidation price estimates.
    • Unified stop loss and take profit management into a single "Set TP and SL" operation.
  • UI/UX Improvements

    • Enhanced transaction signing flow to clearly display "Update Margin" and "Set TP and SL" transaction types.
  • Refactor

    • Consolidated margin adjustment and TP/SL logic for improved maintainability.

@petar-omni petar-omni requested a review from Philippoes April 3, 2026 11:00
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
perps-dashboard Ready Ready Preview, Comment Apr 3, 2026 11:00am
perps-widget Ready Ready Preview, Comment Apr 3, 2026 11:00am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 3, 2026

📝 Walkthrough

Walkthrough

This PR consolidates Take Profit / Stop Loss editing into a single unified action and introduces a new "Adjust Margin" feature for isolated margin positions. Core atoms are refactored to compute actions internally, UI components are made more type-safe, helper functions for margin calculations are added, and new routes and state management support the margin adjustment workflow.

Changes

Cohort / File(s) Summary
Atom & State Refactoring
packages/common/src/atoms/edit-position-atoms.ts, packages/common/src/atoms/position-pending-actions-atom.ts
Removed Atom.family pattern and separate TP/SL action flows; consolidated into single editSLTPAtom that internally computes "setTpAndSl", "takeProfit", or "stopLoss" actions. Replaced pending-action schema to use unified "setTpAndSl" with optional stopLossOrderId / takeProfitOrderId. Removed exported editSLOrTPAtom and TPOrSLOption dependency.
Hook Layer
packages/common/src/hooks/use-edit-position.ts, packages/common/src/hooks/use-position-actions.ts
Consolidated useEditSLTP from separate editTP/editSL to unified editSLTP call; extracted getPositionActions helper function to aggregate decoded pending actions into updateLeverage and setTpAndSl fields, removing stopLoss/takeProfit shape.
UI Components
packages/common/src/components/molecules/toggle-group.tsx, packages/common/src/components/molecules/sign-transactions/index.tsx
Made ToggleGroup generic over string literal type for type safety. Extended transaction type formatting to recognize UPDATE_MARGIN and SET_TP_AND_SL.
Adjust Margin Feature
packages/widget/src/components/modules/PositionDetails/AdjustMargin/*
New feature module: state.tsx defines form/atom family with margin adjustment logic, max-limit validation, and calculation helpers; index.tsx renders main route with form UI and liquidation price estimation; loading.tsx provides skeleton placeholders; sign.tsx routes to signature confirmation.
Position Details UI
packages/widget/src/components/modules/PositionDetails/Overview/index.tsx, packages/widget/src/components/modules/PositionDetails/Overview/Position/index.tsx, packages/widget/src/components/modules/PositionDetails/Overview/adjust-margin-dialog.tsx
Updated to use unified editSLTP instead of separate TP/SL handlers. Changed tab state from local useState to route-driven navigation. Added AdjustMarginDialog for isolated margin positions and consolidated TP/SL dialog into single gate.
Router & Routes
packages/widget/src/routeTree.gen.ts, packages/widget/src/routes/position-details/$marketId/adjust-margin.tsx, packages/widget/src/routes/position-details/$marketId/adjust-margin_/sign.tsx
Generated route tree entries for two new adjust-margin routes (/adjust-margin and /adjust-margin/sign). Added route config with validateSearch schema for `mode: "add"
Math Utilities & Tests
packages/common/src/lib/math.ts, packages/common/tests/adjust-margin.test.ts
Added getSignedUpdateMarginAmount to compute signed margin delta and getEstimatedLiquidationPriceForProjectedMargin for margin projection. New test file validates liquidation price estimation and signed amount calculation across long/short positions.
Minor Updates
packages/common/src/services/index.ts, packages/dashboard/src/components/molecules/positions/index.tsx, packages/widget/src/components/modules/Home/Positions/index.tsx
Removed commented export. Inlined PositionsTableProps type. Replaced array-length checks with isNonEmptyArray predicates.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant AdjustMarginForm
    participant adjustMarginFormAtom
    participant getAdjustMarginCalculations
    participant updateMarginAtom
    participant API as API Client
    participant actionAtom

    User->>AdjustMarginForm: Enter amount & select mode (add/remove)
    AdjustMarginForm->>getAdjustMarginCalculations: Compute projections
    getAdjustMarginCalculations->>getAdjustMarginCalculations: Calculate max limit, projected margin, liquidation price
    getAdjustMarginCalculations-->>AdjustMarginForm: Return calculations
    AdjustMarginForm->>User: Render estimated liquidation price
    User->>AdjustMarginForm: Click Submit
    AdjustMarginForm->>adjustMarginFormAtom: Read form state (amount, mode)
    adjustMarginFormAtom->>adjustMarginFormAtom: Compute signed amount via getSignedUpdateMarginAmount
    adjustMarginFormAtom->>API: Execute updateMargin(marketId, signedAmount)
    API-->>adjustMarginFormAtom: Return action
    adjustMarginFormAtom->>actionAtom: Store action result
    actionAtom-->>AdjustMarginForm: Trigger navigation to sign
Loading
sequenceDiagram
    participant User
    participant TPOrSLDialog
    participant editSLTPAtom
    participant tpSlArgument
    participant Match as Match Logic
    participant API as API Client

    User->>TPOrSLDialog: Submit TP/SL form
    TPOrSLDialog->>editSLTPAtom: Call with settings + optional orderIds
    editSLTPAtom->>tpSlArgument: Derive triggerPrice from settings
    editSLTPAtom->>Match: Check which of newStopLossPrice / newTakeProfitPrice defined
    Match-->>editSLTPAtom: Return actionArgs {action, args}
    editSLTPAtom->>API: Execute ActionsControllerExecuteAction with computed action
    API-->>editSLTPAtom: Return result
    editSLTPAtom-->>TPOrSLDialog: Success/Failure
    TPOrSLDialog->>User: Navigate or show error
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • Chore: polishing and fixes #20: Introduces client/schema changes for setTpAndSL action type and stopLossOrderId/takeProfitOrderId arguments that this PR directly depends on for the unified TP/SL handling.

Suggested reviewers

  • 0xYoki
  • Philippoes

Poem

🐰 From many paths, one unified way,
Margin adjustments light as the day,
Stop loss and take profit now dance as one,
With liquidation prices recalculating—hooray, it's done! 🎯

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly references two feature tickets (ENG-2072, ENG-2073) and accurately summarizes the main changes: margin update functionality and SL/TP (Stop Loss/Take Profit) update consolidation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/misc

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/common/src/atoms/position-pending-actions-atom.ts (1)

33-42: ⚠️ Potential issue | 🟡 Minor

Use position.marginMode instead of hardcoding "isolated".

The marginMode is hardcoded to "isolated", but position.marginMode is available and the system supports both isolated and cross-margin modes. Either parameterize this using position.marginMode if both modes should be supported for updateLeverage, or add a comment explaining why only isolated mode is supported.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/src/atoms/position-pending-actions-atom.ts` around lines 33 -
42, The call to client.ActionsControllerExecuteAction hardcodes marginMode:
"isolated"; change this to use the position's actual mode by passing marginMode:
position.marginMode (or, if only isolated is intentionally supported, add a
clear comment on why) so updateLeverage honors both isolated and cross modes;
locate the call site in the function that invokes
client.ActionsControllerExecuteAction where providerId: selectedProvider.id,
address: wallet.currentAccount.address, action: "updateLeverage", args: {
marketId: position.marketId, leverage: newLeverage, marginMode: ... } and
replace the hardcoded string with position.marginMode (or document the reason
for sticking to "isolated").
🧹 Nitpick comments (4)
packages/common/src/hooks/use-position-actions.ts (1)

36-43: Add Match.orElse for completeness.

The Match.value(...).pipe(...) chain doesn't have a terminal matcher. While this works because unmatched cases just don't modify acc, adding Match.orElse(() => {}) would make the intent explicit and satisfy exhaustiveness if new action types are added.

♻️ Add exhaustive match
       Match.value(decoded).pipe(
         Match.when({ type: "updateLeverage" }, (v) => {
           acc.updateLeverage = v;
         }),
         Match.when({ type: "setTpAndSl" }, (v) => {
           acc.setTpAndSl = v;
         }),
+        Match.orElse(() => {}),
       );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/src/hooks/use-position-actions.ts` around lines 36 - 43, The
Match.value(...).pipe(...) call in use-position-actions.ts uses Match.when for
"updateLeverage" and "setTpAndSl" but has no terminal case; add Match.orElse(()
=> {}) to the pipe to make the match exhaustive and explicit so future action
types won't be silently ignored—place the orElse after the existing Match.when
calls in the same chain (the Match.value(...).pipe(...) that assigns
acc.updateLeverage and acc.setTpAndSl).
packages/common/tests/adjust-margin.test.ts (1)

60-73: Consider adding more edge case tests for robustness.

The invalid margin test only covers projectedMargin: 0. Consider adding tests for:

  • Negative projectedMargin (should return null)
  • Invalid amount inputs to getSignedUpdateMarginAmount (e.g., "abc", NaN, 0, negative values)
🧪 Additional edge case tests
   test("return null for invalid projected margin", () => {
     const position = {
       markPrice: 4_000,
       side: "long" as const,
       size: "1",
     };

     expect(
       getEstimatedLiquidationPriceForProjectedMargin({
         position,
         projectedMargin: 0,
       }),
     ).toBeNull();
+
+    expect(
+      getEstimatedLiquidationPriceForProjectedMargin({
+        position,
+        projectedMargin: -100,
+      }),
+    ).toBeNull();
   });

   test("format update margin amounts for add and remove flows", () => {
     expect(getSignedUpdateMarginAmount({ amount: "125.5", mode: "add" })).toBe(
       "125.5",
     );
     expect(getSignedUpdateMarginAmount({ amount: 125.5, mode: "remove" })).toBe(
       "-125.5",
     );
+    // Invalid inputs should return null
+    expect(getSignedUpdateMarginAmount({ amount: "abc", mode: "add" })).toBeNull();
+    expect(getSignedUpdateMarginAmount({ amount: 0, mode: "add" })).toBeNull();
+    expect(getSignedUpdateMarginAmount({ amount: -50, mode: "add" })).toBe("50");
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/tests/adjust-margin.test.ts` around lines 60 - 73, Add
edge-case tests to cover negative projected margins and invalid amount inputs:
extend the test suite for getEstimatedLiquidationPriceForProjectedMargin to
assert it returns null for projectedMargin < 0 (e.g., -1) in addition to 0, and
add tests for getSignedUpdateMarginAmount that pass invalid amount
strings/values such as "abc", NaN, "0", and negative numbers to assert the
expected failure behavior (null/throw/validation result used by your codebase);
locate tests referencing getEstimatedLiquidationPriceForProjectedMargin and
getSignedUpdateMarginAmount and add assertions matching the existing pattern to
ensure these edge cases are covered.
packages/common/src/atoms/edit-position-atoms.ts (1)

99-101: Consider using Effect.fail instead of Effect.dieMessage for recoverable errors.

Effect.dieMessage creates a defect (unrecoverable error). If a user submits the form without any TP/SL values set, this would crash rather than show a validation error. Consider whether this should be a typed error that callers can handle gracefully.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/src/atoms/edit-position-atoms.ts` around lines 99 - 101,
Replace the unrecoverable defect thrown for missing actionArgs with a
recoverable typed failure so callers can handle validation errors: in the
actionArgs check (the block that currently does yield* Effect.dieMessage("No
TP/SL settings provided")), return yield* Effect.fail(...) with a well-defined
validation error (e.g., a ValidationError tag or specific error object/string)
instead of dieMessage and propagate that error type through the surrounding
effect so callers of the edit-position logic can catch and display a validation
message.
packages/common/src/lib/math.ts (1)

224-239: Consider using parseFloatOr for consistency.

The file already has parseFloatOr (line 27) and parseFloatOrZero (line 36) for safely parsing numeric strings. Using Number() directly here works but is inconsistent with the rest of the file's parsing approach.

♻️ Optional: Use existing parseFloatOr for consistency
 export const getSignedUpdateMarginAmount = ({
   amount,
   mode,
 }: {
   amount: number | string;
   mode: "add" | "remove";
 }) => {
-  const parsedAmount = typeof amount === "string" ? Number(amount) : amount;
+  const parsedAmount = typeof amount === "string" ? parseFloatOr(amount, NaN) : amount;
   const absoluteAmount = Math.abs(parsedAmount);

   if (!Number.isFinite(absoluteAmount) || absoluteAmount <= 0) {
     return null;
   }

   return (mode === "add" ? absoluteAmount : -absoluteAmount).toString();
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/src/lib/math.ts` around lines 224 - 239, The parsing in
getSignedUpdateMarginAmount uses Number(amount) directly; replace that with the
existing parseFloatOr (or parseFloatOrZero if you prefer zero default) to match
file-wide parsing utilities: call parseFloatOr(amount) to obtain parsedAmount,
maintain Math.abs and Number.isFinite checks, preserve the early return of null
for non-finite or non-positive values, and keep returning the signed value as a
string; update imports/usages accordingly so getSignedUpdateMarginAmount relies
on parseFloatOr instead of Number().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@packages/widget/src/components/modules/PositionDetails/AdjustMargin/index.tsx`:
- Around line 267-293: The code incorrectly treats the value returned by
useAdjustMarginPosition as a Result; update AdjustMargin/index.tsx to stop
calling Result.isInitial/Result.isSuccess on the position variable and stop
using position.value. Keep the Result checks for market and providerBalance
only, and instead guard position by checking for null/undefined (or whatever
plain-shape sentinel the hook returns), then pass the plain position into
<AdjustMarginContent wallet={wallet} marketRef={market.value}
position={position} availableBalance={providerBalance.value.availableBalance} />
(i.e. remove .value usage for position and adjust the earlier conditional logic
accordingly).

In
`@packages/widget/src/components/modules/PositionDetails/AdjustMargin/state.tsx`:
- Around line 83-109: The code currently blocks the "remove" flow by always
requiring providerBalance; change the validation so providerBalance is only
required when values.Mode === "add": keep the position check
(registry.get(adjustMarginPositionAtom(key)) -> position) and its marginMode
check as-is, but move or guard the providerBalance check
(registry.get(selectedProviderBalancesAtom(key)) -> providerBalance) behind a
conditional that runs only when values.Mode === "add"; ensure maxAmount
computation still uses providerBalance.availableBalance for Mode === "add" and
position.margin for Mode === "remove" so remove-mode no longer fails when
providerBalance is missing.
- Around line 66-71: The Amount field currently only enforces >0; update the
validation on the Amount field (where Schema.NumberFromString and
Schema.greaterThan(...) are used) to enforce the API minimum of $10 by replacing
the greaterThan(0, ...) check with a minimum-10 check (e.g., use a
greaterThanOrEqual(10, { message: () => "Must be at least $10" }) or equivalent)
so values below $10 are rejected by the form before calling updateMargin.

In
`@packages/widget/src/components/modules/PositionDetails/Overview/Position/index.tsx`:
- Around line 266-268: The AdjustMarginDialog is rendered when
position.marginMode === "isolated" but lacks a provider capability check; update
the PendingActionSchema in use-position-actions.ts to include updateMargin, then
gate rendering by checking positionActions.updateMargin (e.g.,
positionActions.updateMargin && position.marginMode === "isolated") before
rendering <AdjustMarginDialog marketId={position.marketId} /> so it matches the
pattern used for setTpAndSl and updateLeverage.

---

Outside diff comments:
In `@packages/common/src/atoms/position-pending-actions-atom.ts`:
- Around line 33-42: The call to client.ActionsControllerExecuteAction hardcodes
marginMode: "isolated"; change this to use the position's actual mode by passing
marginMode: position.marginMode (or, if only isolated is intentionally
supported, add a clear comment on why) so updateLeverage honors both isolated
and cross modes; locate the call site in the function that invokes
client.ActionsControllerExecuteAction where providerId: selectedProvider.id,
address: wallet.currentAccount.address, action: "updateLeverage", args: {
marketId: position.marketId, leverage: newLeverage, marginMode: ... } and
replace the hardcoded string with position.marginMode (or document the reason
for sticking to "isolated").

---

Nitpick comments:
In `@packages/common/src/atoms/edit-position-atoms.ts`:
- Around line 99-101: Replace the unrecoverable defect thrown for missing
actionArgs with a recoverable typed failure so callers can handle validation
errors: in the actionArgs check (the block that currently does yield*
Effect.dieMessage("No TP/SL settings provided")), return yield* Effect.fail(...)
with a well-defined validation error (e.g., a ValidationError tag or specific
error object/string) instead of dieMessage and propagate that error type through
the surrounding effect so callers of the edit-position logic can catch and
display a validation message.

In `@packages/common/src/hooks/use-position-actions.ts`:
- Around line 36-43: The Match.value(...).pipe(...) call in
use-position-actions.ts uses Match.when for "updateLeverage" and "setTpAndSl"
but has no terminal case; add Match.orElse(() => {}) to the pipe to make the
match exhaustive and explicit so future action types won't be silently
ignored—place the orElse after the existing Match.when calls in the same chain
(the Match.value(...).pipe(...) that assigns acc.updateLeverage and
acc.setTpAndSl).

In `@packages/common/src/lib/math.ts`:
- Around line 224-239: The parsing in getSignedUpdateMarginAmount uses
Number(amount) directly; replace that with the existing parseFloatOr (or
parseFloatOrZero if you prefer zero default) to match file-wide parsing
utilities: call parseFloatOr(amount) to obtain parsedAmount, maintain Math.abs
and Number.isFinite checks, preserve the early return of null for non-finite or
non-positive values, and keep returning the signed value as a string; update
imports/usages accordingly so getSignedUpdateMarginAmount relies on parseFloatOr
instead of Number().

In `@packages/common/tests/adjust-margin.test.ts`:
- Around line 60-73: Add edge-case tests to cover negative projected margins and
invalid amount inputs: extend the test suite for
getEstimatedLiquidationPriceForProjectedMargin to assert it returns null for
projectedMargin < 0 (e.g., -1) in addition to 0, and add tests for
getSignedUpdateMarginAmount that pass invalid amount strings/values such as
"abc", NaN, "0", and negative numbers to assert the expected failure behavior
(null/throw/validation result used by your codebase); locate tests referencing
getEstimatedLiquidationPriceForProjectedMargin and getSignedUpdateMarginAmount
and add assertions matching the existing pattern to ensure these edge cases are
covered.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 72425096-77cd-4221-9ec3-166036002b23

📥 Commits

Reviewing files that changed from the base of the PR and between 3d9e5de and eaad78f.

📒 Files selected for processing (22)
  • packages/common/src/atoms/edit-position-atoms.ts
  • packages/common/src/atoms/position-pending-actions-atom.ts
  • packages/common/src/components/molecules/sign-transactions/index.tsx
  • packages/common/src/components/molecules/toggle-group.tsx
  • packages/common/src/hooks/use-edit-position.ts
  • packages/common/src/hooks/use-position-actions.ts
  • packages/common/src/lib/math.ts
  • packages/common/src/services/index.ts
  • packages/common/tests/adjust-margin.test.ts
  • packages/dashboard/src/components/molecules/positions/index.tsx
  • packages/dashboard/src/components/molecules/positions/positions-tab.tsx
  • packages/widget/src/components/modules/Home/Positions/index.tsx
  • packages/widget/src/components/modules/PositionDetails/AdjustMargin/index.tsx
  • packages/widget/src/components/modules/PositionDetails/AdjustMargin/loading.tsx
  • packages/widget/src/components/modules/PositionDetails/AdjustMargin/sign.tsx
  • packages/widget/src/components/modules/PositionDetails/AdjustMargin/state.tsx
  • packages/widget/src/components/modules/PositionDetails/Overview/Position/index.tsx
  • packages/widget/src/components/modules/PositionDetails/Overview/adjust-margin-dialog.tsx
  • packages/widget/src/components/modules/PositionDetails/Overview/index.tsx
  • packages/widget/src/routeTree.gen.ts
  • packages/widget/src/routes/position-details/$marketId/adjust-margin.tsx
  • packages/widget/src/routes/position-details/$marketId/adjust-margin_/sign.tsx
💤 Files with no reviewable changes (1)
  • packages/common/src/services/index.ts

Comment on lines +267 to +293
const position = useAdjustMarginPosition(formKey);
const providerBalance = useSelectedProviderBalanceResult(
wallet.currentAccount.address,
);

if (
Result.isInitial(market) ||
Result.isInitial(position) ||
Result.isInitial(providerBalance)
) {
return <AdjustMarginLoading />;
}

if (
!Result.isSuccess(market) ||
!Result.isSuccess(position) ||
!Result.isSuccess(providerBalance)
) {
return <Navigate to="/position-details/$marketId" params={{ marketId }} />;
}

return (
<AdjustMarginContent
wallet={wallet}
marketRef={market.value}
position={position.value}
availableBalance={providerBalance.value.availableBalance}
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Apr 3, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Stop treating position as a Result.

useAdjustMarginPosition is implemented as a plain useAtomValue(...) wrapper in packages/widget/src/components/modules/PositionDetails/AdjustMargin/state.tsx:222-226, but this code runs Result.isInitial/isSuccess against it and then reads position.value. As written, the non-success branch will win and the adjust-margin route will bounce back to /position-details/$marketId instead of rendering.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/widget/src/components/modules/PositionDetails/AdjustMargin/index.tsx`
around lines 267 - 293, The code incorrectly treats the value returned by
useAdjustMarginPosition as a Result; update AdjustMargin/index.tsx to stop
calling Result.isInitial/Result.isSuccess on the position variable and stop
using position.value. Keep the Result checks for market and providerBalance
only, and instead guard position by checking for null/undefined (or whatever
plain-shape sentinel the hook returns), then pass the plain position into
<AdjustMarginContent wallet={wallet} marketRef={market.value}
position={position} availableBalance={providerBalance.value.availableBalance} />
(i.e. remove .value usage for position and adjust the earlier conditional logic
accordingly).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

useAdjustMarginPosition() wraps useAtomValue() and returns Result<PositionDto, ...> so this code is legit. check again @coderabbitai

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

Let me inspect the actual implementation to verify.


🏁 Script executed:

#!/bin/bash
# Check the useAdjustMarginPosition and adjustMarginPositionAtom implementations
rg -n "useAdjustMarginPosition|adjustMarginPositionAtom" --type=ts --type=tsx -A 10

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Search for useAdjustMarginPosition implementation
rg -n "useAdjustMarginPosition|adjustMarginPositionAtom" -A 10 --glob="*.ts" --glob="*.tsx"

Length of output: 7518


@petar-omni, you're right — I apologize for the incorrect review comment. adjustMarginPositionAtom is defined as a runtimeAtom.atom(Effect.fn(...)) (Line 48 of state.tsx), so useAtomValue correctly surfaces it as a Result<PositionDto, ...>. The Result.isInitial, Result.isSuccess, and position.value usages in the component are all valid. My original concern was mistaken.

@petar-omni petar-omni merged commit 0faee3e into main Apr 3, 2026
10 checks passed
@petar-omni petar-omni deleted the feat/misc branch April 3, 2026 16:14
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