11import { AccountType , BparamsMsgValue } from "@namada/types" ;
22import { calcAmountWithSlippage } from "@osmonauts/math" ;
33import { 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" ;
513import { createOsmosisSwapTxAtom } from "atoms/transfer/atoms" ;
614import BigNumber from "bignumber.js" ;
715import invariant from "invariant" ;
@@ -11,23 +19,34 @@ import { useEffect, useState } from "react";
1119import { getSdkInstance } from "utils/sdk" ;
1220
1321// 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 > {
1523 const url = `https://api.coingecko.com/api/v3/simple/price?ids=${ coinGeckoIds . join ( ) } &vs_currencies=usd` ;
1624 return await fetch ( url ) . then ( ( res ) => res . json ( ) ) ;
1725}
1826
27+ const SUPPORTED_TOKENS_SYMBOLS = [ "OSMO" , "ATOM" , "TIA" ] as const ;
28+ const SLIPPAGE = 0.1 ;
29+
1930export 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+ ) ;
2036 const { mutateAsync : performOsmosisSwap } = useAtomValue (
2137 createOsmosisSwapTxAtom
2238 ) ;
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
2642 ) ;
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 > ( "" ) ;
2948 const [ quote , setQuote ] = useState <
30- ( SwapResponse & { minAmount : string } ) | null
49+ ( SwapResponseOk & { minAmount : string } ) | null
3150 > ( null ) ;
3251
3352 useEffect ( ( ) => {
@@ -42,11 +61,20 @@ export const OsmosisSwap: React.FC = () => {
4261 ) ;
4362 const response : SwapResponse = await quote . json ( ) ;
4463
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+ }
4773 } ;
48- call ( ) ;
49- } , [ ] ) ;
74+ if ( from && to && amount ) {
75+ call ( ) ;
76+ }
77+ } , [ from , to , amount ] ) ;
5078
5179 const account = useAtomValue ( defaultAccountAtom ) ;
5280
@@ -165,27 +193,79 @@ export const OsmosisSwap: React.FC = () => {
165193
166194 return (
167195 < 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+ />
171220 < p > ---</ p >
172221 < div > Receive: </ div >
173222 { quote && (
174223 < div >
175224 < 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 ( ) }
177268 </ 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 >
189269 </ div >
190270 ) }
191271 </ div >
0 commit comments