Skip to content

Commit

Permalink
add discourse
Browse files Browse the repository at this point in the history
  • Loading branch information
mehdi-torabiv committed Jan 16, 2025
1 parent e71e426 commit a15df17
Show file tree
Hide file tree
Showing 11 changed files with 553 additions and 10 deletions.
102 changes: 102 additions & 0 deletions src/components/pages/attestations/Discourse/StepFour.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { useState } from 'react';
import {
Box,
Button,
CircularProgress,
Stack,
Typography,
} from '@mui/material';
import { FaLink } from 'react-icons/fa';
import { useNavigate } from 'react-router-dom';
import { Address } from 'viem';
import { useAccount } from 'wagmi';

import { AttestPayload } from '../../../../interfaces';
import EASService from '../../../../services/eas.service';
import useSnackbarStore from '../../../../store/useSnackbarStore';
import { contracts } from '../../../../utils/contracts/eas/contracts';
import { useSigner } from '../../../../utils/eas-wagmi-utils';

interface StepFourProps {
attestedSignutare: AttestPayload | null;
}

const StepFour: React.FC<StepFourProps> = ({ attestedSignutare }) => {
const { showSnackbar } = useSnackbarStore();
const navigate = useNavigate();
const signer = useSigner();
const { chainId } = useAccount();
const [isLoading, setIsLoading] = useState<boolean>(false);

const easContractAddress = contracts.find(
(contract) => contract.chainId === chainId
)?.easContractAddress;

const easService = signer
? new EASService(easContractAddress as Address, signer)
: null;

const handleAttestByDelegation = async () => {
if (!easService) {
throw new Error('EAS service not initialized');
}
if (!attestedSignutare) throw new Error('No attested signature provided');

setIsLoading(true);
try {
await easService.attestByDelegation(attestedSignutare);
showSnackbar('Attestation successfully completed.', {
severity: 'success',
});
navigate('/identifiers');
} catch (error) {
console.error('Error attesting identifier:', error);
showSnackbar('Failed to complete the attestation. Please try again.', {
severity: 'error',
});
} finally {
setIsLoading(false);
}
};

return (
<Stack
spacing={3}
sx={{
textAlign: 'center',
py: 12,
px: 2,
}}
>
<Typography variant="h5" fontWeight="bold">
Finalize Delegated Attestation
</Typography>
<Typography>
To complete the process, you will be asked to sign a message with your
wallet, confirming ownership of the provided address.
</Typography>
<Box>
<Button
variant="contained"
startIcon={
isLoading ? (
<CircularProgress color="inherit" size={20} />
) : (
<FaLink />
)
}
sx={{ mt: 2, px: 4 }}
onClick={handleAttestByDelegation}
disabled={isLoading}
>
{isLoading ? 'Processing...' : 'Sign Delegated Attestation'}
</Button>
</Box>
<Typography variant="caption">
You need to pay some <b>gas</b> to complete the process.
</Typography>
</Stack>
);
};

export default StepFour;
73 changes: 73 additions & 0 deletions src/components/pages/attestations/Discourse/StepOne.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Box, Button, Stack, Typography } from '@mui/material';
import { jwtDecode } from 'jwt-decode';
import { FaDiscourse } from 'react-icons/fa';

import { useGenerateDiscourseVerificationTokenMutation } from '../../../../services/api/eas/query';

interface StepOneProps {
handleNextStep: () => void;
}

const StepOne: React.FC<StepOneProps> = ({ handleNextStep }) => {
const { mutate: mutateGenerateDiscourseVerificationToken, isPending } =
useGenerateDiscourseVerificationTokenMutation();

const handleGenerateDiscourseVerificationToken = async () => {
const siweJwt = localStorage.getItem('OCI_TOKEN') as string;

mutateGenerateDiscourseVerificationToken(
{
siweJwt,
},
{
onSuccess: (response) => {
const { data } = response;

localStorage.setItem(
'DISCOURSE_VERIFICATION_TOKEN',
data.verificationJwt
);

const { code } = jwtDecode(data.verificationJwt) as { code: string };
localStorage.setItem('DISCOURSE_VERIFICATION_CODE', code);

handleNextStep();
},
onError: (error) => {
console.error('Failed to generate token:', error);
},
}
);
};

return (
<Stack
spacing={2}
sx={{
textAlign: 'center',
py: 12,
}}
>
<Typography variant="h5" fontWeight="bold">
Let&rsquo;s get started!
</Typography>
<Typography variant="body2">
To attest your Discourse account, you need to generate a token.
</Typography>
<Box sx={{ display: 'block' }}>
<Button
variant="contained"
startIcon={<FaDiscourse />}
disabled={isPending}
onClick={handleGenerateDiscourseVerificationToken}
aria-busy={isPending}
aria-live="polite"
>
{isPending ? 'Generating token...' : 'Generate token'}
</Button>
</Box>
</Stack>
);
};

export default StepOne;
96 changes: 96 additions & 0 deletions src/components/pages/attestations/Discourse/StepThree.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React from 'react';
import {
Box,
Button,
CircularProgress,
Stack,
Typography,
} from '@mui/material';
import { FaLink } from 'react-icons/fa6';
import { useAccount } from 'wagmi';

import { Provider } from '../../../../enums';
import { AttestPayload } from '../../../../interfaces';
import { useLinkIdentifierMutation } from '../../../../services/api/eas/query';
import { capitalize } from '../../../../utils/helper';

interface StepThreeProps {
provider: Provider | undefined;
handlePrepareAttestation: (payload: AttestPayload) => void;
}

const StepThree: React.FC<StepThreeProps> = ({
provider,
handlePrepareAttestation,
}) => {
const { chainId } = useAccount();
const { mutate: mutateIdentifier, isPending } = useLinkIdentifierMutation(
chainId as number
);

const handleGenerateSignedDelegation = async () => {
const siweJwt = localStorage.getItem('OCI_TOKEN');
if (!siweJwt || !provider) return;

const anyJwt = localStorage.getItem('DISCOURSE_JWT') as string;

mutateIdentifier(
{
siweJwt,
anyJwt,
},
{
onSuccess: (response) => {
const { data } = response;
handlePrepareAttestation(data);
},
onError: (error) => {
console.error(error);
},
}
);
};

if (!provider) {
return null;
}

return (
<Stack
spacing={3}
sx={{
textAlign: 'center',
py: 12,
px: 2,
}}
>
<Typography variant="h5" fontWeight="bold">
Connect Your {capitalize(provider)} Account to Your Wallet
</Typography>
<Typography>
To proceed, please verify your account by linking it to your wallet
address. This step ensures your {capitalize(provider)} account is
securely associated with your wallet.
</Typography>
<Box>
<Button
variant="contained"
startIcon={
isPending ? (
<CircularProgress color="inherit" size={20} />
) : (
<FaLink />
)
}
sx={{ mt: 2, px: 4 }}
onClick={handleGenerateSignedDelegation}
disabled={isPending}
>
{isPending ? 'Processing...' : 'Get Signed Delegated Attestation'}
</Button>
</Box>
</Stack>
);
};

export default StepThree;
Loading

0 comments on commit a15df17

Please sign in to comment.