Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/utils/unit-conversion.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ const STROOP_DIVISOR = new Decimal(STROOPS_PER_XLM);
* stroopsToXlm("10000000") // "1.0000000"
*/
export function stroopsToXlm(stroops: bigint | string): string {
return new Decimal(stroops.toString()).dividedBy(STROOP_DIVISOR).toFixed(STROOP_DECIMALS);
const dec = new Decimal(stroops.toString());
if (dec.isNaN()) {
throw new TypeError(`Invalid stroops amount: ${stroops}`);
}
return dec.dividedBy(STROOP_DIVISOR).toFixed(STROOP_DECIMALS);
}

/**
Expand All @@ -35,5 +39,9 @@ export function stroopsToXlm(stroops: bigint | string): string {
* xlmToStroops(1) // 10_000_000n
*/
export function xlmToStroops(xlm: string | number): bigint {
return BigInt(new Decimal(xlm).times(STROOP_DIVISOR).toFixed(0, Decimal.ROUND_DOWN));
const dec = new Decimal(xlm);
if (dec.isNaN()) {
throw new TypeError(`Invalid XLM amount: ${xlm}`);
}
return BigInt(dec.times(STROOP_DIVISOR).toFixed(0, Decimal.ROUND_DOWN));
}
73 changes: 73 additions & 0 deletions tests/unit/utils/unit-conversion.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { stroopsToXlm, xlmToStroops } from "../../../src/utils/unit-conversion.utils";

describe("Unit Conversion Utilities", () => {
describe("stroopsToXlm", () => {
it('should convert 0 stroops (bigint) to "0.0000000"', () => {
expect(stroopsToXlm(0n)).toBe("0.0000000");
});

it('should convert 0 stroops (string) to "0.0000000"', () => {
expect(stroopsToXlm("0")).toBe("0.0000000");
});

it('should convert 1 stroop (bigint) to "0.0000001"', () => {
expect(stroopsToXlm(1n)).toBe("0.0000001");
});

it('should convert 1 stroop (string) to "0.0000001"', () => {
expect(stroopsToXlm("1")).toBe("0.0000001");
});

it('should convert 10,000,000 stroops to "1.0000000"', () => {
expect(stroopsToXlm(10000000n)).toBe("1.0000000");
expect(stroopsToXlm("10000000")).toBe("1.0000000");
});

it("should convert 100,000 XLM (1,000,000,000,000 stroops) correctly", () => {
expect(stroopsToXlm(1000000000000n)).toBe("100000.0000000");
expect(stroopsToXlm("1000000000000")).toBe("100000.0000000");
});

it("should handle fractional representation without precision loss", () => {
expect(stroopsToXlm(123456789n)).toBe("12.3456789");
});

it("should throw an Error for non-numeric input strings", () => {
expect(() => stroopsToXlm("invalid")).toThrow();
});
});

describe("xlmToStroops", () => {
it("should convert 0 XLM (number) to 0n", () => {
expect(xlmToStroops(0)).toBe(0n);
});

it("should convert 0 XLM (string) to 0n", () => {
expect(xlmToStroops("0")).toBe(0n);
});

it("should convert 0.0000001 XLM to 1n stroop", () => {
expect(xlmToStroops(0.0000001)).toBe(1n);
expect(xlmToStroops("0.0000001")).toBe(1n);
});

it("should convert 1 XLM to 10,000,000n stroops", () => {
expect(xlmToStroops(1)).toBe(10000000n);
expect(xlmToStroops("1")).toBe(10000000n);
});

it("should convert 100,000 XLM to 1,000,000,000,000n stroops", () => {
expect(xlmToStroops(100000)).toBe(1000000000000n);
expect(xlmToStroops("100000")).toBe(1000000000000n);
});

it("should prevent floating-point precision loss for tricky decimals", () => {
expect(xlmToStroops("12.3456789")).toBe(123456789n);
expect(xlmToStroops(0.1 + 0.2)).toBe(3000000n);
});

it("should throw an Error for non-numeric input strings", () => {
expect(() => xlmToStroops("invalid")).toThrow();
});
});
});
Loading