From 16cf33e417e33ce90bc4fbc0bd850b6dbae5592a Mon Sep 17 00:00:00 2001 From: Roland Bewick Date: Wed, 9 Apr 2025 16:10:29 +0700 Subject: [PATCH 1/3] feat: add amount and fiat amount types --- src/index.ts | 1 + src/utils/Amount.test.ts | 20 ++++++++++++++++++++ src/utils/Amount.ts | 25 +++++++++++++++++++++++++ src/utils/fiat/FiatAmount.test.ts | 29 +++++++++++++++++++++++++++++ src/utils/fiat/FiatAmount.ts | 19 +++++++++++++++++++ src/utils/{ => fiat}/fiat.ts | 0 src/utils/fiat/index.ts | 2 ++ 7 files changed, 96 insertions(+) create mode 100644 src/utils/Amount.test.ts create mode 100644 src/utils/Amount.ts create mode 100644 src/utils/fiat/FiatAmount.test.ts create mode 100644 src/utils/fiat/FiatAmount.ts rename src/utils/{ => fiat}/fiat.ts (100%) create mode 100644 src/utils/fiat/index.ts diff --git a/src/index.ts b/src/index.ts index acb940e..a06ad01 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,5 +6,6 @@ export * as l402 from "./l402"; export * as boostagrams from "./podcasting2/boostagrams"; export * as fiat from "./utils/fiat"; export * as nostr from "./utils/nostr"; +export * from "./utils/Amount"; export { fetchWithL402, sendBoostagram, LightningAddress, Invoice }; export * from "./types"; diff --git a/src/utils/Amount.test.ts b/src/utils/Amount.test.ts new file mode 100644 index 0000000..f12b890 --- /dev/null +++ b/src/utils/Amount.test.ts @@ -0,0 +1,20 @@ +import { resolveAmount, SATS } from "./Amount"; + +describe("Amount", () => { + test("SATS", async () => { + const amount = SATS(10); + expect(amount.satoshi).toBe(10); + }); + test("resolveAmount", async () => { + const resolved = await resolveAmount({ satoshi: 10 }); + expect(resolved.satoshi).toBe(10); + expect(resolved.millisat).toBe(10_000); + }); + test("resolveAmount async", async () => { + const resolved = await resolveAmount({ + satoshi: new Promise((resolve) => setTimeout(() => resolve(10), 300)), + }); + expect(resolved.satoshi).toBe(10); + expect(resolved.millisat).toBe(10_000); + }); +}); diff --git a/src/utils/Amount.ts b/src/utils/Amount.ts new file mode 100644 index 0000000..194fbd5 --- /dev/null +++ b/src/utils/Amount.ts @@ -0,0 +1,25 @@ +/** + * An amount in satoshis + */ +export type Amount = { satoshi: number } | { satoshi: Promise }; + +export const SATS: (amount: number) => Amount = (amount) => ({ + satoshi: amount, +}); + +export async function resolveAmount( + amount: Amount, +): Promise<{ satoshi: number; millisat: number }> { + if (typeof amount === "number") { + return { + satoshi: amount, + millisat: amount * 1000, + }; + } + const satoshi = await Promise.resolve(amount.satoshi); + + return { + satoshi: satoshi, + millisat: satoshi * 1000, + }; +} diff --git a/src/utils/fiat/FiatAmount.test.ts b/src/utils/fiat/FiatAmount.test.ts new file mode 100644 index 0000000..b644a54 --- /dev/null +++ b/src/utils/fiat/FiatAmount.test.ts @@ -0,0 +1,29 @@ +import { resolveAmount } from "../Amount"; +import { USD } from "./FiatAmount"; +import fetchMock from "jest-fetch-mock"; + +describe("FiatAmount", () => { + test("interoperable with Amount", async () => { + fetchMock.mockIf(/.*/, (_) => { + return Promise.resolve( + JSON.stringify({ + code: "USD", + symbol: "$", + rate: "77135.00", + rate_float: 77135.0, + rate_cents: 7713500, + USD: { + code: "USD", + symbol: "$", + rate: "77135.00", + rate_float: 77135.0, + rate_cents: 7713500, + }, + }), + ); + }); + const fiatAmount = USD(1); + const resolved = await resolveAmount(fiatAmount); + expect(resolved.satoshi).toBeGreaterThan(0); + }); +}); diff --git a/src/utils/fiat/FiatAmount.ts b/src/utils/fiat/FiatAmount.ts new file mode 100644 index 0000000..b416170 --- /dev/null +++ b/src/utils/fiat/FiatAmount.ts @@ -0,0 +1,19 @@ +import { fiat } from "../.."; + +// TODO: move to Lightning Tools +export class FiatAmount { + satoshi: Promise; + constructor(amount: number, currency: string) { + this.satoshi = fiat.getSatoshiValue({ + amount, + currency, + }); + } +} + +// Most popular fiat currencies +export const USD = (amount: number) => new FiatAmount(amount, "USD"); +export const EUR = (amount: number) => new FiatAmount(amount, "EUR"); +export const JPY = (amount: number) => new FiatAmount(amount, "JPY"); +export const GBP = (amount: number) => new FiatAmount(amount, "GBP"); +export const CHF = (amount: number) => new FiatAmount(amount, "CHF"); diff --git a/src/utils/fiat.ts b/src/utils/fiat/fiat.ts similarity index 100% rename from src/utils/fiat.ts rename to src/utils/fiat/fiat.ts diff --git a/src/utils/fiat/index.ts b/src/utils/fiat/index.ts new file mode 100644 index 0000000..7550293 --- /dev/null +++ b/src/utils/fiat/index.ts @@ -0,0 +1,2 @@ +export * from "./fiat"; +export * from "./FiatAmount"; From e846f9629c3caff8e2e635f92129981d544a61e3 Mon Sep 17 00:00:00 2001 From: Roland Bewick Date: Wed, 9 Apr 2025 16:18:28 +0700 Subject: [PATCH 2/3] chore: add documentation for amount --- src/utils/Amount.ts | 3 +++ src/utils/fiat/FiatAmount.ts | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/utils/Amount.ts b/src/utils/Amount.ts index 194fbd5..0c9cf21 100644 --- a/src/utils/Amount.ts +++ b/src/utils/Amount.ts @@ -7,6 +7,9 @@ export const SATS: (amount: number) => Amount = (amount) => ({ satoshi: amount, }); +/** + * Resolve a satoshi amount, possibly from a promise (e.g. from fiat conversion) + */ export async function resolveAmount( amount: Amount, ): Promise<{ satoshi: number; millisat: number }> { diff --git a/src/utils/fiat/FiatAmount.ts b/src/utils/fiat/FiatAmount.ts index b416170..2fef228 100644 --- a/src/utils/fiat/FiatAmount.ts +++ b/src/utils/fiat/FiatAmount.ts @@ -1,6 +1,8 @@ import { fiat } from "../.."; -// TODO: move to Lightning Tools +/** + * An amount in a fiat currency represented in satoshis + */ export class FiatAmount { satoshi: Promise; constructor(amount: number, currency: string) { From 51bc59dd4dd4e901f1ce52d68d72f5dd239f1d9a Mon Sep 17 00:00:00 2001 From: Roland Bewick Date: Thu, 10 Apr 2025 22:49:53 +0700 Subject: [PATCH 3/3] chore: remove unused code --- src/utils/Amount.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/utils/Amount.ts b/src/utils/Amount.ts index 0c9cf21..480f2f1 100644 --- a/src/utils/Amount.ts +++ b/src/utils/Amount.ts @@ -13,12 +13,6 @@ export const SATS: (amount: number) => Amount = (amount) => ({ export async function resolveAmount( amount: Amount, ): Promise<{ satoshi: number; millisat: number }> { - if (typeof amount === "number") { - return { - satoshi: amount, - millisat: amount * 1000, - }; - } const satoshi = await Promise.resolve(amount.satoshi); return {