()
| 105 | } |
| 106 | |
| 107 | export async function getCurrencyRates(): Promise<CurrencyRatesPayload> { |
| 108 | const cached = store.currencyRates.get('cache') |
| 109 | |
| 110 | if (cached && Date.now() - cached.fetchedAt < CACHE_TTL) { |
| 111 | return { |
| 112 | ...cached, |
| 113 | source: 'cache', |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | try { |
| 118 | const [fiatRates, cryptoRates] = await Promise.allSettled([ |
| 119 | fetchFiatRates(), |
| 120 | fetchCryptoRates(), |
| 121 | ]) |
| 122 | |
| 123 | const freshRates: Record<string, number> = {} |
| 124 | |
| 125 | if (fiatRates.status === 'fulfilled') { |
| 126 | Object.assign(freshRates, fiatRates.value) |
| 127 | } |
| 128 | |
| 129 | if (cryptoRates.status === 'fulfilled') { |
| 130 | Object.assign(freshRates, cryptoRates.value) |
| 131 | } |
| 132 | |
| 133 | if (Object.keys(freshRates).length === 0) { |
| 134 | throw new Error('No rates fetched') |
| 135 | } |
| 136 | |
| 137 | if ( |
| 138 | !cached |
| 139 | && (fiatRates.status !== 'fulfilled' || cryptoRates.status !== 'fulfilled') |
| 140 | ) { |
| 141 | return createPayload(freshRates) |
| 142 | } |
| 143 | |
| 144 | const previousRates = cached?.rates || {} |
| 145 | const payload = createPayload({ ...previousRates, ...freshRates }) |
| 146 | |
| 147 | store.currencyRates.set('cache', { |
| 148 | rates: payload.rates, |
| 149 | fetchedAt: payload.fetchedAt, |
| 150 | }) |
| 151 | |
| 152 | return payload |
| 153 | } |
| 154 | catch { |
| 155 | if (cached) { |
| 156 | return { |
| 157 | ...cached, |
| 158 | source: 'cache', |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | return { |
| 163 | rates: {}, |
| 164 | fetchedAt: 0, |
no test coverage detected