Skip to content

Commit 1f9cdca

Browse files
committed
Update conversation rates
1 parent 30d344d commit 1f9cdca

3 files changed

Lines changed: 89 additions & 47 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ Health Check and Statistics
118118
```json
119119
{
120120
"program": "RabbitForexAPI",
121-
"version": "4.0.2",
121+
"version": "4.0.3",
122122
"sourceCode": "https://github.com/Rabbit-Company/RabbitForexAPI",
123123
"monitorStats": {
124124
"currencyCount": 162,

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "rabbitforexapi",
3-
"version": "4.0.2",
3+
"version": "4.0.3",
44
"module": "src/index.ts",
55
"type": "module",
66
"private": true,

src/exchange.ts

Lines changed: 87 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)