diff --git a/src/domain/shared/money/JMDAmount.ts b/src/domain/shared/money/JMDAmount.ts index 87331aeb1..232515bbb 100644 --- a/src/domain/shared/money/JMDAmount.ts +++ b/src/domain/shared/money/JMDAmount.ts @@ -1,6 +1,6 @@ import { getCurrencyMajorExponent } from "@domain/fiat/display-currency" -import Money from "../bigint-money" +import Money, { Round } from "../bigint-money" import { BigIntConversionError } from "../errors" import { WalletCurrency } from "../primitives" @@ -26,7 +26,13 @@ export class JMDAmount extends MoneyAmount { static dollars(d: number): JMDAmount | BigIntConversionError { try { - return new JMDAmount(BigInt(d) * 100n) + // Mirror USDAmount.dollars: use the Money lib for a decimal-safe conversion. + // BigInt(d) throws on any fractional rate (e.g. an NCB rate of 155.5), which + // is what the exchange-rate value virtually always is. + const dollarAmt = new Money(d.toString(), "JMDollars", Round.HALF_TO_EVEN) + const cents = JMDAmount.cents("100") + if (cents instanceof BigIntConversionError) return cents // should never happen + return new JMDAmount(cents.money.multiply(dollarAmt).toFixed(2)) } catch (error) { return new BigIntConversionError( error instanceof Error ? error.message : String(error), diff --git a/test/flash/unit/domain/shared/Money.spec.ts b/test/flash/unit/domain/shared/Money.spec.ts index fd4ce1a5e..349ae7c70 100644 --- a/test/flash/unit/domain/shared/Money.spec.ts +++ b/test/flash/unit/domain/shared/Money.spec.ts @@ -32,6 +32,19 @@ describe("Money Amount", () => { const jmdprice = usdAmount.convertAtRate(rate) expect(jmdprice.asDollars()).toBe("16000.00") }) + + // Regression: the live NCB cashout rate is virtually always fractional + // (e.g. 155.5, 152.7). The old JMDAmount.dollars did `BigInt(d) * 100n`, + // which threw on any non-integer, breaking every JMD cashout offer. + // This imports JMDAmount from @domain/shared — the exact barrel-resolved + // class the cashout path uses (see ErpNext.getCashoutExchangeRate). + it("accepts fractional JMD rates (regression: NCB rate 155.5)", () => { + const amt = JMDAmount.dollars(155.5) + if (amt instanceof Error) throw amt + expect(amt.asDollars()).toBe("155.50") + expect(JMDAmount.dollars(152.7)).not.toBeInstanceOf(Error) + expect(JMDAmount.dollars(0.5)).not.toBeInstanceOf(Error) + }) }) describe("USD Amount", () => {