1
1
import { useOrderEntry , useSymbolsInfo } from '@orderly.network/hooks' ;
2
- import { API , OrderEntity , OrderSide , OrderType } from '@orderly.network/types' ;
2
+ import { API , OrderlyOrder , OrderSide , OrderType } from '@orderly.network/types' ;
3
3
import { Slider } from '@radix-ui/themes' ;
4
4
import { useNotifications } from '@web3-onboard/react' ;
5
5
import { FixedNumber } from 'ethers' ;
6
- import { Dispatch , FC , SetStateAction , useState } from 'react' ;
7
- import { Controller , SubmitHandler , useForm } from 'react-hook-form' ;
6
+ import { Dispatch , FC , SetStateAction , useCallback , useState } from 'react' ;
8
7
9
8
import { Spinner , TokenInput } from '.' ;
10
9
11
10
import { getDecimalsFromTick } from '~/utils' ;
12
11
import { renderFormError } from '~/utils/form' ;
13
12
14
- type Inputs = {
15
- direction : OrderSide ;
16
- type : OrderType ;
17
- quantity : string | number ;
18
- } ;
19
-
20
13
export const ClosePosition : FC < {
21
14
position : API . PositionExt ;
22
- refresh : import ( 'swr/_internal' ) . KeyedMutator < API . PositionInfo > ;
23
15
setOpen : Dispatch < SetStateAction < boolean > > ;
24
- } > = ( { position, refresh , setOpen } ) => {
16
+ } > = ( { position, setOpen } ) => {
25
17
const [ loading , setLoading ] = useState ( false ) ;
26
18
27
19
const symbolsInfo = useSymbolsInfo ( ) ;
28
20
29
- const { register, handleSubmit, control } = useForm < Inputs > ( {
30
- defaultValues : {
31
- direction : position . position_qty > 0 ? OrderSide . SELL : OrderSide . BUY ,
32
- type : OrderType . MARKET ,
33
- quantity : Math . abs ( position . position_qty )
21
+ const {
22
+ submit,
23
+ setValue,
24
+ formattedOrder,
25
+ metaState : { dirty, errors, submitted }
26
+ } = useOrderEntry ( position . symbol , {
27
+ initialOrder : {
28
+ side : position . position_qty > 0 ? OrderSide . SELL : OrderSide . BUY ,
29
+ order_type : OrderType . MARKET ,
30
+ order_quantity : String ( Math . abs ( position . position_qty ) ) ,
31
+ reduce_only : true
34
32
}
35
33
} ) ;
36
- const { onSubmit, helper } = useOrderEntry (
37
- {
38
- symbol : position . symbol ,
39
- side : OrderSide . BUY ,
40
- order_type : OrderType . MARKET
34
+ const hasError = useCallback (
35
+ (
36
+ key : keyof OrderlyOrder
37
+ ) :
38
+ | {
39
+ type : string ;
40
+ message : string ;
41
+ }
42
+ | undefined => {
43
+ if ( ! dirty [ key ] && ! submitted ) {
44
+ return ;
45
+ }
46
+ return errors ?. [ key ] ;
41
47
} ,
42
- { watchOrderbook : true }
48
+ [ errors , dirty , submitted ]
43
49
) ;
44
50
const [ _0 , customNotification ] = useNotifications ( ) ;
45
51
46
52
if ( symbolsInfo . isNil ) {
47
53
return < Spinner /> ;
48
54
}
49
55
50
- const submitForm : SubmitHandler < Inputs > = async ( data ) => {
56
+ const submitForm = async ( ) => {
51
57
setLoading ( true ) ;
52
58
const { update } = customNotification ( {
53
59
eventCode : 'closePosition' ,
54
60
type : 'pending' ,
55
61
message : 'Closing position...'
56
62
} ) ;
57
63
try {
58
- await onSubmit ( getInput ( data , position . symbol ) ) ;
64
+ await submit ( ) ;
59
65
update ( {
60
66
eventCode : 'closePositionSuccess' ,
61
67
type : 'success' ,
@@ -72,7 +78,6 @@ export const ClosePosition: FC<{
72
78
} ) ;
73
79
} finally {
74
80
setLoading ( false ) ;
75
- refresh ( ) ;
76
81
setOpen ( false ) ;
77
82
}
78
83
} ;
@@ -82,62 +87,47 @@ export const ClosePosition: FC<{
82
87
const [ baseDecimals ] = getDecimalsFromTick ( symbolInfo ) ;
83
88
84
89
return (
85
- < form className = "flex flex-1 flex-col gap-6 w-full" onSubmit = { handleSubmit ( submitForm ) } >
90
+ < form
91
+ className = "flex flex-1 flex-col gap-6 w-full"
92
+ onSubmit = { ( event ) => {
93
+ event . preventDefault ( ) ;
94
+ submitForm ( ) ;
95
+ } }
96
+ >
86
97
< div > Partially or fully close your open position at mark price.</ div >
87
98
88
- < input className = "hidden" { ...register ( 'direction' ) } />
89
- < input className = "hidden" { ...register ( 'type' ) } />
90
-
91
99
< label className = "flex flex-col" >
92
100
< span className = "font-bold font-size-5" > Quantity ({ base } )</ span >
93
- < Controller
94
- name = "quantity"
95
- control = { control }
96
- rules = { {
97
- validate : {
98
- custom : async ( _ , data ) => {
99
- const errors = await getValidationErrors ( data , position . symbol , helper . validator ) ;
100
- return errors ?. order_quantity != null ? errors . order_quantity . message : true ;
101
- }
102
- }
101
+
102
+ < TokenInput
103
+ className = { `mb-2 ${ hasError ( 'order_quantity' ) ? 'border-[var(--color-red)]' : '' } ` }
104
+ decimals = { baseDecimals }
105
+ placeholder = "Quantity"
106
+ name = "order_quantity"
107
+ value = { formattedOrder . order_quantity }
108
+ onValueChange = { ( value ) => {
109
+ setValue ( 'order_quantity' , value . toString ( ) ) ;
103
110
} }
104
- render = { ( { field : { name, onBlur, onChange, value } , fieldState : { error } } ) => (
105
- < >
106
- < TokenInput
107
- className = { `mb-2 ${ error != null ? 'border-[var(--color-red)]' : '' } ` }
108
- decimals = { baseDecimals }
109
- placeholder = "Quantity"
110
- name = { name }
111
- onBlur = { onBlur }
112
- onChange = { onChange }
113
- value = { value }
114
- onValueChange = { ( newVal ) => {
115
- value = newVal . toString ( ) ;
116
- } }
117
- min = { FixedNumber . fromString ( '0' ) }
118
- max = { FixedNumber . fromString ( String ( Math . abs ( position . position_qty ) ) ) }
119
- hasError = { error != null }
120
- />
121
- < Slider
122
- value = { [ Number ( value ) ] }
123
- defaultValue = { [ 100 ] }
124
- variant = "surface"
125
- name = { name }
126
- onValueChange = { ( value ) => {
127
- onChange ( value [ 0 ] ) ;
128
- } }
129
- onValueCommit = { onBlur }
130
- min = { 0 }
131
- max = { Math . abs ( position . position_qty ) }
132
- step = { symbolInfo . base_tick }
133
- />
134
- < div className = "font-size-[1.1rem] flex w-full justify-center my-1" >
135
- { value } { base }
136
- </ div >
137
- { renderFormError ( error ) }
138
- </ >
139
- ) }
111
+ min = { FixedNumber . fromString ( '0' ) }
112
+ max = { FixedNumber . fromString ( String ( Math . abs ( position . position_qty ) ) ) }
113
+ hasError = { ! ! hasError ( 'order_quantity' ) }
140
114
/>
115
+ < Slider
116
+ value = { [ Number ( formattedOrder . order_quantity ) ] }
117
+ defaultValue = { [ 100 ] }
118
+ variant = "surface"
119
+ name = "order_quantity"
120
+ onValueChange = { ( value ) => {
121
+ setValue ( 'order_quantity' , value . toString ( ) ) ;
122
+ } }
123
+ min = { 0 }
124
+ max = { Math . abs ( position . position_qty ) }
125
+ step = { symbolInfo . base_tick }
126
+ />
127
+ < div className = "font-size-[1.1rem] flex w-full justify-center my-1" >
128
+ { formattedOrder . order_quantity } { base }
129
+ </ div >
130
+ { renderFormError ( hasError ( 'order_quantity' ) ) }
141
131
</ label >
142
132
143
133
< button
@@ -150,21 +140,3 @@ export const ClosePosition: FC<{
150
140
</ form >
151
141
) ;
152
142
} ;
153
-
154
- async function getValidationErrors (
155
- data : Inputs ,
156
- symbol : string ,
157
- validator : ReturnType < typeof useOrderEntry > [ 'helper' ] [ 'validator' ]
158
- ) : Promise < ReturnType < ReturnType < typeof useOrderEntry > [ 'helper' ] [ 'validator' ] > > {
159
- return validator ( getInput ( data , symbol ) ) ;
160
- }
161
-
162
- function getInput ( data : Inputs , symbol : string ) : OrderEntity {
163
- return {
164
- symbol,
165
- side : data . direction ,
166
- order_type : data . type ,
167
- order_quantity : String ( data . quantity ) ,
168
- reduce_only : true
169
- } ;
170
- }
0 commit comments