1
1
import { AccountType , BparamsMsgValue } from "@namada/types" ;
2
2
import { calcAmountWithSlippage } from "@osmonauts/math" ;
3
3
import { defaultAccountAtom } from "atoms/accounts" ;
4
- import { SwapResponse } from "atoms/swaps" ;
4
+ import {
5
+ namadaShieldedAssetsAtom ,
6
+ namadaTransparentAssetsAtom ,
7
+ } from "atoms/balance" ;
8
+ import {
9
+ osmosisBaseAssetMapAtom ,
10
+ osmosisSymbolAssetMapAtom ,
11
+ } from "atoms/chain" ;
12
+ import { SwapResponse , SwapResponseError , SwapResponseOk } from "atoms/swaps" ;
5
13
import { createOsmosisSwapTxAtom } from "atoms/transfer/atoms" ;
6
14
import BigNumber from "bignumber.js" ;
7
15
import invariant from "invariant" ;
@@ -11,23 +19,34 @@ import { useEffect, useState } from "react";
11
19
import { getSdkInstance } from "utils/sdk" ;
12
20
13
21
// eslint-disable-next-line @typescript-eslint/no-explicit-any
14
- async function fetchPrices ( coinGeckoIds : string [ ] ) : Promise < any > {
22
+ async function _fetchPrices ( coinGeckoIds : string [ ] ) : Promise < any > {
15
23
const url = `https://api.coingecko.com/api/v3/simple/price?ids=${ coinGeckoIds . join ( ) } &vs_currencies=usd` ;
16
24
return await fetch ( url ) . then ( ( res ) => res . json ( ) ) ;
17
25
}
18
26
27
+ const SUPPORTED_TOKENS_SYMBOLS = [ "OSMO" , "ATOM" , "TIA" ] as const ;
28
+ const SLIPPAGE = 0.1 ;
29
+
19
30
export const OsmosisSwap : React . FC = ( ) => {
31
+ const osmosisSymbolAssetsMap = useAtomValue ( osmosisSymbolAssetMapAtom ) ;
32
+ const osmosisBaseAssetsMap = useAtomValue ( osmosisBaseAssetMapAtom ) ;
33
+ const supportedAssets = SUPPORTED_TOKENS_SYMBOLS . map (
34
+ ( s ) => osmosisSymbolAssetsMap [ s ]
35
+ ) ;
20
36
const { mutateAsync : performOsmosisSwap } = useAtomValue (
21
37
createOsmosisSwapTxAtom
22
38
) ;
23
-
24
- const [ from , setFrom ] = useState < string | null > (
25
- "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2"
39
+ const [ shielded , _setShielded ] = useState < boolean > ( true ) ;
40
+ const { data : availableAssets , isLoading : _isLoadingAssets } = useAtomValue (
41
+ shielded ? namadaShieldedAssetsAtom : namadaTransparentAssetsAtom
26
42
) ;
27
- const [ to , setTo ] = useState < string > ( "uosmo" ) ;
28
- const [ amount , setAmount ] = useState < string > ( "10000" ) ;
43
+
44
+ // const www = Object.values(availableAssets || {})?.[0]?.asset.base || null;
45
+ const [ from , setFrom ] = useState < string > ( "" ) ;
46
+ const [ to , setTo ] = useState < string > ( "" ) ;
47
+ const [ amount , setAmount ] = useState < string > ( "" ) ;
29
48
const [ quote , setQuote ] = useState <
30
- ( SwapResponse & { minAmount : string } ) | null
49
+ ( SwapResponseOk & { minAmount : string } ) | null
31
50
> ( null ) ;
32
51
33
52
useEffect ( ( ) => {
@@ -42,11 +61,20 @@ export const OsmosisSwap: React.FC = () => {
42
61
) ;
43
62
const response : SwapResponse = await quote . json ( ) ;
44
63
45
- const minAmount = calcAmountWithSlippage ( response . amount_out , 0.1 ) ;
46
- setQuote ( { ...response , minAmount } ) ;
64
+ if ( ! ( response as SwapResponseError ) . message ) {
65
+ const minAmount = calcAmountWithSlippage (
66
+ ( response as SwapResponseOk ) . amount_out ,
67
+ SLIPPAGE
68
+ ) ;
69
+ setQuote ( { ...( response as SwapResponseOk ) , minAmount } ) ;
70
+ } else {
71
+ setQuote ( null ) ;
72
+ }
47
73
} ;
48
- call ( ) ;
49
- } , [ ] ) ;
74
+ if ( from && to && amount ) {
75
+ call ( ) ;
76
+ }
77
+ } , [ from , to , amount ] ) ;
50
78
51
79
const account = useAtomValue ( defaultAccountAtom ) ;
52
80
@@ -165,27 +193,79 @@ export const OsmosisSwap: React.FC = () => {
165
193
166
194
return (
167
195
< div className = "text-white" >
168
- < div > From: { from } </ div >
169
- < div > To: { to } </ div >
170
- < div > Amount: { amount } </ div >
196
+ < div > From:</ div >
197
+ < select className = "text-black" onChange = { ( e ) => setFrom ( e . target . value ) } >
198
+ < option value = "" > </ option >
199
+ { Object . values ( availableAssets || { } ) . map ( ( al ) => (
200
+ < option key = { al . asset . base } value = { al . asset . base } >
201
+ { al . asset . symbol }
202
+ </ option >
203
+ ) ) }
204
+ </ select >
205
+ < div > To:</ div >
206
+ < select className = "text-black" onChange = { ( e ) => setTo ( e . target . value ) } >
207
+ < option value = "" > </ option >
208
+ { supportedAssets . map ( ( asset ) => (
209
+ < option key = { asset . base } value = { asset . base } >
210
+ { asset . symbol }
211
+ </ option >
212
+ ) ) }
213
+ </ select >
214
+ < div > Amount in base denom:</ div >
215
+ < input
216
+ className = "text-black"
217
+ type = "text"
218
+ onChange = { ( e ) => setAmount ( e . target . value ) }
219
+ />
171
220
< p > ---</ p >
172
221
< div > Receive: </ div >
173
222
{ quote && (
174
223
< div >
175
224
< div >
176
- Amount in: { quote . amount_in . denom } : { quote . amount_in . amount }
225
+ Amount in: { quote . amount_in . amount }
226
+ { osmosisBaseAssetsMap [ from ] . denom_units [ 0 ] . aliases ?. [ 0 ] || from }
227
+ </ div >
228
+ < div >
229
+ Amount out: { quote . amount_out }
230
+ { osmosisBaseAssetsMap [ to ] . denom_units [ 0 ] . aliases ?. [ 0 ] || to }
231
+ </ div >
232
+ < div >
233
+ Min amount out: { quote . minAmount }
234
+ { osmosisBaseAssetsMap [ to ] . denom_units [ 0 ] . aliases ?. [ 0 ] || to }
235
+ </ div >
236
+ < div > Slippage: { SLIPPAGE } %</ div >
237
+ < div > Routes: </ div >
238
+ < ul className = "list-disc list-inside" >
239
+ { quote . route . map ( ( r , i ) => (
240
+ < li key = { i } >
241
+ Route{ i + 1 }
242
+ < ul className = "list-disc list-inside pl-4" >
243
+ { r . pools . map ( ( p , i ) => (
244
+ < li key = { i } >
245
+ { p . id } : { osmosisBaseAssetsMap [ p . token_out_denom ] . symbol }
246
+ (Fee: { BigNumber ( p . taker_fee ) . toString ( ) } )
247
+ </ li >
248
+ ) ) }
249
+ </ ul >
250
+ </ li >
251
+ ) ) }
252
+ </ ul >
253
+ < div > Effective fee: { BigNumber ( quote . effective_fee ) . toString ( ) } </ div >
254
+ < div >
255
+ Price: 1 { osmosisBaseAssetsMap [ from ] . symbol } ≈{ " " }
256
+ { BigNumber ( quote . in_base_out_quote_spot_price )
257
+ . times (
258
+ BigNumber ( 1 )
259
+ . minus ( BigNumber ( quote . effective_fee ) )
260
+ . plus ( BigNumber ( quote . price_impact ) )
261
+ )
262
+ . dp ( 3 )
263
+ . toString ( ) } { " " }
264
+ { osmosisBaseAssetsMap [ to ] . symbol }
265
+ </ div >
266
+ < div >
267
+ Price impact: { BigNumber ( quote . price_impact ) . dp ( 3 ) . toString ( ) }
177
268
</ div >
178
- < div > Amount out: { quote . amount_out } </ div >
179
- < div > Route: </ div >
180
- { quote . route [ 0 ] . pools . map ( ( p , i ) => (
181
- < div key = { i } >
182
- { p . id } : { p . token_out_denom } (Fee: { p . taker_fee } )
183
- </ div >
184
- ) ) }
185
- < div > Effective fee: { quote . effective_fee } </ div >
186
- < div > Spot price: { quote . in_base_out_quote_spot_price } </ div >
187
- < div > Price impact: { quote . price_impact } </ div >
188
- < div > Min amount out: { quote . minAmount } </ div >
189
269
</ div >
190
270
) }
191
271
</ div >
0 commit comments