Skip to content

Commit

Permalink
add update sequence number
Browse files Browse the repository at this point in the history
  • Loading branch information
Hemanthghs committed Dec 2, 2024
1 parent 525943d commit dd68df4
Show file tree
Hide file tree
Showing 13 changed files with 374 additions and 236 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import CustomButton from '@/components/common/CustomButton';
import { Dialog, DialogContent } from '@mui/material';
import Image from 'next/image';
import React from 'react';

const DialogUpdateSequence = ({
open,
onClose,
onUpdateSequence,
loading,
}: {
open: boolean;
onClose: () => void;
onUpdateSequence: () => void;
loading: boolean;
}) => {
return (
<Dialog
open={open}
onClose={onClose}
maxWidth="lg"
sx={{
'& .MuiDialog-paper': {
color: 'white',
},
}}
PaperProps={{
sx: {
borderRadius: '16px',
background: '#1C1C20',
},
}}
>
<DialogContent sx={{ padding: 0 }}>
<div className="w-[550px] p-4 relative">
<button
className="absolute top-6 right-6 hover:bg-[#ffffff10] w-8 h-8 rounded-full flex items-center justify-center"
onClick={onClose}
>
<Image src="/close.svg" width={20} height={20} alt="close-icon" />
</button>
<div className="px-10 py-20 space-y-10">
<div className="flex flex-col items-center gap-6">
<div className="border-[4px] bg-[#F3B2AD] border-[#933A42] rounded-full w-16 h-16 mx-auto flex justify-center items-center">
<div className="p-6 leading-none font-bold text-[48px] text-[#933A42] select-none">
!
</div>
</div>
<div className="flex items-center flex-col gap-2">
<div className="text-h2 !font-bold">Transaction Sequence Outdated</div>
<div className="text-b1-light text-center">
Transaction sequence is outdated. To broadcast this
transaction, the sequence number needs to be updated.
</div>
<div className="text-b1-light text-center">
Would you like to update?
</div>
</div>
</div>
<div className="space-y-6">
<div className="text-b1-light !font-normal rounded-lg bg-[#ffffff0d] p-2 !text-red-400">
After this action all the signers will be required to re-sign.
</div>
<CustomButton
btnOnClick={onUpdateSequence}
btnText="Update Sequence"
btnLoading={loading}
btnStyles="w-full !border-[#D92101] !bg-[#D921011A] delete-multisig-btn"
/>
</div>
</div>
</div>
</DialogContent>
</Dialog>
);
};

export default DialogUpdateSequence;
160 changes: 70 additions & 90 deletions frontend/src/app/(routes)/multisig/components/common/BroadCastTxn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,28 @@ import useGetChainInfo from '@/custom-hooks/useGetChainInfo';
import { setError } from '@/store/features/common/commonSlice';
import {
broadcastTransaction,
resetUpdateTxnSequences,
resetUpdateTxnState,
setVerifyDialogOpen,
updateTxnSequences,
} from '@/store/features/multisig/multisigSlice';
import { RootState } from '@/store/store';
import { MultisigAddressPubkey, Txn } from '@/types/multisig';
import React, { useEffect, useState } from 'react';
import { FAILED_TO_BROADCAST_ERROR } from '@/utils/errors';
import {
CANNOT_BROADCAST_ERROR,
FAILED_TO_BROADCAST_ERROR,
FAILED_TO_BROADCAST_TRY_AGAIN,
FAILED_TO_UPDATE_SEQUENCE,
UPDATED_SEQUENCE_SUCCESSFULLY,
} from '@/utils/errors';
import useVerifyAccount from '@/custom-hooks/useVerifyAccount';
import CustomButton from '@/components/common/CustomButton';
import { useRouter } from 'next/navigation';
import CustomDialog from '@/components/common/CustomDialog';
import { Dialog, DialogContent } from '@mui/material';
import Image from 'next/image';
import { DELETE_ILLUSTRATION } from '@/constants/image-names';
import DialogUpdateSequence from '../DialogUpdateSequence';
import { getAuthToken } from '@/utils/localStorage';
import { COSMOS_CHAIN_ID } from '@/utils/constants';
import { TxStatus } from '@/types/enums';

