11import axios from 'axios'
2- import { orderBy } from 'lodash'
32import urlcat from 'urlcat'
43import {
54 EVMChainId ,
@@ -12,17 +11,85 @@ import {
1211 SolanaChainId ,
1312 SourceType ,
1413} from '../type'
14+ import { orderBy } from 'lodash'
1515import { delay } from '../utils'
1616
1717const baseURL = 'https://nftscan-proxy.r2d2.to'
1818
19- const config = {
20- chain : 'eth' ,
19+ const evmConfigs = [
20+ {
21+ chain : 'eth' ,
22+ chainId : EVMChainId . Mainnet ,
23+ pluginID : NetworkPluginID . PLUGIN_EVM ,
24+ url : 'https://restapi.nftscan.com' ,
25+ coin : 'ETH' ,
26+ limit : 500 ,
27+ } ,
28+ {
29+ chain : 'bnb' ,
30+ chainId : EVMChainId . BNB ,
31+ pluginID : NetworkPluginID . PLUGIN_EVM ,
32+ url : 'https://bnbapi.nftscan.com' ,
33+ coin : 'BNB' ,
34+ limit : 500 ,
35+ } ,
36+ {
37+ chain : 'polygon' ,
38+ chainId : EVMChainId . Polygon ,
39+ pluginID : NetworkPluginID . PLUGIN_EVM ,
40+ url : 'https://polygonapi.nftscan.com' ,
41+ coin : 'MATIC' ,
42+ limit : 500 ,
43+ } ,
44+ {
45+ chain : 'moonbeam' ,
46+ chainId : EVMChainId . Moonbeam ,
47+ pluginID : NetworkPluginID . PLUGIN_EVM ,
48+ url : 'https://restapi.nftscan.com' ,
49+ coin : 'GLMR' ,
50+ limit : 200 ,
51+ } ,
52+ {
53+ chain : 'arbitrum' ,
54+ chainId : EVMChainId . Arbitrum ,
55+ pluginID : NetworkPluginID . PLUGIN_EVM ,
56+ url : 'https://arbitrumapi.nftscan.com' ,
57+ coin : 'ETH' ,
58+ limit : 200 ,
59+ } ,
60+ {
61+ chain : 'optimism' ,
62+ chainId : EVMChainId . Optimistic ,
63+ pluginID : NetworkPluginID . PLUGIN_EVM ,
64+ url : 'https://optimismapi.nftscan.com' ,
65+ coin : 'ETH' ,
66+ limit : 200 ,
67+ } ,
68+ // {
69+ // chain: 'cronos',
70+ // chainId: ChainId.xDai,
71+ // pluginID: NetworkPluginID.PLUGIN_EVM,
72+ // url: 'https://cronosapi.nftscan.com',
73+ // coin: 'CRO',
74+ // limit: 200
75+ // },
76+ {
77+ chain : 'avalanche' ,
78+ chainId : EVMChainId . Avalanche ,
79+ pluginID : NetworkPluginID . PLUGIN_EVM ,
80+ url : 'https://avaxapi.nftscan.com' ,
81+ coin : 'AVAX' ,
82+ limit : 200 ,
83+ } ,
84+ ]
85+
86+ const solanaConfigs = {
87+ chain : 'solana' ,
2188 chainId : EVMChainId . Mainnet ,
22- pluginID : NetworkPluginID . PLUGIN_EVM ,
23- url : 'https://restapi .nftscan.com' ,
24- coin : 'ETH ' ,
25- limit : 500 ,
89+ pluginID : NetworkPluginID . PLUGIN_SOLANA ,
90+ url : 'https://solana .nftscan.com' ,
91+ coin : 'SOL ' ,
92+ limit : 200 ,
2693}
2794
2895export type Response = {
@@ -99,17 +166,18 @@ export class NFTScanToken implements NonFungibleTokenProvider {
99166 async getTopTokens ( ) {
100167 let result : NonFungibleToken [ ] = [ ]
101168
102- const url = urlcat ( baseURL , '/api/v2/statistics/ranking/marketcap' )
103- const list = await axios . get < Response > ( url , {
104- headers : {
105- 'content-type' : 'application/json' ,
106- 'x-app-chainid' : config . chainId . toString ( ) ,
107- } ,
108- } )
169+ for ( let config of evmConfigs ) {
170+ const url = urlcat ( baseURL , '/api/v2/statistics/ranking/marketcap' )
171+ const list = await axios . get < Response > ( url , {
172+ headers : {
173+ 'content-type' : 'application/json' ,
174+ 'x-app-chainid' : config . pluginID === NetworkPluginID . PLUGIN_SOLANA ? 'solana' : config . chainId . toString ( ) ,
175+ } ,
176+ } )
109177
110- const data = list . data . data
111- . map (
112- ( x , index ) =>
178+ const data = list . data . data
179+ . map (
180+ ( x , index ) =>
113181 ( {
114182 pluginID : config . pluginID ,
115183 address : x . contract_address ,
@@ -120,10 +188,11 @@ export class NFTScanToken implements NonFungibleTokenProvider {
120188 logoURL : x . logo_url ,
121189 rank : index + 1 ,
122190 } as NonFungibleToken ) ,
123- )
124- . slice ( 0 , config . limit )
191+ )
192+ . slice ( 0 , config . limit )
125193
126- result = [ ...result , ...data ]
194+ result = [ ...result , ...data ]
195+ }
127196
128197 return result
129198 }
@@ -133,8 +202,6 @@ export class NFTScanToken implements NonFungibleTokenProvider {
133202 }
134203}
135204
136- let cache : NonFungibleCollection [ ] | undefined = undefined
137-
138205export class NFTScanCollection implements NonFungibleCollectionProvider {
139206 async getSolanaCollection ( name : string , rank : number ) {
140207 const collectionURL = urlcat ( baseURL , '/api/sol/collections/:collection_name' , { collection_name : name } )
@@ -229,27 +296,52 @@ export class NFTScanCollection implements NonFungibleCollectionProvider {
229296 async getCollections ( ) : Promise < NonFungibleCollection [ ] > {
230297 let result : NonFungibleCollection [ ] = [ ]
231298
232- const chainId = config . chainId . toString ( )
233- const url = urlcat ( baseURL , '/api/v2/statistics/ranking/marketcap' )
299+ for ( let config of evmConfigs ) {
300+ const chainId = config . pluginID === NetworkPluginID . PLUGIN_SOLANA ? 'solana' : config . chainId . toString ( )
301+ const url = urlcat ( baseURL , '/api/v2/statistics/ranking/marketcap' )
234302
235- const list = await axios . get < CollectionsRankingResponse > ( url , {
303+ const list = await axios . get < CollectionsRankingResponse > ( url , {
304+ headers : {
305+ 'content-type' : 'application/json' ,
306+ 'x-app-chainid' : chainId ,
307+ } ,
308+ } )
309+
310+ const data = orderBy ( list . data . data , [ 'market_cap' ] , [ 'desc' ] ) . slice ( 0 , config . limit )
311+
312+ for ( let i = 0 ; i < data . length ; i ++ ) {
313+ const item = data [ i ]
314+ try {
315+ const collection = await this . getCollection ( item . contract_address , chainId , i + 1 , config )
316+ if ( collection ) {
317+ result = [ ...result , collection ]
318+ }
319+ } catch ( e ) {
320+ console . log ( `Fetch error for ${ config . chainId } ${ item . contract_address } from nftscan` )
321+ }
322+ }
323+ }
324+
325+ const solanaURL = urlcat ( baseURL , '/api/sol/statistics/ranking/trade' )
326+
327+ const list = await axios . get < SolanaCollectionsRankingResponse > ( solanaURL , {
236328 headers : {
237329 'content-type' : 'application/json' ,
238- 'x-app-chainid' : chainId ,
330+ 'x-app-chainid' : 'solana' ,
239331 } ,
240332 } )
241333
242- const data = orderBy ( list . data . data , [ 'market_cap' ] , [ 'desc' ] ) . slice ( 0 , config . limit )
334+ const data = orderBy ( list . data . data , [ 'market_cap' ] , [ 'desc' ] ) . slice ( 0 , 200 )
243335
244336 for ( let i = 0 ; i < data . length ; i ++ ) {
245337 const item = data [ i ]
246338 try {
247- const collection = await this . getCollection ( item . contract_address , chainId , i + 1 , config )
339+ const collection = await this . getSolanaCollection ( item . collection , i + 1 )
248340 if ( collection ) {
249341 result = [ ...result , collection ]
250342 }
251343 } catch ( e ) {
252- console . log ( `Fetch error for ${ config . chainId } ${ item . contract_address } from nftscan` )
344+ console . log ( `Fetch error for solana ${ item . collection } from nftscan` )
253345 }
254346 }
255347
@@ -259,4 +351,4 @@ export class NFTScanCollection implements NonFungibleCollectionProvider {
259351 getProviderName ( ) : SourceType {
260352 return SourceType . NFTScan
261353 }
262- }
354+ }
0 commit comments