diff --git a/src/app/components/SatButtons/index.tsx b/src/app/components/SatButtons/index.tsx index 4805244ee4..1a5d72f0ab 100644 --- a/src/app/components/SatButtons/index.tsx +++ b/src/app/components/SatButtons/index.tsx @@ -5,39 +5,69 @@ import Button from "../Button"; type Props = { onClick: (amount: string) => void; disabled?: boolean; + min?: number; + max?: number; }; -function SatButtons({ onClick, disabled }: Props) { +function stringifyThousands(number: number) { + return number < 1000 + ? `${Math.round(number)}` + : number < 1_000_000 + ? `${Math.floor(number / 1000)}K` + : `${Math.floor(number / 1_000_000)}M`; +} + +function tensRounder(number: number, index: number) { + const rounded = Math.round(number); + const tens = Math.round(Math.log(rounded) * Math.LOG10E) - 1; + const integralFunction = index === 0 ? Math.ceil : Math.trunc; + return integralFunction(rounded / Math.pow(10, tens)) * Math.pow(10, tens); +} + +function amountsArray(min: number, max: number) { + let safeMin = Math.max(Math.ceil(min), 100); + const safeMax = Math.min(Math.floor(max), 100_000_000); + if (safeMin >= safeMax) { + safeMin = Math.ceil(min); + } + const distance = Math.round( + Math.log(Math.round(safeMax / safeMin)) * Math.LOG10E + ); // we define the distance as the number of tens of the ratio + if (distance >= 3) { + const factor = Math.pow(10, distance - 3); + return distance % 2 === 0 + ? [safeMin, factor * 50 * safeMin, factor * 100 * safeMin, safeMax].map( + (x, index) => tensRounder(x, index) + ) + : [safeMin, factor * 10 * safeMin, factor * 100 * safeMin, safeMax].map( + (x, index) => tensRounder(x, index) + ); + } else if (distance === 2) { + return [safeMin, 5 * safeMin, 10 * safeMin, safeMax].map((x, index) => + tensRounder(x, index) + ); + } else { + return [safeMin, (safeMin + safeMax) / 2, safeMax].map((x, index) => + tensRounder(x, index) + ); + } +} + +function SatButtons({ onClick, disabled, min = 100, max = 10000 }: Props) { + // we use Set to dedup the array, useful if the min-max range is tight + const amounts = [...new Set(amountsArray(min, max))]; return ( -
-
); } diff --git a/src/app/screens/LNURLPay/index.tsx b/src/app/screens/LNURLPay/index.tsx index da9b25c936..72d66f975b 100644 --- a/src/app/screens/LNURLPay/index.tsx +++ b/src/app/screens/LNURLPay/index.tsx @@ -1,13 +1,13 @@ import Button from "@components/Button"; import ConfirmOrCancel from "@components/ConfirmOrCancel"; import Container from "@components/Container"; +import DualCurrencyField from "@components/form/DualCurrencyField"; +import TextField from "@components/form/TextField"; import PublisherCard from "@components/PublisherCard"; import ResultCard from "@components/ResultCard"; import SatButtons from "@components/SatButtons"; -import DualCurrencyField from "@components/form/DualCurrencyField"; -import TextField from "@components/form/TextField"; import axios from "axios"; -import React, { Fragment, useState, useEffect } from "react"; +import React, { Fragment, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import { toast } from "react-toastify"; @@ -398,6 +398,8 @@ function LNURLPay() { )} @@ -447,7 +449,12 @@ function LNURLPay() { isFocused={false} label={tCommon("actions.confirm")} loading={loadingConfirm} - disabled={loadingConfirm || !valueSat} + disabled={ + loadingConfirm || + !valueSat || + +valueSat < +details.minSendable / 1000 || + +valueSat > +details.maxSendable / 1000 + } onCancel={reject} />