Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,6 @@ const PerpsClosePositionView: React.FC = () => {
(orderType === 'limit' &&
(!limitPrice || parseFloat(limitPrice) <= 0)) ||
(orderType === 'market' && closePercentage === 0) ||
receiveAmount <= 0 ||
!validationResult.isValid
}
loading={isClosing}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ describe('usePerpsClosePositionValidation', () => {
expect(result.current.errors).toHaveLength(0);
});

it('should return error when user will receive negative amount', async () => {
it('returns warning (not error) when user will receive negative amount', async () => {
mockValidateClosePosition.mockResolvedValue({ isValid: true });

const params = {
Expand All @@ -126,9 +126,12 @@ describe('usePerpsClosePositionValidation', () => {
expect(result.current.isValidating).toBe(false);
});

expect(result.current.isValid).toBe(false);
expect(result.current.errors).toContain(
strings('perps.close_position.negative_receive_amount'),
expect(result.current.isValid).toBe(true);
expect(result.current.errors).toHaveLength(0);
expect(result.current.warnings).toContain(
strings('perps.close_position.negative_receive_warning', {
amount: '100.00',
}),
);
});

Expand Down
24 changes: 14 additions & 10 deletions app/components/UI/Perps/hooks/usePerpsClosePositionValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,12 @@ interface ValidationResult {
* - Example: ERROR - Trying to close a $5 position (below $6 minimum on mainnet)
* - Note: This shouldn't happen if positions were opened correctly
*
* 4. NEGATIVE RECEIVE AMOUNT
* - When fees exceed the position value + P&L
* - Example: ERROR - Position worth $10, fees are $12, user would receive -$2
* - Protects users from paying to close losing positions
*
* 5. MISSING LIMIT PRICE (checked by protocol validation)
* 4. MISSING LIMIT PRICE (checked by protocol validation)
* - Limit orders require a price to be specified
* - Example: ERROR - Limit order with no price or price <= 0
* - Note: This is validated by the provider, not duplicate-checked in UI
*
* 6. ZERO AMOUNT FOR MARKET ORDER
* 5. ZERO AMOUNT FOR MARKET ORDER
* - Market orders with 0% close percentage
* - Example: ERROR - Slider at 0% for market order
*
Expand All @@ -84,6 +79,11 @@ interface ValidationResult {
* - Example: WARNING - Closing only 2% of a $5,000 position ($100)
* - Useful for taking small profits but may not justify transaction costs
*
* 3. NEGATIVE RECEIVE AMOUNT
* - When fees exceed the recoverable value from the position
* - Example: WARNING - Closing will cost you $2 due to fees and losses
* - User can still proceed to close the position if they choose to exit
*
* ==========================================
* SPECIAL BEHAVIORS:
* ==========================================
Expand Down Expand Up @@ -168,9 +168,13 @@ export function usePerpsClosePositionValidation(
);
}

// Check if user will receive a positive amount after fees
if (receiveAmount <= 0) {
errors.push(strings('perps.close_position.negative_receive_amount'));
// Warn if user will receive negative amount (but allow them to proceed)
if (receiveAmount < 0) {
warnings.push(
strings('perps.close_position.negative_receive_warning', {
amount: Math.abs(receiveAmount).toFixed(2),
}),
);
}

// Limit order specific validation (price warning only - required check is done by protocol)
Expand Down
1 change: 1 addition & 0 deletions locales/languages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,7 @@
"minimum_remaining_error": "Cannot partial close: remaining position (${{remaining}}) would be below minimum order size (${{minimum}}). Please close 100% instead.",
"must_close_full_below_minimum": "Position value is below $10. You must close 100% of the position.",
"negative_receive_amount": "The fees exceed your position value",
"negative_receive_warning": "Closing this position will cost you ${{amount}} due to fees and losses.",
"no_amount_selected": "Please select an amount to close",
"order_type_reverted_to_market_order": "Changed to market order",
"you_need_set_price_limit_order": "You need to set a price for a limit order."
Expand Down
Loading