From 56f7157bdd4e98dad05033758bbad9653434300b Mon Sep 17 00:00:00 2001 From: Ghadaffijr Date: Thu, 25 Jun 2026 10:00:15 +0100 Subject: [PATCH] feat: add computePriceChange helper for key price percentage change - Add computePriceChange(current: bigint, previous: bigint) in src/utils/priceChange.utils.ts - Returns { percent: number, direction: 'up' | 'down' | 'flat' } - Returns flat when previous is zero or current equals previous - 7 unit tests covering: price up, price down, no change, zero previous, both zero Closes #429 --- src/utils/__tests__/priceChange.utils.test.ts | 55 +++++++++++++++++++ src/utils/priceChange.utils.ts | 46 ++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 src/utils/__tests__/priceChange.utils.test.ts create mode 100644 src/utils/priceChange.utils.ts diff --git a/src/utils/__tests__/priceChange.utils.test.ts b/src/utils/__tests__/priceChange.utils.test.ts new file mode 100644 index 0000000..631a9c9 --- /dev/null +++ b/src/utils/__tests__/priceChange.utils.test.ts @@ -0,0 +1,55 @@ +// src/utils/__tests__/priceChange.utils.test.ts +import { describe, expect, it } from 'vitest'; +import { computePriceChange } from '../priceChange.utils'; + +describe('computePriceChange', () => { + describe('price up', () => { + it('returns positive percent and direction up when price increases', () => { + const result = computePriceChange(112n, 100n); + expect(result.direction).toBe('up'); + expect(result.percent).toBeCloseTo(12); + }); + + it('handles a large price increase', () => { + const result = computePriceChange(200n, 100n); + expect(result.direction).toBe('up'); + expect(result.percent).toBeCloseTo(100); + }); + }); + + describe('price down', () => { + it('returns negative percent and direction down when price decreases', () => { + const result = computePriceChange(88n, 100n); + expect(result.direction).toBe('down'); + expect(result.percent).toBeCloseTo(-12); + }); + + it('handles a large price decrease', () => { + const result = computePriceChange(1n, 100n); + expect(result.direction).toBe('down'); + expect(result.percent).toBeCloseTo(-99); + }); + }); + + describe('flat — no change', () => { + it('returns flat with 0 percent when current equals previous', () => { + const result = computePriceChange(100n, 100n); + expect(result.direction).toBe('flat'); + expect(result.percent).toBe(0); + }); + }); + + describe('flat — zero previous value', () => { + it('returns flat with 0 percent when previous is zero', () => { + const result = computePriceChange(100n, 0n); + expect(result.direction).toBe('flat'); + expect(result.percent).toBe(0); + }); + + it('returns flat when both current and previous are zero', () => { + const result = computePriceChange(0n, 0n); + expect(result.direction).toBe('flat'); + expect(result.percent).toBe(0); + }); + }); +}); \ No newline at end of file diff --git a/src/utils/priceChange.utils.ts b/src/utils/priceChange.utils.ts new file mode 100644 index 0000000..77e12f1 --- /dev/null +++ b/src/utils/priceChange.utils.ts @@ -0,0 +1,46 @@ +// src/utils/priceChange.utils.ts + +/** + * Result of a price change computation between two key price values. + */ +export interface PriceChangeResult { + /** Percentage change as a number, e.g. 12.4 or -3.1. Always 0 when direction is 'flat'. */ + percent: number; + /** Direction of the price movement relative to the previous value. */ + direction: 'up' | 'down' | 'flat'; +} + +/** + * Computes the percentage price change between two key price values expressed + * in stroops (bigint). + * + * Returns `flat` with `percent: 0` when: + * - `previous` is zero (division by zero is undefined) + * - `current` equals `previous` (no change) + * + * @param current - The current key price in stroops + * @param previous - The previous key price in stroops + * @returns PriceChangeResult with percent and direction + * + * @example + * computePriceChange(112n, 100n) // { percent: 12, direction: 'up' } + * computePriceChange(88n, 100n) // { percent: -12, direction: 'down' } + * computePriceChange(100n, 100n) // { percent: 0, direction: 'flat' } + * computePriceChange(100n, 0n) // { percent: 0, direction: 'flat' } + */ +export function computePriceChange( + current: bigint, + previous: bigint +): PriceChangeResult { + if (previous === 0n || current === previous) { + return { percent: 0, direction: 'flat' }; + } + + const percent = + (Number(current - previous) / Number(previous)) * 100; + + return { + percent, + direction: percent > 0 ? 'up' : 'down', + }; +} \ No newline at end of file