Skip to content

Commit b54b1bf

Browse files
committed
Hack support for non-USD targetFiat
1 parent 56d9855 commit b54b1bf

File tree

1 file changed

+77
-4
lines changed

1 file changed

+77
-4
lines changed

src/v3/router.ts

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
asGetRatesParams,
1313
asIncomingGetRatesParams,
1414
type CrossChainMapping,
15+
type CryptoRate,
16+
type FiatRate,
1517
type GetRatesParams,
1618
type IncomingGetRatesParams
1719
} from './types'
@@ -32,9 +34,6 @@ const fixIncomingGetRatesParams = (
3234
if (params.fiat.length > 256) {
3335
throw new Error('fiat array must be less than 256')
3436
}
35-
if (params.targetFiat !== 'USD') {
36-
throw new Error('targetFiat must be USD')
37-
}
3837

3938
params.crypto.forEach(crypto => {
4039
// Sanity check that the tokenId doesn't include _
@@ -114,6 +113,76 @@ automatedCrossChainSyncDoc.onChange(automatedMappings => {
114113
}
115114
})
116115

116+
const toDatedFiatKey = (asset: FiatRate): string => {
117+
return `${asset.isoDate.toISOString()}_${asset.fiatCode}`
118+
}
119+
const toDatedCryptoKey = (asset: CryptoRate): string => {
120+
return `${asset.isoDate.toISOString()}_${toCryptoKey(asset.asset)}`
121+
}
122+
/**
123+
* Break up a non-USD request into two queries. The first finds all the
124+
* USD rates and the second finds all of the fiat/USD rates on across all
125+
* the dates requested.
126+
*/
127+
const getNonUsdRates = async (
128+
initialParams: GetRatesParams,
129+
rightNow: Date
130+
): Promise<GetRatesParams> => {
131+
// Get requested rates in USD
132+
const usdParams = {
133+
...initialParams,
134+
targetFiat: 'USD'
135+
}
136+
const usdResult = await getRates(usdParams, rightNow)
137+
138+
// Loop over the USD rates and store them in a map. At the same time,
139+
// save the date strings we'll need to query the original requested fiat for
140+
const usdCryptoRatesMap = new Map<string, number | undefined>()
141+
const fiatUsdDateExchangeRateMap = new Map<string, number | undefined>()
142+
for (const crypto of usdResult.crypto) {
143+
usdCryptoRatesMap.set(toDatedCryptoKey(crypto), crypto.rate)
144+
fiatUsdDateExchangeRateMap.set(crypto.isoDate.toISOString(), undefined)
145+
}
146+
const usdFiatRatesMap = new Map<string, number | undefined>()
147+
for (const fiat of usdResult.fiat) {
148+
usdFiatRatesMap.set(toDatedFiatKey(fiat), fiat.rate)
149+
fiatUsdDateExchangeRateMap.set(fiat.isoDate.toISOString(), undefined)
150+
}
151+
152+
// Get fiat/USD rates
153+
const fiatParams = {
154+
targetFiat: 'USD',
155+
crypto: [],
156+
fiat: [...fiatUsdDateExchangeRateMap.keys()].map(date => ({
157+
isoDate: new Date(date),
158+
fiatCode: initialParams.targetFiat,
159+
rate: undefined
160+
}))
161+
}
162+
const fiatResult = await getRates(fiatParams, rightNow)
163+
for (const fiat of fiatResult.fiat) {
164+
fiatUsdDateExchangeRateMap.set(fiat.isoDate.toISOString(), fiat.rate)
165+
}
166+
167+
// Loop over the initial request and bridge the rates
168+
for (const crypto of initialParams.crypto) {
169+
const usdCryptoRate = usdCryptoRatesMap.get(toDatedCryptoKey(crypto))
170+
const fiatRate = fiatUsdDateExchangeRateMap.get(
171+
crypto.isoDate.toISOString()
172+
)
173+
if (usdCryptoRate == null || fiatRate == null) continue
174+
crypto.rate = usdCryptoRate / fiatRate
175+
}
176+
for (const fiat of initialParams.fiat) {
177+
const usdFiatRate = usdFiatRatesMap.get(toDatedFiatKey(fiat))
178+
const fiatRate = fiatUsdDateExchangeRateMap.get(fiat.isoDate.toISOString())
179+
if (usdFiatRate == null || fiatRate == null) continue
180+
fiat.rate = usdFiatRate / fiatRate
181+
}
182+
183+
return initialParams
184+
}
185+
117186
export const ratesV3 = async (
118187
request: ExpressRequest
119188
): Promise<HttpResponse> => {
@@ -124,7 +193,11 @@ export const ratesV3 = async (
124193
// Map all incoming crypto assets to their canonical versions
125194
const { mappedParams, originalToCanonicalKey } =
126195
applyCrossChainMappings(params)
127-
const result = await getRates(mappedParams, rightNow)
196+
197+
const result =
198+
mappedParams.targetFiat === 'USD'
199+
? await getRates(mappedParams, rightNow)
200+
: await getNonUsdRates(mappedParams, rightNow)
128201

129202
// Build a quick lookup from canonical key + isoDate -> rate
130203
const canonicalLookup = new Map<string, number>()

0 commit comments

Comments
 (0)