Skip to content

[playground] implemented smart account settings #817

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
export enum ActiveComponent {
RpcUrl = "RpcUrl",
InfoAndBalances = "InfoAndBalances",
Main = "Main",
Topup = "Topup",
SmartAccountSelector = "SmartAccountSelector",
SettingsScreen = "SettingsScreen",
PrivateKeyScreen = "PrivateKeyScreen",
AccountRegenerationScreen = "AccountRegenerationScreen",
RpcUrlScreen = "RpcUrlScreen",
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export const PrivateKeyIcon = () => {
return (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<title>Private key</title>
<path
d="M11.4341 12.1494C12.7053 13.397 13.2069 15.2265 12.7486 16.9434C12.2902 18.6603 10.9422 20.0012 9.21627 20.4571C7.49032 20.913 5.65111 20.414 4.39688 19.1496C2.51104 17.2073 2.53801 14.1199 4.45749 12.2106C6.37698 10.3012 9.48066 10.2744 11.4332 12.1503L11.4341 12.1494Z"
stroke="#F1F1F1"
stroke-linejoin="round"
/>
<path d="M11.5 12L20 3.5" stroke="#F1F1F1" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M15.1523 8.44981L17.8666 11.1498L21.0333 7.99981L18.319 5.2998L15.1523 8.44981Z"
stroke="#F1F1F1"
stroke-linejoin="round"
/>
</svg>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export const ResetAccountIcon = () => {
return (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<title>Reset account</title>
<path
d="M20.0601 8C18.5874 5.03656 15.5293 3 11.9956 3C8.46186 3 5.4727 5.03656 4 8"
stroke="#FD6670"
stroke-linecap="round"
/>
<path d="M4 4V8" stroke="#FD6670" stroke-linecap="round" />
<path d="M7.39014 8L4.00006 8" stroke="#FD6670" stroke-linecap="round" />
<path
d="M4 16C5.4727 18.9634 8.53076 21 12.0645 21C15.5982 21 18.5874 18.9634 20.0601 16"
stroke="#FD6670"
stroke-linecap="round"
/>
<path d="M20.0601 20V16" stroke="#FD6670" stroke-linecap="round" />
<path d="M16.6699 16L20.06 16" stroke="#FD6670" stroke-linecap="round" />
</svg>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export const RpcUrlIcon = () => {
return (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<title>RPC URL</title>
<path
d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"
stroke="#F1F1F1"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path d="M7.5 12H16.5" stroke="#F1F1F1" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M9.75 8.10291L14.25 15.8971"
stroke="#F1F1F1"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M14.25 8.10291L9.75 15.8971"
stroke="#F1F1F1"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const SettingsIcon = () => {
return (
<svg width="16" height="14" viewBox="0 0 16 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<title>Settings</title>
<path
d="M6.09501 13.3904C4.97799 13.0578 3.98368 12.4404 3.19636 11.6223C3.49006 11.2742 3.66707 10.8244 3.66707 10.3333C3.66707 9.22877 2.77164 8.33333 1.66707 8.33333C1.60026 8.33333 1.5342 8.33661 1.46907 8.34301C1.38034 7.9092 1.33374 7.46004 1.33374 7C1.33374 6.30313 1.44066 5.63123 1.639 4.99981C1.64834 4.99994 1.6577 5 1.66707 5C2.77164 5 3.66707 4.10457 3.66707 3C3.66707 2.68291 3.59328 2.38305 3.46193 2.11666C4.23292 1.39979 5.17391 0.863299 6.21776 0.574341C6.54854 1.22269 7.22262 1.66667 8.00041 1.66667C8.77819 1.66667 9.45228 1.22269 9.78306 0.574341C10.8269 0.863299 11.7679 1.39979 12.5389 2.11666C12.4075 2.38305 12.3337 2.68291 12.3337 3C12.3337 4.10457 13.2292 5 14.3337 5C14.3431 5 14.3525 4.99994 14.3618 4.99981C14.5601 5.63123 14.6671 6.30313 14.6671 7C14.6671 7.46004 14.6205 7.9092 14.5317 8.34301C14.4666 8.33661 14.4006 8.33333 14.3337 8.33333C13.2292 8.33333 12.3337 9.22877 12.3337 10.3333C12.3337 10.8244 12.5107 11.2742 12.8045 11.6223C12.0171 12.4404 11.0228 13.0578 9.9058 13.3904C9.64801 12.5839 8.8924 12 8.00041 12C7.10841 12 6.35281 12.5839 6.09501 13.3904Z"
stroke="#A3A3A3"
stroke-linejoin="round"
/>
<path
d="M8.00045 9.33329C9.28911 9.33329 10.3338 8.28862 10.3338 6.99996C10.3338 5.71129 9.28911 4.66663 8.00045 4.66663C6.71178 4.66663 5.66711 5.71129 5.66711 6.99996C5.66711 8.28862 6.71178 9.33329 8.00045 9.33329Z"
stroke="#A3A3A3"
stroke-linejoin="round"
/>
</svg>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,30 @@ import { expandProperty } from "inline-style-expand-shorthand";
import { useSwipeable } from "react-swipeable";
import { ActiveComponent } from "../ActiveComponent";
import { $activeComponent, setActiveComponent } from "../model";
import { AccountRegenerationScreen } from "./AccountRegenerationScreen.tsx";
import { InfoAndBalancesScreen } from "./InfoAndBalancesScreen.tsx";
import { MainScreen } from "./MainScreen";
import { PrivateKeyScreen } from "./PrivateKeyScreen.tsx";
import { RpcUrlScreen } from "./RpcUrlScreen.tsx";
import { SettingsScreen } from "./SettingsScreen.tsx";
import { TopUpPanel } from "./TopUpPanel";

const featureMap = new Map();
featureMap.set(ActiveComponent.RpcUrl, RpcUrlScreen);
featureMap.set(ActiveComponent.InfoAndBalances, InfoAndBalancesScreen);
featureMap.set(ActiveComponent.Main, MainScreen);
featureMap.set(ActiveComponent.Topup, TopUpPanel);
featureMap.set(ActiveComponent.SettingsScreen, SettingsScreen);
featureMap.set(ActiveComponent.PrivateKeyScreen, PrivateKeyScreen);
featureMap.set(ActiveComponent.AccountRegenerationScreen, AccountRegenerationScreen);
featureMap.set(ActiveComponent.RpcUrlScreen, RpcUrlScreen);

const AccountContainer = () => {
const activeComponent = useUnit($activeComponent);
const Component = activeComponent ? featureMap.get(activeComponent) : null;
const [css, theme] = useStyletron();
const handlers = useSwipeable({
onSwipedLeft: () => setActiveComponent(ActiveComponent.RpcUrl),
onSwipedRight: () => setActiveComponent(ActiveComponent.RpcUrl),
onSwipedLeft: () => setActiveComponent(ActiveComponent.InfoAndBalances),
onSwipedRight: () => setActiveComponent(ActiveComponent.InfoAndBalances),
});

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { COLORS, LabelLarge, LabelSmall } from "@nilfoundation/ui-kit";
import { useStyletron } from "baseui";
import { useUnit } from "effector-react";
import lottie from "lottie-web/build/player/lottie_light";
import { useEffect, useRef, useState } from "react";
import { ActiveComponent } from "../ActiveComponent";
import animationData from "../assets/wallet-creation.json";
import {
$initializingSmartAccountError,
$initializingSmartAccountState,
createSmartAccountFx,
setActiveComponent,
} from "../model";
import { BackLink } from "./BackLink";

export const AccountRegenerationScreen = () => {
const [css, theme] = useStyletron();
const [error, setError] = useState("");
const [isDisabled, setIsDisabled] = useState(false);

const animationContainerRef = useRef<HTMLDivElement | null>(null);

const [
initializingSmartAccountState,
initializingSmartAccountError,
isPendingSmartAccountCreation,
] = useUnit([
$initializingSmartAccountState,
$initializingSmartAccountError,
createSmartAccountFx.pending,
]);

// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
useEffect(() => {
if (animationContainerRef.current) {
const animationInstance = lottie.loadAnimation({
container: animationContainerRef.current as Element,
renderer: "svg",
loop: true,
autoplay: true,
animationData,
});

return () => animationInstance.destroy();
}
}, [isPendingSmartAccountCreation]);

useEffect(() => {
if (initializingSmartAccountError) {
setIsDisabled(false);
setError(initializingSmartAccountError);
}
}, [initializingSmartAccountError]);

return (
<div
className={css({
display: "flex",
flexDirection: "column",
minHeight: "400px", // Or use 100vh to cover the entire viewport height
})}
>
{/* Optional fixed header */}
{!isPendingSmartAccountCreation && (
<div>
<BackLink
title="Regenerate smart account"
goBackCb={() => {
setActiveComponent(ActiveComponent.SettingsScreen);
}}
/>
</div>
)}

{/* Main Content Container */}
<div
className={css({
flex: 1,
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
textAlign: "center",
gap: "16px",
padding: "0 16px",
})}
>
{isPendingSmartAccountCreation ? (
<>
<div ref={animationContainerRef} style={{ width: 124, height: 124 }} />
<LabelLarge style={{ color: COLORS.gray200 }}>
{initializingSmartAccountState}
</LabelLarge>
<LabelSmall style={{ color: COLORS.red400 }}>{error}</LabelSmall>
</>
) : (
<>
<LabelSmall style={{ color: COLORS.green400 }}>
A new smart account has been created!
</LabelSmall>
<LabelSmall style={{ color: COLORS.red400 }}>{error}</LabelSmall>
</>
)}
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { BUTTON_KIND, ButtonIcon } from "@nilfoundation/ui-kit";
import { useStyletron } from "baseui";
import { ActiveComponent } from "../ActiveComponent";
import { SettingsIcon } from "../assets/SettingsIcon";
import { setActiveComponent } from "../model";

export const AccountSettingsButton = () => {
const [css, theme] = useStyletron();

return (
<ButtonIcon
className={css({
width: "32px",
height: "32px",
flexShrink: 0,
backgroundColor: `${theme.colors.accountSettingsButtonBackgroundColor} !important`,
":hover": {
backgroundColor: `${theme.colors.accountSettingsButtonBackgroundHoverColor} !important`,
},
})}
icon={<SettingsIcon />}
kind={BUTTON_KIND.secondary}
onClick={() => setActiveComponent(ActiveComponent.SettingsScreen)}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {
COLORS,
LabelMedium,
} from "@nilfoundation/ui-kit";
import { useStyletron } from "baseui";
import type { FC } from "react";
import { useStyletron } from "styletron-react";

type BackLinkProps = {
title: string;
Expand All @@ -16,7 +16,7 @@ type BackLinkProps = {
};

const BackLink: FC<BackLinkProps> = ({ title, goBackCb, disabled }) => {
const [css] = useStyletron();
const [css, theme] = useStyletron();

return (
<div
Expand All @@ -38,6 +38,10 @@ const BackLink: FC<BackLinkProps> = ({ title, goBackCb, disabled }) => {
style: {
paddingLeft: 0,
paddingRight: 0,
backgroundColor: theme.colors.backLinkBackgroundColor,
":hover": {
backgroundColor: theme.colors.backLinkBackgroundHoverColor,
},
},
},
}}
Expand Down
Loading