From f83ed494c1a353c6b07e79ddcc606cfb81573ad2 Mon Sep 17 00:00:00 2001 From: charymalloju Date: Mon, 11 Nov 2024 15:32:55 +0530 Subject: [PATCH 01/17] update transactions delete api --- server/handler/transactions.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/server/handler/transactions.go b/server/handler/transactions.go index 8a1c51254..73e61d6be 100644 --- a/server/handler/transactions.go +++ b/server/handler/transactions.go @@ -513,6 +513,14 @@ func (h *Handler) DeleteTransaction(c echo.Context) error { }) } + _, err = h.DB.Exec("UPDATE transactions SET signatures='[]'::jsonb WHERE multisig_address=$1", address) + if err != nil { + return c.JSON(http.StatusBadRequest, model.ErrorResponse{ + Status: "error", + Message: err.Error(), + }) + } + return c.JSON(http.StatusOK, model.SuccessResponse{ Status: "transaction deleted", }) From 43dc0dc7f1e2a80afe9d5a29040c0f662b1e5acc Mon Sep 17 00:00:00 2001 From: charymalloju Date: Mon, 11 Nov 2024 15:36:58 +0530 Subject: [PATCH 02/17] add conditin to delete api --- server/handler/transactions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/handler/transactions.go b/server/handler/transactions.go index 73e61d6be..cf50b0669 100644 --- a/server/handler/transactions.go +++ b/server/handler/transactions.go @@ -513,7 +513,7 @@ func (h *Handler) DeleteTransaction(c echo.Context) error { }) } - _, err = h.DB.Exec("UPDATE transactions SET signatures='[]'::jsonb WHERE multisig_address=$1", address) + _, err = h.DB.Exec("UPDATE transactions SET signatures='[]'::jsonb WHERE multisig_address=$1 and status='PENDING'", address) if err != nil { return c.JSON(http.StatusBadRequest, model.ErrorResponse{ Status: "error", From dd81a62a75acdfb9851affd487c4017b0cda3109 Mon Sep 17 00:00:00 2001 From: charymalloju Date: Mon, 11 Nov 2024 16:40:30 +0530 Subject: [PATCH 03/17] add signedat to the transaction --- server/handler/transactions.go | 18 ++++++++++++++++-- server/schema/transactions.go | 2 ++ server/schema/update_schema.sql | 13 +++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/server/handler/transactions.go b/server/handler/transactions.go index cf50b0669..a9b19f552 100644 --- a/server/handler/transactions.go +++ b/server/handler/transactions.go @@ -436,7 +436,7 @@ func (h *Handler) SignTransaction(c echo.Context) error { }) } - _, err = h.DB.Exec("UPDATE transactions SET signatures=$1 WHERE id=$2", bz, id) + _, err = h.DB.Exec("UPDATE transactions SET signatures=$1, signed_at=$2 WHERE id=$3", bz, time.Now().UTC(), id) if err != nil { return c.JSON(http.StatusBadRequest, model.ErrorResponse{ Status: "error", @@ -513,7 +513,21 @@ func (h *Handler) DeleteTransaction(c echo.Context) error { }) } - _, err = h.DB.Exec("UPDATE transactions SET signatures='[]'::jsonb WHERE multisig_address=$1 and status='PENDING'", address) + row := h.DB.QueryRow(`SELECT signed_at FROM transactions WHERE id=$1 AND multisig_address=$2`, txId, address) + + var transaction schema.Transaction + if err := row.Scan( + &transaction.Signatures, + ); err != nil { + return c.JSON(http.StatusBadRequest, model.ErrorResponse{ + Status: "error", + Message: err.Error(), + }) + } + + txSignedAt := transaction.SignedAt + + _, err = h.DB.Exec("UPDATE transactions SET signatures='[]'::jsonb WHERE multisig_address=$1 and signed_at > $2", address, txSignedAt) if err != nil { return c.JSON(http.StatusBadRequest, model.ErrorResponse{ Status: "error", diff --git a/server/schema/transactions.go b/server/schema/transactions.go index 35c894807..c0eece9e0 100644 --- a/server/schema/transactions.go +++ b/server/schema/transactions.go @@ -17,6 +17,7 @@ type Transaction struct { Signatures json.RawMessage `pg:"signatures" json:"signatures"` LastUpdated time.Time `pg:"last_updated,use_zero" json:"last_updated"` CreatedAt time.Time `pg:"created_at,use_zero" json:"created_at"` + SignedAt time.Time `pg:"signed_at,use_zero" sql:"-" json:"signed_at,omitempty"` } type TransactionCount struct { @@ -39,4 +40,5 @@ type AllTransactionResult struct { CreatedAt time.Time `pg:"created_at" sql:"-" json:"created_at,omitempty"` Threshold int `pg:"threshold" json:"threshold"` Pubkeys json.RawMessage `pg:"pubkeys" json:"pubkeys"` + SignedAt time.Time `pg:"signed_at" sql:"-" json:"signed_at,omitempty"` } diff --git a/server/schema/update_schema.sql b/server/schema/update_schema.sql index 43f739066..46b74c741 100644 --- a/server/schema/update_schema.sql +++ b/server/schema/update_schema.sql @@ -12,3 +12,16 @@ BEGIN ADD COLUMN title VARCHAR(255) DEFAULT ''; END IF; END $$; + +DO $$ +BEGIN + -- Check and add new_column_name if it doesn't exist + IF NOT EXISTS ( + SELECT 1 + FROM information_schema.columns + WHERE table_name = 'transactions' AND column_name = 'signed_at' + ) THEN + ALTER TABLE transactions + ADD COLUMN signed_at TIMESTAMP DEFAULT NULL; + END IF; +END $$; From c57f8373d606b60fa6b84dc8a627922e680fc6da Mon Sep 17 00:00:00 2001 From: charymalloju Date: Mon, 11 Nov 2024 17:03:10 +0530 Subject: [PATCH 04/17] fix the rror --- server/handler/transactions.go | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/server/handler/transactions.go b/server/handler/transactions.go index a9b19f552..e1e9dbe6d 100644 --- a/server/handler/transactions.go +++ b/server/handler/transactions.go @@ -516,23 +516,20 @@ func (h *Handler) DeleteTransaction(c echo.Context) error { row := h.DB.QueryRow(`SELECT signed_at FROM transactions WHERE id=$1 AND multisig_address=$2`, txId, address) var transaction schema.Transaction - if err := row.Scan( + row.Scan( &transaction.Signatures, - ); err != nil { - return c.JSON(http.StatusBadRequest, model.ErrorResponse{ - Status: "error", - Message: err.Error(), - }) - } + ) - txSignedAt := transaction.SignedAt + if !transaction.SignedAt.IsZero() { + txSignedAt := transaction.SignedAt - _, err = h.DB.Exec("UPDATE transactions SET signatures='[]'::jsonb WHERE multisig_address=$1 and signed_at > $2", address, txSignedAt) - if err != nil { - return c.JSON(http.StatusBadRequest, model.ErrorResponse{ - Status: "error", - Message: err.Error(), - }) + _, err = h.DB.Exec("UPDATE transactions SET signatures='[]'::jsonb WHERE multisig_address=$1 AND signed_at > $2", address, txSignedAt) + if err != nil { + return c.JSON(http.StatusBadRequest, model.ErrorResponse{ + Status: "error", + Message: err.Error(), + }) + } } return c.JSON(http.StatusOK, model.SuccessResponse{ From 4cd79a730a9d23ae194b633075fc664007d64550 Mon Sep 17 00:00:00 2001 From: charymalloju Date: Mon, 11 Nov 2024 17:51:15 +0530 Subject: [PATCH 05/17] update get transactions --- server/handler/transactions.go | 5 +++-- server/schema/transactions.go | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/server/handler/transactions.go b/server/handler/transactions.go index e1e9dbe6d..828b309e1 100644 --- a/server/handler/transactions.go +++ b/server/handler/transactions.go @@ -145,11 +145,11 @@ func (h *Handler) GetTransactions(c echo.Context) error { status := utils.GetStatus(c.QueryParam("status")) var rows *sql.Rows if status == model.Pending { - rows, err = h.DB.Query(`SELECT t.id,t.multisig_address,t.status,t.created_at,t.last_updated,t.memo,t.signatures,t.messages,t.hash,t.err_msg,t.fee, m.threshold, + rows, err = h.DB.Query(`SELECT t.id,t.signed_at,t.multisig_address,t.status,t.created_at,t.last_updated,t.memo,t.signatures,t.messages,t.hash,t.err_msg,t.fee, m.threshold, json_agg(jsonb_build_object('pubkey', p.pubkey, 'address', p.address, 'multisig_address',p.multisig_address)) AS pubkeys FROM transactions t JOIN multisig_accounts m ON t.multisig_address = m.address JOIN pubkeys p ON t.multisig_address = p.multisig_address WHERE t.multisig_address=$1 and t.status='PENDING' GROUP BY t.id, t.multisig_address, m.threshold, t.messages LIMIT $2 OFFSET $3`, address, limit, (page-1)*limit) } else { - rows, err = h.DB.Query(`SELECT t.id,t.multisig_address,t.status,t.created_at,t.last_updated,t.memo,t.signatures,t.messages,t.hash,t.err_msg,t.fee, m.threshold, + rows, err = h.DB.Query(`SELECT t.id,t.signed_at,t.multisig_address,t.status,t.created_at,t.last_updated,t.memo,t.signatures,t.messages,t.hash,t.err_msg,t.fee, m.threshold, json_agg(jsonb_build_object('pubkey', p.pubkey, 'address', p.address, 'multisig_address',p.multisig_address)) AS pubkeys FROM transactions t JOIN multisig_accounts m ON t.multisig_address = m.address JOIN pubkeys p ON t.multisig_address = p.multisig_address WHERE t.multisig_address=$1 and t.status <> 'PENDING' GROUP BY t.id, t.multisig_address, m.threshold, t.messages LIMIT $2 OFFSET $3`, address, limit, (page-1)*limit) } @@ -187,6 +187,7 @@ func (h *Handler) GetTransactions(c echo.Context) error { &transaction.Fee, &transaction.Threshold, &transaction.Pubkeys, + &transaction.SignedAt, ); err != nil { return c.JSON(http.StatusInternalServerError, model.ErrorResponse{ Status: "error", diff --git a/server/schema/transactions.go b/server/schema/transactions.go index c0eece9e0..98d5e508a 100644 --- a/server/schema/transactions.go +++ b/server/schema/transactions.go @@ -40,5 +40,5 @@ type AllTransactionResult struct { CreatedAt time.Time `pg:"created_at" sql:"-" json:"created_at,omitempty"` Threshold int `pg:"threshold" json:"threshold"` Pubkeys json.RawMessage `pg:"pubkeys" json:"pubkeys"` - SignedAt time.Time `pg:"signed_at" sql:"-" json:"signed_at,omitempty"` + SignedAt time.Time `pg:"signed_at,use_zero" sql:"-" json:"signed_at,omitempty"` } From 8b9b98abb49ac629b019cbf97eedb61077ec199b Mon Sep 17 00:00:00 2001 From: charymalloju Date: Mon, 11 Nov 2024 18:01:23 +0530 Subject: [PATCH 06/17] handle null values --- server/schema/transactions.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/schema/transactions.go b/server/schema/transactions.go index 98d5e508a..947890dfa 100644 --- a/server/schema/transactions.go +++ b/server/schema/transactions.go @@ -1,6 +1,7 @@ package schema import ( + "database/sql" "encoding/json" "time" ) @@ -40,5 +41,5 @@ type AllTransactionResult struct { CreatedAt time.Time `pg:"created_at" sql:"-" json:"created_at,omitempty"` Threshold int `pg:"threshold" json:"threshold"` Pubkeys json.RawMessage `pg:"pubkeys" json:"pubkeys"` - SignedAt time.Time `pg:"signed_at,use_zero" sql:"-" json:"signed_at,omitempty"` + SignedAt sql.NullTime `pg:"signed_at,use_zero" sql:"-" json:"signed_at,omitempty"` } From 8f5dda321c049375bfef32b2c2081c3bd1217ed6 Mon Sep 17 00:00:00 2001 From: charymalloju Date: Mon, 11 Nov 2024 18:10:40 +0530 Subject: [PATCH 07/17] add condition for signedat --- server/handler/transactions.go | 12 +++++++++++- server/schema/transactions.go | 3 +-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/server/handler/transactions.go b/server/handler/transactions.go index 828b309e1..28daef164 100644 --- a/server/handler/transactions.go +++ b/server/handler/transactions.go @@ -173,6 +173,8 @@ func (h *Handler) GetTransactions(c echo.Context) error { transactions := make([]schema.AllTransactionResult, 0) for rows.Next() { var transaction schema.AllTransactionResult + var signedAt sql.NullTime + if err := rows.Scan( &transaction.ID, &transaction.MultisigAddress, @@ -187,7 +189,7 @@ func (h *Handler) GetTransactions(c echo.Context) error { &transaction.Fee, &transaction.Threshold, &transaction.Pubkeys, - &transaction.SignedAt, + &signedAt, ); err != nil { return c.JSON(http.StatusInternalServerError, model.ErrorResponse{ Status: "error", @@ -195,6 +197,14 @@ func (h *Handler) GetTransactions(c echo.Context) error { Log: err.Error(), }) } + + // Conditionally set transaction.SignedAt based on whether signedAt is valid + if signedAt.Valid { + transaction.SignedAt = signedAt.Time // Assign the time if it's non-NULL + } else { + transaction.SignedAt = time.Time{} // Or set to the zero value of time.Time + } + transactions = append(transactions, transaction) } diff --git a/server/schema/transactions.go b/server/schema/transactions.go index 947890dfa..98d5e508a 100644 --- a/server/schema/transactions.go +++ b/server/schema/transactions.go @@ -1,7 +1,6 @@ package schema import ( - "database/sql" "encoding/json" "time" ) @@ -41,5 +40,5 @@ type AllTransactionResult struct { CreatedAt time.Time `pg:"created_at" sql:"-" json:"created_at,omitempty"` Threshold int `pg:"threshold" json:"threshold"` Pubkeys json.RawMessage `pg:"pubkeys" json:"pubkeys"` - SignedAt sql.NullTime `pg:"signed_at,use_zero" sql:"-" json:"signed_at,omitempty"` + SignedAt time.Time `pg:"signed_at,use_zero" sql:"-" json:"signed_at,omitempty"` } From 9f2361ad9c46eb8c4b83021bcf7c38d57a7da792 Mon Sep 17 00:00:00 2001 From: charymalloju Date: Mon, 11 Nov 2024 19:02:49 +0530 Subject: [PATCH 08/17] updated sql signedat code --- server/handler/transactions.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server/handler/transactions.go b/server/handler/transactions.go index 28daef164..83bad469f 100644 --- a/server/handler/transactions.go +++ b/server/handler/transactions.go @@ -198,11 +198,12 @@ func (h *Handler) GetTransactions(c echo.Context) error { }) } - // Conditionally set transaction.SignedAt based on whether signedAt is valid + // Check if signedAt is valid and set SignedAt accordingly if signedAt.Valid { - transaction.SignedAt = signedAt.Time // Assign the time if it's non-NULL + transaction.SignedAt = signedAt.Time } else { - transaction.SignedAt = time.Time{} // Or set to the zero value of time.Time + // If signed_at is NULL, set it to a default value (e.g., current time) + transaction.SignedAt = time.Now() // You can change this to a default timestamp if needed } transactions = append(transactions, transaction) From ee02b5d89c09b5497e00a92faa0207d65d6c6b18 Mon Sep 17 00:00:00 2001 From: charymalloju Date: Mon, 11 Nov 2024 19:14:27 +0530 Subject: [PATCH 09/17] fix errors --- server/handler/transactions.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/server/handler/transactions.go b/server/handler/transactions.go index 83bad469f..ff1b92d70 100644 --- a/server/handler/transactions.go +++ b/server/handler/transactions.go @@ -145,11 +145,11 @@ func (h *Handler) GetTransactions(c echo.Context) error { status := utils.GetStatus(c.QueryParam("status")) var rows *sql.Rows if status == model.Pending { - rows, err = h.DB.Query(`SELECT t.id,t.signed_at,t.multisig_address,t.status,t.created_at,t.last_updated,t.memo,t.signatures,t.messages,t.hash,t.err_msg,t.fee, m.threshold, + rows, err = h.DB.Query(`SELECT t.id,COALESCE(t.signed_at, '0001-01-01 00:00:00'::timestamp) AS signed_at,t.multisig_address,t.status,t.created_at,t.last_updated,t.memo,t.signatures,t.messages,t.hash,t.err_msg,t.fee, m.threshold, json_agg(jsonb_build_object('pubkey', p.pubkey, 'address', p.address, 'multisig_address',p.multisig_address)) AS pubkeys FROM transactions t JOIN multisig_accounts m ON t.multisig_address = m.address JOIN pubkeys p ON t.multisig_address = p.multisig_address WHERE t.multisig_address=$1 and t.status='PENDING' GROUP BY t.id, t.multisig_address, m.threshold, t.messages LIMIT $2 OFFSET $3`, address, limit, (page-1)*limit) } else { - rows, err = h.DB.Query(`SELECT t.id,t.signed_at,t.multisig_address,t.status,t.created_at,t.last_updated,t.memo,t.signatures,t.messages,t.hash,t.err_msg,t.fee, m.threshold, + rows, err = h.DB.Query(`SELECT t.id,COALESCE(t.signed_at, '0001-01-01 00:00:00'::timestamp) AS signed_at,t.multisig_address,t.status,t.created_at,t.last_updated,t.memo,t.signatures,t.messages,t.hash,t.err_msg,t.fee, m.threshold, json_agg(jsonb_build_object('pubkey', p.pubkey, 'address', p.address, 'multisig_address',p.multisig_address)) AS pubkeys FROM transactions t JOIN multisig_accounts m ON t.multisig_address = m.address JOIN pubkeys p ON t.multisig_address = p.multisig_address WHERE t.multisig_address=$1 and t.status <> 'PENDING' GROUP BY t.id, t.multisig_address, m.threshold, t.messages LIMIT $2 OFFSET $3`, address, limit, (page-1)*limit) } @@ -173,10 +173,11 @@ func (h *Handler) GetTransactions(c echo.Context) error { transactions := make([]schema.AllTransactionResult, 0) for rows.Next() { var transaction schema.AllTransactionResult - var signedAt sql.NullTime + var signedAt time.Time if err := rows.Scan( &transaction.ID, + &signedAt, &transaction.MultisigAddress, &transaction.Status, &transaction.CreatedAt, @@ -189,7 +190,6 @@ func (h *Handler) GetTransactions(c echo.Context) error { &transaction.Fee, &transaction.Threshold, &transaction.Pubkeys, - &signedAt, ); err != nil { return c.JSON(http.StatusInternalServerError, model.ErrorResponse{ Status: "error", @@ -198,12 +198,10 @@ func (h *Handler) GetTransactions(c echo.Context) error { }) } - // Check if signedAt is valid and set SignedAt accordingly - if signedAt.Valid { - transaction.SignedAt = signedAt.Time + if signedAt.IsZero() { + transaction.SignedAt = time.Time{} // Set it to zero time if not set } else { - // If signed_at is NULL, set it to a default value (e.g., current time) - transaction.SignedAt = time.Now() // You can change this to a default timestamp if needed + transaction.SignedAt = signedAt // Otherwise, set the actual signed time } transactions = append(transactions, transaction) From 98590af9152ef2bfe56d9319b216155e4fd1b67d Mon Sep 17 00:00:00 2001 From: hemanthghs Date: Tue, 12 Nov 2024 10:44:10 +0530 Subject: [PATCH 10/17] feat: Implement offchain sequence management for multisig --- .../components/common/BroadCastTxn.tsx | 24 +++++++++++-- .../multisig/components/common/SignTxn.tsx | 33 ++++++++++++++--- .../multisig/components/common/TxnsCard.tsx | 16 +++++++-- .../multisig-account/DialogConfirmDelete.tsx | 2 +- .../multisig-account/Transactions.tsx | 35 ++++++++++++------- .../multisig-dashboard/RecentTransactions.tsx | 13 ++++--- .../multisig/utils/multisigSigning.ts | 5 +-- .../src/components/common/CustomButton.tsx | 2 +- .../store/features/multisig/multisigSlice.ts | 4 ++- frontend/src/types/multisig.d.ts | 1 + 10 files changed, 103 insertions(+), 32 deletions(-) diff --git a/frontend/src/app/(routes)/multisig/components/common/BroadCastTxn.tsx b/frontend/src/app/(routes)/multisig/components/common/BroadCastTxn.tsx index a8b0f7d95..82beaae44 100644 --- a/frontend/src/app/(routes)/multisig/components/common/BroadCastTxn.tsx +++ b/frontend/src/app/(routes)/multisig/components/common/BroadCastTxn.tsx @@ -12,6 +12,7 @@ import React, { useEffect } from 'react'; import { FAILED_TO_BROADCAST_ERROR } from '@/utils/errors'; import useVerifyAccount from '@/custom-hooks/useVerifyAccount'; import CustomButton from '@/components/common/CustomButton'; +import { useRouter } from 'next/navigation'; interface BroadCastTxnProps { txn: Txn; @@ -20,20 +21,33 @@ interface BroadCastTxnProps { pubKeys: MultisigAddressPubkey[]; chainID: string; isMember: boolean; + disableBroadcast?: boolean; + isOverview?: boolean; } const BroadCastTxn: React.FC = (props) => { - const { txn, multisigAddress, pubKeys, threshold, chainID, isMember } = props; + const { + txn, + multisigAddress, + pubKeys, + threshold, + chainID, + isMember, + disableBroadcast, + isOverview, + } = props; const dispatch = useAppDispatch(); const { getChainInfo } = useGetChainInfo(); const { address: walletAddress, restURLs: baseURLs, rpcURLs, + chainName, } = getChainInfo(chainID); const { isAccountVerified } = useVerifyAccount({ address: walletAddress, }); + const router = useRouter(); const updateTxnRes = useAppSelector( (state: RootState) => state.multisig.updateTxnRes @@ -78,9 +92,13 @@ const BroadCastTxn: React.FC = (props) => { { - broadcastTxn(); + if (isOverview) { + router.push(`/multisig/${chainName}/${multisigAddress}`); + } else { + broadcastTxn(); + } }} - btnDisabled={!isMember} + btnDisabled={!isMember || disableBroadcast} btnStyles="w-[115px]" /> ); diff --git a/frontend/src/app/(routes)/multisig/components/common/SignTxn.tsx b/frontend/src/app/(routes)/multisig/components/common/SignTxn.tsx index 784c6f61b..bf2ee18a5 100644 --- a/frontend/src/app/(routes)/multisig/components/common/SignTxn.tsx +++ b/frontend/src/app/(routes)/multisig/components/common/SignTxn.tsx @@ -1,4 +1,4 @@ -import { useAppDispatch } from '@/custom-hooks/StateHooks'; +import { useAppDispatch, useAppSelector } from '@/custom-hooks/StateHooks'; import useGetChainInfo from '@/custom-hooks/useGetChainInfo'; import { setVerifyDialogOpen, @@ -8,6 +8,7 @@ import { Txn } from '@/types/multisig'; import React from 'react'; import useVerifyAccount from '@/custom-hooks/useVerifyAccount'; import CustomButton from '@/components/common/CustomButton'; +import { useRouter } from 'next/navigation'; interface SignTxnProps { address: string; @@ -15,16 +16,33 @@ interface SignTxnProps { unSignedTxn: Txn; isMember: boolean; chainID: string; + isOverview?: boolean; } const SignTxn: React.FC = (props) => { - const { address, isMember, unSignedTxn, chainID } = props; + const { address, isMember, unSignedTxn, chainID, isOverview } = props; const dispatch = useAppDispatch(); const { getChainInfo } = useGetChainInfo(); - const { address: walletAddress, rpcURLs } = getChainInfo(chainID); + const { address: walletAddress, rpcURLs, chainName } = getChainInfo(chainID); const { isAccountVerified } = useVerifyAccount({ address: walletAddress, }); + const router = useRouter(); + + const txnsCount = useAppSelector((state) => state.multisig.txns.Count); + const getCount = (option: string) => { + let count = 0; + /* eslint-disable @typescript-eslint/no-explicit-any */ + txnsCount && + txnsCount.forEach((t: any) => { + if (t?.computed_status?.toLowerCase() === option.toLowerCase()) { + count = t?.count; + } + }); + + return count; + }; + const toBeBroadcastedCount = getCount('to-broadcast'); const signTheTx = async () => { if (!isAccountVerified()) { @@ -37,7 +55,8 @@ const SignTxn: React.FC = (props) => { multisigAddress: address, unSignedTxn, walletAddress, - rpcURLs + rpcURLs, + toBeBroadcastedCount, }) ); }; @@ -47,7 +66,11 @@ const SignTxn: React.FC = (props) => { btnText="Sign" btnDisabled={!isMember} btnOnClick={() => { - signTheTx(); + if (isOverview) { + router.push(`/multisig/${chainName}/${address}`); + } else { + signTheTx(); + } }} btnStyles="w-[115px]" /> diff --git a/frontend/src/app/(routes)/multisig/components/common/TxnsCard.tsx b/frontend/src/app/(routes)/multisig/components/common/TxnsCard.tsx index b10e1d786..4319fcdb9 100644 --- a/frontend/src/app/(routes)/multisig/components/common/TxnsCard.tsx +++ b/frontend/src/app/(routes)/multisig/components/common/TxnsCard.tsx @@ -40,6 +40,8 @@ export const TxnsCard = ({ isHistory, onViewError, allowRepeat, + disableBroadcast, + isOverview, }: { txn: Txn; currency: Currency; @@ -49,6 +51,8 @@ export const TxnsCard = ({ isHistory: boolean; onViewError?: (errMsg: string) => void; allowRepeat?: boolean; + disableBroadcast?: boolean; + isOverview?: boolean; }) => { const dispatch = useAppDispatch(); const { getChainInfo } = useGetChainInfo(); @@ -208,7 +212,7 @@ export const TxnsCard = ({
{isHistory || isReadyToBroadcast() - ? getTimeDifferenceToFutureDate(txn.last_updated, true) + ? getTimeDifferenceToFutureDate(txn.signed_at, true) : getTimeDifferenceToFutureDate(txn.created_at, true)}
@@ -268,6 +272,8 @@ export const TxnsCard = ({ threshold={threshold} chainID={chainID} isMember={isMember} + disableBroadcast={disableBroadcast} + isOverview={isOverview} /> ) : ( )} @@ -303,7 +310,12 @@ export const TxnsCard = ({ open={deleteDialogOpen} onClose={() => setDeleteDialogOpen(false)} title="Delete Transaction" - description=" Are you sure you want to delete the transaction ?" + description={ + 'Are you sure you want to delete the transaction?' + + (isReadyToBroadcast() + ? ' This action will require re-signing any already signed subsequent transactions.' + : '') + } onDelete={onDeleteTxn} loading={loading === TxStatus.PENDING} /> diff --git a/frontend/src/app/(routes)/multisig/components/multisig-account/DialogConfirmDelete.tsx b/frontend/src/app/(routes)/multisig/components/multisig-account/DialogConfirmDelete.tsx index 965458753..0b59195a6 100644 --- a/frontend/src/app/(routes)/multisig/components/multisig-account/DialogConfirmDelete.tsx +++ b/frontend/src/app/(routes)/multisig/components/multisig-account/DialogConfirmDelete.tsx @@ -54,7 +54,7 @@ const DialogConfirmDelete = ({ />
{title}
-
{description}
+
{description}
state.multisig.txns.Count) + const txnsCount = useAppSelector((state) => state.multisig.txns.Count); const txnsStatus = useAppSelector((state) => state.multisig.txns.status); const deleteTxnRes = useAppSelector((state) => state.multisig.deleteTxnRes); const signTxStatus = useAppSelector( @@ -172,21 +172,21 @@ const TransactionsFilters = ({ }: { txnsType: string; handleTxnsTypeChange: (type: string) => void; - /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ + /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ txnsCount: any; }) => { - const getCount = (option: string) => { let count = 0; - /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ - txnsCount && txnsCount.forEach((t: any) => { - if (t?.computed_status?.toLowerCase() === option.toLowerCase()) { - count = t?.count - } - }) + /* eslint-disable @typescript-eslint/no-explicit-any */ + txnsCount && + txnsCount.forEach((t: any) => { + if (t?.computed_status?.toLowerCase() === option.toLowerCase()) { + count = t?.count; + } + }); - return count - } + return count; + }; return (
@@ -244,9 +244,19 @@ const TransactionsList = ({ setErrMsg(errMsg); setViewErrorDialogOpen(true); }; + const sortedTxns = [...txns].sort((a, b) => { + const dateA = new Date( + txnsType === 'to-broadcast' ? a.signed_at : a.created_at + ).getTime(); + const dateB = new Date( + txnsType === 'to-broadcast' ? b.signed_at : b.created_at + ).getTime(); + return txnsType === 'to-broadcast' ? dateA - dateB : dateB - dateA; + }); + return (
- {txns.map((txn, index) => ( + {sortedTxns.map((txn, index) => ( 0} /> ))} ))}
-
- -
+ {txns?.length > 1 ? ( +
+ +
+ ) : null}
); }; diff --git a/frontend/src/app/(routes)/multisig/utils/multisigSigning.ts b/frontend/src/app/(routes)/multisig/utils/multisigSigning.ts index 9c7d45b4a..f1a43051d 100644 --- a/frontend/src/app/(routes)/multisig/utils/multisigSigning.ts +++ b/frontend/src/app/(routes)/multisig/utils/multisigSigning.ts @@ -24,7 +24,8 @@ const signTransaction = async ( multisigAddress: string, unSignedTxn: Txn, walletAddress: string, - rpcURLs: string[] + rpcURLs: string[], + toBeBroadcastedCount: number ) => { try { window.wallet.defaultOptions = { @@ -47,7 +48,7 @@ const signTransaction = async ( const signerData = { accountNumber: multisigAcc?.accountNumber, - sequence: multisigAcc?.sequence, + sequence: multisigAcc?.sequence + toBeBroadcastedCount, chainId: chainID, }; diff --git a/frontend/src/components/common/CustomButton.tsx b/frontend/src/components/common/CustomButton.tsx index 500ba337d..1a6a47e48 100644 --- a/frontend/src/components/common/CustomButton.tsx +++ b/frontend/src/components/common/CustomButton.tsx @@ -30,7 +30,7 @@ const CustomButton = ({ }: CustomButtonProps) => { return (