Skip to content
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
156 changes: 78 additions & 78 deletions src/components/auth-sign-in/auth-link.tsx
Original file line number Diff line number Diff line change
@@ -1,78 +1,78 @@
import { Link } from '@mui/material'
import { useState, useEffect } from 'react'
import useWallet from '@/hooks/wallets/useWallet'
import { createWeb3 } from '@/hooks/wallets/web3'
import { authenticateWallet } from './helpers'
import { setCookie } from 'typescript-cookie';

export const SignInLink: React.FC<{
setAuth: any
}> = ({ setAuth }) => {
const [loading, setLoading] = useState<boolean>(false)
const [nonce, setNonce] = useState<string>('')

const wallet = useWallet()

useEffect(() => {
const handleNonce = async() => {
await handleGetNonce()
}
if (wallet?.address) {
handleNonce()
}
}, [wallet?.address])

const handleGetNonce = async () => {
try {
const address = wallet?.address
const response = await fetch('/api/nonce', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ address }),
});

if (!response.ok) {
throw new Error('Failed to get nonce.');
}

const data = await response.json();
console.log(data, 'data')
setNonce(data.nonce);
} catch (error: any) {
console.error('Error fetching nonce:', error.message);
}
};

const handleAuthenticate = async () => {
if (!wallet) return
const address = wallet?.address
const provider = createWeb3(wallet?.provider)
const token = await authenticateWallet(provider, nonce)

const loginResponse = await fetch('/api/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ address, token, nonce }),
});

const data = await loginResponse.json();
setCookie(address, data.token, { path: '/' });
if (token.length) {
setAuth(true)
setLoading(false)
}
}

return (
<>
{ nonce ? <Link sx={{ cursor: 'pointer' }} onClick={handleAuthenticate}>Verify here</Link> : 'loading...' }
</>

)
}

export default SignInLink
import { Link } from '@mui/material'
import { useState, useEffect } from 'react'
import useWallet from '@/hooks/wallets/useWallet'
import { createWeb3 } from '@/hooks/wallets/web3'
import { authenticateWallet } from './helpers'
import { setCookie } from 'typescript-cookie';
export const SignInLink: React.FC<{
setAuth: any
}> = ({ setAuth }) => {
const [loading, setLoading] = useState<boolean>(false)
const [nonce, setNonce] = useState<string>('')
const wallet = useWallet()
useEffect(() => {
const handleNonce = async() => {
await handleGetNonce()
}
if (wallet?.address) {
handleNonce()
}
}, [wallet?.address])
const handleGetNonce = async () => {
try {
const address = wallet?.address
const response = await fetch('/api/nonce', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ address }),
});
if (!response.ok) {
throw new Error('Failed to get nonce.');
}
const data = await response.json();
console.log(data, 'data')
setNonce(data.nonce);
} catch (error: any) {
console.error('Error fetching nonce:', error.message);
}
};
const handleAuthenticate = async () => {
if (!wallet) return
const address = wallet?.address
const provider = createWeb3(wallet?.provider)
const token = await authenticateWallet(provider, nonce)
const loginResponse = await fetch('/api/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ address, token, nonce }),
});
const data = await loginResponse.json();
setCookie(address, data.token, { path: '/' });
if (token.length) {
setAuth(true)
setLoading(false)
}
}
return (
<>
{ nonce ? <Link sx={{ cursor: 'pointer' }} onClick={handleAuthenticate}>Verify here</Link> : 'loading...' }
</>
)
}
export default SignInLink
66 changes: 33 additions & 33 deletions src/components/auth-sign-in/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
import { createToken, verifyToken } from '../../utils/did';
import {
clearToken,
getTokenFromStore,
setTokenInStore,
} from '../../lib/auth';
import type { Web3Provider } from '@ethersproject/providers';

export async function getExistingAuth(
ethersProvider: Web3Provider,
connectedAddress: string,
): Promise<string | null> {
const token = getTokenFromStore();
if (!token) return null;

try {
await verifyToken(token, ethersProvider, connectedAddress);
return token;
} catch (e) {
clearToken();
return null;
}
}

