qortal-mobile/src/App.tsx

2301 lines
67 KiB
TypeScript
Raw Normal View History

2024-09-09 20:36:39 +03:00
import {
createContext,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
2024-04-14 14:57:30 +03:00
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import "./App.css";
import { useDropzone } from "react-dropzone";
2024-09-09 20:36:39 +03:00
import {
Box,
Button,
Checkbox,
CircularProgress,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
Input,
InputLabel,
Popover,
Tooltip,
Typography,
} from "@mui/material";
2024-04-14 14:57:30 +03:00
import { decryptStoredWallet } from "./utils/decryptWallet";
import { CountdownCircleTimer } from "react-countdown-circle-timer";
2024-04-14 21:14:13 +03:00
import Logo1 from "./assets/svgs/Logo1.svg";
2024-04-15 22:30:49 +03:00
import Logo1Dark from "./assets/svgs/Logo1Dark.svg";
2024-09-09 20:36:39 +03:00
import RefreshIcon from "@mui/icons-material/Refresh";
2024-04-14 21:14:13 +03:00
import Logo2 from "./assets/svgs/Logo2.svg";
import Copy from "./assets/svgs/Copy.svg";
2024-09-09 20:36:39 +03:00
import ltcLogo from "./assets/ltc.png";
import qortLogo from "./assets/qort.png";
2024-04-14 21:14:13 +03:00
import { CopyToClipboard } from "react-copy-to-clipboard";
import Download from "./assets/svgs/Download.svg";
import Logout from "./assets/svgs/Logout.svg";
import Return from "./assets/svgs/Return.svg";
2024-04-14 23:01:28 +03:00
import Success from "./assets/svgs/Success.svg";
2024-04-15 22:30:49 +03:00
import Info from "./assets/svgs/Info.svg";
2024-04-14 14:57:30 +03:00
import {
createAccount,
generateRandomSentence,
saveFileToDisk,
} from "./utils/generateWallet/generateWallet";
import { kdf } from "./deps/kdf";
import { generateSaveWalletData } from "./utils/generateWallet/storeWallet";
import { crypto, walletVersion } from "./constants/decryptWallet";
import PhraseWallet from "./utils/generateWallet/phrase-wallet";
2024-04-14 21:14:13 +03:00
import {
AddressBox,
AppContainer,
AuthenticatedContainer,
AuthenticatedContainerInnerLeft,
AuthenticatedContainerInnerRight,
CustomButton,
CustomInput,
CustomLabel,
TextItalic,
TextP,
TextSpan,
} from "./App-styles";
import { Spacer } from "./common/Spacer";
2024-04-15 22:30:49 +03:00
import { Loader } from "./components/Loader";
import { PasswordField, ErrorText } from "./components";
2024-09-09 20:36:39 +03:00
import { ChatGroup } from "./components/Chat/ChatGroup";
import { Group, requestQueueMemberNames } from "./components/Group/Group";
import { TaskManger } from "./components/TaskManager/TaskManger";
import { useModal } from "./common/useModal";
import { LoadingButton } from "@mui/lab";
import { Label } from "./components/Group/AddGroup";
import { CustomizedSnackbars } from "./components/Snackbar/Snackbar";
import {
getFee,
groupApi,
groupApiLocal,
groupApiSocket,
groupApiSocketLocal,
} from "./background";
import { executeEvent } from "./utils/events";
import { requestQueueCommentCount, requestQueuePublishedAccouncements } from "./components/Chat/GroupAnnouncements";
import { requestQueueGroupJoinRequests } from "./components/Group/GroupJoinRequests";
2024-04-14 14:57:30 +03:00
type extStates =
| "not-authenticated"
| "authenticated"
| "send-qort"
| "web-app-request-connection"
| "web-app-request-payment"
| "web-app-request-authentication"
| "download-wallet"
2024-04-15 22:30:49 +03:00
| "create-wallet"
| "transfer-success-regular"
2024-07-09 00:44:02 +03:00
| "transfer-success-request"
| "wallet-dropped"
2024-07-12 23:44:21 -04:00
| "web-app-request-buy-order"
2024-07-17 17:00:43 -04:00
| "buy-order-submitted"
2024-09-09 20:36:39 +03:00
| "group";
interface MyContextInterface {
txList: any[];
memberGroups: any[];
setTxList: (val) => void;
setMemberGroups: (val) => void;
isShow: boolean;
onCancel: () => void;
onOk: () => void;
show: () => void;
message: any;
}
const defaultValues: MyContextInterface = {
txList: [],
memberGroups: [],
setTxList: () => {},
setMemberGroups: () => {},
isShow: false,
onCancel: () => {},
onOk: () => {},
show: () => {},
message: {
publishFee: "",
message: "",
},
};
export const allQueues = {
requestQueueCommentCount: requestQueueCommentCount,
requestQueuePublishedAccouncements: requestQueuePublishedAccouncements,
requestQueueMemberNames: requestQueueMemberNames,
requestQueueGroupJoinRequests: requestQueueGroupJoinRequests
}
const controlAllQueues = (action) => {
Object.keys(allQueues).forEach((key) => {
const val = allQueues[key];
try {
if (typeof val[action] === 'function') {
val[action]();
}
} catch (error) {
console.error(error);
}
});
};
export const clearAllQueues = () => {
Object.keys(allQueues).forEach((key) => {
const val = allQueues[key];
try {
val.clear();
} catch (error) {
console.error(error);
}
});
}
export const pauseAllQueues = () => controlAllQueues('pause');
export const resumeAllQueues = () => controlAllQueues('resume');
2024-04-14 14:57:30 +03:00
2024-09-09 20:36:39 +03:00
export const MyContext = createContext<MyContextInterface>(defaultValues);
export let globalApiKey: string | null = null;
export const getBaseApiReact = (customApi?: string) => {
if (customApi) {
return customApi;
}
if (globalApiKey) {
return groupApiLocal;
} else {
return groupApi;
}
};
export const getBaseApiReactSocket = (customApi?: string) => {
if (customApi) {
return customApi;
}
if (globalApiKey) {
return groupApiSocketLocal;
} else {
return groupApiSocket;
}
};
export const isMainWindow = window?.location?.href?.includes("?main=true");
2024-04-14 14:57:30 +03:00
function App() {
const [extState, setExtstate] = useState<extStates>("not-authenticated");
const [backupjson, setBackupjson] = useState<any>(null);
const [rawWallet, setRawWallet] = useState<any>(null);
2024-07-17 20:53:38 -04:00
const [ltcBalanceLoading, setLtcBalanceLoading] = useState<boolean>(false);
2024-09-09 20:36:39 +03:00
const [qortBalanceLoading, setQortBalanceLoading] = useState<boolean>(false);
2024-04-14 14:57:30 +03:00
const [decryptedWallet, setdecryptedWallet] = useState<any>(null);
const [requestConnection, setRequestConnection] = useState<any>(null);
2024-07-12 23:44:21 -04:00
const [requestBuyOrder, setRequestBuyOrder] = useState<any>(null);
2024-09-09 20:36:39 +03:00
const [authenticatedMode, setAuthenticatedMode] = useState("qort");
2024-04-14 14:57:30 +03:00
const [requestAuthentication, setRequestAuthentication] = useState<any>(null);
const [userInfo, setUserInfo] = useState<any>(null);
const [balance, setBalance] = useState<any>(null);
2024-09-09 20:36:39 +03:00
const [ltcBalance, setLtcBalance] = useState<any>(null);
2024-04-14 14:57:30 +03:00
const [paymentTo, setPaymentTo] = useState<string>("");
const [paymentAmount, setPaymentAmount] = useState<number>(0);
const [paymentPassword, setPaymentPassword] = useState<string>("");
const [sendPaymentError, setSendPaymentError] = useState<string>("");
const [sendPaymentSuccess, setSendPaymentSuccess] = useState<string>("");
const [countdown, setCountdown] = useState<null | number>(null);
const [walletToBeDownloaded, setWalletToBeDownloaded] = useState<any>(null);
const [walletToBeDownloadedPassword, setWalletToBeDownloadedPassword] =
useState<string>("");
2024-09-09 20:36:39 +03:00
const [isMain, setIsMain] = useState<boolean>(
window?.location?.href?.includes("?main=true")
);
const isMainRef = useRef(false);
const [authenticatePassword, setAuthenticatePassword] = useState<string>("");
2024-04-15 22:30:49 +03:00
const [sendqortState, setSendqortState] = useState<any>(null);
2024-09-09 20:36:39 +03:00
const [isLoading, setIsLoading] = useState<boolean>(false);
2024-04-14 21:14:13 +03:00
const [
walletToBeDownloadedPasswordConfirm,
setWalletToBeDownloadedPasswordConfirm,
] = useState<string>("");
2024-04-14 14:57:30 +03:00
const [walletToBeDownloadedError, setWalletToBeDownloadedError] =
useState<string>("");
2024-07-17 20:53:38 -04:00
const [walletToBeDecryptedError, setWalletToBeDecryptedError] =
2024-07-09 00:44:02 +03:00
useState<string>("");
2024-09-09 20:36:39 +03:00
const [txList, setTxList] = useState([]);
const [memberGroups, setMemberGroups] = useState([]);
const [isFocused, setIsFocused] = useState(true);
const holdRefExtState = useRef<extStates>("not-authenticated");
const isFocusedRef = useRef<boolean>(true);
const { isShow, onCancel, onOk, show, message } = useModal();
const [openRegisterName, setOpenRegisterName] = useState(false);
const registerNamePopoverRef = useRef(null);
const [isLoadingRegisterName, setIsLoadingRegisterName] = useState(false);
const [registerNameValue, setRegisterNameValue] = useState("");
const [infoSnack, setInfoSnack] = useState(null);
const [openSnack, setOpenSnack] = useState(false);
const [hasLocalNode, setHasLocalNode] = useState(false);
const [openAdvancedSettings, setOpenAdvancedSettings] = useState(false);
const [useLocalNode, setUseLocalNode] = useState(false);
const [confirmUseOfLocal, setConfirmUseOfLocal] = useState(false);
const [apiKey, setApiKey] = useState("");
useEffect(() => {
chrome.runtime.sendMessage({ action: "getApiKey" }, (response) => {
if (response) {
globalApiKey = response;
setApiKey(response);
setUseLocalNode(true)
setConfirmUseOfLocal(true)
setOpenAdvancedSettings(true)
}
});
}, []);
2024-07-17 20:53:38 -04:00
useEffect(() => {
if (extState) {
2024-09-09 20:36:39 +03:00
holdRefExtState.current = extState;
2024-04-25 12:48:26 +03:00
}
2024-09-09 20:36:39 +03:00
}, [extState]);
2024-04-25 12:48:26 +03:00
2024-09-09 20:36:39 +03:00
useEffect(() => {
isFocusedRef.current = isFocused;
}, [isFocused]);
// Handler for file selection
const handleFileChangeApiKey = (event) => {
const file = event.target.files[0]; // Get the selected file
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
const text = e.target.result; // Get the file content
setApiKey(text); // Store the file content in the state
};
reader.readAsText(file); // Read the file as text
}
};
const checkIfUserHasLocalNode = useCallback(async () => {
try {
const url = `http://127.0.0.1:12391/admin/status`;
const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
const data = await response.json();
if (data?.isSynchronizing === false && data?.syncPercent === 100) {
setHasLocalNode(true);
}
} catch (error) {}
}, []);
useEffect(() => {
checkIfUserHasLocalNode();
}, [extState]);
2024-07-18 12:26:13 -04:00
2024-04-14 14:57:30 +03:00
const address = useMemo(() => {
if (!rawWallet?.address0) return "";
return rawWallet.address0;
}, [rawWallet]);
const { getRootProps, getInputProps } = useDropzone({
accept: {
"application/json": [".json"], // Only accept JSON files
},
maxFiles: 1,
onDrop: async (acceptedFiles) => {
const file: any = acceptedFiles[0];
const fileContents = await new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onabort = () => reject("File reading was aborted");
reader.onerror = () => reject("File reading has failed");
reader.onload = () => {
// Resolve the promise with the reader result when reading completes
resolve(reader.result);
};
// Read the file as text
reader.readAsText(file);
});
2024-07-17 20:53:38 -04:00
2024-04-14 14:57:30 +03:00
let error: any = null;
let pf: any;
try {
if (typeof fileContents !== "string") return;
pf = JSON.parse(fileContents);
2024-09-09 20:36:39 +03:00
} catch (e) {}
2024-04-14 14:57:30 +03:00
try {
const requiredFields = [
"address0",
"salt",
"iv",
"version",
"encryptedSeed",
"mac",
"kdfThreads",
];
for (const field of requiredFields) {
if (!(field in pf)) throw new Error(field + " not found in JSON");
}
2024-07-09 00:44:02 +03:00
// storeWalletInfo(pf);
2024-04-14 14:57:30 +03:00
setRawWallet(pf);
2024-07-09 00:44:02 +03:00
// setExtstate("authenticated");
setExtstate("wallet-dropped");
2024-04-14 14:57:30 +03:00
setdecryptedWallet(null);
} catch (e) {
console.log(e);
error = e;
}
},
});
const saveWalletFunc = async (password: string) => {
let wallet = structuredClone(rawWallet);
2024-04-14 21:14:13 +03:00
const res = await decryptStoredWallet(password, wallet);
const wallet2 = new PhraseWallet(res, walletVersion);
wallet = await wallet2.generateSaveWalletData(
password,
crypto.kdfThreads,
2024-09-09 20:36:39 +03:00
() => {}
2024-04-14 21:14:13 +03:00
);
2024-04-14 14:57:30 +03:00
setWalletToBeDownloaded({
wallet,
qortAddress: rawWallet.address0,
});
return {
wallet,
qortAddress: rawWallet.address0,
};
};
const storeWalletInfo = (wallet: any) => {
chrome.runtime.sendMessage(
{ action: "storeWalletInfo", wallet },
(response) => {
if (response) {
}
}
);
chrome.tabs.query(
{ active: true, currentWindow: true },
function (tabs: any[]) {
chrome.tabs.sendMessage(
tabs[0].id,
{ from: "popup", subject: "anySubject" },
2024-09-09 20:36:39 +03:00
function (response) {}
2024-04-14 14:57:30 +03:00
);
}
);
};
2024-07-17 20:53:38 -04:00
2024-04-14 14:57:30 +03:00
const getBalanceFunc = () => {
2024-09-09 20:36:39 +03:00
setQortBalanceLoading(true);
2024-04-14 14:57:30 +03:00
chrome.runtime.sendMessage({ action: "balance" }, (response) => {
2024-07-18 12:26:13 -04:00
if (!response?.error && !isNaN(+response)) {
2024-04-14 14:57:30 +03:00
setBalance(response);
}
2024-09-09 20:36:39 +03:00
setQortBalanceLoading(false);
2024-07-17 20:53:38 -04:00
});
};
const getLtcBalanceFunc = () => {
2024-09-09 20:36:39 +03:00
setLtcBalanceLoading(true);
2024-07-17 20:53:38 -04:00
chrome.runtime.sendMessage({ action: "ltcBalance" }, (response) => {
2024-07-18 12:26:13 -04:00
if (!response?.error && !isNaN(+response)) {
2024-07-17 20:53:38 -04:00
setLtcBalance(response);
}
2024-09-09 20:36:39 +03:00
setLtcBalanceLoading(false);
2024-04-14 14:57:30 +03:00
});
};
const sendCoinFunc = () => {
setSendPaymentError("");
setSendPaymentSuccess("");
if (!paymentTo) {
setSendPaymentError("Please enter a recipient");
return;
}
if (!paymentAmount) {
setSendPaymentError("Please enter an amount greater than 0");
return;
}
if (!paymentPassword) {
setSendPaymentError("Please enter your wallet password");
return;
}
2024-09-09 20:36:39 +03:00
setIsLoading(true);
2024-04-14 14:57:30 +03:00
chrome.runtime.sendMessage(
{
action: "sendCoin",
payload: {
amount: Number(paymentAmount),
receiver: paymentTo.trim(),
password: paymentPassword,
},
},
(response) => {
if (response?.error) {
setSendPaymentError(response.error);
} else {
2024-04-15 22:30:49 +03:00
setExtstate("transfer-success-regular");
// setSendPaymentSuccess("Payment successfully sent");
2024-04-14 14:57:30 +03:00
}
2024-09-09 20:36:39 +03:00
setIsLoading(false);
2024-04-14 14:57:30 +03:00
}
);
};
const clearAllStates = () => {
setRequestConnection(null);
setRequestAuthentication(null);
};
useEffect(() => {
// Listen for messages from the background script
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
// Check if the message is to update the state
2024-09-09 20:36:39 +03:00
if (
message.action === "UPDATE_STATE_CONFIRM_SEND_QORT" &&
!isMainWindow
) {
2024-04-14 14:57:30 +03:00
// Update the component state with the received 'sendqort' state
setSendqortState(message.payload);
setExtstate("web-app-request-payment");
2024-09-09 20:36:39 +03:00
} else if (message.action === "closePopup" && !isMainWindow) {
2024-04-14 14:57:30 +03:00
// Update the component state with the received 'sendqort' state
window.close();
2024-09-09 20:36:39 +03:00
} else if (
message.action === "UPDATE_STATE_REQUEST_CONNECTION" &&
!isMainWindow
) {
2024-04-14 14:57:30 +03:00
// Update the component state with the received 'sendqort' state
setRequestConnection(message.payload);
setExtstate("web-app-request-connection");
2024-09-09 20:36:39 +03:00
} else if (
message.action === "UPDATE_STATE_REQUEST_BUY_ORDER" &&
!isMainWindow
) {
2024-07-12 23:44:21 -04:00
// Update the component state with the received 'sendqort' state
setRequestBuyOrder(message.payload);
setExtstate("web-app-request-buy-order");
2024-09-09 20:36:39 +03:00
} else if (
message.action === "UPDATE_STATE_REQUEST_AUTHENTICATION" &&
!isMainWindow
) {
2024-04-14 14:57:30 +03:00
// Update the component state with the received 'sendqort' state
setRequestAuthentication(message.payload);
setExtstate("web-app-request-authentication");
2024-09-09 20:36:39 +03:00
} else if (message.action === "SET_COUNTDOWN" && !isMainWindow) {
2024-04-14 14:57:30 +03:00
setCountdown(message.payload);
2024-09-09 20:36:39 +03:00
} else if (message.action === "INITIATE_MAIN") {
// Update the component state with the received 'sendqort' state
setIsMain(true);
isMainRef.current = true;
} else if (message.action === "CHECK_FOCUS" && isMainWindow) {
sendResponse(isFocusedRef.current);
} else if (
message.action === "NOTIFICATION_OPEN_DIRECT" &&
isMainWindow
) {
executeEvent("openDirectMessage", {
from: message.payload.from,
});
} else if (message.action === "NOTIFICATION_OPEN_GROUP" && isMainWindow) {
executeEvent("openGroupMessage", {
from: message.payload.from,
});
} else if (
message.action === "NOTIFICATION_OPEN_ANNOUNCEMENT_GROUP" &&
isMainWindow
) {
executeEvent("openGroupAnnouncement", {
from: message.payload.from,
});
} else if (
message.action === "NOTIFICATION_OPEN_THREAD_NEW_POST" &&
isMainWindow
) {
executeEvent("openThreadNewPost", {
data: message.payload.data,
});
2024-04-14 14:57:30 +03:00
}
});
2024-04-14 21:14:13 +03:00
}, []);
2024-04-14 14:57:30 +03:00
2024-07-17 20:53:38 -04:00
2024-04-14 14:57:30 +03:00
//param = isDecline
const confirmPayment = (isDecline: boolean) => {
if (isDecline) {
chrome.runtime.sendMessage(
{
action: "sendQortConfirmation",
payload: {
amount: sendqortState?.amount,
receiver: sendqortState?.address,
password: paymentPassword,
interactionId: sendqortState?.interactionId,
isDecline: true,
},
},
(response) => {
if (response) {
setSendPaymentSuccess("Payment successfully sent");
} else {
window.close();
}
}
);
return;
}
2024-07-12 23:44:21 -04:00
2024-09-09 20:36:39 +03:00
setIsLoading(true);
2024-04-14 14:57:30 +03:00
chrome.runtime.sendMessage(
{
action: "sendQortConfirmation",
payload: {
amount: sendqortState.amount,
receiver: sendqortState.address,
password: paymentPassword,
interactionId: sendqortState.interactionId,
isDecline: false,
},
},
(response) => {
2024-04-15 22:30:49 +03:00
if (response === true) {
setExtstate("transfer-success-request");
setCountdown(null);
2024-07-12 23:44:21 -04:00
} else {
setSendPaymentError(
response?.error || "Unable to perform payment. Please try again."
);
}
2024-09-09 20:36:39 +03:00
setIsLoading(false);
2024-07-12 23:44:21 -04:00
}
);
};
const confirmBuyOrder = (isDecline: boolean) => {
if (isDecline) {
chrome.runtime.sendMessage(
{
action: "buyOrderConfirmation",
payload: {
crosschainAtInfo: requestBuyOrder?.crosschainAtInfo,
interactionId: requestBuyOrder?.interactionId,
isDecline: true,
},
},
(response) => {
2024-07-17 20:53:38 -04:00
window.close();
2024-07-12 23:44:21 -04:00
}
);
return;
}
2024-09-09 20:36:39 +03:00
setIsLoading(true);
2024-07-12 23:44:21 -04:00
chrome.runtime.sendMessage(
{
action: "buyOrderConfirmation",
payload: {
crosschainAtInfo: requestBuyOrder?.crosschainAtInfo,
2024-07-17 20:53:38 -04:00
interactionId: requestBuyOrder?.interactionId,
isDecline: false,
2024-07-12 23:44:21 -04:00
},
},
(response) => {
if (response === true) {
2024-07-17 17:00:43 -04:00
setExtstate("buy-order-submitted");
2024-07-12 23:44:21 -04:00
setCountdown(null);
2024-04-15 22:30:49 +03:00
} else {
setSendPaymentError(
response?.error || "Unable to perform payment. Please try again."
);
2024-04-14 14:57:30 +03:00
}
2024-09-09 20:36:39 +03:00
setIsLoading(false);
2024-04-14 14:57:30 +03:00
}
);
};
const responseToConnectionRequest = (
isOkay: boolean,
hostname: string,
interactionId: string
) => {
chrome.runtime.sendMessage(
{
action: "responseToConnectionRequest",
payload: { isOkay, hostname, interactionId },
},
(response) => {
if (response === false || response === true) {
window.close();
}
}
);
};
2024-04-14 23:01:28 +03:00
// const rawWalletRef = useRef(null)
// useEffect(()=> {
// rawWalletRef.current = rawWallet
// }, [rawWallet])
2024-07-17 20:53:38 -04:00
2024-04-14 14:57:30 +03:00
useEffect(() => {
try {
2024-09-09 20:36:39 +03:00
setIsLoading(true);
2024-04-14 14:57:30 +03:00
chrome.runtime.sendMessage({ action: "getWalletInfo" }, (response) => {
if (response && response?.walletInfo) {
setRawWallet(response?.walletInfo);
2024-09-09 20:36:39 +03:00
if (
holdRefExtState.current === "web-app-request-payment" ||
holdRefExtState.current === "web-app-request-connection" ||
holdRefExtState.current === "web-app-request-buy-order"
)
return;
2024-04-14 14:57:30 +03:00
setExtstate("authenticated");
}
});
2024-09-09 20:36:39 +03:00
} catch (error) {
} finally {
setIsLoading(false);
2024-04-16 13:25:36 +03:00
}
2024-04-14 23:01:28 +03:00
}, []);
2024-04-14 14:57:30 +03:00
2024-09-09 20:36:39 +03:00
const getUserInfo = useCallback(async (useTimer?: boolean) => {
2024-04-14 14:57:30 +03:00
try {
2024-09-09 20:36:39 +03:00
if (useTimer) {
await new Promise((res) => {
setTimeout(() => {
res(null);
}, 10000);
});
}
2024-04-14 14:57:30 +03:00
chrome.runtime.sendMessage({ action: "userInfo" }, (response) => {
if (response && !response.error) {
setUserInfo(response);
}
});
getBalanceFunc();
2024-09-09 20:36:39 +03:00
} catch (error) {}
}, []);
useEffect(() => {
if (!address) return;
getUserInfo();
2024-04-14 14:57:30 +03:00
}, [address]);
useEffect(() => {
return () => {
console.log("exit");
};
}, []);
2024-09-09 20:36:39 +03:00
useEffect(() => {
if (
authenticatedMode === "ltc" &&
!ltcBalanceLoading &&
ltcBalance === null
) {
getLtcBalanceFunc();
2024-07-18 11:22:51 -04:00
}
2024-09-09 20:36:39 +03:00
}, [authenticatedMode]);
2024-07-18 11:22:51 -04:00
2024-04-14 14:57:30 +03:00
const confirmPasswordToDownload = async () => {
try {
setWalletToBeDownloadedError("");
if (!walletToBeDownloadedPassword) {
setSendPaymentError("Please enter your password");
return;
}
2024-09-09 20:36:39 +03:00
setIsLoading(true);
2024-07-17 20:53:38 -04:00
await new Promise<void>((res) => {
setTimeout(() => {
2024-09-09 20:36:39 +03:00
res();
}, 250);
});
2024-04-14 14:57:30 +03:00
const res = await saveWalletFunc(walletToBeDownloadedPassword);
} catch (error: any) {
setWalletToBeDownloadedError(error?.message);
2024-04-15 22:30:49 +03:00
} finally {
2024-09-09 20:36:39 +03:00
setIsLoading(false);
2024-04-14 14:57:30 +03:00
}
};
const saveFileToDiskFunc = async () => {
try {
await saveFileToDisk(
walletToBeDownloaded.wallet,
walletToBeDownloaded.qortAddress
);
} catch (error: any) {
setWalletToBeDownloadedError(error?.message);
2024-04-15 22:30:49 +03:00
} finally {
2024-04-14 14:57:30 +03:00
}
};
const createAccountFunc = async () => {
try {
if (!walletToBeDownloadedPassword) {
setWalletToBeDownloadedError("Please enter a password");
return;
}
if (!walletToBeDownloadedPasswordConfirm) {
setWalletToBeDownloadedError("Please confirm your password");
return;
}
2024-04-14 21:14:13 +03:00
if (
walletToBeDownloadedPasswordConfirm !== walletToBeDownloadedPassword
) {
2024-04-14 14:57:30 +03:00
setWalletToBeDownloadedError("Password fields do not match!");
return;
}
2024-09-09 20:36:39 +03:00
setIsLoading(true);
2024-07-17 20:53:38 -04:00
await new Promise<void>((res) => {
setTimeout(() => {
2024-09-09 20:36:39 +03:00
res();
}, 250);
});
2024-04-14 21:14:13 +03:00
const res = await createAccount();
const wallet = await res.generateSaveWalletData(
walletToBeDownloadedPassword,
crypto.kdfThreads,
2024-09-09 20:36:39 +03:00
() => {}
2024-04-14 21:14:13 +03:00
);
2024-09-09 20:36:39 +03:00
chrome.runtime.sendMessage(
{
action: "decryptWallet",
payload: {
password: walletToBeDownloadedPassword,
2024-07-09 00:44:02 +03:00
wallet,
2024-09-09 20:36:39 +03:00
},
},
(response) => {
if (response && !response?.error) {
setRawWallet(wallet);
setWalletToBeDownloaded({
wallet,
qortAddress: wallet.address0,
});
chrome.runtime.sendMessage({ action: "userInfo" }, (response2) => {
setIsLoading(false);
if (response2 && !response2.error) {
setUserInfo(response);
}
});
getBalanceFunc();
} else if (response?.error) {
setIsLoading(false);
setWalletToBeDecryptedError(response.error);
}
2024-07-09 00:44:02 +03:00
}
2024-09-09 20:36:39 +03:00
);
2024-04-14 14:57:30 +03:00
} catch (error: any) {
setWalletToBeDownloadedError(error?.message);
2024-09-09 20:36:39 +03:00
setIsLoading(false);
2024-07-17 20:53:38 -04:00
}
2024-04-14 14:57:30 +03:00
};
2024-04-14 21:14:13 +03:00
const logoutFunc = () => {
2024-04-14 14:57:30 +03:00
try {
chrome.runtime.sendMessage({ action: "logout" }, (response) => {
if (response) {
2024-04-15 22:30:49 +03:00
resetAllStates();
2024-04-14 14:57:30 +03:00
}
});
2024-09-09 20:36:39 +03:00
} catch (error) {}
2024-04-14 21:14:13 +03:00
};
2024-04-14 23:01:28 +03:00
const returnToMain = () => {
2024-04-14 21:14:13 +03:00
setPaymentTo("");
setPaymentAmount(0);
setPaymentPassword("");
setSendPaymentError("");
setSendPaymentSuccess("");
setCountdown(null);
setWalletToBeDownloaded(null);
setWalletToBeDownloadedPassword("");
2024-04-14 23:01:28 +03:00
setExtstate("authenticated");
};
2024-04-15 22:30:49 +03:00
const resetAllStates = () => {
setExtstate("not-authenticated");
2024-09-09 20:36:39 +03:00
setAuthenticatedMode("qort");
2024-04-15 22:30:49 +03:00
setBackupjson(null);
setRawWallet(null);
setdecryptedWallet(null);
setRequestConnection(null);
2024-09-09 20:36:39 +03:00
setRequestBuyOrder(null);
2024-04-15 22:30:49 +03:00
setRequestAuthentication(null);
setUserInfo(null);
setBalance(null);
2024-09-09 20:36:39 +03:00
setLtcBalance(null);
2024-04-15 22:30:49 +03:00
setPaymentTo("");
setPaymentAmount(0);
setPaymentPassword("");
setSendPaymentError("");
setSendPaymentSuccess("");
setCountdown(null);
setWalletToBeDownloaded(null);
setWalletToBeDownloadedPassword("");
setWalletToBeDownloadedPasswordConfirm("");
setWalletToBeDownloadedError("");
setSendqortState(null);
2024-09-09 20:36:39 +03:00
globalApiKey = null;
setApiKey("");
setUseLocalNode(false);
setHasLocalNode(false);
setOpenAdvancedSettings(false);
setConfirmUseOfLocal(false)
2024-04-15 22:30:49 +03:00
};
2024-07-17 20:53:38 -04:00
const authenticateWallet = async () => {
2024-07-09 00:44:02 +03:00
try {
2024-09-09 20:36:39 +03:00
setIsLoading(true);
setWalletToBeDecryptedError("");
2024-07-17 20:53:38 -04:00
await new Promise<void>((res) => {
setTimeout(() => {
2024-09-09 20:36:39 +03:00
res();
}, 250);
});
chrome.runtime.sendMessage(
{
action: "decryptWallet",
payload: {
password: authenticatePassword,
wallet: rawWallet,
},
},
(response) => {
if (response && !response?.error) {
setAuthenticatePassword("");
setExtstate("authenticated");
setWalletToBeDecryptedError("");
chrome.runtime.sendMessage({ action: "userInfo" }, (response) => {
setIsLoading(false);
if (response && !response.error) {
setUserInfo(response);
}
});
getBalanceFunc();
chrome.runtime.sendMessage(
{ action: "getWalletInfo" },
(response) => {
if (response && response?.walletInfo) {
setRawWallet(response?.walletInfo);
}
}
);
} else if (response?.error) {
setIsLoading(false);
setWalletToBeDecryptedError(response.error);
}
2024-07-17 20:53:38 -04:00
}
2024-09-09 20:36:39 +03:00
);
} catch (error) {
setWalletToBeDecryptedError("Unable to authenticate. Wrong password");
}
};
// const handleBeforeUnload = (e)=> {
// const shouldClose = confirm('Are you sure you want to close this window? You may have unsaved changes.');
// if (!shouldClose) {
// // Prevent the window from closing
// e.preventDefault();
// e.returnValue = ''; // Required for Chrome
// } else {
// // Allow the window to close
// // No need to call preventDefault here; returnValue must be left empty
// }
// }
// useEffect(()=> {
// window.addEventListener('beforeunload', handleBeforeUnload);
// return ()=> {
// window.removeEventListener('beforeunload', handleBeforeUnload);
// }
// }, [])
useEffect(() => {
if (!isMainWindow) return;
const handleBeforeUnload = (e) => {
e.preventDefault();
e.returnValue = ""; // This is required for Chrome to display the confirmation dialog.
};
// Add the event listener when the component mounts
window.addEventListener("beforeunload", handleBeforeUnload);
// Clean up the event listener when the component unmounts
return () => {
window.removeEventListener("beforeunload", handleBeforeUnload);
};
}, []);
useEffect(() => {
if (!isMainWindow) return;
// Handler for when the window gains focus
const handleFocus = () => {
setIsFocused(true);
console.log("Webview is focused");
};
// Handler for when the window loses focus
const handleBlur = () => {
setIsFocused(false);
console.log("Webview is not focused");
};
// Attach the event listeners
window.addEventListener("focus", handleFocus);
window.addEventListener("blur", handleBlur);
// Optionally, listen for visibility changes
const handleVisibilityChange = () => {
if (document.visibilityState === "visible") {
setIsFocused(true);
console.log("Webview is visible");
} else {
setIsFocused(false);
console.log("Webview is hidden");
}
};
document.addEventListener("visibilitychange", handleVisibilityChange);
// Cleanup the event listeners on component unmount
return () => {
window.removeEventListener("focus", handleFocus);
window.removeEventListener("blur", handleBlur);
document.removeEventListener("visibilitychange", handleVisibilityChange);
};
}, []);
const registerName = async () => {
try {
if (!userInfo?.address) throw new Error("Your address was not found");
const fee = await getFee("REGISTER_NAME");
await show({
message: "Would you like to register this name?",
publishFee: fee.fee + " QORT",
});
setIsLoadingRegisterName(true);
new Promise((res, rej) => {
chrome.runtime.sendMessage(
{
action: "registerName",
payload: {
name: registerNameValue,
},
},
(response) => {
if (!response?.error) {
res(response);
setIsLoadingRegisterName(false);
setInfoSnack({
type: "success",
message:
"Successfully registered. It may take a couple of minutes for the changes to propagate",
});
setOpenRegisterName(false);
setRegisterNameValue("");
setOpenSnack(true);
setTxList((prev) => [
{
...response,
type: "register-name",
label: `Registered name: awaiting confirmation. This may take a couple minutes.`,
labelDone: `Registered name: success!`,
done: false,
},
...prev.filter((item) => !item.done),
]);
return;
2024-07-18 12:26:13 -04:00
}
2024-09-09 20:36:39 +03:00
setInfoSnack({
type: "error",
message: response?.error,
});
setOpenSnack(true);
rej(response.error);
}
);
2024-07-09 00:44:02 +03:00
});
} catch (error) {
2024-09-09 20:36:39 +03:00
if (error?.message) {
setInfoSnack({
type: "error",
message: error?.message,
});
}
} finally {
setIsLoadingRegisterName(false);
2024-07-17 20:53:38 -04:00
}
2024-09-09 20:36:39 +03:00
};
2024-07-09 00:44:02 +03:00
2024-04-14 14:57:30 +03:00
return (
2024-04-14 21:14:13 +03:00
<AppContainer>
2024-09-09 20:36:39 +03:00
{/* {extState === 'group' && (
<Group myAddress={userInfo?.address} />
)} */}
2024-04-14 14:57:30 +03:00
{extState === "not-authenticated" && (
<>
2024-04-14 21:14:13 +03:00
<Spacer height="48px" />
2024-09-09 20:36:39 +03:00
<div
className="image-container"
style={{
width: "136px",
height: "154px",
}}
>
2024-04-15 22:30:49 +03:00
<img src={Logo1} className="base-image" />
<img src={Logo1Dark} className="hover-image" />
</div>
2024-04-14 21:14:13 +03:00
<Spacer height="38px" />
<TextP
sx={{
textAlign: "center",
lineHeight: "15px",
}}
>
WELCOME TO <TextItalic>YOUR</TextItalic> <br></br>
<TextSpan> QORTAL WALLET</TextSpan>
</TextP>
<Spacer height="38px" />
2024-04-15 22:30:49 +03:00
<Box
sx={{
display: "flex",
gap: "10px",
alignItems: "center",
marginLeft: "28px",
}}
>
<CustomButton {...getRootProps()}>
<input {...getInputProps()} />
Authenticate
</CustomButton>
<Tooltip
title="Authenticate by importing your Qortal JSON file"
arrow
>
<img src={Info} />
</Tooltip>
</Box>
2024-04-14 21:14:13 +03:00
<Spacer height="6px" />
2024-04-15 22:30:49 +03:00
<Box
sx={{
display: "flex",
gap: "10px",
alignItems: "center",
marginLeft: "28px",
2024-04-14 21:14:13 +03:00
}}
>
2024-04-15 22:30:49 +03:00
<CustomButton
onClick={() => {
setExtstate("create-wallet");
}}
>
Create account
</CustomButton>
<img
src={Info}
style={{
visibility: "hidden",
}}
/>
</Box>
2024-09-09 20:36:39 +03:00
{hasLocalNode && (
<>
<Spacer height="15px" />
<Box
sx={{
display: "flex",
gap: "10px",
alignItems: "center",
flexDirection: "column",
}}
>
<Typography
sx={{
cursor: 'pointer',
fontSize: '14px'
}}
onClick={() => {
setOpenAdvancedSettings(true);
}}
>
Advanced settings
</Typography>
{openAdvancedSettings && (
<>
<Box
sx={{
display: "flex",
gap: "10px",
alignItems: "center",
justifyContent: 'center',
width: '100%'
}}
>
<Checkbox
edge="start"
checked={useLocalNode}
tabIndex={-1}
disableRipple
onChange={(event) => {
setUseLocalNode(event.target.checked);
}}
disabled={confirmUseOfLocal}
sx={{
"&.Mui-checked": {
color: "white", // Customize the color when checked
},
"& .MuiSvgIcon-root": {
color: "white",
},
}}
/>
<Typography>Use local node</Typography>
</Box>
{useLocalNode && (
<>
<Button disabled={confirmUseOfLocal} variant="contained" component="label">
Select apiKey.txt
<input
type="file"
accept=".txt"
hidden
onChange={handleFileChangeApiKey} // File input handler
/>
</Button>
<Spacer height="5px" />
<Typography
sx={{
fontSize: "12px",
}}
>
{apiKey}
</Typography>
<Spacer height="5px" />
<Button
onClick={() => {
const valueToSet = !confirmUseOfLocal
const payload = valueToSet ? apiKey : null
chrome.runtime.sendMessage(
{ action: "setApiKey", payload },
(response) => {
if (response) {
globalApiKey = payload;
setConfirmUseOfLocal(valueToSet)
if(!globalApiKey){
setUseLocalNode(false)
setOpenAdvancedSettings(false)
setApiKey('')
}
}
}
);
}}
variant="contained"
sx={{
color: "white",
}}
>
{!confirmUseOfLocal ? 'Confirm use of local node' : 'Switch back to gateway'}
</Button>
</>
)}
</>
)}
</Box>
</>
)}
2024-04-14 14:57:30 +03:00
</>
)}
2024-04-14 21:14:13 +03:00
{/* {extState !== "not-authenticated" && (
2024-04-14 14:57:30 +03:00
<button onClick={logoutFunc}>logout</button>
2024-04-14 21:14:13 +03:00
)} */}
2024-09-09 20:36:39 +03:00
{extState === "authenticated" && isMainWindow && (
<MyContext.Provider
value={{
txList,
setTxList,
memberGroups,
setMemberGroups,
isShow,
onCancel,
onOk,
show,
message,
}}
>
<Box
sx={{
width: "100vw",
height: "100vh",
display: "flex",
}}
>
<Group
balance={balance}
userInfo={userInfo}
myAddress={userInfo?.address}
isFocused={isFocused}
isMain={isMain}
/>
<AuthenticatedContainer sx={{ width: "350px" }}>
<AuthenticatedContainerInnerLeft>
<Spacer height="48px" />
{authenticatedMode === "ltc" ? (
<>
<img src={ltcLogo} />
<Spacer height="32px" />
<CopyToClipboard text={rawWallet?.ltcAddress}>
<AddressBox>
{rawWallet?.ltcAddress?.slice(0, 6)}...
{rawWallet?.ltcAddress?.slice(-4)} <img src={Copy} />
</AddressBox>
</CopyToClipboard>
<Spacer height="10px" />
{ltcBalanceLoading && (
<CircularProgress color="success" size={16} />
)}
{!isNaN(+ltcBalance) && !ltcBalanceLoading && (
<Box
sx={{
gap: "10px",
display: "flex",
alignItems: "center",
}}
>
<TextP
sx={{
textAlign: "center",
lineHeight: "24px",
fontSize: "20px",
fontWeight: 700,
}}
>
{ltcBalance} LTC
</TextP>
<RefreshIcon
onClick={getLtcBalanceFunc}
sx={{
fontSize: "16px",
color: "white",
cursor: "pointer",
}}
/>
</Box>
)}
</>
) : (
<>
<img src={Logo2} />
<Spacer height="32px" />
2024-07-17 20:53:38 -04:00
<TextP
sx={{
textAlign: "center",
lineHeight: "24px",
fontSize: "20px",
}}
>
2024-09-09 20:36:39 +03:00
{userInfo?.name}
2024-07-17 20:53:38 -04:00
</TextP>
2024-09-09 20:36:39 +03:00
<Spacer height="10px" />
<CopyToClipboard text={rawWallet?.address0}>
<AddressBox>
{rawWallet?.address0?.slice(0, 6)}...
{rawWallet?.address0?.slice(-4)} <img src={Copy} />
</AddressBox>
</CopyToClipboard>
<Spacer height="10px" />
{qortBalanceLoading && (
<CircularProgress color="success" size={16} />
)}
{!qortBalanceLoading && balance >= 0 && (
<Box
sx={{
gap: "10px",
display: "flex",
alignItems: "center",
}}
>
<TextP
sx={{
textAlign: "center",
lineHeight: "24px",
fontSize: "20px",
fontWeight: 700,
}}
>
{balance?.toFixed(2)} QORT
</TextP>
<RefreshIcon
onClick={getBalanceFunc}
sx={{
fontSize: "16px",
color: "white",
cursor: "pointer",
}}
/>
</Box>
)}
<Spacer height="35px" />
{userInfo && !userInfo?.name && (
<TextP
ref={registerNamePopoverRef}
sx={{
textAlign: "center",
lineHeight: 1.2,
fontSize: "16px",
fontWeight: 500,
cursor: "pointer",
marginTop: "10px",
color: "red",
textDecoration: "underline",
}}
onClick={() => {
setOpenRegisterName(true);
}}
>
REGISTER NAME
</TextP>
)}
<Spacer height="20px" />
<CustomButton
onClick={() => {
setExtstate("send-qort");
}}
>
Transfer QORT
</CustomButton>
</>
2024-07-17 20:53:38 -04:00
)}
<TextP
sx={{
textAlign: "center",
lineHeight: "24px",
2024-09-09 20:36:39 +03:00
fontSize: "12px",
fontWeight: 500,
cursor: "pointer",
marginTop: "10px",
textDecoration: "underline",
}}
onClick={() => {
chrome.tabs.create({ url: "https://www.qort.trade" });
2024-07-17 20:53:38 -04:00
}}
>
2024-09-09 20:36:39 +03:00
Get QORT at qort.trade
2024-07-17 20:53:38 -04:00
</TextP>
2024-09-09 20:36:39 +03:00
</AuthenticatedContainerInnerLeft>
<AuthenticatedContainerInnerRight>
<Spacer height="20px" />
<img
2024-07-17 20:53:38 -04:00
onClick={() => {
2024-09-09 20:36:39 +03:00
setExtstate("download-wallet");
2024-07-17 20:53:38 -04:00
}}
2024-09-09 20:36:39 +03:00
src={Download}
style={{
cursor: "pointer",
}}
/>
<Spacer height="20px" />
<img
src={Logout}
onClick={logoutFunc}
style={{
cursor: "pointer",
}}
/>
<Spacer height="20px" />
{authenticatedMode === "qort" && (
<img
onClick={() => {
setAuthenticatedMode("ltc");
}}
src={ltcLogo}
style={{
cursor: "pointer",
width: "20px",
height: "auto",
}}
/>
)}
{authenticatedMode === "ltc" && (
<img
onClick={() => {
setAuthenticatedMode("qort");
}}
src={qortLogo}
style={{
cursor: "pointer",
width: "20px",
height: "auto",
}}
/>
)}
</AuthenticatedContainerInnerRight>
</AuthenticatedContainer>
</Box>
<Box
sx={{
position: "fixed",
right: "25px",
bottom: "25px",
width: "350px",
zIndex: 100000,
}}
>
<TaskManger getUserInfo={getUserInfo} />
</Box>
</MyContext.Provider>
2024-04-14 14:57:30 +03:00
)}
2024-09-09 20:36:39 +03:00
{extState === "send-qort" && isMainWindow && (
2024-04-14 14:57:30 +03:00
<>
2024-04-14 21:14:13 +03:00
<Spacer height="22px" />
<Box
sx={{
display: "flex",
width: "100%",
justifyContent: "flex-start",
2024-04-14 23:01:28 +03:00
paddingLeft: "22px",
boxSizing: "border-box",
2024-04-14 21:14:13 +03:00
}}
>
<img
style={{
cursor: "pointer",
}}
onClick={returnToMain}
src={Return}
/>
</Box>
<Spacer height="35px" />
2024-04-14 23:01:28 +03:00
<Box
2024-04-14 21:14:13 +03:00
sx={{
2024-04-14 23:01:28 +03:00
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
2024-04-14 21:14:13 +03:00
}}
>
2024-04-14 23:01:28 +03:00
<TextP
sx={{
textAlign: "start",
lineHeight: "24px",
fontSize: "20px",
fontWeight: 600,
}}
>
Transfer QORT
</TextP>
<Spacer height="35px" />
<TextP
sx={{
textAlign: "start",
lineHeight: "16px",
fontSize: "20px",
fontWeight: 600,
color: "rgba(255, 255, 255, 0.5)",
}}
>
Balance:
</TextP>
<TextP
sx={{
textAlign: "start",
lineHeight: "24px",
fontSize: "20px",
fontWeight: 700,
}}
>
2024-07-18 12:26:13 -04:00
{balance?.toFixed(2)} QORT
2024-04-14 23:01:28 +03:00
</TextP>
2024-04-14 21:14:13 +03:00
</Box>
<Spacer height="35px" />
2024-04-14 14:57:30 +03:00
<Box>
2024-04-14 21:14:13 +03:00
<CustomLabel htmlFor="standard-adornment-name">To</CustomLabel>
<Spacer height="5px" />
<CustomInput
2024-04-14 14:57:30 +03:00
id="standard-adornment-name"
value={paymentTo}
onChange={(e) => setPaymentTo(e.target.value)}
2024-04-14 21:14:13 +03:00
autoComplete="off"
2024-04-14 14:57:30 +03:00
/>
2024-04-14 21:14:13 +03:00
<Spacer height="6px" />
2024-04-14 23:01:28 +03:00
<CustomLabel htmlFor="standard-adornment-amount">
Amount
</CustomLabel>
2024-04-14 21:14:13 +03:00
<Spacer height="5px" />
<CustomInput
2024-04-14 14:57:30 +03:00
id="standard-adornment-amount"
type="number"
value={paymentAmount}
onChange={(e) => setPaymentAmount(+e.target.value)}
2024-04-14 21:14:13 +03:00
autoComplete="off"
2024-04-14 14:57:30 +03:00
/>
2024-04-14 21:14:13 +03:00
<Spacer height="6px" />
<CustomLabel htmlFor="standard-adornment-password">
2024-04-15 22:30:49 +03:00
Confirm Wallet Password
2024-04-14 21:14:13 +03:00
</CustomLabel>
<Spacer height="5px" />
2024-07-02 19:02:02 -04:00
<PasswordField
2024-04-14 14:57:30 +03:00
id="standard-adornment-password"
value={paymentPassword}
onChange={(e) => setPaymentPassword(e.target.value)}
2024-04-14 21:14:13 +03:00
autoComplete="off"
2024-04-14 14:57:30 +03:00
/>
</Box>
2024-04-16 13:25:36 +03:00
<Spacer height="10px" />
<ErrorText>{sendPaymentError}</ErrorText>
2024-04-16 13:25:36 +03:00
{/* <Typography>{sendPaymentSuccess}</Typography> */}
2024-04-14 21:14:13 +03:00
<Spacer height="25px" />
<CustomButton
2024-04-14 14:57:30 +03:00
onClick={() => {
sendCoinFunc();
}}
>
2024-04-14 21:14:13 +03:00
Send
</CustomButton>
2024-04-14 14:57:30 +03:00
</>
2024-07-12 23:44:21 -04:00
)}
2024-09-09 20:36:39 +03:00
{extState === "web-app-request-buy-order" && !isMainWindow && (
2024-07-12 23:44:21 -04:00
<>
<Spacer height="100px" />
<TextP
sx={{
textAlign: "center",
lineHeight: "15px",
}}
>
The Application <br></br>{" "}
<TextItalic>{requestBuyOrder?.hostname}</TextItalic> <br></br>
<TextSpan>is requesting a buy order</TextSpan>
</TextP>
<Spacer height="10px" />
<TextP
sx={{
textAlign: "center",
2024-07-18 00:05:45 -04:00
lineHeight: "24px",
fontSize: "20px",
fontWeight: 700,
2024-07-12 23:44:21 -04:00
}}
>
2024-07-18 00:05:45 -04:00
{+requestBuyOrder?.crosschainAtInfo?.qortAmount} QORT
2024-07-12 23:44:21 -04:00
</TextP>
<Spacer height="15px" />
<TextP
sx={{
textAlign: "center",
lineHeight: "15px",
2024-07-18 00:05:45 -04:00
fontSize: "14px",
2024-07-12 23:44:21 -04:00
}}
>
FOR
</TextP>
<Spacer height="15px" />
<TextP
sx={{
textAlign: "center",
lineHeight: "24px",
fontSize: "20px",
fontWeight: 700,
}}
>
2024-09-09 20:36:39 +03:00
{requestBuyOrder?.crosschainAtInfo?.expectedForeignAmount}{" "}
{requestBuyOrder?.crosschainAtInfo?.foreignBlockchain}
2024-07-12 23:44:21 -04:00
</TextP>
{/* <Spacer height="29px" />
<CustomLabel htmlFor="standard-adornment-password">
Confirm Wallet Password
</CustomLabel>
<Spacer height="5px" />
<PasswordField
id="standard-adornment-password"
value={paymentPassword}
onChange={(e) => setPaymentPassword(e.target.value)}
/> */}
<Spacer height="29px" />
<Box
sx={{
display: "flex",
alignItems: "center",
gap: "14px",
}}
>
<CustomButton
sx={{
minWidth: "102px",
}}
onClick={() => confirmBuyOrder(false)}
>
accept
</CustomButton>
<CustomButton
sx={{
minWidth: "102px",
}}
onClick={() => confirmBuyOrder(true)}
>
decline
</CustomButton>
</Box>
<ErrorText>{sendPaymentError}</ErrorText>
</>
2024-04-14 14:57:30 +03:00
)}
2024-09-09 20:36:39 +03:00
{extState === "web-app-request-payment" && !isMainWindow && (
2024-04-14 14:57:30 +03:00
<>
2024-04-15 22:30:49 +03:00
<Spacer height="100px" />
2024-04-14 23:19:55 +03:00
2024-04-15 22:30:49 +03:00
<TextP
2024-04-14 23:19:55 +03:00
sx={{
textAlign: "center",
lineHeight: "15px",
}}
>
The Application <br></br>{" "}
<TextItalic>{sendqortState?.hostname}</TextItalic> <br></br>
<TextSpan>is requesting a payment</TextSpan>
</TextP>
<Spacer height="10px" />
<TextP
sx={{
textAlign: "center",
lineHeight: "15px",
2024-04-15 22:30:49 +03:00
fontSize: "10px",
2024-04-14 23:19:55 +03:00
}}
2024-04-15 22:30:49 +03:00
>
{sendqortState?.description}
</TextP>
2024-04-14 23:19:55 +03:00
<Spacer height="15px" />
<TextP
2024-04-15 22:30:49 +03:00
sx={{
textAlign: "center",
lineHeight: "24px",
fontSize: "20px",
fontWeight: 700,
}}
>
{sendqortState?.amount} QORT
</TextP>
2024-07-09 00:44:02 +03:00
{/* <Spacer height="29px" />
2024-04-14 23:19:55 +03:00
<CustomLabel htmlFor="standard-adornment-password">
2024-04-15 22:30:49 +03:00
Confirm Wallet Password
2024-04-14 23:19:55 +03:00
</CustomLabel>
<Spacer height="5px" />
2024-07-02 19:02:02 -04:00
<PasswordField
2024-04-14 14:57:30 +03:00
id="standard-adornment-password"
value={paymentPassword}
onChange={(e) => setPaymentPassword(e.target.value)}
2024-07-09 00:44:02 +03:00
/> */}
2024-04-15 22:30:49 +03:00
<Spacer height="29px" />
<Box
2024-04-14 23:19:55 +03:00
sx={{
display: "flex",
alignItems: "center",
gap: "14px",
}}
>
<CustomButton
sx={{
minWidth: "102px",
}}
onClick={() => confirmPayment(false)}
>
accept
</CustomButton>
<CustomButton
sx={{
minWidth: "102px",
}}
onClick={() => confirmPayment(true)}
>
decline
</CustomButton>
</Box>
<ErrorText>{sendPaymentError}</ErrorText>
2024-04-14 14:57:30 +03:00
</>
)}
2024-09-09 20:36:39 +03:00
{extState === "web-app-request-connection" && !isMainWindow && (
2024-04-14 14:57:30 +03:00
<>
2024-04-14 23:01:28 +03:00
<Spacer height="48px" />
2024-09-09 20:36:39 +03:00
<div
className="image-container"
style={{
width: "136px",
height: "154px",
}}
>
2024-04-15 22:30:49 +03:00
<img src={Logo1} className="base-image" />
<img src={Logo1Dark} className="hover-image" />
</div>
2024-04-14 23:01:28 +03:00
<Spacer height="38px" />
<TextP
sx={{
textAlign: "center",
lineHeight: "15px",
}}
2024-04-14 14:57:30 +03:00
>
2024-04-14 23:01:28 +03:00
The Application <br></br>{" "}
<TextItalic>{requestConnection?.hostname}</TextItalic> <br></br>
<TextSpan>is requestion a connection</TextSpan>
</TextP>
<Spacer height="38px" />
<Box
sx={{
display: "flex",
alignItems: "center",
gap: "14px",
}}
2024-04-14 14:57:30 +03:00
>
2024-04-14 23:01:28 +03:00
<CustomButton
sx={{
minWidth: "102px",
}}
onClick={() =>
responseToConnectionRequest(
true,
requestConnection?.hostname,
requestConnection.interactionId
)
}
>
accept
</CustomButton>
<CustomButton
sx={{
minWidth: "102px",
}}
onClick={() =>
responseToConnectionRequest(
false,
requestConnection?.hostname,
requestConnection.interactionId
)
}
>
decline
</CustomButton>
</Box>
2024-04-14 14:57:30 +03:00
</>
)}
2024-09-09 20:36:39 +03:00
{extState === "web-app-request-authentication" && !isMainWindow && (
2024-04-14 14:57:30 +03:00
<>
2024-04-14 23:01:28 +03:00
<Spacer height="48px" />
2024-09-09 20:36:39 +03:00
<div
className="image-container"
style={{
width: "136px",
height: "154px",
}}
>
2024-04-15 22:30:49 +03:00
<img src={Logo1} className="base-image" />
<img src={Logo1Dark} className="hover-image" />
</div>
2024-04-14 23:01:28 +03:00
<Spacer height="38px" />
<TextP
sx={{
textAlign: "center",
lineHeight: "15px",
}}
>
The Application <br></br>{" "}
<TextItalic>{requestConnection?.hostname}</TextItalic> <br></br>
<TextSpan>requests authentication</TextSpan>
</TextP>
<Spacer height="38px" />
<Box
sx={{
display: "flex",
alignItems: "center",
gap: "14px",
}}
></Box>
<Spacer height="38px" />
<CustomButton {...getRootProps()}>
<input {...getInputProps()} />
Authenticate
</CustomButton>
<Spacer height="6px" />
<CustomButton
2024-04-14 21:14:13 +03:00
onClick={() => {
setExtstate("create-wallet");
}}
>
Create account
2024-04-14 23:01:28 +03:00
</CustomButton>
2024-04-14 14:57:30 +03:00
</>
)}
2024-09-09 20:36:39 +03:00
{rawWallet && extState === "wallet-dropped" && (
2024-07-09 00:44:02 +03:00
<>
<Spacer height="22px" />
<Box
sx={{
display: "flex",
width: "100%",
justifyContent: "flex-start",
paddingLeft: "22px",
boxSizing: "border-box",
}}
>
<img
style={{
cursor: "pointer",
}}
2024-07-17 20:53:38 -04:00
onClick={() => {
2024-07-09 00:44:02 +03:00
setRawWallet(null);
setExtstate("not-authenticated");
}}
src={Return}
/>
</Box>
<Spacer height="10px" />
2024-09-09 20:36:39 +03:00
<div
className="image-container"
style={{
width: "136px",
height: "154px",
}}
>
2024-07-09 00:44:02 +03:00
<img src={Logo1} className="base-image" />
<img src={Logo1Dark} className="hover-image" />
</div>
<Spacer height="35px" />
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
}}
>
<TextP
sx={{
textAlign: "start",
lineHeight: "24px",
fontSize: "20px",
fontWeight: 600,
}}
>
Authenticate
</TextP>
</Box>
<Spacer height="35px" />
2024-07-17 20:53:38 -04:00
<>
<CustomLabel htmlFor="standard-adornment-password">
Wallet Password
</CustomLabel>
<Spacer height="5px" />
<PasswordField
id="standard-adornment-password"
value={authenticatePassword}
2024-09-09 20:36:39 +03:00
onChange={(e) => setAuthenticatePassword(e.target.value)}
2024-07-17 20:53:38 -04:00
onKeyDown={(e) => {
if (e.key === "Enter") {
authenticateWallet();
2024-07-09 00:44:02 +03:00
}
2024-07-17 20:53:38 -04:00
}}
/>
<Spacer height="20px" />
2024-09-09 20:36:39 +03:00
<CustomButton onClick={authenticateWallet}>
2024-07-17 20:53:38 -04:00
Authenticate
</CustomButton>
2024-09-09 20:36:39 +03:00
<ErrorText>{walletToBeDecryptedError}</ErrorText>
2024-07-17 20:53:38 -04:00
</>
2024-07-09 00:44:02 +03:00
</>
)}
2024-04-14 14:57:30 +03:00
{extState === "download-wallet" && (
<>
2024-04-15 22:30:49 +03:00
<Spacer height="22px" />
<Box
sx={{
display: "flex",
width: "100%",
justifyContent: "flex-start",
paddingLeft: "22px",
boxSizing: "border-box",
}}
>
<img
style={{
cursor: "pointer",
}}
onClick={returnToMain}
src={Return}
/>
</Box>
<Spacer height="10px" />
2024-09-09 20:36:39 +03:00
<div
className="image-container"
style={{
width: "136px",
height: "154px",
}}
>
2024-04-15 22:30:49 +03:00
<img src={Logo1} className="base-image" />
<img src={Logo1Dark} className="hover-image" />
2024-04-14 14:57:30 +03:00
</div>
2024-04-15 22:30:49 +03:00
<Spacer height="35px" />
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
}}
>
<TextP
sx={{
textAlign: "start",
lineHeight: "24px",
fontSize: "20px",
fontWeight: 600,
}}
>
Download Wallet
</TextP>
</Box>
<Spacer height="35px" />
2024-04-14 14:57:30 +03:00
{!walletToBeDownloaded && (
<>
2024-04-15 22:30:49 +03:00
<CustomLabel htmlFor="standard-adornment-password">
Confirm Wallet Password
</CustomLabel>
<Spacer height="5px" />
2024-07-02 19:02:02 -04:00
<PasswordField
2024-04-14 14:57:30 +03:00
id="standard-adornment-password"
value={walletToBeDownloadedPassword}
onChange={(e) =>
setWalletToBeDownloadedPassword(e.target.value)
}
/>
2024-04-15 22:30:49 +03:00
<Spacer height="20px" />
<CustomButton onClick={confirmPasswordToDownload}>
2024-04-14 14:57:30 +03:00
Confirm password
2024-04-15 22:30:49 +03:00
</CustomButton>
2024-09-09 20:36:39 +03:00
<ErrorText>{walletToBeDownloadedError}</ErrorText>
2024-04-14 14:57:30 +03:00
</>
)}
{walletToBeDownloaded && (
<>
2024-04-15 22:30:49 +03:00
<CustomButton onClick={saveFileToDiskFunc}>
Download wallet
</CustomButton>
2024-04-14 14:57:30 +03:00
</>
)}
</>
)}
{extState === "create-wallet" && (
<>
{!walletToBeDownloaded && (
<>
2024-07-17 20:53:38 -04:00
<Spacer height="22px" />
<Box
sx={{
display: "flex",
width: "100%",
justifyContent: "flex-start",
paddingLeft: "22px",
boxSizing: "border-box",
}}
>
<img
style={{
cursor: "pointer",
}}
onClick={() => {
2024-09-09 20:36:39 +03:00
setExtstate("not-authenticated");
2024-07-17 20:53:38 -04:00
}}
src={Return}
/>
</Box>
2024-04-15 22:30:49 +03:00
<Spacer height="15px" />
2024-09-09 20:36:39 +03:00
<div
className="image-container"
style={{
width: "136px",
height: "154px",
}}
>
2024-07-17 20:53:38 -04:00
<img src={Logo1} className="base-image" />
<img src={Logo1Dark} className="hover-image" />
</div>
2024-04-14 23:01:28 +03:00
<Spacer height="38px" />
<TextP
sx={{
textAlign: "center",
lineHeight: "15px",
}}
>
Set up your Qortal account
</TextP>
<Spacer height="14px" />
<CustomLabel htmlFor="standard-adornment-password">
2024-04-15 22:30:49 +03:00
Wallet Password
2024-04-14 23:01:28 +03:00
</CustomLabel>
<Spacer height="5px" />
2024-07-02 19:02:02 -04:00
<PasswordField
2024-04-14 14:57:30 +03:00
id="standard-adornment-password"
value={walletToBeDownloadedPassword}
onChange={(e) =>
setWalletToBeDownloadedPassword(e.target.value)
}
/>
2024-04-14 23:01:28 +03:00
<Spacer height="6px" />
<CustomLabel htmlFor="standard-adornment-password">
2024-04-15 22:30:49 +03:00
Confirm Wallet Password
2024-04-14 23:01:28 +03:00
</CustomLabel>
<Spacer height="5px" />
2024-07-02 19:02:02 -04:00
<PasswordField
2024-04-14 14:57:30 +03:00
id="standard-adornment-password"
value={walletToBeDownloadedPasswordConfirm}
onChange={(e) =>
setWalletToBeDownloadedPasswordConfirm(e.target.value)
}
/>
2024-04-14 23:01:28 +03:00
<Spacer height="17px" />
<CustomButton onClick={createAccountFunc}>
Create Account
</CustomButton>
2024-09-09 20:36:39 +03:00
<ErrorText>{walletToBeDownloadedError}</ErrorText>
2024-04-14 14:57:30 +03:00
</>
)}
{walletToBeDownloaded && (
<>
2024-04-14 23:01:28 +03:00
<Spacer height="48px" />
<img src={Success} />
<Spacer height="45px" />
<TextP
sx={{
textAlign: "center",
lineHeight: "15px",
}}
>
Congrats, youre all set up!
</TextP>
<Spacer height="100px" />
2024-04-15 22:30:49 +03:00
<CustomButton
onClick={() => {
saveFileToDiskFunc();
returnToMain();
}}
>
2024-04-14 23:01:28 +03:00
Backup Account
</CustomButton>
2024-04-14 14:57:30 +03:00
</>
)}
</>
)}
2024-04-15 22:30:49 +03:00
{extState === "transfer-success-regular" && (
<>
<Spacer height="48px" />
<img src={Success} />
<Spacer height="45px" />
<TextP
sx={{
textAlign: "center",
lineHeight: "15px",
}}
>
The transfer was succesful!
</TextP>
<Spacer height="100px" />
<CustomButton
onClick={() => {
returnToMain();
}}
>
Continue
</CustomButton>
</>
)}
{extState === "transfer-success-request" && (
<>
<Spacer height="48px" />
<img src={Success} />
<Spacer height="45px" />
<TextP
sx={{
textAlign: "center",
lineHeight: "15px",
}}
>
The transfer was succesful!
</TextP>
<Spacer height="100px" />
<CustomButton
onClick={() => {
window.close();
}}
>
Continue
</CustomButton>
</>
)}
2024-07-17 17:00:43 -04:00
{extState === "buy-order-submitted" && (
<>
<Spacer height="48px" />
<img src={Success} />
<Spacer height="45px" />
<TextP
sx={{
textAlign: "center",
lineHeight: "15px",
}}
>
Your buy order was submitted
</TextP>
<Spacer height="100px" />
<CustomButton
onClick={() => {
window.close();
}}
>
Close
</CustomButton>
</>
)}
2024-04-14 14:57:30 +03:00
{countdown && (
2024-04-14 23:01:28 +03:00
<Box
style={{
position: "absolute",
top: "20px",
left: "20px",
2024-04-14 14:57:30 +03:00
}}
>
2024-04-14 23:01:28 +03:00
{/* <Spacer height="25px"/> */}
<CountdownCircleTimer
isPlaying
duration={countdown}
colors={["#004777", "#F7B801", "#A30000", "#A30000"]}
colorsTime={[7, 5, 2, 0]}
onComplete={() => {
window.close();
}}
size={75}
strokeWidth={8}
>
{({ remainingTime }) => <TextP>{remainingTime}</TextP>}
</CountdownCircleTimer>
</Box>
2024-04-14 14:57:30 +03:00
)}
2024-04-15 22:30:49 +03:00
{isLoading && <Loader />}
2024-09-09 20:36:39 +03:00
{isShow && (
<Dialog
open={isShow}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{"Publish"}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
{message.message}
</DialogContentText>
<DialogContentText id="alert-dialog-description2">
publish fee: {message.publishFee}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button variant="contained" onClick={onCancel}>
Disagree
</Button>
<Button variant="contained" onClick={onOk} autoFocus>
Agree
</Button>
</DialogActions>
</Dialog>
)}
<Popover
open={openRegisterName}
anchorEl={registerNamePopoverRef.current}
onClose={() => {
setOpenRegisterName(false);
setRegisterNameValue("");
}}
anchorOrigin={{
vertical: "bottom",
horizontal: "center",
}}
transformOrigin={{
vertical: "top",
horizontal: "center",
}}
style={{ marginTop: "8px" }}
>
<Box
sx={{
width: "325px",
height: "250px",
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "10px",
padding: "10px",
}}
>
<Label>Choose a name</Label>
<Input
onChange={(e) => setRegisterNameValue(e.target.value)}
value={registerNameValue}
placeholder="Choose a name"
/>
<Spacer height="25px" />
<LoadingButton
loading={isLoadingRegisterName}
loadingPosition="start"
variant="contained"
disabled={!registerNameValue}
onClick={registerName}
>
Register Name
</LoadingButton>
</Box>
</Popover>
<CustomizedSnackbars
open={openSnack}
setOpen={setOpenSnack}
info={infoSnack}
setInfo={setInfoSnack}
/>
2024-04-14 21:14:13 +03:00
</AppContainer>
2024-04-14 14:57:30 +03:00
);
}
export default App;