Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Create buildPrice utility function #26

Merged
merged 1 commit into from
Apr 19, 2024
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
4 changes: 2 additions & 2 deletions src/currency.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,13 @@ describe("parseStringToCurrency() function", () => {

it("should throw an error for invalid currency string", () => {
expect(() => parseStringToCurrency("invalid")).toThrow(
"Input string is not a valid currency"
"Cannot convert: \"invalid\" to a recognized Currency"
);
});

it("should throw an error for empty string", () => {
expect(() => parseStringToCurrency("")).toThrow(
"Input string is not a valid currency"
"Cannot convert: \"\" to a recognized Currency"
);
});
});
2 changes: 1 addition & 1 deletion src/currency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export const parseStringToCurrency = (str: string): Currency => {
const curatedStr = str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
const currency = Currency[curatedStr as keyof typeof Currency];

if (!currency) throw new Error("Input string is not a valid currency");
if (!currency) throw new Error(`Cannot convert: "${str}" to a recognized Currency`);

return currency;
};
44 changes: 43 additions & 1 deletion src/price.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,50 @@
import { describe, it, expect } from "vitest";

import { Price, convertCurrencyWithRates, formattedPrice } from "./price";
import { Price, buildPrice, convertCurrencyWithRates, formattedPrice } from "./price";
import { Currency, PriceCurrencyFormat } from "./currency";

describe("buildPrice() function", () => {

it("Build from string values", () => {
const value = "100";
const currency = "USD";

const result = buildPrice(value, currency);

expect(result).toStrictEqual({
value: 100n,
currency: Currency.Usd,
});
});

it("Build from non-string values", () => {
const value = 100n;
const currency = Currency.Usd;

const result = buildPrice(value, currency);

expect(result).toStrictEqual({
value: 100n,
currency: Currency.Usd,
});
});

it("Invalid value", () => {
const value = "abc";
const currency = "USD";

expect(() => buildPrice(value, currency)).toThrow(`Cannot convert string: ${value} to BigInt`);
});

it("Invalid currency", () => {
const value = "100";
const currency = "invalid";

expect(() => buildPrice(value, currency)).toThrow(`Cannot convert: "${currency}" to a recognized Currency`);
});

});

enum CurrencyTestScenario {
"UNDERFLOW",
"MIN",
Expand Down
42 changes: 40 additions & 2 deletions src/price.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import { Currency, PriceCurrencyFormat } from "./currency";
import { approxScaleBigInt } from "./number";
import { Currency, PriceCurrencyFormat, parseStringToCurrency } from "./currency";
import { approxScaleBigInt, stringToBigInt } from "./number";

export interface Price {

// TODO: consider adding a constraint where value is never negative
/**
* The value of the price. This is a BigInt to avoid floating point math issues when working with prices.
* For example, a price of 1.23 USD would be represented as 123n with a currency of USD.
* Note that the value is always in the smallest unit of the currency (e.g. cents for USD, wei for ETH).
* See the CurrencyConfig for the related currency for the number of decimals to use when converting the value to a human-readable format.
*/
value: bigint;

currency: Currency;
}

Expand All @@ -11,6 +20,35 @@ export interface Price {
// { ETH: 1737.16, DAI: 0.99999703, USDC: 1, WETH: 1737.16, USD: 1 }
export interface ExchangeRates extends Partial<Record<Currency, number>> {}

/**
* Builds a Price object.
* @param value the value of the price. This is a BigInt to avoid floating point math issues when working with prices.
* For example, a price of 1.23 USD would be represented as 123n with a currency of USD.
* Note that the value is always in the smallest unit of the currency (e.g. cents for USD, wei for ETH).
* See the CurrencyConfig for the related currency for the number of decimals to use when converting the value to a human-readable format.
* @param currency
* @returns
*/
export const buildPrice = (value: bigint | string, currency: Currency | string): Price => {

let priceValue : bigint;
let priceCurrency : Currency;

if (typeof value === "string") {
priceValue = stringToBigInt(value)
} else {
priceValue = value;
}

if (typeof currency === "string") {
priceCurrency = parseStringToCurrency(currency);
} else {
priceCurrency = currency;
}

return { value: priceValue, currency: priceCurrency };
}

export const priceAsNumber = (price: Price): number => {
return (
Number(price.value) /
Expand Down
Loading