export async function authenticateWallet(
ethersProvider: Web3Provider,
msg: string,
): Promise<string> {
console.log(msg, 'msg')
const token = await createToken(ethersProvider, msg);
console.log('token', token)
setTokenInStore(token);
return token;
import { createToken, verifyToken } from '../../utils/did';
import {
clearToken,
getTokenFromStore,
setTokenInStore,
} from '../../lib/auth';
import type { Web3Provider } from '@ethersproject/providers';
export async function getExistingAuth(
ethersProvider: Web3Provider,
connectedAddress: string,
): Promise<string | null> {
const token = getTokenFromStore();
if (!token) return null;
try {
await verifyToken(token, ethersProvider, connectedAddress);
return token;
} catch (e) {
clearToken();
return null;
}
}
export async function authenticateWallet(
ethersProvider: Web3Provider,
msg: string,
): Promise<string> {
console.log(msg, 'msg')
const token = await createToken(ethersProvider, msg);
console.log('token', token)
setTokenInStore(token);
return token;
}
27 changes: 27 additions & 0 deletions src/components/chat/AppsSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import css from '@/components/chat/styles.module.css'
import { useAppDispatch } from "@/store"
import { openModal } from "@/store/modalServiceSlice"
import { Box, Button, Typography } from "@mui/material"
import { modalTypes } from "./modals"

const AppsSection = () => {
const dispatch = useAppDispatch()
return (
<Box sx={{ p: 3 }}>
<Typography sx={{ fontWeight: 600 }} paragraph>
Apps
</Typography>
<Typography paragraph whiteSpace="pre-line">
Explore the Safe Apps ecosystem &mdash; connect to your favourite web3 applications with your Safe wallet,
securely and efficiently
</Typography>
{/* <Link href={{ pathname: AppRoutes.apps.index, query: { safe: `${safeAddress}` } }} key={`${safe}`} passHref> */}
<Button variant="outlined" className={css.buttonstyled} size="small" onClick={() => dispatch(openModal({ modalName: modalTypes.appsModal, modalProps: '' }))}>
Explore Apps
</Button>
{/* </Link> */}
</Box>
)
}

export default AppsSection
29 changes: 29 additions & 0 deletions src/components/chat/AssetsSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import css from '@/components/chat/styles.module.css';
import { useAppDispatch } from '@/store';
import { openModal } from '@/store/modalServiceSlice';
import { Box, Button, Typography } from "@mui/material";
import { modalTypes } from './modals';

const AssetsSection = () => {
const dispatch = useAppDispatch()
return (
<Box sx={{ p: 3 }}>
<Typography sx={{ fontWeight: 600 }} paragraph>
Assets
</Typography>
<Typography paragraph>View all tokens and NFTs the Safe holds.</Typography>
{/* <Link href={{ pathname: AppRoutes.balances.index, query: { safe: `${safeAddress}` } }} key={`${safe}`} passHref> */}
<Button
variant="outlined"
className={css.buttonstyled}
onClick={() => dispatch(openModal({ modalName: modalTypes.assetsModals, modalProps: { nfts: false } }))}
size="small"
>
View Assets
</Button>
{/* </Link> */}
</Box>
)
}

export default AssetsSection
15 changes: 8 additions & 7 deletions src/components/chat/ModalListContextMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import ContextMenu from '@/components/common/ContextMenu'
import AddIcon from '@/public/images/common/add.svg'
import AddChatIcon from '@/public/images/chat/add-chat-icon.svg'
import AddIcon from '@/public/images/common/add.svg'
import { useAppDispatch } from '@/store'
import { openModal } from '@/store/modalServiceSlice'
import { SvgIcon } from '@mui/material'
import IconButton from '@mui/material/IconButton'
import ListItemIcon from '@mui/material/ListItemIcon'
import ListItemText from '@mui/material/ListItemText'
import MenuItem from '@mui/material/MenuItem'
import type { MouseEvent } from 'react'
import { useState } from 'react'
import { AddFolderModal } from './modals/AddFolderModal'
import { modalTypes } from './modals'

enum ModalType {
ADDFOLDER = 'Add Folder',
ADDSAFE = 'Add Safe',
}

const ModalListContextMenu: React.FC<{ createSafe: boolean, setCreateSafe: any }> = ({ createSafe, setCreateSafe }) => {
const ModalListContextMenu = () => {
const [anchorEl, setAnchorEl] = useState<HTMLElement | undefined>()
const [addFolder, setAddFolder] = useState<boolean>(false)
const dispatch = useAppDispatch()

const handleOpenContextMenu = (e: MouseEvent<HTMLButtonElement, globalThis.MouseEvent>) => {
setAnchorEl(e.currentTarget)
Expand All @@ -29,7 +31,6 @@ const ModalListContextMenu: React.FC<{ createSafe: boolean, setCreateSafe: any }

return (
<>
{addFolder && <AddFolderModal open={addFolder} onClose={() => setAddFolder(!addFolder)} />}
<IconButton
sx={{ border: '1px solid var(--color-border-light)', color: 'currentColor', borderRadius: '6px', padding: '7px', width: '32px', height: '32px' }}
aria-label="open context menu"
Expand All @@ -39,15 +40,15 @@ const ModalListContextMenu: React.FC<{ createSafe: boolean, setCreateSafe: any }
</IconButton>
<ContextMenu anchorEl={anchorEl} open={!!anchorEl} onClose={handleCloseContextMenu}>
<MenuItem
onClick={() => setAddFolder(!addFolder)}
onClick={() => dispatch(openModal({ modalName: modalTypes.addFolderModal, modalProps: '' }))}
>
<ListItemIcon>
<SvgIcon component={AddIcon} inheritViewBox fontSize="small" color="primary" />
</ListItemIcon>
<ListItemText>{ModalType.ADDFOLDER}</ListItemText>
</MenuItem>
<MenuItem
onClick={() => setCreateSafe(!createSafe)}
onClick={() => dispatch(openModal({ modalName: modalTypes.createSafe, modalProps: '' }))}
>
<ListItemIcon>
<SvgIcon component={AddIcon} inheritViewBox fontSize="small" color="primary" />
Expand Down
25 changes: 25 additions & 0 deletions src/components/chat/OverviewDisplay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import useSafeInfo from "@/hooks/useSafeInfo";
import { Box } from "@mui/material";
import Members from "../common/Members";
import TransactionHistory from "../common/TransactionHistory";
import TransactionQueue from "../common/TransactionQueue";
import AppsSection from "./AppsSection";
import AssetsSection from "./AssetsSection";
import type { Pages } from "./OverviewDrawer";
import OverviewSection from "./OverviewSection";

const OverviewDisplay = ({ page, owners }: { page: Pages, owners: any[] }) => {
const { safe, safeAddress } = useSafeInfo()
const currentView = {
Overview: <OverviewSection />,
Members: <Members members={owners} />,
TransactionQueue: <TransactionQueue key={safeAddress} />,
TransactionHistory: <TransactionHistory />,
Assets: <AssetsSection />,
Apps: <AppsSection />
}[page]

return <Box>{currentView}</Box>
}

export default OverviewDisplay
Loading