UNPKG

@yoroi/portfolio

Version:

The Portfolio package of Yoroi SDK

141 lines (117 loc) 4.04 kB
import {Api, Portfolio} from '@yoroi/types' import {BigNumber} from 'bignumber.js' import {freeze} from 'immer' import {parseSecondaryTokenInfoWithCacheRecord} from '../../validators/token-info' import { DullahanApiCachedIdsRequest, DullahanApiTokenActivityResponse, DullahanApiTokenHistoryResponse, DullahanApiTokenInfosResponse, } from './types' import {z} from 'zod' export const toSecondaryTokenInfos = ( apiTokenInfosResponse: DullahanApiTokenInfosResponse, ) => { const apiCachedTokenInfos: Record< Portfolio.Token.Id, Api.ResponseWithCache<Portfolio.Token.Info> > = {} return Object.entries(apiTokenInfosResponse).reduce( (acc, [id, tokenInfoWithCache]) => { const castedId = id as Portfolio.Token.Id const castedTokenInfoWithCache = tokenInfoWithCache as Api.ResponseWithCache<Portfolio.Token.Info> if (!parseSecondaryTokenInfoWithCacheRecord(castedTokenInfoWithCache)) { console.warn('Failed to transform token info ', id) return acc } const [statusCode] = castedTokenInfoWithCache if (statusCode === Api.HttpStatusCode.NotModified) { return {...acc, [castedId]: castedTokenInfoWithCache} } if (statusCode === Api.HttpStatusCode.InternalServerError) { return acc } const [, tokenInfo, hash, maxAge] = castedTokenInfoWithCache acc[castedId] = [statusCode, tokenInfo, hash, maxAge] return acc }, apiCachedTokenInfos, ) } export const toTokenActivity = ( apiTokenActivityResponse: Readonly<DullahanApiTokenActivityResponse>, ) => { const tokenActivity: Record<Portfolio.Token.Id, Portfolio.Token.Activity> = {} return freeze( Object.entries(apiTokenActivityResponse).reduce((acc, [id, response]) => { if (!Array.isArray(response)) return acc const castedId = id as Portfolio.Token.Id const [statusCode, tokenActivityData] = response if (statusCode !== Api.HttpStatusCode.Ok) return acc if (!TokenActivityResponseSchema.safeParse(tokenActivityData).success) return acc const parsedTokenActivity: Portfolio.Token.Activity = { price: { ts: tokenActivityData.price.ts, open: new BigNumber(tokenActivityData.price.open), close: new BigNumber(tokenActivityData.price.close), low: new BigNumber(tokenActivityData.price.low), high: new BigNumber(tokenActivityData.price.high), change: tokenActivityData.price.change, }, } acc[castedId] = parsedTokenActivity return acc }, tokenActivity), true, ) } export const toTokenHistory = ( apiTokenHistoryResponse: Readonly<DullahanApiTokenHistoryResponse>, ) => { if (!TokenHistoryResponseSchema.safeParse(apiTokenHistoryResponse).success) return undefined return freeze({ prices: apiTokenHistoryResponse.prices.map((tokenHistoryRecord) => ({ ts: tokenHistoryRecord.ts, open: new BigNumber(tokenHistoryRecord.open), close: new BigNumber(tokenHistoryRecord.close), low: new BigNumber(tokenHistoryRecord.low), high: new BigNumber(tokenHistoryRecord.high), change: tokenHistoryRecord.change, })), }) } export const toDullahanRequest = ( request: ReadonlyArray<Api.RequestWithCache<Portfolio.Token.Id>>, ) => request.map( ([tokenId, hash]) => `${tokenId}:${hash}`, ) as DullahanApiCachedIdsRequest const TokenActivityResponseSchema = z.object({ price: z.object({ ts: z.number(), open: z.string(), close: z.string(), low: z.string(), high: z.string(), change: z.number(), }), }) const TokenHistoryResponseSchema = z.object({ prices: z.array( z.object({ ts: z.number(), open: z.string(), close: z.string(), low: z.string(), high: z.string(), change: z.number(), }), ), }) export const toProcessedMediaRequest = (request: Portfolio.Token.Id) => { const [policy, name] = request.split('.') as [string, string] return {policy, name} }