1
1
import axios from 'axios'
2
- import { orderBy } from 'lodash'
3
2
import urlcat from 'urlcat'
4
3
import {
5
4
EVMChainId ,
@@ -12,17 +11,85 @@ import {
12
11
SolanaChainId ,
13
12
SourceType ,
14
13
} from '../type'
14
+ import { orderBy } from 'lodash'
15
15
import { delay } from '../utils'
16
16
17
17
const baseURL = 'https://nftscan-proxy.r2d2.to'
18
18
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' ,
21
88
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 ,
26
93
}
27
94
28
95
export type Response = {
@@ -99,17 +166,18 @@ export class NFTScanToken implements NonFungibleTokenProvider {
99
166
async getTopTokens ( ) {
100
167
let result : NonFungibleToken [ ] = [ ]
101
168
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
+ } )
109
177
110
- const data = list . data . data
111
- . map (
112
- ( x , index ) =>
178
+ const data = list . data . data
179
+ . map (
180
+ ( x , index ) =>
113
181
( {
114
182
pluginID : config . pluginID ,
115
183
address : x . contract_address ,
@@ -120,10 +188,11 @@ export class NFTScanToken implements NonFungibleTokenProvider {
120
188
logoURL : x . logo_url ,
121
189
rank : index + 1 ,
122
190
} as NonFungibleToken ) ,
123
- )
124
- . slice ( 0 , config . limit )
191
+ )
192
+ . slice ( 0 , config . limit )
125
193
126
- result = [ ...result , ...data ]
194
+ result = [ ...result , ...data ]
195
+ }
127
196
128
197
return result
129
198
}
@@ -133,8 +202,6 @@ export class NFTScanToken implements NonFungibleTokenProvider {
133
202
}
134
203
}
135
204
136
- let cache : NonFungibleCollection [ ] | undefined = undefined
137
-
138
205
export class NFTScanCollection implements NonFungibleCollectionProvider {
139
206
async getSolanaCollection ( name : string , rank : number ) {
140
207
const collectionURL = urlcat ( baseURL , '/api/sol/collections/:collection_name' , { collection_name : name } )
@@ -229,27 +296,52 @@ export class NFTScanCollection implements NonFungibleCollectionProvider {
229
296
async getCollections ( ) : Promise < NonFungibleCollection [ ] > {
230
297
let result : NonFungibleCollection [ ] = [ ]
231
298
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' )
234
302
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 , {
236
328
headers : {
237
329
'content-type' : 'application/json' ,
238
- 'x-app-chainid' : chainId ,
330
+ 'x-app-chainid' : 'solana' ,
239
331
} ,
240
332
} )
241
333
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 )
243
335
244
336
for ( let i = 0 ; i < data . length ; i ++ ) {
245
337
const item = data [ i ]
246
338
try {
247
- const collection = await this . getCollection ( item . contract_address , chainId , i + 1 , config )
339
+ const collection = await this . getSolanaCollection ( item . collection , i + 1 )
248
340
if ( collection ) {
249
341
result = [ ...result , collection ]
250
342
}
251
343
} 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` )
253
345
}
254
346
}
255
347
@@ -259,4 +351,4 @@ export class NFTScanCollection implements NonFungibleCollectionProvider {
259
351
getProviderName ( ) : SourceType {
260
352
return SourceType . NFTScan
261
353
}
262
- }
354
+ }
0 commit comments