diff --git a/src/App.tsx b/src/App.tsx
index 6e58e83..eb5b5b0 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -133,6 +133,8 @@ import { RandomSentenceGenerator } from "./utils/seedPhrase/RandomSentenceGenera
import { useFetchResources } from "./common/useFetchResources";
import { Tutorials } from "./components/Tutorials/Tutorials";
import { useHandleTutorials } from "./components/Tutorials/useHandleTutorials";
+import { removeLeadingZero } from "./utils/helpers";
+import BoundedNumericTextField from "./common/BoundedNumericTextField";
type extStates =
| "not-authenticated"
@@ -657,7 +659,8 @@ function App() {
setLtcBalanceLoading(false);
});
};
- const sendCoinFunc = () => {
+ const sendCoinFunc = async() => {
+ try {
setSendPaymentError("");
setSendPaymentSuccess("");
if (!paymentTo) {
@@ -672,6 +675,12 @@ function App() {
setSendPaymentError("Please enter your wallet password");
return;
}
+ const fee = await getFee('PAYMENT')
+
+ await show({
+ message: `Would you like to transfer ${Number(paymentAmount)} QORT?` ,
+ paymentFee: fee.fee + ' QORT'
+ })
setIsLoading(true);
window
.sendMessage("sendCoin", {
@@ -692,6 +701,9 @@ function App() {
console.error("Failed to send coin:", error);
setIsLoading(false);
});
+ } catch (error) {
+ // error
+ }
};
const clearAllStates = () => {
@@ -1778,12 +1790,22 @@ function App() {
Amount
- setPaymentAmount(+e.target.value)}
autoComplete="off"
+ onInput={removeLeadingZero}
+ /> */}
+ setPaymentAmount(+e)}
/>
@@ -2822,14 +2844,21 @@ function App() {
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
- {"Publish"}
+ {message.paymentFee ? "Payment" : "Publish"}
{message.message}
-
- publish fee: {message.publishFee}
-
+ {message?.paymentFee && (
+
+ payment fee: {message.paymentFee}
+
+ )}
+ {message?.publishFee && (
+
+ publish fee: {message.publishFee}
+
+ )}
diff --git a/src/background.ts b/src/background.ts
index bef13d3..f466154 100644
--- a/src/background.ts
+++ b/src/background.ts
@@ -2282,7 +2282,7 @@ export async function sendCoin(
const lastRef = await getLastRef();
const fee = await sendQortFee();
- const validApi = await findUsableApi();
+ const validApi = null;
const res = await makeTransactionRequest(
confirmReceiver,
diff --git a/src/common/BoundedNumericTextField.tsx b/src/common/BoundedNumericTextField.tsx
new file mode 100644
index 0000000..c997f8a
--- /dev/null
+++ b/src/common/BoundedNumericTextField.tsx
@@ -0,0 +1,158 @@
+import {
+ IconButton,
+ InputAdornment,
+ TextField,
+ TextFieldProps,
+} from "@mui/material";
+import React, { useRef, useState } from "react";
+import AddIcon from "@mui/icons-material/Add";
+import RemoveIcon from "@mui/icons-material/Remove";
+import {
+ removeTrailingZeros,
+ setNumberWithinBounds,
+} from "./numberFunctions.ts";
+import { CustomInput } from "../App-styles.ts";
+
+type eventType = React.ChangeEvent;
+type BoundedNumericTextFieldProps = {
+ minValue: number;
+ maxValue: number;
+ addIconButtons?: boolean;
+ allowDecimals?: boolean;
+ allowNegatives?: boolean;
+ afterChange?: (s: string) => void;
+ initialValue?: string;
+ maxSigDigits?: number;
+} & TextFieldProps;
+
+export const BoundedNumericTextField = ({
+ minValue,
+ maxValue,
+ addIconButtons = true,
+ allowDecimals = true,
+ allowNegatives = false,
+ afterChange,
+ initialValue,
+ maxSigDigits = 6,
+ ...props
+}: BoundedNumericTextFieldProps) => {
+ const [textFieldValue, setTextFieldValue] = useState(
+ initialValue || ""
+ );
+ const ref = useRef(null);
+
+ const stringIsEmpty = (value: string) => {
+ return value === "";
+ };
+ const isAllZerosNum = /^0*\.?0*$/;
+ const isFloatNum = /^-?[0-9]*\.?[0-9]*$/;
+ const isIntegerNum = /^-?[0-9]+$/;
+ const skipMinMaxCheck = (value: string) => {
+ const lastIndexIsDecimal = value.charAt(value.length - 1) === ".";
+ const isEmpty = stringIsEmpty(value);
+ const isAllZeros = isAllZerosNum.test(value);
+ const isInteger = isIntegerNum.test(value);
+ // skipping minMax on all 0s allows values less than 1 to be entered
+
+ return lastIndexIsDecimal || isEmpty || (isAllZeros && !isInteger);
+ };
+
+ const setMinMaxValue = (value: string): string => {
+ if (skipMinMaxCheck(value)) return value;
+ const valueNum = Number(value);
+
+ const boundedNum = setNumberWithinBounds(valueNum, minValue, maxValue);
+
+ const numberInBounds = boundedNum === valueNum;
+ return numberInBounds ? value : boundedNum.toString();
+ };
+
+ const getSigDigits = (number: string) => {
+ if (isIntegerNum.test(number)) return 0;
+ const decimalSplit = number.split(".");
+ return decimalSplit[decimalSplit.length - 1].length;
+ };
+
+ const sigDigitsExceeded = (number: string, sigDigits: number) => {
+ return getSigDigits(number) > sigDigits;
+ };
+
+ const filterTypes = (value: string) => {
+ if (allowDecimals === false) value = value.replace(".", "");
+ if (allowNegatives === false) value = value.replace("-", "");
+ if (sigDigitsExceeded(value, maxSigDigits)) {
+ value = value.substring(0, value.length - 1);
+ }
+ return value;
+ };
+ const filterValue = (value: string) => {
+ if (stringIsEmpty(value)) return "";
+ value = filterTypes(value);
+ if (isFloatNum.test(value)) {
+ return setMinMaxValue(value);
+ }
+ return textFieldValue;
+ };
+
+ const listeners = (e: eventType) => {
+ const newValue = filterValue(e.target.value);
+ setTextFieldValue(newValue);
+ if (afterChange) afterChange(newValue);
+ };
+
+ const changeValueWithIncDecButton = (changeAmount: number) => {
+ const changedValue = (+textFieldValue + changeAmount).toString();
+ const inBoundsValue = setMinMaxValue(changedValue);
+ setTextFieldValue(inBoundsValue);
+ if (afterChange) afterChange(inBoundsValue);
+ };
+
+ const formatValueOnBlur = (e: eventType) => {
+ let value = e.target.value;
+ if (stringIsEmpty(value) || value === ".") {
+ setTextFieldValue("");
+ return;
+ }
+
+ value = setMinMaxValue(value);
+ value = removeTrailingZeros(value);
+ if (isAllZerosNum.test(value)) value = minValue.toString();
+
+ setTextFieldValue(value);
+ };
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const { onChange, ...noChangeProps } = { ...props };
+ return (
+
+ changeValueWithIncDecButton(1)}>
+ {" "}
+
+ changeValueWithIncDecButton(-1)}>
+ {" "}
+
+
+ ) : (
+ <>>
+ ),
+ }}
+ onChange={e => listeners(e as eventType)}
+ onBlur={e => {
+ formatValueOnBlur(e as eventType);
+ }}
+ autoComplete="off"
+ value={textFieldValue}
+ inputRef={ref}
+ />
+ );
+};
+
+export default BoundedNumericTextField;
diff --git a/src/common/numberFunctions.ts b/src/common/numberFunctions.ts
new file mode 100644
index 0000000..583196c
--- /dev/null
+++ b/src/common/numberFunctions.ts
@@ -0,0 +1,63 @@
+export const truncateNumber = (value: string | number, sigDigits: number) => {
+ return Number(value).toFixed(sigDigits);
+};
+
+export const removeTrailingZeros = (s: string) => {
+ return Number(s).toString();
+};
+
+export const setNumberWithinBounds = (
+ num: number,
+ minValue: number,
+ maxValue: number
+) => {
+ if (num > maxValue) return maxValue;
+ if (num < minValue) return minValue;
+ return num;
+};
+
+export const numberToInt = (num: number) => {
+ return Math.floor(num);
+};
+
+type ByteFormat = "Decimal" | "Binary";
+export function formatBytes(
+ bytes: number,
+ decimals = 2,
+ format: ByteFormat = "Binary"
+) {
+ if (bytes === 0) return "0 Bytes";
+
+ const k = format === "Binary" ? 1024 : 1000;
+ const dm = decimals < 0 ? 0 : decimals;
+ const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
+
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
+
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
+}
+
+export function formatTime(seconds: number): string {
+ seconds = Math.floor(seconds);
+ const minutes: number | string = Math.floor(seconds / 60);
+ let hours: number | string = Math.floor(minutes / 60);
+
+ let remainingSeconds: number | string = seconds % 60;
+ let remainingMinutes: number | string = minutes % 60;
+
+ if (remainingSeconds < 10) {
+ remainingSeconds = "0" + remainingSeconds;
+ }
+
+ if (remainingMinutes < 10) {
+ remainingMinutes = "0" + remainingMinutes;
+ }
+
+ if (hours === 0) {
+ hours = "";
+ } else {
+ hours = hours + ":";
+ }
+
+ return hours + remainingMinutes + ":" + remainingSeconds;
+}