1- import { formatUnits , parseUnits } from "viem" ;
21import { apiAtom } from "@/lib/atoms" ;
32import { PvqProgram } from "@open-web3/pvq" ;
3+ import type { Option , u128 , Vec } from "@polkadot/types" ;
4+ import type { ITuple } from "@polkadot/types/types" ;
5+ import { u8aToString } from "@polkadot/util" ;
46import { atom } from "jotai" ;
57import { atomWithQuery } from "jotai-tanstack-query" ;
8+ import { atomFamily } from "jotai/utils" ;
9+ import { formatUnits , parseUnits } from "viem" ;
610import { guestSwapInfoProgram } from "./assets/guest-swap-info" ;
711import metadata from "./assets/guest-swap-info-metadata.json" ;
8- import type { Bytes , Vec , Option , u128 } from "@polkadot/types" ;
9- import type { Codec , ITuple } from "@polkadot/types/types" ;
10- import { compactStripLength , u8aToString } from "@polkadot/util" ;
11- import { atomFamily } from "jotai/utils" ;
12+
13+ type AssetInfo = {
14+ assetId : string ;
15+ decimals : number ;
16+ name : string ;
17+ symbol : string ;
18+ } ;
1219
1320export const lpProgramAtom = atom < PvqProgram | null > ( ( get ) => {
1421 const api = get ( apiAtom ) ;
@@ -18,122 +25,81 @@ export const lpProgramAtom = atom<PvqProgram | null>((get) => {
1825
1926export const poolListAtom = atomWithQuery ( ( get ) => ( {
2027 queryKey : [ "poolList" ] ,
28+ onError : ( error : Error ) => {
29+ console . error ( "Error fetching pool list" , error . message ) ;
30+ } ,
31+ throwOnError : true ,
32+ retry : false ,
2133 queryFn : async ( ) => {
34+ console . log ( "fetching pool list" ) ;
2235 const program = get ( lpProgramAtom ) ;
2336 if ( ! program ) throw new Error ( "Program not initialized" ) ;
24- const lpList = await program . executeQuery < Vec < ITuple < [ Bytes , Bytes ] > > > (
37+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38+ const lpList = await program . executeQuery < Vec < ITuple < [ any , any ] > > > (
2539 "entrypoint_list_pools" ,
2640 undefined ,
2741 [ ]
2842 ) ;
29- return lpList . map (
30- ( [ assetId1 , assetId2 ] ) => [ assetId1 . toHex ( ) , assetId2 . toHex ( ) ] as const
31- ) ;
43+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
44+ const getAssetInfo = ( asset : any ) : AssetInfo => {
45+ return {
46+ assetId : asset . assetId . toHex ( ) as string ,
47+ decimals : asset . decimals . toNumber ( ) as number ,
48+ name : u8aToString ( asset . name ) ,
49+ symbol : u8aToString ( asset . symbol ) . replace ( / [ ^ a - z A - Z 0 - 9 ] / g, "" ) ,
50+ } ;
51+ } ;
52+
53+ const result = lpList . map ( ( [ assetId1 , assetId2 ] ) => {
54+ const asset1 = getAssetInfo ( assetId1 ) ;
55+ const asset2 = getAssetInfo ( assetId2 ) ;
56+ return {
57+ asset1,
58+ asset2,
59+ key : `${ assetId1 . assetId } -${ assetId2 . assetId } ` ,
60+ } ;
61+ } ) ;
62+
63+ console . log ( "pools" , result ) ;
64+ return result ;
3265 } ,
3366 enabled : ! ! get ( lpProgramAtom ) ,
3467} ) ) ;
3568
3669export const assetsInfoAtom = atomWithQuery ( ( get ) => {
37- const { data : poolList , isFetched } = get ( poolListAtom ) ;
38- const program = get ( lpProgramAtom ) ;
39- const assetIds = [
40- ...new Set (
41- poolList ?. flatMap ( ( [ assetId1 , assetId2 ] ) => [ assetId1 , assetId2 ] )
42- ) ,
43- ] ;
70+ const { data : poolList } = get ( poolListAtom ) ;
4471
4572 return {
46- queryKey : [ "assetsInfo" , assetIds ] ,
47- queryFn : async ( ) : Promise <
48- {
49- assetId : string ;
50- decimals : number ;
51- name : string ;
52- symbol : string ;
53- } [ ]
54- > => {
55- if ( ! program ) throw new Error ( "Program not initialized" ) ;
56- const result = await Promise . all (
57- assetIds !
58- . filter ( ( assetId ) => assetId !== "0x040d000000" )
59- . map ( async ( assetId ) => {
60- // console.log("assetId1", assetId);
61-
62- const res = await program . executeQuery < Option < Codec > > (
63- "entrypoint_asset_info" ,
64- undefined ,
65- [ assetId ]
66- ) ;
67-
68- if ( res . isEmpty ) return null ;
69-
70- // eslint-disable-next-line @typescript-eslint/no-explicit-any
71- const asset : any = res . unwrap ( ) ;
72- const [ , name ] = compactStripLength ( asset . name ) ;
73- const [ , symbol ] = compactStripLength ( asset . symbol ) ;
74- return {
75- assetId : asset . assetId . toHex ( ) as string ,
76- decimals : asset . decimals . toNumber ( ) as number ,
77- name : u8aToString ( name ) ,
78- symbol : u8aToString ( symbol ) ,
79- } ;
80- } )
81- ) ;
73+ queryKey : [ "assetsInfo" ] ,
74+ queryFn : async ( ) => {
75+ const assetsInfo =
76+ poolList ?. flatMap ( ( pool ) => [ pool . asset1 , pool . asset2 ] ) ?? [ ] ;
77+ const uniqueAssetsInfo : AssetInfo [ ] = [ ] ;
78+
79+ for ( const asset of assetsInfo ) {
80+ if ( ! uniqueAssetsInfo . some ( ( a ) => a . assetId === asset . assetId ) ) {
81+ uniqueAssetsInfo . push ( asset ) ;
82+ }
83+ }
8284
83- return result
84- . concat ( {
85- assetId : "0x040d000000" ,
86- decimals : 10 ,
87- name : "lcDOT" ,
88- symbol : "lcDOT" ,
89- } )
90- . filter ( Boolean ) as {
91- assetId : string ;
92- decimals : number ;
93- name : string ;
94- symbol : string ;
95- } [ ] ;
85+ return uniqueAssetsInfo ;
9686 } ,
97- enabled : isFetched && ! ! program ,
87+ enabled : ! ! poolList ,
9888 } ;
9989} ) ;
10090
10191export const assetsInfoFamily = atomFamily ( ( id : string ) =>
10292 atom ( ( get ) => {
10393 const { data : assetsInfo } = get ( assetsInfoAtom ) ;
104-
10594 return assetsInfo ?. find ( ( asset ) => asset . assetId === id ) ;
10695 } )
10796) ;
10897
109- export const poolListDetailAtom = atomWithQuery ( ( get ) => {
110- const { data : poolList , isFetched : isPoolListFetched } = get ( poolListAtom ) ;
111- const { data : assetsInfo , isFetched : isAssetsInfoFetched } =
112- get ( assetsInfoAtom ) ;
113-
114- return {
115- queryKey : [ "poolListDetail" ] ,
116- queryFn : async ( ) => {
117- console . log ( "poolList" , poolList , isPoolListFetched , isAssetsInfoFetched ) ;
118- return poolList ?. map ( ( [ assetId1 , assetId2 ] ) => {
119- const asset1 = assetsInfo ?. find ( ( asset ) => asset . assetId === assetId1 ) ;
120- const asset2 = assetsInfo ?. find ( ( asset ) => asset . assetId === assetId2 ) ;
121- return {
122- asset1 : asset1 ! ,
123- asset2 : asset2 ! ,
124- key : `${ assetId1 } -${ assetId2 } ` ,
125- } ;
126- } ) ;
127- } ,
128- enabled : isPoolListFetched && isAssetsInfoFetched ,
129- } ;
130- } ) ;
131-
13298export const selectedPoolAtom = atom < string | null > ( null ) ;
13399export const selectedPoolInfoAtom = atom ( ( get ) => {
134100 const selectedPool = get ( selectedPoolAtom ) ;
135- const { data : poolListDetail } = get ( poolListDetailAtom ) ;
136- return poolListDetail ?. find ( ( pool ) => pool . key === selectedPool ) ;
101+ const { data : poolList } = get ( poolListAtom ) ;
102+ return poolList ?. find ( ( pool ) => pool . key === selectedPool ) ;
137103} ) ;
138104
139105export const poolSizeAtom = atomWithQuery ( ( get ) => {
@@ -151,7 +117,16 @@ export const poolSizeAtom = atomWithQuery((get) => {
151117 undefined ,
152118 [ selectedPool . asset1 . assetId , selectedPool . asset2 . assetId ]
153119 ) ;
154- if ( poolSize . isEmpty ) return ;
120+ if ( poolSize . isEmpty )
121+ return {
122+ size : [ BigInt ( 0 ) , BigInt ( 0 ) ] ,
123+ asset1 : selectedPool . asset1 ,
124+ asset2 : selectedPool . asset2 ,
125+ asset1Amount : "0" ,
126+ asset2Amount : "0" ,
127+ price : 0 ,
128+ } ;
129+
155130 const [ asset1Amount , asset2Amount ] = poolSize . unwrap ( ) ;
156131 const asset1AmountFormatted = formatUnits (
157132 asset1Amount . toBigInt ( ) ,
@@ -178,74 +153,58 @@ export const poolSizeAtom = atomWithQuery((get) => {
178153 } ;
179154} ) ;
180155
181- export const getQuoteAmountAtom = atom ( ( get ) => {
156+ export const getExactAmountOutAtom = atom ( ( get ) => {
182157 const program = get ( lpProgramAtom ) ;
183158
184- return async ( baseToken : string , quoteToken : string , baseAmount : string ) => {
159+ return async ( sellToken : string , buyToken : string , sellAmount : string ) => {
185160 if ( ! program ) throw new Error ( "Program not initialized" ) ;
186161
187- const quoteTokenDecimals = get ( assetsInfoFamily ( quoteToken ) ) ?. decimals ;
188- const baseTokenDecimals = get ( assetsInfoFamily ( baseToken ) ) ?. decimals ;
189- if ( ! quoteTokenDecimals || ! baseTokenDecimals )
190- throw new Error ( "quoteTokenDecimals or baseTokenDecimals is not set" ) ;
162+ const sellTokenDecimals = get ( assetsInfoFamily ( sellToken ) ) ?. decimals ;
163+ const buyTokenDecimals = get ( assetsInfoFamily ( buyToken ) ) ?. decimals ;
164+ if ( sellTokenDecimals === undefined || buyTokenDecimals === undefined )
165+ throw new Error ( "sellTokenDecimals or buyTokenDecimals is not set" ) ;
191166
192- const quoteAmount = await program . executeQuery < Option < u128 > > (
167+ const buyAmount = await program . executeQuery < Option < u128 > > (
193168 "entrypoint_quote_price_exact_tokens_for_tokens" ,
194169 undefined ,
195- [ baseToken , quoteToken , parseUnits ( baseAmount , baseTokenDecimals ) ]
170+ [ sellToken , buyToken , parseUnits ( sellAmount , sellTokenDecimals ) ]
196171 ) ;
197172
198- console . log (
199- `Get ${ quoteToken } amount:` ,
200- baseToken ,
201- quoteToken ,
202- baseAmount ,
203- quoteAmount . toHuman ( )
204- ) ;
205-
206- if ( quoteAmount . isEmpty ) return "0" ;
173+ if ( buyAmount . isEmpty ) return "0" ;
207174 return formatUnits (
208- quoteAmount . unwrap ( ) . toBigInt ( ) as bigint ,
209- quoteTokenDecimals
175+ buyAmount . unwrap ( ) . toBigInt ( ) as bigint ,
176+ buyTokenDecimals
210177 ) ;
211178 } ;
212179} ) ;
213180
214- export const getBaseAmountAtom = atom ( ( get ) => {
181+ export const getExactAmountInAtom = atom ( ( get ) => {
215182 const program = get ( lpProgramAtom ) ;
216183
217- return async ( baseToken : string , quoteToken : string , quoteAmount : string ) => {
184+ return async ( sellToken : string , buyToken : string , buyAmount : string ) => {
218185 if ( ! program ) throw new Error ( "Program not initialized" ) ;
219186
220- const quoteTokenDecimals = get ( assetsInfoFamily ( quoteToken ) ) ?. decimals ;
221- const baseTokenDecimals = get ( assetsInfoFamily ( baseToken ) ) ?. decimals ;
222- if ( ! quoteTokenDecimals || ! baseTokenDecimals )
223- throw new Error ( "quoteTokenDecimals or baseTokenDecimals is not set" ) ;
187+ const buyTokenDecimals = get ( assetsInfoFamily ( buyToken ) ) ?. decimals ;
188+ const sellTokenDecimals = get ( assetsInfoFamily ( sellToken ) ) ?. decimals ;
189+ if ( buyTokenDecimals === undefined || sellTokenDecimals === undefined )
190+ throw new Error ( "buyTokenDecimals or sellTokenDecimals is not set" ) ;
224191
225- const baseAmount = await program . executeQuery < Option < u128 > > (
192+ const sellAmount = await program . executeQuery < Option < u128 > > (
226193 "entrypoint_quote_price_tokens_for_exact_tokens" ,
227194 undefined ,
228- [ baseToken , quoteToken , parseUnits ( quoteAmount , quoteTokenDecimals ) ]
229- ) ;
230-
231- console . log (
232- `Get ${ baseToken } amount:` ,
233- baseToken ,
234- quoteToken ,
235- quoteAmount ,
236- baseAmount . toHuman ( )
195+ [ sellToken , buyToken , parseUnits ( buyAmount , buyTokenDecimals ) ]
237196 ) ;
238197
239- if ( baseAmount . isEmpty ) return "0" ;
198+ if ( sellAmount . isEmpty ) return "0" ;
240199
241200 return formatUnits (
242- baseAmount . unwrap ( ) . toBigInt ( ) as bigint ,
243- baseTokenDecimals
201+ sellAmount . unwrap ( ) . toBigInt ( ) as bigint ,
202+ sellTokenDecimals
244203 ) ;
245204 } ;
246205} ) ;
247206
248- export const getReceiveAmountAtom = atom ( ( get ) => {
207+ export const calcReceiveAmountAtom = atom ( ( get ) => {
249208 return async (
250209 sellToken : string ,
251210 buyToken : string ,
@@ -310,3 +269,20 @@ export const getReceiveAmountAtom = atom((get) => {
310269 }
311270 } ;
312271} ) ;
272+
273+ export const getReceiveAmountAtom = atom ( ( get ) => {
274+ return async (
275+ sellToken : string ,
276+ buyToken : string ,
277+ amount : string ,
278+ isSell : boolean
279+ ) => {
280+ const getExactAmountOut = get ( getExactAmountOutAtom ) ;
281+ const getExactAmountIn = get ( getExactAmountInAtom ) ;
282+ if ( isSell ) {
283+ return getExactAmountOut ( sellToken , buyToken , amount ) ;
284+ } else {
285+ return getExactAmountIn ( sellToken , buyToken , amount ) ;
286+ }
287+ } ;
288+ } ) ;
0 commit comments