Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tips modal and text copies #31

Merged
merged 3 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/nextjs/components/CustomPortal/CustomPortal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface IProps {
title: string;
image?: string;
video?: string;
children?: JSX.Element;
close?: () => void;
description: string;
button?: {
Expand All @@ -19,7 +20,7 @@ interface IProps {
};
indicator?: number;
}
export const CustomPortal = ({ indicator, title, image, video, description, button, close }: IProps) => {
export const CustomPortal = ({ indicator, title, image, children, video, description, button, close }: IProps) => {
const [mounted, setMounted] = useState(false);

useEffect(() => {
Expand Down Expand Up @@ -54,6 +55,7 @@ export const CustomPortal = ({ indicator, title, image, video, description, butt

{!!video ? <Image className={`${styles.image}`} src={video} alt={""} /> : <></>}
<p className={`${styles.text} text-secondary-content`}>{description}</p>
{!!children ? children : <></>}
{!!button ? (
<CustomButton
type="btn-primary"
Expand Down
3 changes: 2 additions & 1 deletion packages/nextjs/components/MetaHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ type MetaHeaderProps = {
const baseUrl = process.env.NEXT_PUBLIC_VERCEL_URL ? `https://${process.env.NEXT_PUBLIC_VERCEL_URL}/` : "/";

export const MetaHeader = ({
//TODO Modify after find an app name
title = "Flashbot Bundler for Recoveries",
description = "Built with 🏗 Scaffold-ETH 2",
description = "I've successfully recovered my hacked assets using this powerful tool. #AssetRecovery",
image = "thumbnail.jpg",
twitterCard = "summary_large_image",
children,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,28 @@ export const SideBarSteps = ({ activeStep }: ISideBar) => {
<SideBarStepInfo
index={BundlingSteps.HACKED_ADDRESS_INPUT}
activeStep={activeStep}
title={"Enter the hacked address"}
title={"Provide the Hacked Address"}
description={"Provide the address that was hacked so we can search for your assets."}
/>
<SideBarStepInfo
index={BundlingSteps.ASSET_SELECTION}
activeStep={activeStep}
title={"Select your assets"}
title={"Choose your assets"}
description={
"Your assets will be listed, select the ones you want to transfer or add manually if you miss someone"
"Choose the assets you wish to transfer from the list, or manually add any missing ones."
}
/>
<SideBarStepInfo
index={BundlingSteps.TX_BUNDLE}
activeStep={activeStep}
title={"Confirm the bundle"}
description={"Review the transactions that are going to be generated to recover your assets"}
title={"Review the transactions"}
description={"Take a moment to review the transactions being generated for asset recovery."}
/>
<SideBarStepInfo
index={BundlingSteps.SIGN_RECOVERY_TXS}
activeStep={activeStep}
title={"Recover your assets"}
description={"Follow the steps to retrieve your assets, this is a critical process, so please be patient."}
description={"Follow the steps to retrieve your assets, this is a critical process so please be patient."}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ export const ConnectionProcess = ({ isVisible, safeAddress, connectedAddress, se
exit={{ opacity: 0 }}
className={styles.container}
>
<h1 className={styles.title}>Welcome to Flashbot Recovery</h1>
<Image className={styles.illustration} src={IllustrationSvg} alt="" />
<p className={`${styles.text} text-secondary-content`}>
Connect your "Safe Wallet" where the assets will be send after the recovery process.
</p>
<h1 className={styles.title}>Let's recover your hacked assets</h1>
<Image className={styles.illustration} src={IllustrationSvg} alt="An ethereum icon with nfts and tokens around" />
<h2 className={`${styles.text} text-secondary-content`}>
Follow the steps and reclaim your assets with a "Secure Wallet" under your control. Connect the wallet to begin the process.
</h2>
<div className={styles.buttonContainer}>
<RainbowKitCustomConnectButton />
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import React from "react";
import React, { useState } from "react";
import Image from "next/image";
import styles from "./recoveryProcess.module.css";
import { CustomPortal } from "~~/components/CustomPortal/CustomPortal";
import { InputBase } from "~~/components/scaffold-eth";
import { useShowError } from "~~/hooks/flashbotRecoveryBundle/useShowError";
import ClockSvg from "~~/public/assets/flashbotRecovery/clock.svg";
import LogoSvg from "~~/public/assets/flashbotRecovery/logo.svg";
import SuccessSvg from "~~/public/assets/flashbotRecovery/success.svg";
import TelegramSvg from "~~/public/assets/flashbotRecovery/telegram.svg";
import TipsSvg from "~~/public/assets/flashbotRecovery/tips.svg";
import TwitterSvg from "~~/public/assets/flashbotRecovery/twitter.svg";
import VideoSvg from "~~/public/assets/flashbotRecovery/video.svg";
import { RecoveryProcessStatus } from "~~/types/enums";

interface IProps {
recoveryStatus: RecoveryProcessStatus;
startSigning: () => void;
finishProcess: () => void;
showTipsModal: () => void;
startProcess: () => void;
connectedAddress: string | undefined;
safeAddress: string;
Expand All @@ -23,19 +30,24 @@ export const RecoveryProcess = ({
startSigning,
startProcess,
finishProcess,
showTipsModal,
blockCountdown,
connectedAddress,
safeAddress,
hackedAddress,
}: IProps) => {
const {showError} = useShowError();
const { showError } = useShowError();
const [donationValue, setDonationValue] = useState<string>("");

if (recoveryStatus == RecoveryProcessStatus.INITIAL) {
return <></>;
}

if (recoveryStatus == RecoveryProcessStatus.GAS_PAID) {
showError("you already covered the gas. If you're in a confussy situation, clear cookies and refresh page.");
showError(
"It appears that gas costs have been covered for this action. If you're encountering any confusion, consider clearing your cookies and refreshing the page.",
);
//TODO provide clear data mechanism title "Gas Covered Already"
return;
}

Expand All @@ -44,10 +56,11 @@ export const RecoveryProcess = ({
<CustomPortal
title={"Clear cache"}
description={
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti."
"We've encountered an issue due to outdated cached data. Please clear your app's cache to resolve this error."
}
image={VideoSvg}
/>
//TODO provide clear data mechanism
);
}

Expand All @@ -56,7 +69,7 @@ export const RecoveryProcess = ({
<CustomPortal
title={"Switch to safe address"}
description={
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti."
"To ensure a secure asset transfer, switch to your safe wallet. This step guarantees the safe retrieval of your assets without any further risks."
}
button={{
text: "Continue",
Expand All @@ -72,7 +85,7 @@ export const RecoveryProcess = ({
return (
<CustomPortal
title={"Switching Network"}
description={"Switch to personal Flashbot RPC network to prepare the transacion you will pay"}
description={"Allow us to create and switch to your personal RPC network to prepare the transaction bundle"}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user doesn't need to know that we are creating the personal RPC and they don't need to know about bundles. Maybe we could simplify this while also giving them some safety assurance by linking to flashbots.

Proposed wording: "Now you are being switched to a new Flashbots(link to https://www.flashbots.net/) RPC. This will enable you to send transactions that are undetected by the hacker until after your assets have been recovered. Please approve the network change in your wallet after you read over the RPC details and feel safe moving forward."

It's a little wordy but I feel like it explains just enough to help the user know what is happening and also buys some clout by linking to a reputable site. Users will probably be on high alert after just being hacked so we want to ease their fears as much as possible.

image={VideoSvg}
/>
);
Expand All @@ -82,7 +95,9 @@ export const RecoveryProcess = ({
return (
<CustomPortal
title={"Increase the gas"}
description={"Switch to personal Flashbot RPC network to prepare the transacion you will pay"}
description={
"We recommend set a hight gas to ensure a successful asset recovery. Your increased gas allocation will facilitate the seamless completion of the transaction."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"We recommend to use a custom gas price to ensure successful asset recovery."

}
image={VideoSvg}
/>
);
Expand All @@ -91,9 +106,9 @@ export const RecoveryProcess = ({
if (recoveryStatus == RecoveryProcessStatus.SWITCH_TO_HACKED_ACCOUNT) {
return (
<CustomPortal
title={"Switch to hacked address"}
title={"Switch to Hacked Address"}
description={
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti."
"To proceed with asset recovery, switch to the compromised address in your wallet. This step is essential to verify ownership and continue with the recovery process."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"To proceed with asset recovery, switch to the compromised wallet. This step is essential to verify ownership and continue with the recovery process."

}
button={{
text: "Continue",
Expand All @@ -114,7 +129,7 @@ export const RecoveryProcess = ({
<CustomPortal
title={"Sign each transaction"}
description={
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti."
"Each bundled transaction requires your individual signature to verify and complete the asset recovery process. Please sign each transaction as they appear."
}
image={LogoSvg}
/>
Expand All @@ -124,9 +139,9 @@ export const RecoveryProcess = ({
if (recoveryStatus == RecoveryProcessStatus.LISTEN_BUNDLE) {
return (
<CustomPortal
title={"Wait without refreshing the page"}
title={"Stay Patient, Stay Secure"}
description={
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio matt"
"Your asset recovery is in progress. To ensure a successful retrieval and accurate transaction completion stay on the page."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove "and accurate transaction completion".

}
image={ClockSvg}
indicator={blockCountdown}
Expand All @@ -139,15 +154,57 @@ export const RecoveryProcess = ({
<CustomPortal
title={"Your assets have been recovered!"}
description={
"If we have helped you please, share the tool and if you want let us a tip to continue contributing"
"Check your safe wallet for your retrieved assets. Share your journey and consider to support us with a tip to continue serving the crypto community."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Check your safe wallet for your retrieved assets. If you were helped by this tool, please consider sharing this on social media and if you are feeling generous, consider giving us a small tip so we can continue providing helpful tools to the crypto community."

}
button={{
text: "Continue",
disabled: connectedAddress !== hackedAddress,
action: () => finishProcess(),
text: "Finish",
disabled: false,
action: () => showTipsModal(),
}}
image={SuccessSvg}
/>
>
<div className={styles.shareButtons}>
<a
href="https://twitter.com/intent/tweet?url=https://yourwebsite.com&text=I%20have%20been%20helped%20to%20recover%20my%20assets%20with%20this%20amazing%20tool"
target="_blank"
rel="noopener noreferrer"
>
<Image width={40} src={TwitterSvg} alt={""} />
</a>
<a
href="https://t.me/share/url?url=https://yourwebsite.com&text=I%20have%20been%20helped%20to%20recover%20my%20assets%20with%20this%20amazing%20tool"
target="_blank"
rel="noopener noreferrer"
>
<Image width={40} src={TelegramSvg} alt={""} />
</a>
</div>
</CustomPortal>
);
}
if (recoveryStatus !== RecoveryProcessStatus.DONATE) {
return (
<CustomPortal
title={"Support Our Mission"}
description={
"Your contribution can significantly impact our mission to provide safe and free tools that empower the community."
}
button={{
text: "Finish",
disabled: false,
action: () => finishProcess(),
}}
image={TipsSvg}
>
<div className={styles.inputContainer}>
<label className={styles.label} htmlFor="tip">
Tip
</label>
<div className="mt-2" />
<InputBase name="tip" placeholder="0.0" value={donationValue} onChange={setDonationValue} />
<span className={`${styles.eth} text-base-100`}>ETH</span>
</div>
</CustomPortal>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.shareButtons {
display: flex;
justify-content: space-between;
align-items: center;
}
.shareButtons a {
margin: 0 10px;
}
.inputContainer{
width: 80%;
position: relative;
}
.inputContainer > div {
border-radius: 4px;
padding: 4px;
}

.inputContainer label {
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: normal;
margin-bottom: 12px;
}
.eth{
position: absolute;
bottom: 12px;
right: 14px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,10 @@ export const useRecoveryProcess = () => {
}
};

const showTipsModal = () => {
setStepActive(RecoveryProcessStatus.DONATE)
}

return {
data: stepActive,
sentBlock,
Expand All @@ -268,5 +272,6 @@ export const useRecoveryProcess = () => {
startRecoveryProcess,
signRecoveryTransactions,
resetStatus,
showTipsModal
};
};
45 changes: 4 additions & 41 deletions packages/nextjs/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const Home: NextPage = () => {
const [currentBundleId, setCurrentBundleId] = useLocalStorage<string>("bundleUuid", "");
const { error, resetError } = useShowError();

const { data: processStatus, startRecoveryProcess, signRecoveryTransactions, blockCountdown } = useRecoveryProcess();
const { data: processStatus, startRecoveryProcess, signRecoveryTransactions, blockCountdown, showTipsModal } = useRecoveryProcess();

const startSigning = () => {
signRecoveryTransactions(hackedAddress, unsignedTxs, currentBundleId, false);
Expand Down Expand Up @@ -56,6 +56,8 @@ const Home: NextPage = () => {
}
return BundlingSteps.HACKED_ADDRESS_INPUT;
};


const reload = () => {
localStorage.clear();
window.location.reload();
Expand Down Expand Up @@ -101,6 +103,7 @@ const Home: NextPage = () => {
recoveryStatus={processStatus}
finishProcess={reload}
startSigning={startSigning}
showTipsModal={showTipsModal}
startProcess={startRecovery}
blockCountdown={blockCountdown}
connectedAddress={connectedAddress}
Expand All @@ -118,46 +121,6 @@ const Home: NextPage = () => {
) : (
<></>
)}

{/* <CustomPortal
title={"Switch to hacked adress"}
description={
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti."
}
image={LogoSvg}
/> */}
{/* <CustomPortal
title={"Rise your gas"}
description={
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti."
}
image={VideoSvg}
/> */}
{/* <CustomPortal
title={"Wait without refreshing the page"}
description={
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti."
}
image={LogoSvg}
/> */}
{/* <CustomPortal
title={"Success"}
description={
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti."
}
image={VideoSvg}
/> */}
{/* <CustomPortal
title={"Error"}
description={
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti."
}
image={VideoSvg}
button={{
action:() => ({}),
text:"Retry"
}}
/> */}
</div>
</>
);
Expand Down
Loading