@@ -20,8 +20,7 @@ export const TOKEN_METADATA_NO_SUPPORT_ERROR =
2020 */
2121function getTokensURL ( chainId : Hex ) {
2222 const occurrenceFloor = chainId === ChainId [ 'linea-mainnet' ] ? 1 : 3 ;
23- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
24- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
23+
2524 return `${ TOKEN_END_POINT_API } /tokens/${ convertHexToDecimal (
2625 chainId ,
2726 ) } ?occurrenceFloor=${ occurrenceFloor } &includeNativeAssets=false&includeTokenFees=false&includeAssetType=false&includeERC20Permit=false&includeStorage=false`;
@@ -35,13 +34,20 @@ function getTokensURL(chainId: Hex) {
3534 * @returns The token metadata URL.
3635 */
3736function getTokenMetadataURL ( chainId : Hex , tokenAddress : string ) {
38- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
39- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
4037 return `${ TOKEN_END_POINT_API } /token/${ convertHexToDecimal (
4138 chainId ,
4239 ) } ?address=${ tokenAddress } `;
4340}
4441
42+ /**
43+ * The sort by field for trending tokens.
44+ */
45+ export type SortTrendingBy =
46+ | 'm5_trending'
47+ | 'h1_trending'
48+ | 'h6_trending'
49+ | 'h24_trending' ;
50+
4551/**
4652 * Get the token search URL for the given networks and search query.
4753 *
@@ -58,6 +64,43 @@ function getTokenSearchURL(chainIds: CaipChainId[], query: string, limit = 10) {
5864 return `${ TOKEN_END_POINT_API } /tokens/search?chainIds=${ encodedChainIds } &query=${ encodedQuery } &limit=${ limit } ` ;
5965}
6066
67+ /**
68+ * Get the trending tokens URL for the given networks and search query.
69+ *
70+ * @param options - Options for getting trending tokens.
71+ * @param options.chainIds - Array of CAIP format chain IDs (e.g., ['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp']).
72+ * @param options.sortBy - The sort by field.
73+ * @param options.minLiquidity - The minimum liquidity.
74+ * @param options.minVolume24hUsd - The minimum volume 24h in USD.
75+ * @param options.maxVolume24hUsd - The maximum volume 24h in USD.
76+ * @param options.minMarketCap - The minimum market cap.
77+ * @param options.maxMarketCap - The maximum market cap.
78+ * @returns The trending tokens URL.
79+ */
80+ function getTrendingTokensURL ( options : {
81+ chainIds : CaipChainId [ ] ;
82+ sortBy ?: SortTrendingBy ;
83+ minLiquidity ?: number ;
84+ minVolume24hUsd ?: number ;
85+ maxVolume24hUsd ?: number ;
86+ minMarketCap ?: number ;
87+ maxMarketCap ?: number ;
88+ } ) : string {
89+ const encodedChainIds = options . chainIds
90+ . map ( ( id ) => encodeURIComponent ( id ) )
91+ . join ( ',' ) ;
92+ // Add the rest of query params if they are defined
93+ const queryParams = new URLSearchParams ( ) ;
94+ const { chainIds, ...rest } = options ;
95+ Object . entries ( rest ) . forEach ( ( [ key , value ] ) => {
96+ if ( value !== undefined ) {
97+ queryParams . append ( key , String ( value ) ) ;
98+ }
99+ } ) ;
100+
101+ return `${ TOKEN_END_POINT_API } /v3/tokens/trending?chainIds=${ encodedChainIds } ${ queryParams . toString ( ) ? `&${ queryParams . toString ( ) } ` : '' } ` ;
102+ }
103+
61104const tenSecondsInMilliseconds = 10_000 ;
62105
63106// Token list averages 1.6 MB in size
@@ -134,6 +177,91 @@ export async function searchTokens(
134177 }
135178}
136179
180+ /**
181+ * The trending asset type.
182+ */
183+ export type TrendingAsset = {
184+ assetId : string ;
185+ name : string ;
186+ symbol : string ;
187+ decimals : number ;
188+ price : string ;
189+ aggregatedUsdVolume : number ;
190+ marketCap : number ;
191+ priceChangePct ?: {
192+ m5 ?: string ;
193+ m15 ?: string ;
194+ m30 ?: string ;
195+ h1 ?: string ;
196+ h6 ?: string ;
197+ h24 ?: string ;
198+ } ;
199+ labels ?: string [ ] ;
200+ } ;
201+
202+ /**
203+ * Get the trending tokens for the given chains.
204+ *
205+ * @param options - Options for getting trending tokens.
206+ * @param options.chainIds - The chains to get the trending tokens for.
207+ * @param options.sortBy - The sort by field.
208+ * @param options.minLiquidity - The minimum liquidity.
209+ * @param options.minVolume24hUsd - The minimum volume 24h in USD.
210+ * @param options.maxVolume24hUsd - The maximum volume 24h in USD.
211+ * @param options.minMarketCap - The minimum market cap.
212+ * @param options.maxMarketCap - The maximum market cap.
213+ * @returns The trending tokens.
214+ * @throws Will throw if the request fails.
215+ */
216+ export async function getTrendingTokens ( {
217+ chainIds,
218+ sortBy,
219+ minLiquidity,
220+ minVolume24hUsd,
221+ maxVolume24hUsd,
222+ minMarketCap,
223+ maxMarketCap,
224+ } : {
225+ chainIds : CaipChainId [ ] ;
226+ sortBy ?: SortTrendingBy ;
227+ minLiquidity ?: number ;
228+ minVolume24hUsd ?: number ;
229+ maxVolume24hUsd ?: number ;
230+ minMarketCap ?: number ;
231+ maxMarketCap ?: number ;
232+ } ) : Promise < TrendingAsset [ ] > {
233+ if ( chainIds . length === 0 ) {
234+ console . error ( 'No chains provided' ) ;
235+ return [ ] ;
236+ }
237+
238+ const trendingTokensURL = getTrendingTokensURL ( {
239+ chainIds,
240+ sortBy,
241+ minLiquidity,
242+ minVolume24hUsd,
243+ maxVolume24hUsd,
244+ minMarketCap,
245+ maxMarketCap,
246+ } ) ;
247+
248+ try {
249+ const result = await handleFetch ( trendingTokensURL ) ;
250+
251+ // Validate that the API returned an array
252+ if ( Array . isArray ( result ) ) {
253+ return result ;
254+ }
255+
256+ // Handle non-expected responses
257+ console . error ( 'Trending tokens API returned non-array response:' , result ) ;
258+ return [ ] ;
259+ } catch ( error ) {
260+ console . error ( 'Trending tokens request failed:' , error ) ;
261+ return [ ] ;
262+ }
263+ }
264+
137265/**
138266 * Fetch metadata for the token address provided for a given network. This request is cancellable
139267 * using the abort signal passed in.
@@ -145,8 +273,6 @@ export async function searchTokens(
145273 * @param options.timeout - The fetch timeout.
146274 * @returns The token metadata, or `undefined` if the request was either aborted or failed.
147275 */
148- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
149- // eslint-disable-next-line @typescript-eslint/naming-convention
150276export async function fetchTokenMetadata < T > (
151277 chainId : Hex ,
152278 tokenAddress : string ,
@@ -208,8 +334,6 @@ async function parseJsonResponse(apiResponse: Response): Promise<unknown> {
208334 const responseObj = await apiResponse . json ( ) ;
209335 // api may return errors as json without setting an error http status code
210336 if ( responseObj ?. error ) {
211- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
212- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
213337 throw new Error ( `TokenService Error: ${ responseObj . error } ` ) ;
214338 }
215339 return responseObj ;
0 commit comments