-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fetch token prices from data-api (#1019)
* fetch prices from data-api * test data-api service * update data-api url * include self url * include features * fix configs * add data api feature config * SERVICES-1446 fix some tests * SERVICES-1446 fix some tests (2) * SERVICES-1446 skip tests until ES are solved * SERVICES-1446 check getEsdtTokenPrice when API feature isDataApiFeatureEnabled is false * fix errors * mock error logger * add fields interceptors to data api calls * SERVICES-1446 replace in nft contoller tests beforeEach with beforeAll * elrond => multiversx * tokens as object * SERVICES-1446 update data-api tests --------- Co-authored-by: catalinfaurpaul <[email protected]> Co-authored-by: tanghel <[email protected]>
- Loading branch information
1 parent
4a148e8
commit eed4751
Showing
25 changed files
with
419 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Global, Module } from "@nestjs/common"; | ||
import { DynamicModuleUtils } from "src/utils/dynamic.module.utils"; | ||
import { ApiConfigModule } from "../api-config/api.config.module"; | ||
import { DataApiService } from "./data-api.service"; | ||
|
||
@Global() | ||
@Module({ | ||
imports: [ | ||
ApiConfigModule, | ||
DynamicModuleUtils.getApiModule(), | ||
DynamicModuleUtils.getCachingModule(), | ||
], | ||
providers: [ | ||
DataApiService, | ||
], | ||
exports: [ | ||
DataApiService, | ||
], | ||
}) | ||
export class DataApiModule { } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { Injectable } from "@nestjs/common"; | ||
import { ApiConfigService } from "../api-config/api.config.service"; | ||
import { ApiService, CachingService, OriginLogger } from "@multiversx/sdk-nestjs"; | ||
import { DataApiToken } from "./entities/data-api.token"; | ||
import { CacheInfo } from "src/utils/cache.info"; | ||
|
||
@Injectable() | ||
export class DataApiService { | ||
private readonly logger = new OriginLogger(DataApiService.name); | ||
|
||
constructor( | ||
private readonly apiConfigService: ApiConfigService, | ||
private readonly apiService: ApiService, | ||
private readonly cachingService: CachingService, | ||
) { } | ||
|
||
public async getEgldPrice(timestamp?: number): Promise<number | undefined> { | ||
return await this.getEsdtTokenPrice('EGLD', timestamp); | ||
} | ||
|
||
public async getEsdtTokenPrice(identifier: string, timestamp?: number): Promise<number | undefined> { | ||
return await this.cachingService.getOrSetCache( | ||
CacheInfo.DataApiTokenPrice(identifier, timestamp).key, | ||
async () => await this.getEsdtTokenPriceRaw(identifier, timestamp), | ||
CacheInfo.DataApiTokenPrice(identifier, timestamp).ttl | ||
); | ||
} | ||
|
||
private async getEsdtTokenPriceRaw(identifier: string, timestamp?: number): Promise<number | undefined> { | ||
if (!this.apiConfigService.isDataApiFeatureEnabled()) { | ||
return undefined; | ||
} | ||
|
||
const token = await this.getDataApiToken(identifier); | ||
if (!token) { | ||
return undefined; | ||
} | ||
|
||
try { | ||
const priceDate = timestamp ? new Date(timestamp * 1000).toISODateString() : undefined; | ||
const dateQuery = priceDate ? `&date=${priceDate}` : ''; | ||
const priceUrl = `${this.apiConfigService.getDataApiServiceUrl()}/v1/quotes/${token.market}/${token.identifier}?extract=price${dateQuery}`; | ||
|
||
const response = await this.apiService.get(priceUrl); | ||
return response?.data; | ||
} catch (error) { | ||
this.logger.error(`An unexpected error occurred while fetching price for token ${identifier} from Data API.`); | ||
this.logger.error(error); | ||
} | ||
|
||
return undefined; | ||
} | ||
|
||
public async getDataApiToken(identifier: string): Promise<DataApiToken | undefined> { | ||
const tokens = await this.getDataApiTokens(); | ||
return tokens[identifier]; | ||
} | ||
|
||
public async getDataApiTokens(): Promise<Record<string, DataApiToken>> { | ||
return await this.cachingService.getOrSetCache( | ||
CacheInfo.DataApiTokens.key, | ||
async () => await this.getDataApiTokensRaw(), | ||
CacheInfo.DataApiTokens.ttl | ||
); | ||
} | ||
|
||
public async getDataApiTokensRaw(): Promise<Record<string, DataApiToken>> { | ||
if (!this.apiConfigService.isDataApiFeatureEnabled()) { | ||
return {}; | ||
} | ||
|
||
try { | ||
const [cexTokensRaw, xExchangeTokensRaw] = await Promise.all([ | ||
this.apiService.get(`${this.apiConfigService.getDataApiServiceUrl()}/v1/tokens/cex?fields=identifier`), | ||
this.apiService.get(`${this.apiConfigService.getDataApiServiceUrl()}/v1/tokens/xexchange?fields=identifier`), | ||
]); | ||
|
||
const cexTokens: DataApiToken[] = cexTokensRaw.data.map((token: any) => new DataApiToken({ identifier: token.identifier, market: 'cex' })); | ||
const xExchangeTokens: DataApiToken[] = xExchangeTokensRaw.data.map((token: any) => new DataApiToken({ identifier: token.identifier, market: 'xexchange' })); | ||
|
||
const tokens = [...cexTokens, ...xExchangeTokens].toRecord<DataApiToken>(x => x.identifier); | ||
return tokens; | ||
} catch (error) { | ||
this.logger.error(`An unexpected error occurred while fetching tokens from Data API.`); | ||
this.logger.error(error); | ||
return {}; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export class DataApiToken { | ||
constructor(init?: Partial<DataApiToken>) { | ||
Object.assign(this, init); | ||
} | ||
|
||
identifier: string = ''; | ||
market: 'cex' | 'xexchange' = 'cex'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.