Skip to content

Commit

Permalink
Merge pull request #80 from CityOfZion/CU-86duaemfq
Browse files Browse the repository at this point in the history
CU-86duaemfq - BSEthereum - Fixes for token prices
  • Loading branch information
lopescode authored Aug 5, 2024
2 parents d6e5b39 + 30a461c commit 0c8d9a5
Show file tree
Hide file tree
Showing 4 changed files with 1,021 additions and 49 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@cityofzion/bs-ethereum",
"comment": "Fixes for token prices",
"type": "patch"
}
],
"packageName": "@cityofzion/bs-ethereum"
}
4 changes: 2 additions & 2 deletions packages/bs-ethereum/src/MoralisBDSEthereum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,14 @@ export class MoralisBDSEthereum extends RpcBDSEthereum {
const { data: erc20Balances } = await client.get<MoralisERC20BalanceResponse[]>(`${address}/erc20`)

erc20Balances.forEach(balance => {
if (balance.possible_spam) return
if (balance.possible_spam || !balance.decimals || !balance.token_address || !balance.symbol) return

balances.push({
amount: ethers.utils.formatUnits(balance.balance, balance.decimals),
token: {
decimals: balance.decimals,
hash: balance.token_address,
name: balance.name,
name: balance.name ?? '',
symbol: balance.symbol,
},
})
Expand Down
105 changes: 60 additions & 45 deletions packages/bs-ethereum/src/MoralisEDSEthereum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,15 @@ type MoralisERC20PriceResponse = {
tokenDecimals: string
usdPrice: number
tokenAddress: string
}

type MoralisBlockResponse = {
timestamp: string
blockTimestamp: string
}

export class MoralisEDSEthereum extends CryptoCompareEDS implements ExchangeDataService {
readonly #network: Network<BSEthereumNetworkId>
readonly #blockchainDataService: BlockchainDataService
readonly #numberOfBlockByHour = (15 / 60) * 60
readonly #numberOfBlockByDay = this.#numberOfBlockByHour * 24
readonly #maxTokenPricesPerCall = 24

constructor(network: Network<BSEthereumNetworkId>, blockchainDataService: BlockchainDataService) {
super()
Expand Down Expand Up @@ -90,32 +88,45 @@ export class MoralisEDSEthereum extends CryptoCompareEDS implements ExchangeData
}
})

const { data } = await client.post<MoralisERC20PriceResponse[]>(`/erc20/prices`, {
tokens: tokensBody,
})
const splitTokensBody = []
for (let i = 0; i < tokensBody.length; i += this.#maxTokenPricesPerCall) {
splitTokensBody.push(tokensBody.slice(i, i + this.#maxTokenPricesPerCall))
}

return data.map(item => {
let token: Token

if (
BSEthereumHelper.normalizeHash(item.tokenAddress) ===
BSEthereumHelper.normalizeHash(wrappedNativeToken?.hash ?? '')
) {
token = nativeToken
} else {
token = {
decimals: Number(item.tokenDecimals),
hash: item.tokenAddress,
name: item.tokenName,
symbol: item.tokenSymbol,
}
}
const response: TokenPricesResponse[] = []

return {
usdPrice: item.usdPrice,
token,
}
})
await Promise.allSettled(
splitTokensBody.slice(0, 1).map(async body => {
const { data } = await client.post<MoralisERC20PriceResponse[]>('/erc20/prices', {
tokens: body,
})

data.forEach(item => {
let token: Token

if (
BSEthereumHelper.normalizeHash(item.tokenAddress) ===
BSEthereumHelper.normalizeHash(wrappedNativeToken?.hash ?? '')
) {
token = nativeToken
} else {
token = {
decimals: Number(item.tokenDecimals),
hash: item.tokenAddress,
name: item.tokenName,
symbol: item.tokenSymbol,
}
}

response.push({
usdPrice: item.usdPrice,
token,
})
})
})
)

return response
}

async getTokenPriceHistory(params: GetTokenPriceHistoryParams): Promise<TokenPricesHistoryResponse[]> {
Expand All @@ -132,27 +143,31 @@ export class MoralisEDSEthereum extends CryptoCompareEDS implements ExchangeData
}

const client = MoralisBDSEthereum.getClient(this.#network)
const actualBlockNumber = (await this.#blockchainDataService.getBlockHeight()) - 1 // Last block is not included
const currentBlockNumber = (await this.#blockchainDataService.getBlockHeight()) - 1 // Last block is not included

const history: TokenPricesHistoryResponse[] = []
const tokensBody = Array.from({ length: params.limit }).map((_, index) => ({
token_address: token.hash,
to_block:
currentBlockNumber - index * (params.type === 'hour' ? this.#numberOfBlockByHour : this.#numberOfBlockByDay),
}))

await Promise.allSettled(
Array.from({ length: params.limit }).map(async (_, index) => {
const block =
actualBlockNumber - index * (params.type === 'hour' ? this.#numberOfBlockByHour : this.#numberOfBlockByDay)

const priceResponse = await client.get<MoralisERC20PriceResponse>(`/erc20/${token.hash}/price`, {
params: {
to_block: block,
},
})
const splitTokensBody = []
for (let i = 0; i < tokensBody.length; i += this.#maxTokenPricesPerCall) {
splitTokensBody.push(tokensBody.slice(i, i + this.#maxTokenPricesPerCall))
}

const blockResponse = await client.get<MoralisBlockResponse>(`/block/${block}`)
const history: TokenPricesHistoryResponse[] = []

history.push({
timestamp: new Date(blockResponse.data.timestamp).getTime(),
usdPrice: priceResponse.data.usdPrice,
token: params.token,
await Promise.allSettled(
splitTokensBody.map(async body => {
const priceResponse = await client.post<MoralisERC20PriceResponse[]>('/erc20/prices', { tokens: body })

priceResponse.data.forEach(item => {
history.push({
timestamp: Number(item.blockTimestamp),
usdPrice: item.usdPrice,
token: params.token,
})
})
})
)
Expand Down
Loading

0 comments on commit 0c8d9a5

Please sign in to comment.