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

Elliptic analysis #14

Open
wants to merge 7 commits into
base: develop
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
1 change: 1 addition & 0 deletions .env-example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_SDAI_API_URL=http://127.0.0.1:5000
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ dist-ssr
*.njsproj
*.sln
*.sw?

.env
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"ethers": "^6.7.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-toastify": "^10.0.4",
"viem": "^1.14.0",
"wagmi": "^1.4.2"
},
Expand Down
23 changes: 23 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 62 additions & 2 deletions src/components/ActionButton/ActionButton.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import React, { useEffect } from "react";
import { TransactionReceipt } from "viem";
import { useWaitForTransaction } from "wagmi";
import { WriteContractResult } from "wagmi/actions";
import { disconnect, WriteContractResult } from "wagmi/actions";
import { toast } from 'react-toastify';
import { SDAI_API_URL } from "../../constants";
import { useLoadingStore } from "../../stores/loading";

interface IActionButtonProps {
method: string;
mutationData?: WriteContractResult;
mutationTrigger?: () => void;
isDenied: boolean;
addressToAnalyze?: `0x${string}` | null

// TODO: Import this type? Define it dynamically somehow?
onSettled?: (
Expand All @@ -23,7 +27,11 @@ const ActionButton: React.FC<IActionButtonProps> = ({
mutationData,
onSettled,
isDenied,
addressToAnalyze
}) => {

const { set: setLoading } = useLoadingStore()

if (!isDenied) {
const { data, error } = useWaitForTransaction({
confirmations: 1,
Expand All @@ -35,11 +43,63 @@ const ActionButton: React.FC<IActionButtonProps> = ({
);
}

const handleClick = async () => {
setLoading(true);

if (isDenied) {
toast.error('Action failed');
console.error('Action failed, is denied');
setLoading(false);
return;
}

if (addressToAnalyze) {
const blockAddress = async () => {
toast.error(
'AML verification has not been successfully completed, you will be redirected to another page',
{
onClose: async () => {
await disconnect();
setLoading(false);
window.location.href = '/block/index.html'
}
})
}

try {
const res = await fetch(`${SDAI_API_URL}/analyze-address`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ address: addressToAnalyze })
});

if (res.status !== 200) {
throw new Error();
}

const { isAllowed } = await res.json();
if (!isAllowed) {
blockAddress();
return;
}
} catch (error) {
setLoading(false);
toast.error("Couldn't run AML control");
return;
}
}

mutationTrigger?.();
setLoading(false);
}

return (
// <div className="full-width">
<button
className="border rounded-md w-full bg-[#FFC549] hover:border-[#FFC549] active:opacity-90 p-4 my-1 text-[#1C352A] text-center font-semibold text-xl "
onClick={() => { isDenied ? console.error('Action failed') : mutationTrigger?.()}}
onClick={handleClick}
>
{method}
</button>
Expand Down
7 changes: 5 additions & 2 deletions src/components/Form/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import AddToken from "../../components/AddToken/AddToken";
import TransactionOverview from "../../components/TransactionOverview/TransactionOverview";
import ContractsOverview from "../../components/ContractsOverview/ContractsOverview";
import { usePrepareContractWrite, useContractWrite, erc20ABI, erc4626ABI } from "wagmi";
import { toast } from 'react-toastify';

import { MAX_UINT256 } from "../../constants";

Expand Down Expand Up @@ -201,7 +202,8 @@ const Form: React.FC = () => {
) => {
// TODO: Handle this in the UI
if (error) {
throw error;
// throw error;
toast.error(error.message);
}

if (handled[hash] || !data) {
Expand Down Expand Up @@ -231,7 +233,7 @@ const Form: React.FC = () => {
`page-component__main__action-modal-display__item${deposit === isDeposit ? "__action" : ""}`;

return (
<div className="m-auto flex flex-col content-center py-10 gap-10 sm:flex-row">
<div className="m-auto flex flex-col content-center my-10 gap-10 sm:flex-row">
<div className="flex flex-col gap-5 rounded-lg w-full sm:w-3/5">
<div className="page-component__main__action-modal-display">
<div className={actionModalDisplay(true)} onClick={() => setIsDeposit(true)}>
Expand Down Expand Up @@ -281,6 +283,7 @@ const Form: React.FC = () => {
mutationData={method.data}
onSettled={onSettled}
isDenied={account.isDenied}
addressToAnalyze={action.action === Actions.DepositXDAI || action.action === Actions.DepositWXDAI ? address : null}
/>
</div>

Expand Down
26 changes: 26 additions & 0 deletions src/components/Loading/Loading.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.loading-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(240, 235, 222, 0.7);
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}

.loading-spinner {
border: 6px solid #dd7143;
border-top: 6px solid transparent;
border-radius: 50%;
width: 70px;
height: 70px;
animation: spin 1s linear infinite;
}

@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
10 changes: 10 additions & 0 deletions src/components/Loading/Loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import './Loading.css';

const Loading: React.FC = () => (
<div className="loading-overlay">
<div className="loading-spinner"></div>
</div>
);

export default Loading;
2 changes: 1 addition & 1 deletion src/components/Main/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const Main: React.FC = () => {

return (
<div className="bg-transparent m-auto w-full h-fit p-4 sm:p-1 sm:w-4/5 md:w-3/4 xl:w-1/2 sm:max-w-4xl">
<div className="flex flex-col items-center justify-center mx-auto mt-0 sm:-mt-24 w-full gap-1 sm:flex-wrap-reverse sm:flex-row sm:gap-5 md:flex-nowrap 2xl:gap-10 ">
<div className="flex flex-col items-center justify-center mx-auto w-full gap-1 sm:flex-wrap-reverse sm:flex-row sm:gap-5 md:flex-nowrap 2xl:gap-10 my-10">
<Card title="MY SHARES" value={sharesBalance.value ?? BigInt(0)} currency="sDAI" />
<Card title="VALUE" value={sharesValue} currency="xDAI" smallDecimals={3} />
<Card title="VAULT APY" value={apy ? apy * 100n : 0n} currency="%" />
Expand Down
2 changes: 2 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,5 @@ export const MAX_UINT256 = 0xfffffffffffffffffffffffffffffffffffffffffffffffffff
export const WEI_PER_ETHER = 1000000000000000000n;

export const paragraph_aboutSDai = `All DAI bridged to Gnosis earn interest at MakerDAO. This interest is given to sDAI holder. You can use sDAI in Gnosis Defi like you would use DAI.`;

export const SDAI_API_URL: string = import.meta.env.VITE_SDAI_API_URL ?? 'https://sdai-api.dev.gnosisdev.com/api/v1/'
14 changes: 12 additions & 2 deletions src/pages/Home/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useEffect } from "react";
import { Web3NetworkSwitch, Web3Button, useWeb3Modal } from "@web3modal/react";
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

// Stores
import { useAccountStore, useIsAccountStoreLoaded } from "../../stores/account";
Expand All @@ -8,6 +10,7 @@ import { useIsVaultStoreLoaded, useVaultStore } from "../../stores/vault";

// Components
import Main from "../../components/Main/Main";
import Loading from "../../components/Loading/Loading";

// CSS
import "./Home.css";
Expand All @@ -21,6 +24,7 @@ import refresh from "../../assets/refresh.svg";

// Constants
import { paragraph_aboutSDai } from "../../constants";
import { useLoadingStore } from "../../stores/loading";

export const Home = () => {
// Modal close
Expand All @@ -32,6 +36,8 @@ export const Home = () => {
const vaultStoreLoaded = useIsVaultStoreLoaded();
const loaded = accountStoreLoaded && chainStoreLoaded && vaultStoreLoaded;

const { loading } = useLoadingStore();

useEffect(() => {
useAccountStore.getState().watch();
useChainStore.getState().watch();
Expand All @@ -45,6 +51,8 @@ export const Home = () => {
}
});

console.log("loading", loading)

return (
<div className="page-home">
<header className="header flex shrink-0 content-between items-center mt-6 z-10 mx-auto w-full w-full h-fit sm:p-1 sm:w-4/5 md:w-3/4 xl:w-1/2 sm:max-w-4xl">
Expand All @@ -68,14 +76,15 @@ export const Home = () => {
</div>
</header>
<main className="w-full h-full mx-auto">
<div className="rounded-t-3xl mt-0 h-full sm:pt-10 sm:mt-24">
<div className="rounded-t-3xl mt-0 h-full relative">
{loaded ? (
<Main />
) : (
<div className="page-component__prewallet h-36 py-36 text-[#45433C] text-2xl">
<div className="page-component__prewallet h-56 text-[#45433C] text-2xl flex flex-col justify-center sm:mb-10">
<h1>Connect your Wallet to Gnosis</h1>
</div>
)}
{loading && <Loading />}
</div>
<div className="footer w-full bg-[#F2EEE3] h-fit text-base">
<div className="m-auto flex flex-col w-full p-5 sm:p-0 sm:w-4/5 md:w-3/4 xl:w-1/2 sm:max-w-4xl gap-12 sm:flex-row">
Expand Down Expand Up @@ -109,6 +118,7 @@ export const Home = () => {
</div>
</div>
</div>
<ToastContainer />
</main>
<footer className="bg-[#133629] text-[#f0ebde] font-karla">
<div className="justify-center pt-6 pb-14 flex box-border">
Expand Down
12 changes: 9 additions & 3 deletions src/stores/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ let currentlyLoading:
| undefined;

export interface AccountStore {
address?: `0x${string}`;
address?: `0x${string}` | undefined;
loading: boolean;
setAddress: (address: `0x${string}`) => Promise<void>;
setAddress: (address: `0x${string}` | undefined) => Promise<void>;
fetch: () => Promise<void>;
watch: () => void;
isDenied: boolean;
Expand Down Expand Up @@ -58,7 +58,7 @@ export const useAccountStore = create<AnyAccountStore>((set, get) => ({
address: undefined,
isDenied: false,
loading: false,
setAddress: async (address: `0x${string}`) => {
setAddress: async (address: `0x${string}` | undefined) => {
set({ address, loading: true });
try {
const response = await fetch(`https://sdai-api.dev.gnosisdev.com/api/v1/denylist/${address}`);
Expand Down Expand Up @@ -136,7 +136,13 @@ export const useAccountStore = create<AnyAccountStore>((set, get) => ({
},
watch: () => {
const unwatchAccount = watchAccount(account => {
// account.address && get().setAddress(account.address);
account.address && get().setAddress(account.address);
if (account.address) {
get().setAddress(account.address);
} else {
get().setAddress(undefined);
}
});

const unwatchChain = useChainStore.subscribe(() => get().fetch());
Expand Down
11 changes: 11 additions & 0 deletions src/stores/loading.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { create } from "zustand";

interface LoadingState {
loading: boolean;
set: (_loading: boolean) => void;
}

export const useLoadingStore = create<LoadingState>()((set) => ({
loading: false,
set: (loading) => set({ loading })
}));