From 6b0cdc63c0ac1d5f059dcea2b14179179f812c48 Mon Sep 17 00:00:00 2001 From: Polybius93 Date: Thu, 6 Mar 2025 16:38:52 +0100 Subject: [PATCH] feat: update proof of reserve hook to match api updates --- .../token-stats-board-chain-value.tsx | 3 +- .../proof-of-reserve/proof-of-reserve.tsx | 3 +- src/app/hooks/use-proof-of-reserve.ts | 113 ++++++------------ src/shared/constants/ripple.constants.ts | 6 - src/shared/utils.ts | 15 +-- 5 files changed, 44 insertions(+), 96 deletions(-) diff --git a/src/app/components/proof-of-reserve/components/token-stats-board/components/token-stats-board-chain-value.tsx b/src/app/components/proof-of-reserve/components/token-stats-board/components/token-stats-board-chain-value.tsx index 67ad5f3b..f1519782 100644 --- a/src/app/components/proof-of-reserve/components/token-stats-board/components/token-stats-board-chain-value.tsx +++ b/src/app/components/proof-of-reserve/components/token-stats-board/components/token-stats-board-chain-value.tsx @@ -1,6 +1,5 @@ import { HStack, Image, Text } from '@chakra-ui/react'; import { useBitcoinPrice } from '@hooks/use-bitcoin-price'; -import { unshiftValue } from 'dlc-btc-lib/utilities'; import { convertBitcoinToUSD } from '@shared/utils'; @@ -16,7 +15,7 @@ export function TokenStatsBoardChainValue({ const { data: bitcoinPrice } = useBitcoinPrice(); const chainValueInUSD = - chainValue && bitcoinPrice ? convertBitcoinToUSD(unshiftValue(bitcoinPrice), chainValue) : 0; + chainValue && bitcoinPrice ? convertBitcoinToUSD(bitcoinPrice, chainValue) : 0; return ( diff --git a/src/app/components/proof-of-reserve/proof-of-reserve.tsx b/src/app/components/proof-of-reserve/proof-of-reserve.tsx index 988de7d9..3b6a1dd6 100644 --- a/src/app/components/proof-of-reserve/proof-of-reserve.tsx +++ b/src/app/components/proof-of-reserve/proof-of-reserve.tsx @@ -49,6 +49,7 @@ export function ProofOfReserve(): React.JSX.Element { 'evm-hardhat-arb': '', 'evm-hardhat-eth': '', 'ripple-xrpl-mainnet': '/images/logos/xrpl-token.svg', + 'ripple-xrpl-testnet': '/images/logos/xrpl-token.svg', }; return chainImagePaths[chainName]; } @@ -56,7 +57,7 @@ export function ProofOfReserve(): React.JSX.Element { const chainData: ChainData[] = proofOfReserveByChain.map(chain => { return { chain: getChainImagePath(chain.chain), - value: chain.value, + value: chain.proofOfReserve, }; }); diff --git a/src/app/hooks/use-proof-of-reserve.ts b/src/app/hooks/use-proof-of-reserve.ts index 74a62398..08e880da 100644 --- a/src/app/hooks/use-proof-of-reserve.ts +++ b/src/app/hooks/use-proof-of-reserve.ts @@ -1,29 +1,32 @@ -import { useContext } from 'react'; - import { Merchant, MerchantProofOfReserve } from '@models/merchant'; -import { EthereumNetworkConfigurationContext } from '@providers/ethereum-network-configuration.provider'; -import { RippleNetworkConfigurationContext } from '@providers/ripple-network-configuration.provider'; import { useQuery } from '@tanstack/react-query'; +import { Decimal } from 'decimal.js'; import { AttestorChainID } from 'dlc-btc-lib/models'; -import { unshiftValue } from 'dlc-btc-lib/utilities'; import { API_HELPERS } from '@shared/constants/api.constants'; -import { EVMAttestorChainIDMap } from '@shared/constants/ethereum.constants'; -import { XRPLAttestorChainIDMap } from '@shared/constants/ripple.constants'; export interface UseProofOfReserveReturnType { proofOfReserveSum?: number; merchantProofOfReserves: MerchantProofOfReserve[]; - proofOfReserveByChain: ProofOfReserveByChainReturnType[]; + proofOfReserveByChain: ProofOfReserveResult[]; +} + +interface ProofOfReserveResult { + chain: AttestorChainID; + proofOfReserve: number; + error?: string; } -interface ProofOfReserveByChainReturnType { - chain: string; - value: number; +interface AggregatedProofOfReserveData { + proofOfReserve: number; + error?: string; + chains: ProofOfReserveResult[]; } export function useProofOfReserve(): UseProofOfReserveReturnType { - async function fetchProofOfReserve(merchantAddress?: string): Promise { + async function fetchProofOfReserve( + merchantAddress?: string + ): Promise { try { const apiURL = API_HELPERS.getProofOfReserveURL({ address: merchantAddress }); @@ -37,85 +40,41 @@ export function useProofOfReserve(): UseProofOfReserveReturnType { } catch (error) { // eslint-disable-next-line no-console console.error('Error fetching Proof of Reserve', error); - return 0; - } - } - - async function fetchProofOfReserveByChain( - chainName: AttestorChainID - ): Promise { - try { - const apiUrl = API_HELPERS.getProofOfReserveURL({ chain: chainName }); - - const response = await fetch(apiUrl); - if (!response.ok) { - throw new Error('Error fetching Proof of Reserve by Chain'); - } - - const data = await response.json(); return { - chain: chainName, - value: data, - }; - } catch (error) { - // eslint-disable-next-line no-console - console.error('Error fetching Proof of Reserve by Chain', error); - return { - chain: chainName, - value: 0, + proofOfReserve: 0, + error: 'Error fetching Proof of Reserve', + chains: [], }; } } - const { - ethereumNetworkConfiguration: { enabledEthereumNetworks }, - } = useContext(EthereumNetworkConfigurationContext); - const { enabledRippleNetworks } = useContext(RippleNetworkConfigurationContext); - async function fetchAllProofOfReserve(): Promise { const proofOfReserve = await fetchProofOfReserve(); - const evmAttestorChainIDs = enabledEthereumNetworks.map( - network => EVMAttestorChainIDMap[network.id] - ); - const xrpAttestorChainIDs = enabledRippleNetworks.map( - network => XRPLAttestorChainIDMap[network.id] - ); - - const evmPorByChains = await Promise.allSettled( - evmAttestorChainIDs.map(async chain => fetchProofOfReserveByChain(chain)) - ); - const xrplPorByChains = await Promise.allSettled( - xrpAttestorChainIDs.map(async chain => fetchProofOfReserveByChain(chain)) - ); - - const fulfilledPorByChains = [...evmPorByChains, ...xrplPorByChains] - .filter(por => por.status === 'fulfilled') - .map(por => por.value); - - const promises = appConfiguration.merchants.map(async (merchant: Merchant) => { - const proofOfReserve = ( - await Promise.all( + const merchantProofOfReserves = await Promise.all( + appConfiguration.merchants.map(async merchant => { + const proofOfReserves = await Promise.all( merchant.addresses.map(async address => { return await fetchProofOfReserve(address); }) - ) - ).reduce( - (totalProofOfReserve, addressProofOfReserve) => totalProofOfReserve + addressProofOfReserve, - 0 - ); - return { - merchant, - iBTCAmount: unshiftValue(proofOfReserve), - }; - }); - - const merchantProofOfReserves = await Promise.all(promises); + ); + + const iBTCAmount = proofOfReserves.reduce( + (sum, proof) => new Decimal(sum).add(proof.proofOfReserve).toNumber(), + 0 + ); + + return { + merchant, + iBTCAmount, + }; + }) + ); return { - proofOfReserveSum: unshiftValue(proofOfReserve), + proofOfReserveSum: proofOfReserve.proofOfReserve, merchantProofOfReserves, - proofOfReserveByChain: fulfilledPorByChains, + proofOfReserveByChain: proofOfReserve.chains, }; } diff --git a/src/shared/constants/ripple.constants.ts b/src/shared/constants/ripple.constants.ts index 9a96982a..ee8d7b06 100644 --- a/src/shared/constants/ripple.constants.ts +++ b/src/shared/constants/ripple.constants.ts @@ -1,5 +1,4 @@ import { RippleNetwork, RippleNetworkID } from '@models/ripple.models'; -import { XRPLAttestorChainID } from 'dlc-btc-lib/models'; const RippleMainnet: RippleNetwork = { id: RippleNetworkID.Mainnet, @@ -13,8 +12,3 @@ const RippleTestnet: RippleNetwork = { }; export const supportedRippleNetworks: RippleNetwork[] = [RippleMainnet, RippleTestnet]; - -export const XRPLAttestorChainIDMap: Record = { - [RippleNetworkID.Mainnet]: XRPLAttestorChainID['ripple-xrpl-mainnet'], - [RippleNetworkID.Testnet]: XRPLAttestorChainID['ripple-xrpl-testnet'], -}; diff --git a/src/shared/utils.ts b/src/shared/utils.ts index e1f037fc..e3ef81e4 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -2,7 +2,6 @@ import { DetailedEvent, FormattedEvent } from '@models/ethereum-models'; import Decimal from 'decimal.js'; import { EVMAttestorChainID, EthereumNetworkID } from 'dlc-btc-lib/models'; import { unshiftValue } from 'dlc-btc-lib/utilities'; -import { pipe, when } from 'ramda'; import { Chain } from 'viem'; import { EVMAttestorChainIDMap, SUPPORTED_VIEM_CHAINS } from './constants/ethereum.constants'; @@ -68,15 +67,11 @@ export const convertBitcoinToUSD = ( bitcoinPrice: number, bitcoinAmount: number, shouldRound = true -): number => - pipe( - (amount: number) => new Decimal(amount).mul(bitcoinPrice), - when( - () => shouldRound, - decimal => decimal.floor() - ), - (decimal: Decimal) => decimal.toNumber() - )(bitcoinAmount); +): number => { + const amount = new Decimal(bitcoinAmount).mul(bitcoinPrice); + + return shouldRound ? amount.floor().toNumber() : amount.toNumber(); +}; export function getEthereumNetworkIDByAttestorChainID(attestorChainID: EVMAttestorChainID): Chain { const networkID = Object.entries(EVMAttestorChainIDMap).find(