@@ -31,6 +31,7 @@ import { NftCollection } from "src/endpoints/collections/entities/nft.collection
3131import { EsdtSupply } from "src/endpoints/esdt/entities/esdt.supply" ;
3232import { TokenDetailed } from "src/endpoints/tokens/entities/token.detailed" ;
3333import { NumberUtils } from "@multiversx/sdk-nestjs-common" ;
34+ import { TokenAssetsPriceSourceType } from "../../../common/assets/entities/token.assets.price.source.type" ;
3435
3536describe ( 'Token Service' , ( ) => {
3637 let tokenService : TokenService ;
@@ -592,6 +593,25 @@ describe('Token Service', () => {
592593 expect ( result ) . toBeGreaterThanOrEqual ( 261151384.6163954 ) ;
593594 expect ( getAllTokensMock ) . toHaveBeenCalledTimes ( 1 ) ;
594595 } ) ;
596+
597+ it ( 'should not include custom priced tokens in market cap' , async ( ) => {
598+ const mockTokens = JSON . parse ( fs . readFileSync ( path . join ( __dirname , '../../mocks/tokens.mock.json' ) , 'utf-8' ) ) ;
599+ const getAllTokensMock = jest . spyOn ( tokenService , 'getAllTokens' ) . mockResolvedValue ( mockTokens ) ;
600+
601+ const result = await tokenService . getTokenMarketCapRaw ( ) ;
602+ expect ( result ) . toBeGreaterThanOrEqual ( 261151384.6163954 ) ;
603+ expect ( getAllTokensMock ) . toHaveBeenCalledTimes ( 1 ) ;
604+
605+ const secondToken = mockTokens [ 1 ] ;
606+ secondToken . assets . priceSource = { type : 'customUrl' } ;
607+ const newExpectedMarketCap = result - secondToken . marketCap ;
608+ mockTokens [ 1 ] = secondToken ;
609+
610+ jest . spyOn ( tokenService , 'getAllTokens' ) . mockResolvedValue ( mockTokens ) ;
611+
612+ const newResult = await tokenService . getTokenMarketCapRaw ( ) ;
613+ expect ( newResult ) . toBe ( newExpectedMarketCap ) ;
614+ } ) ;
595615 } ) ;
596616
597617 describe ( 'getAllTokens' , ( ) => {
@@ -787,6 +807,109 @@ describe('Token Service', () => {
787807 } ) ;
788808 } ) ;
789809
810+ it ( 'adjusts the order depending on the price source and market cap' , async ( ) => {
811+ jest . spyOn ( tokenService [ 'apiConfigService' ] , 'isTokensFetchFeatureEnabled' ) . mockReturnValue ( false ) ;
812+ jest . spyOn ( tokenService [ 'esdtService' ] , 'getAllFungibleTokenProperties' ) . mockResolvedValue ( [
813+ new TokenProperties ( { identifier : 'token1' } ) ,
814+ new TokenProperties ( { identifier : 'token2' } ) , // <- will have custom price source
815+ new TokenProperties ( { identifier : 'token3' } ) ,
816+ new TokenProperties ( { identifier : 'token4' } ) ,
817+ new TokenProperties ( { identifier : 'token5' } ) ,
818+ ] ) ;
819+
820+ // Only token2 has a custom price source
821+ // eslint-disable-next-line require-await
822+ jest . spyOn ( tokenService [ 'assetsService' ] , 'getTokenAssets' ) . mockImplementation ( async ( identifier : string ) => {
823+ if ( identifier === 'token2' ) {
824+ return new TokenAssets ( {
825+ name : `Token ${ identifier } ` ,
826+ priceSource : {
827+ type : TokenAssetsPriceSourceType . customUrl ,
828+ path : '0.usdPrice' ,
829+ url : 'url' ,
830+ } ,
831+ } ) ;
832+ }
833+ return new TokenAssets ( {
834+ name : `Token ${ identifier } ` ,
835+ // No priceSource
836+ } ) ;
837+ } ) ;
838+
839+ jest . spyOn ( tokenService [ 'collectionService' ] , 'getNftCollections' ) . mockResolvedValue ( [ ] ) ;
840+
841+ jest . spyOn ( tokenService [ 'dataApiService' ] , 'getEgldPrice' ) . mockResolvedValue ( 0 ) ;
842+ jest . spyOn ( tokenService [ 'dataApiService' ] , 'getEsdtTokenPrice' ) . mockResolvedValue ( 1 ) ;
843+ jest . spyOn ( tokenService [ 'esdtService' ] , 'getTokenSupply' ) . mockResolvedValue ( {
844+ minted : '1000000' ,
845+ initialMinted : '1000000' ,
846+ burned : '0' ,
847+ totalSupply : '1000000' ,
848+ circulatingSupply : '1000000' ,
849+ lockedAccounts : undefined ,
850+ } ) ;
851+
852+ // Fake other dependencies
853+ jest . spyOn ( tokenService as any , 'applyMexLiquidity' ) . mockResolvedValue ( undefined ) ;
854+ jest . spyOn ( tokenService as any , 'applyMexPrices' ) . mockResolvedValue ( undefined ) ;
855+ jest . spyOn ( tokenService as any , 'applyMexPairType' ) . mockResolvedValue ( undefined ) ;
856+ jest . spyOn ( tokenService as any , 'applyMexPairTradesCount' ) . mockResolvedValue ( undefined ) ;
857+ jest . spyOn ( tokenService [ 'apiService' ] as any , 'get' ) . mockResolvedValue ( { data : [ { usdPrice : 1.0 } ] } ) ;
858+ jest . spyOn ( tokenService [ 'cachingService' ] , 'batchApplyAll' ) . mockImplementation (
859+ // eslint-disable-next-line require-await
860+ async ( ...args : unknown [ ] ) => {
861+ const tokens = args [ 0 ] as TokenDetailed [ ] ;
862+ const apply = args [ 3 ] as ( token : TokenDetailed , assets : TokenAssets , fromGetter : boolean ) => void ;
863+
864+ for ( const token of tokens ) {
865+ if ( token . identifier === 'token2' ) {
866+ apply ( token , new TokenAssets ( {
867+ name : `Token ${ token . identifier } ` ,
868+ priceSource : {
869+ type : TokenAssetsPriceSourceType . customUrl ,
870+ path : '0.usdPrice' ,
871+ url : 'url' ,
872+ } ,
873+ } ) , true ) ;
874+ } else {
875+ apply ( token , new TokenAssets ( {
876+ name : `Token ${ token . identifier } ` ,
877+ // No priceSource
878+ } ) , true ) ;
879+ }
880+ }
881+ }
882+ ) ;
883+
884+ // eslint-disable-next-line require-await
885+ jest . spyOn ( tokenService as any , 'batchProcessTokens' ) . mockImplementation ( async ( tokens : any ) => {
886+ const marketCaps = {
887+ token1 : 500 ,
888+ token2 : 400 ,
889+ token3 : 300 ,
890+ token4 : 200 ,
891+ token5 : 100 ,
892+ } ;
893+ for ( const [ index , token ] of tokens . entries ( ) ) {
894+ token . decimals = 18 ;
895+ token . isLowLiquidity = false ;
896+ token . transactions = 10 ;
897+ if ( index === 3 ) {
898+ continue ; // make one of the tokens (token4) not to have any price or market cap at all
899+ }
900+ // @ts -ignore
901+ token . marketCap = marketCaps [ token . identifier ] ;
902+ token . price = 1 ;
903+ }
904+ } ) ;
905+
906+ const result = await tokenService . getAllTokensRaw ( ) ;
907+ const sortedIdentifiers = result . map ( t => t . identifier ) ;
908+
909+ // token2 has custom price source, token4 does not have price/market cap at all
910+ expect ( sortedIdentifiers . slice ( 0 , 5 ) ) . toEqual ( [ 'token5' , 'token3' , 'token1' , 'token2' , 'token4' ] ) ;
911+ } ) ;
912+
790913 it ( 'should return values from cache' , async ( ) => {
791914 const cachedValueMock = jest . spyOn ( tokenService [ 'cachingService' ] , 'getOrSet' ) . mockResolvedValue ( mockTokens ) ;
792915
0 commit comments