qortal-mobile/src/App.tsx

1335 lines
38 KiB
TypeScript
Raw Normal View History

2024-04-14 23:01:28 +03:00
import { 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-04-15 22:30:49 +03:00
import { Box, Input, InputLabel, 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-04-14 21:14:13 +03:00
import Logo2 from "./assets/svgs/Logo2.svg";
import Copy from "./assets/svgs/Copy.svg";
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-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-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);
const [decryptedWallet, setdecryptedWallet] = useState<any>(null);
const [requestConnection, setRequestConnection] = useState<any>(null);
const [requestAuthentication, setRequestAuthentication] = useState<any>(null);
const [userInfo, setUserInfo] = useState<any>(null);
const [balance, setBalance] = useState<any>(null);
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-07-09 00:44:02 +03:00
const [authenticatePassword, setAuthenticatePassword] =
useState<string>("");
2024-04-15 22:30:49 +03:00
const [sendqortState, setSendqortState] = useState<any>(null);
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-09 00:44:02 +03:00
const [walletToBeDecryptedError, setWalletToBeDecryptedError] =
useState<string>("");
2024-04-25 12:48:26 +03:00
const holdRefExtState = useRef<extStates>("not-authenticated")
useEffect(()=> {
if(extState){
holdRefExtState.current = extState
}
}, [extState])
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-04-15 22:30:49 +03: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);
} catch (e) {}
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;
}
},
});
2024-04-15 22:30:49 +03:00
2024-04-14 14:57:30 +03:00
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-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" },
function (response) {
2024-04-15 22:30:49 +03:00
2024-04-14 14:57:30 +03:00
}
);
}
);
};
2024-04-15 22:30:49 +03:00
2024-04-14 14:57:30 +03:00
const getBalanceFunc = () => {
chrome.runtime.sendMessage({ action: "balance" }, (response) => {
if (response && !response?.error) {
setBalance(response);
}
});
};
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-04-15 22:30:49 +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-04-15 22:30:49 +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) => {
2024-04-15 22:30:49 +03:00
2024-04-14 14:57:30 +03:00
// Check if the message is to update the state
if (message.action === "UPDATE_STATE_CONFIRM_SEND_QORT") {
// Update the component state with the received 'sendqort' state
setSendqortState(message.payload);
setExtstate("web-app-request-payment");
} else if (message.action === "closePopup") {
// Update the component state with the received 'sendqort' state
window.close();
} else if (message.action === "UPDATE_STATE_REQUEST_CONNECTION") {
// Update the component state with the received 'sendqort' state
setRequestConnection(message.payload);
setExtstate("web-app-request-connection");
} else if (message.action === "UPDATE_STATE_REQUEST_AUTHENTICATION") {
// Update the component state with the received 'sendqort' state
setRequestAuthentication(message.payload);
setExtstate("web-app-request-authentication");
} else if (message.action === "SET_COUNTDOWN") {
setCountdown(message.payload);
}
});
2024-04-14 21:14:13 +03:00
}, []);
2024-04-14 14:57:30 +03:00
2024-04-15 22:30:49 +03: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-09 00:44:02 +03:00
// if (!paymentPassword) {
// setSendPaymentError("Please enter your wallet password");
// return;
// }
2024-04-15 22:30:49 +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);
// setSendPaymentSuccess("Payment successfully sent");
} else {
setSendPaymentError(
response?.error || "Unable to perform payment. Please try again."
);
2024-04-14 14:57:30 +03:00
}
2024-04-15 22:30:49 +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-04-25 12:48:26 +03:00
2024-04-14 14:57:30 +03:00
useEffect(() => {
try {
2024-04-16 13:25:36 +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-04-25 12:48:26 +03:00
if(holdRefExtState.current === 'web-app-request-payment' || holdRefExtState.current === 'web-app-request-connection') return
2024-04-14 14:57:30 +03:00
setExtstate("authenticated");
}
});
2024-04-16 13:25:36 +03:00
} catch (error) {} finally {
setIsLoading(false)
}
2024-04-14 23:01:28 +03:00
}, []);
2024-04-14 14:57:30 +03:00
useEffect(() => {
if (!address) return;
try {
chrome.runtime.sendMessage({ action: "userInfo" }, (response) => {
if (response && !response.error) {
setUserInfo(response);
}
});
getBalanceFunc();
} catch (error) {}
}, [address]);
useEffect(() => {
return () => {
console.log("exit");
};
}, []);
const confirmPasswordToDownload = async () => {
try {
setWalletToBeDownloadedError("");
if (!walletToBeDownloadedPassword) {
setSendPaymentError("Please enter your password");
return;
}
2024-04-15 22:30:49 +03:00
setIsLoading(true)
await new Promise<void>((res)=> {
setTimeout(()=> {
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 {
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-04-15 22:30:49 +03:00
setIsLoading(true)
await new Promise<void>((res)=> {
setTimeout(()=> {
res()
}, 250)
})
2024-04-14 21:14:13 +03:00
const res = await createAccount();
const wallet = await res.generateSaveWalletData(
walletToBeDownloadedPassword,
crypto.kdfThreads,
() => {}
);
2024-07-09 00:44:02 +03:00
chrome.runtime.sendMessage({ action: "decryptWallet", payload: {
password: walletToBeDownloadedPassword,
wallet
} }, (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-04-14 21:14:13 +03:00
});
2024-07-09 00:44:02 +03:00
2024-04-14 14:57:30 +03:00
} catch (error: any) {
setWalletToBeDownloadedError(error?.message);
2024-04-15 22:30:49 +03:00
setIsLoading(false)
2024-07-09 00:44:02 +03: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-04-14 21:14:13 +03:00
} catch (error) {}
};
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");
setBackupjson(null);
setRawWallet(null);
setdecryptedWallet(null);
setRequestConnection(null);
setRequestAuthentication(null);
setUserInfo(null);
setBalance(null);
setPaymentTo("");
setPaymentAmount(0);
setPaymentPassword("");
setSendPaymentError("");
setSendPaymentSuccess("");
setCountdown(null);
setWalletToBeDownloaded(null);
setWalletToBeDownloadedPassword("");
setWalletToBeDownloadedPasswordConfirm("");
setWalletToBeDownloadedError("");
setSendqortState(null);
};
2024-07-09 00:44:02 +03:00
const authenticateWallet = async()=> {
try {
setIsLoading(true)
setWalletToBeDecryptedError('')
await new Promise<void>((res)=> {
setTimeout(()=> {
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();
} else if(response?.error){
setIsLoading(false)
setWalletToBeDecryptedError(response.error)
}
});
} catch (error) {
setWalletToBeDecryptedError('Unable to authenticate. Wrong password')
}
}
2024-04-14 14:57:30 +03:00
return (
2024-04-14 21:14:13 +03:00
<AppContainer>
2024-04-14 14:57:30 +03:00
{extState === "not-authenticated" && (
<>
2024-04-14 21:14:13 +03:00
<Spacer height="48px" />
2024-04-15 22:30:49 +03:00
<div className="image-container" style={{
width: '136px',
height: '154px'
}}>
<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-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-04-14 14:57:30 +03:00
{extState === "authenticated" && (
2024-04-14 21:14:13 +03:00
<AuthenticatedContainer>
<AuthenticatedContainerInnerLeft>
<Spacer height="48px" />
<img src={Logo2} />
<Spacer height="32px" />
<TextP
sx={{
textAlign: "center",
lineHeight: "24px",
fontSize: "20px",
}}
>
{userInfo?.name}
</TextP>
<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" />
2024-04-15 22:30:49 +03:00
{balance && (
<TextP
sx={{
textAlign: "center",
lineHeight: "24px",
fontSize: "20px",
fontWeight: 700,
}}
>
{balance?.toFixed(2)} QORT
</TextP>
)}
2024-04-14 21:14:13 +03:00
{/* <p>balance: {balance}</p> */}
<Spacer height="55px" />
{/* <CustomButton
2024-04-14 14:57:30 +03:00
onClick={() => {
setExtstate("download-wallet");
}}
>
Download Wallet
2024-04-14 21:14:13 +03:00
</CustomButton> */}
<CustomButton
onClick={() => {
setExtstate("send-qort");
}}
>
Transfer QORT
</CustomButton>
</AuthenticatedContainerInnerLeft>
<AuthenticatedContainerInnerRight>
<Spacer height="20px" />
<img
onClick={() => {
setExtstate("download-wallet");
}}
src={Download}
style={{
cursor: "pointer",
}}
/>
<Spacer height="20px" />
<img
src={Logout}
onClick={logoutFunc}
style={{
cursor: "pointer",
}}
/>
</AuthenticatedContainerInnerRight>
</AuthenticatedContainer>
2024-04-14 14:57:30 +03:00
)}
{extState === "send-qort" && (
<>
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,
}}
>
{balance?.toFixed(2)} QORT
</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
</>
)}
{extState === "web-app-request-payment" && (
<>
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
</>
)}
{extState === "web-app-request-connection" && (
<>
2024-04-14 23:01:28 +03:00
<Spacer height="48px" />
2024-04-15 22:30:49 +03:00
<div className="image-container" style={{
width: '136px',
height: '154px'
}}>
<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
</>
)}
{extState === "web-app-request-authentication" && (
<>
2024-04-14 23:01:28 +03:00
<Spacer height="48px" />
2024-04-15 22:30:49 +03:00
<div className="image-container" style={{
width: '136px',
height: '154px'
}}>
<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-07-09 00:44:02 +03:00
{rawWallet && extState === 'wallet-dropped' && (
<>
<Spacer height="22px" />
<Box
sx={{
display: "flex",
width: "100%",
justifyContent: "flex-start",
paddingLeft: "22px",
boxSizing: "border-box",
}}
>
<img
style={{
cursor: "pointer",
}}
onClick={()=> {
setRawWallet(null);
setExtstate("not-authenticated");
}}
src={Return}
/>
</Box>
<Spacer height="10px" />
<div className="image-container" style={{
width: '136px',
height: '154px'
}}>
<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" />
<>
<CustomLabel htmlFor="standard-adornment-password">
Wallet Password
</CustomLabel>
<Spacer height="5px" />
<PasswordField
id="standard-adornment-password"
value={authenticatePassword}
onChange={(e) =>
setAuthenticatePassword(e.target.value)
}
2024-07-10 01:21:50 +03:00
onKeyDown={(e) => {
if (e.key === "Enter") {
authenticateWallet();
}
}}
2024-07-09 00:44:02 +03:00
/>
<Spacer height="20px" />
2024-07-10 01:21:50 +03:00
<CustomButton onClick={authenticateWallet} >
2024-07-09 00:44:02 +03:00
Authenticate
</CustomButton>
<ErrorText>
2024-07-09 00:44:02 +03:00
{walletToBeDecryptedError}
</ErrorText>
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" />
<div className="image-container" style={{
width: '136px',
height: '154px'
}}>
<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>
<ErrorText>
2024-04-14 21:14:13 +03:00
{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-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={()=> {
setExtstate("not-authenticated")
}}
src={Return}
/>
</Box>
<Spacer height="15px" />
<div className="image-container" style={{
width: '136px',
height: '154px'
}}>
<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>
<ErrorText>
2024-04-14 21:14:13 +03:00
{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-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-04-14 21:14:13 +03:00
</AppContainer>
2024-04-14 14:57:30 +03:00
);
}
export default App;