@@ -96,7 +96,7 @@ export class Exchange {
9696
9797 for ( const rate of data ) {
9898 if ( rate . source === this . baseCurrency && rate . target !== this . baseCurrency ) {
99- usdBaseRates [ rate . target ] = rate . rate ;
99+ usdBaseRates [ rate . target ] = 1 / rate . rate ;
100100 currencies . add ( rate . target ) ;
101101 }
102102 }
@@ -145,11 +145,11 @@ export class Exchange {
145145 for ( const forex of forexAssets ) {
146146 if ( forex === "USD" ) continue ;
147147
148- // Get forex to USD rate from forex rates
148+ // Get USD to forex rate from forex rates
149149 const usdToForex = this . forexRates [ "USD" ] ?. [ forex ] ;
150150 if ( usdToForex && usdToForex > 0 ) {
151151 // metal -> USD -> forex
152- rates [ metal ] [ forex ] = this . roundRate ( metalPriceUSD / usdToForex ) ;
152+ rates [ metal ] [ forex ] = this . roundRate ( metalPriceUSD * usdToForex ) ;
153153 }
154154 }
155155 }
@@ -160,15 +160,18 @@ export class Exchange {
160160 rates [ forex ] = { } ;
161161 }
162162
163- const forexToUsd = this . forexRates [ "USD" ] ?. [ forex ] ;
164- if ( forexToUsd && forexToUsd > 0 ) {
163+ // Get USD to forex rate from forex rates
164+ const usdToForex = this . forexRates [ "USD" ] ?. [ forex ] ;
165+ if ( usdToForex && usdToForex > 0 ) {
165166 for ( const metal of metalAssets ) {
166167 const metalData = metalRates [ metal ] ;
167168 if ( ! metalData ) continue ;
168169
169170 const metalPriceUSD = metalData . price ;
170171 // forex -> USD -> metal
171- rates [ forex ] [ metal ] = this . roundRate ( forexToUsd / metalPriceUSD ) ;
172+ // If 1 USD = X forex, then 1 forex = 1/X USD
173+ // So 1 forex = (1/X) / metalPriceUSD grams of metal
174+ rates [ forex ] [ metal ] = this . roundRate ( 1 / usdToForex / metalPriceUSD ) ;
172175 }
173176 }
174177 }
@@ -212,15 +215,11 @@ export class Exchange {
212215 continue ;
213216 }
214217
215- if ( from === this . baseCurrency ) {
216- rates [ from ] [ to ] = this . roundRate ( 1 / ( usdBaseRates [ to ] || 1 ) ) ;
217- } else if ( to === this . baseCurrency ) {
218- rates [ from ] [ to ] = this . roundRate ( usdBaseRates [ from ] || 1 ) ;
219- } else {
220- const fromToUsd = usdBaseRates [ from ] || 1 ;
221- const toToUsd = usdBaseRates [ to ] || 1 ;
222- rates [ from ] [ to ] = this . roundRate ( fromToUsd / toToUsd ) ;
223- }
218+ const fromToUsd = from === "USD" ? 1 : usdBaseRates [ from ] || 1 ;
219+ const toToUsd = to === "USD" ? 1 : usdBaseRates [ to ] || 1 ;
220+
221+ // from -> USD -> to
222+ rates [ from ] [ to ] = this . roundRate ( fromToUsd / toToUsd ) ;
224223 }
225224 }
226225
@@ -242,11 +241,11 @@ export class Exchange {
242241 for ( const forex of forexAssets ) {
243242 if ( forex === "USD" ) continue ;
244243
245- // Get forex to USD rate from forex rates
244+ // Get USD to forex rate from forex rates
246245 const usdToForex = this . forexRates [ "USD" ] ?. [ forex ] ;
247246 if ( usdToForex && usdToForex > 0 ) {
248247 // crypto -> USD -> forex
249- rates [ crypto ] [ forex ] = this . roundRate ( cryptoUsdRate / usdToForex ) ;
248+ rates [ crypto ] [ forex ] = this . roundRate ( cryptoUsdRate * usdToForex ) ;
250249 }
251250 }
252251 }
@@ -257,12 +256,15 @@ export class Exchange {
257256 rates [ forex ] = { } ;
258257 }
259258
260- const forexToUsd = this . forexRates [ "USD" ] ?. [ forex ] ;
261- if ( forexToUsd && forexToUsd > 0 ) {
259+ // Get USD to forex rate from forex rates
260+ const usdToForex = this . forexRates [ "USD" ] ?. [ forex ] ;
261+ if ( usdToForex && usdToForex > 0 ) {
262262 for ( const crypto of cryptoAssets ) {
263263 const cryptoUsdRate = cryptoRates [ crypto ] ! ;
264264 // forex -> USD -> crypto
265- rates [ forex ] [ crypto ] = this . roundRate ( forexToUsd / cryptoUsdRate ) ;
265+ // If 1 USD = X forex, then 1 forex = 1/X USD
266+ // So 1 forex = (1/X) / cryptoUsdRate crypto
267+ rates [ forex ] [ crypto ] = this . roundRate ( 1 / usdToForex / cryptoUsdRate ) ;
266268 }
267269 }
268270 }
@@ -311,11 +313,11 @@ export class Exchange {
311313 for ( const forex of forexAssets ) {
312314 if ( forex === stockCurrency ) continue ;
313315
314- // Get forex conversion rate from forex rates
316+ // Get stock currency to forex conversion rate from forex rates
315317 const currencyToForex = this . forexRates [ stockCurrency ] ?. [ forex ] ;
316318 if ( currencyToForex && currencyToForex > 0 ) {
317319 // stock -> stockCurrency -> forex
318- rates [ stock ] [ forex ] = this . roundRate ( stockPrice / currencyToForex ) ;
320+ rates [ stock ] [ forex ] = this . roundRate ( stockPrice * currencyToForex ) ;
319321 }
320322 }
321323 }
@@ -334,10 +336,10 @@ export class Exchange {
334336 const stockCurrency = stockData . currency ;
335337
336338 // Get forex to stock's currency rate
337- const currencyToForex = this . forexRates [ forex ] ?. [ stockCurrency ] ;
338- if ( currencyToForex && currencyToForex > 0 ) {
339+ const forexToCurrency = this . forexRates [ forex ] ?. [ stockCurrency ] ;
340+ if ( forexToCurrency && forexToCurrency > 0 ) {
339341 // forex -> stockCurrency -> stock
340- rates [ forex ] [ stock ] = this . roundRate ( 1 / ( stockPrice * currencyToForex ) ) ;
342+ rates [ forex ] [ stock ] = this . roundRate ( forexToCurrency / stockPrice ) ;
341343 }
342344 }
343345 }
@@ -365,31 +367,71 @@ export class Exchange {
365367 this . metalExchange . stop ( ) ;
366368 }
367369
368- convertForex ( amount : number , from : string , to : string ) : number | undefined {
369- const fromRates = this . forexRates [ from ] ;
370- if ( ! fromRates ) return undefined ;
371- const rate = fromRates [ to ] ;
372- if ( ! rate ) return undefined ;
373- return amount * rate ;
374- }
370+ convert ( amount : number , from : string , to : string ) : number | undefined {
371+ if ( from === to ) return amount ;
372+
373+ // Try direct conversion first
374+ let rate : number | undefined ;
375+
376+ if ( this . isCurrency ( from ) && this . isCurrency ( to ) ) {
377+ rate = this . forexRates [ from ] ?. [ to ] ;
378+ } else if ( this . isMetal ( from ) && this . isMetal ( to ) ) {
379+ rate = this . metalRates [ from ] ?. [ to ] ;
380+ } else if ( this . isCryptocurrency ( from ) && this . isCryptocurrency ( to ) ) {
381+ rate = this . cryptoRates [ from ] ?. [ to ] ;
382+ } else if ( this . isStock ( from ) && this . isStock ( to ) ) {
383+ rate = this . stockRates [ from ] ?. [ to ] ;
384+ } else {
385+ // Cross-asset conversion via USD
386+ const fromUsdValue = this . getUsdValue ( from ) ;
387+ if ( fromUsdValue === undefined ) return undefined ;
375388
376- convertCrypto ( amount : number , from : string , to : string ) : number | undefined {
377- const fromRates = this . cryptoRates [ from ] ;
378- if ( ! fromRates ) return undefined ;
379- const rate = fromRates [ to ] ;
380- if ( ! rate ) return undefined ;
381- return amount * rate ;
389+ const usdAmount = amount * fromUsdValue ;
390+ return this . getAssetFromUsd ( usdAmount , to ) ;
391+ }
392+
393+ return rate !== undefined ? amount * rate : undefined ;
382394 }
383395
384- convert ( amount : number , from : string , to : string ) : number | undefined {
385- const fromIsCrypto = this . isCryptocurrency ( from ) ;
386- const toIsCrypto = this . isCryptocurrency ( to ) ;
396+ private getUsdValue ( asset : string ) : number | undefined {
397+ if ( asset === "USD" ) return 1 ;
387398
388- if ( fromIsCrypto || toIsCrypto ) {
389- return this . convertCrypto ( amount , from , to ) ;
390- } else {
391- return this . convertForex ( amount , from , to ) ;
399+ if ( this . isCurrency ( asset ) ) {
400+ return this . forexRates [ asset ] ?. [ "USD" ] ;
401+ } else if ( this . isMetal ( asset ) ) {
402+ return this . metalRates [ asset ] ?. [ "USD" ] ;
403+ } else if ( this . isCryptocurrency ( asset ) ) {
404+ return this . cryptoRates [ asset ] ?. [ "USD" ] ;
405+ } else if ( this . isStock ( asset ) ) {
406+ const stockData = this . stockExchange . getStocks ( ) . stocks [ asset ] ;
407+ if ( ! stockData ) return undefined ;
408+ const currencyRate = this . forexRates [ stockData . currency ] ?. [ "USD" ] ;
409+ if ( ! currencyRate ) return undefined ;
410+ return stockData . price * currencyRate ;
411+ }
412+ return undefined ;
413+ }
414+
415+ private getAssetFromUsd ( usdAmount : number , toAsset : string ) : number | undefined {
416+ if ( toAsset === "USD" ) return usdAmount ;
417+
418+ if ( this . isCurrency ( toAsset ) ) {
419+ const rate = this . forexRates [ "USD" ] ?. [ toAsset ] ;
420+ return rate ? usdAmount * rate : undefined ;
421+ } else if ( this . isMetal ( toAsset ) ) {
422+ const rate = this . metalRates [ "USD" ] ?. [ toAsset ] ;
423+ return rate ? usdAmount * rate : undefined ;
424+ } else if ( this . isCryptocurrency ( toAsset ) ) {
425+ const rate = this . cryptoRates [ "USD" ] ?. [ toAsset ] ;
426+ return rate ? usdAmount * rate : undefined ;
427+ } else if ( this . isStock ( toAsset ) ) {
428+ const stockData = this . stockExchange . getStocks ( ) . stocks [ toAsset ] ;
429+ if ( ! stockData ) return undefined ;
430+ const currencyRate = this . forexRates [ "USD" ] ?. [ stockData . currency ] ;
431+ if ( ! currencyRate ) return undefined ;
432+ return ( usdAmount * currencyRate ) / stockData . price ;
392433 }
434+ return undefined ;
393435 }
394436
395437 getForexRates ( base : string = "USD" ) : Record < string , number > {
0 commit comments