const ProgressBar = VM.require("mike.near/widget/ProgressBar"); console.log('props', props); const yoctoZeroes = "000000000000000000000000"; const [stakingAmount, setStakingAmount] = useState("6"); const [unstakingWithdrawlAmount, setUnstakingWithdrawlAmount] = useState("19"); const StakeUnstakeWithdraw = ({ validator, method, amount }) => { const openAnotherModal = ({validator, method, amount}) => { // Let's explicitly have these in a switch so no one tries any funny business with methods switch (method) { case 'stake': Near.call(validator, "deposit_and_stake", { amount: `${stakingAmount}${yoctoZeroes}` }, null, amount); break; case 'unstake': Near.call(validator, "unstake", { amount: unstakingWithdrawlAmount + yoctoZeroes }); break; case 'withdraw': Near.call(validator, "withdraw", { amount: unstakingWithdrawlAmount + yoctoZeroes }); break; } }; const handleCancel = () => { // eventually add fade-out effect setShowStakingModal(false); }; const handleUnstake = (amount) => { console.log("Unstaking…", amount); openAnotherModal({validator, method, amount}); }; const handleStake = (amount) => { console.log("Staking…", amount); openAnotherModal({validator, method, amount}); }; const handleWithdraw = () => { console.log("Withdrawing…", unstakingWithdrawlAmount); openAnotherModal({validator, method, amount: unstakingWithdrawlAmount}); }; const containerStyle = { boxShadow: "0 3px 6px rgba(0, 0, 0, 0.6)", border: "3px solid #f2f1e9", backgroundColor: "rgba(0, 0, 0, .7)", background: "radial-gradient(circle at center, rgba(255, 255, 255, 0.7), rgba(0, 0, 0, 0.7) 100%), radial-gradient(circle at 10% 90%, rgba(200, 200, 255, 0.8), transparent 60%),radial-gradient(circle at 50% 50%, rgba(151, 151, 255, 0.7), transparent 50%)", padding: "20px", width: "100%", margin: "0 auto", borderRadius: "13px", overflow: "auto", display: "flex", flexDirection: "column", transition: "opacity 0.3s ease-out", }; const titleStyle = { textAlign: "center", color: "#f2f1e9", fontWeight: "bold", marginBottom: "6px", textShadow: ` -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000`, letterSpacing: "1px", }; return (

{method} NEAR

{method == "stake" ? ( setStakingAmount(e.target.value)} style={{ padding: "13px", width: "80%", margin: "13px auto", display: "block", }} /> ) : ( setUnstakingWithdrawlAmount(e.target.value)} style={{ padding: "13px", width: "80%", margin: "13px auto", display: "block", }} /> )}
); }; // Interesting, this seems to need to be above the StakeUnstakeWithdrawModal declaration const walletUnstake = ({ validator, amount }) => { setStakingModalData({ validator, method: "unstake", amount }); setShowStakingModal(true); }; const walletWithdraw = ({ validator, amount }) => { console.log('aloha walletWithdraw amount', amount); setStakingModalData({ validator, method: "withdraw" }); setShowStakingModal(true); }; const walletStake = ({ validator, amount }) => { console.log('aloha stake validator', validator) setStakingModalData({ validator, method: "stake", amount }); setShowStakingModal(true); }; // State initialization const [progressVal, setProgressVal] = useState(0); const [progressMax, setProgressMax] = useState(1_000); const [started, setStarted] = useState(false); const [showProgressBar, setShowProgressBar] = useState(true); const [validatorStakingDetails, setValidatorStakingDetails] = useState([]); const [isLoading, setIsLoading] = useState(true); const [showStakingModal, setShowStakingModal] = useState(false); const [stakingModalData, setStakingModalData] = useState(false); const YOCTO_DIGITS = 24; // being modified from near-js utils function cleanupAmount(amt) { // Remove commas by splitting on them and joining the parts back together return amt.split(",").join("").trim(); } function trimLeadingZeroes(str) { // Find the first non-zero character let firstNonZeroIndex = 0; while (firstNonZeroIndex < str.length && str[firstNonZeroIndex] === "0") { firstNonZeroIndex++; } // Return the substring from the first non-zero character or '0' if all characters were zeroes return firstNonZeroIndex === str.length ? "0" : str.substring(firstNonZeroIndex); } function parseNearAmount(amt) { if (!amt) { return null; } amt = cleanupAmount(amt); const split = amt.split("."); const wholePart = split[0]; const fracPart = split[1] || ""; // Check for valid format if (split.length > 2 || fracPart.length > YOCTO_DIGITS) { throw new Error(`Cannot parse '${amt}' as NEAR amount`); } // Combine the whole part and the fractional part padded to NEAR_NOMINATION_EXP length return trimLeadingZeroes(wholePart + fracPart.padEnd(YOCTO_DIGITS, "0")); } // end modified from near-js utils // this is a strange function that'll help with removing the modal nicely // seems to be somewhat a BOS-related piquant feature useEffect(async () => { if (progressVal >= progressMax) { const timer = setTimeout(() => setIsLoading(false), 300); return () => clearTimeout(timer); } }, [progressVal, progressMax]); const LoadingModal = () => { // This helps with the flash of red if it hasn't loaded yet if (!!!ProgressBar) { return <>; } else { if (!!!context.accountId) { console.log("(BOS variable) context.accountId not ready"); return; } return (
); } }; // debug by commenting this badboy out to see it const stakingModalDisplayStyles = { display: showStakingModal ? "flex" : "none", opacity: showStakingModal ? 1 : 0, }; const StakeUnstakeWithdrawModal = () => { if (!StakeUnstakeWithdraw) { return <>; } else { const handleOutsideClick = (e) => { setShowStakingModal(false); }; const outerDivStyle = { position: "fixed", top: "6%", left: 0, width: "100%", backgroundImage: "radial-gradient(ellipse, rgba(0, 0, 0, 0.3) 66%, transparent 80%)", display: "flex", justifyContent: "center", zIndex: 998, cursor: "pointer", ...stakingModalDisplayStyles, }; const innerDivStyle = { cursor: "auto", position: "relative", width: "37%", height: "auto", overflowY: "hidden", padding: "1%", background: "radial-gradient(ellipse, rgba(151, 151, 255, .8) 19%, rgba(0, 0, 0, 0.8) 100%)", borderRadius: "13px", boxShadow: "0 0 15px rgba(255, 255, 255, 0.6), 0 0 20px rgba(255, 255, 255, 0.4), 0 0 25px rgba(255, 255, 255, 0.3), 0 0 30px rgba(255, 255, 255, 0.2), 0 0 35px rgba(255, 255, 255, 0.1), 0 0 40px rgba(255, 255, 255, 0.05)", display: "flex", flexDirection: "column", justifyContent: "center", }; return (
e.stopPropagation()}>
); } }; // begin styles const formContainerStyle = { background: "radial-gradient(circle at top left, rgba(0, 0, 0, 0.6) 30%, rgba(0, 0, 0, 0.2) 70%)", filter: "drop-shadow(3px 3px 3px rgba(255, 255, 255, 0.6))", backdropFilter: "contrast(0.1)", padding: "20px", margin: "20px auto", color: "#fff", borderRadius: "6px", boxShadow: "0 0 1px 0 #f2f1e9", }; const leftSideStyle = { display: "flex", flexDirection: "column", gap: "10px", flex: "1 1 auto", }; const formStyle = { display: "flex", alignItems: "flex-end", justifyContent: "space-between", gap: "20px", }; const rightSideStyle = { background: "#111", borderRadius: "6px", color: "#f2f1e9", border: "none", padding: "20px 20px 20px 20px", display: "flex", flexDirection: "row", justifyContent: "space-between", gap: "10px", flex: "1 1 600px", minHeight: "fit-content", marginLeft: "20px", }; const rightBoxStyle = { flex: "1", display: "flex", flexDirection: "column", justifyContent: "center", alignItems: "center", padding: "20px", borderRadius: "6px", background: "rgba(255, 255, 255, 0.1)", border: "1px solid rgba(255, 255, 255, 0.2)", }; const fieldStyle = { background: "rgba(255, 255, 255, 0.1)", border: "1px solid #f2f1e9", borderRadius: "4px", color: "#fff", padding: "10px 15px", }; const buttonStyle = { background: "linear-gradient(to right, #9797ff 6%, rgba(151, 151, 255, 0.6) 100%)", color: "#fff", border: "none", borderRadius: "4px", padding: "10px 20px", cursor: "pointer", }; // end styles return ( <> {!context.accountId && (

Please login →

)}
{/* todo: check for modals and stuff */}

Chain Signatures

Bitcoin

Balance

{/* Right side content, the second box */}

Right side content

Ethereum

Balance

Right side content

Dogecoin

Balance

Right side content

Celestia

Balance

Right side content

);