interface BroadCastTxnProps {
txn: Txn;
Expand All @@ -25,12 +33,12 @@ interface BroadCastTxnProps {
pubKeys: MultisigAddressPubkey[];
chainID: string;
isMember: boolean;
disableBroadcast?: boolean;
isOverview?: boolean;
broadcastInfo?: {
disable: boolean;
isSequenceLess: boolean;
isSequenceGreater: boolean;
isSequenceAvailable: boolean;
};
}

Expand All @@ -42,7 +50,6 @@ const BroadCastTxn: React.FC<BroadCastTxnProps> = (props) => {
threshold,
chainID,
isMember,
disableBroadcast,
isOverview,
broadcastInfo,
} = props;
Expand All @@ -59,9 +66,15 @@ const BroadCastTxn: React.FC<BroadCastTxnProps> = (props) => {
});
const router = useRouter();

const [seqNotSyncOpen, setSeqNotSyncOpen] = useState(false);
const updateTxnRes = useAppSelector(
(state: RootState) => state.multisig.updateTxnRes
);
const updateTxnSequencesStatus = useAppSelector(
(state) => state.multisig.updateTxnSequences
);

const authToken = getAuthToken(COSMOS_CHAIN_ID);

useEffect(() => {
if (updateTxnRes.status === 'rejected') {
Expand All @@ -81,10 +94,6 @@ const BroadCastTxn: React.FC<BroadCastTxnProps> = (props) => {
}, []);

const broadcastTxn = async () => {
if (!isAccountVerified()) {
dispatch(setVerifyDialogOpen(true));
return;
}
dispatch(
broadcastTransaction({
chainID,
Expand All @@ -98,26 +107,65 @@ const BroadCastTxn: React.FC<BroadCastTxnProps> = (props) => {
})
);
};
const [pendingSeqOpen, setPendingSeqOpen] = useState(false);
const [seqNotSyncOpen, setSeqNotSyncOpen] = useState(false);

const handleBroadcast = () => {
if (!isAccountVerified()) {
dispatch(setVerifyDialogOpen(true));
return;
}
if (isOverview) {
router.push(`/multisig/${chainName}/${multisigAddress}`);
} else if (broadcastInfo) {
if (broadcastInfo.isSequenceLess) {
// alert('Sequence is not in sync');
setSeqNotSyncOpen(true);
} else if (broadcastInfo.isSequenceGreater) {
setPendingSeqOpen(true);
setSeqNotSyncOpen(true);
// alert(
// 'There is a transaction that needs to be broadcasted before this'
// );
dispatch(setError({ type: 'error', message: CANNOT_BROADCAST_ERROR }));
} else if (!broadcastInfo.isSequenceAvailable) {
// TODO: Sequence number is not available is the txn is signed before adding txn_Sequence into db
// This needs to be handled
dispatch(
setError({ type: 'error', message: "Seqeunce not found" })
);
} else if (!broadcastInfo.disable) {
broadcastTxn();
} else {
dispatch(
setError({ type: 'error', message: FAILED_TO_BROADCAST_TRY_AGAIN })
);
}
}
};

const handleUpdateSequence = () => {
dispatch(
updateTxnSequences({
data: { address: multisigAddress },
queryParams: {
address: walletAddress,
signature: authToken?.signature || '',
},
})
);
};

useEffect(() => {
if (updateTxnSequencesStatus.status === TxStatus.IDLE) {
dispatch(
setError({ type: 'success', message: UPDATED_SEQUENCE_SUCCESSFULLY })
);
dispatch(resetUpdateTxnSequences());
setSeqNotSyncOpen(false);
}
if (updateTxnSequencesStatus.status === TxStatus.REJECTED) {
dispatch(
setError({
type: 'error',
message: updateTxnSequencesStatus?.error || FAILED_TO_UPDATE_SEQUENCE,
})
);
}
}, [updateTxnSequencesStatus]);

return (
<>
<CustomButton
Expand All @@ -126,82 +174,14 @@ const BroadCastTxn: React.FC<BroadCastTxnProps> = (props) => {
btnDisabled={!isMember}
btnStyles="w-[115px]"
/>
<DialogSequenceMissMatch
<DialogUpdateSequence
open={seqNotSyncOpen}
onClose={() => setSeqNotSyncOpen(false)}
onUpdateSequence={() => console.log('update')}
onUpdateSequence={handleUpdateSequence}
loading={updateTxnSequencesStatus.status === TxStatus.PENDING}
/>
</>
);
};

export default BroadCastTxn;

const DialogSequenceMissMatch = ({
open,
onClose,
onUpdateSequence,
}: {
open: boolean;
onClose: () => void;
onUpdateSequence: () => void;
}) => {
return (
<Dialog
open={open}
onClose={onClose}
maxWidth="lg"
sx={{
'& .MuiDialog-paper': {
color: 'white',
},
}}
PaperProps={{
sx: {
borderRadius: '16px',
background: '#1C1C20',
},
}}
>
<DialogContent sx={{ padding: 0 }}>
<div className="w-[550px] p-4 relative">
<button
className="absolute top-6 right-6 hover:bg-[#ffffff10] w-8 h-8 rounded-full flex items-center justify-center"
onClick={onClose}
>
<Image src="/close.svg" width={20} height={20} alt="close-icon" />
</button>
<div className="px-10 py-20 space-y-10">
<div className="flex flex-col items-center gap-6">
<div className="border-[4px] bg-[#F3B2AD] border-[#933A42] rounded-full w-16 h-16 mx-auto flex justify-center items-center">
<div className="p-6 leading-none font-bold text-[48px] text-[#933A42] select-none">
!
</div>
</div>
<div className="flex items-center flex-col gap-2">
<div className="text-h2 !font-bold">Sequence Outdated</div>
<div className="text-b1-light text-center">
Transaction sequence is outdated. To broadcast this
transaction, the sequence number needs to be updated.
</div>
<div className="text-b1-light text-center">
Would you like to update?
</div>
</div>
</div>
<div className="space-y-6">
<div className="text-b1-light !font-normal rounded-lg bg-[#ffffff0d] p-2 !text-red-400">
After this action all the signers will be required to re-sign.
</div>
<CustomButton
btnOnClick={onUpdateSequence}
btnText="Update Sequence"
btnStyles="w-full !border-[#D92101] !bg-[#D921011A] delete-multisig-btn"
/>
</div>
</div>
</div>
</DialogContent>
</Dialog>
);
};
11 changes: 8 additions & 3 deletions frontend/src/app/(routes)/multisig/components/common/SignTxn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@ interface SignTxnProps {
unSignedTxn: Txn;
isMember: boolean;
chainID: string;
isSigned: boolean;
isOverview?: boolean;
}

// TODO: Sequence number is not available is the txn is signed before adding txn_Sequence into db
// This needs to be handled

const SignTxn: React.FC<SignTxnProps> = (props) => {
const { address, isMember, unSignedTxn, chainID, isOverview } = props;
const { address, isMember, unSignedTxn, chainID, isOverview, isSigned } =
props;
const dispatch = useAppDispatch();
const { getChainInfo } = useGetChainInfo();
const { address: walletAddress, rpcURLs, chainName } = getChainInfo(chainID);
Expand Down Expand Up @@ -69,14 +74,14 @@ const SignTxn: React.FC<SignTxnProps> = (props) => {
rpcURLs,
txnSequence: unSignedTxn.txn_sequence,
toBeBroadcastedCount,
partiallySignedCount: partiallySigned?.length
partiallySignedCount: partiallySigned?.length,
})
);
};

return (
<CustomButton
btnText="Sign"
btnText={isSigned ? 'Signed' : 'Sign'}
btnDisabled={!isMember}
btnOnClick={() => {
if (isOverview) {
Expand Down
Loading

0 comments on commit dd68df4

Please sign in to comment.