@@ -4,7 +4,7 @@ import { Aptos, AptosConfig, Deserializer, Ed25519PublicKey, Ed25519Signature, N
44import { Card , CardContent , CardHeader , CardTitle } from "@/components/ui/card"
55import { Button } from "@/components/ui/button"
66import { computeMultiSigAddress , toHex } from "@/utils/signature"
7- import { makeEntryFunctionTx , makeInitTx , type EntryFunctionArgs , type IMultiSig , type IAccount , assembleMultiSig , assembleMultiSigTxn , makeSubmitSignatureTxn } from "@/utils/msafe-txn"
7+ import { makeEntryFunctionTx , makeInitTx , type EntryFunctionArgs , type IMultiSig , type IAccount , assembleMultiSig , assembleMultiSigTxn , makeSubmitSignatureTxn , makeMSafeRevertTx } from "@/utils/msafe-txn"
88import { WalletConnectors } from "msafe-wallet-adaptor"
99import { BCS , TxnBuilderTypes , HexString } from "aptos"
1010
@@ -983,6 +983,90 @@ export function MSafeAccountList({ onAccountSelect }: MSafeAccountListProps) {
983983 }
984984 } , [ selectedAccount , account , getSequenceNumber , loadWithdrawalRequests , signAndSubmitTransaction , aptos . transaction ] )
985985
986+ const rejectMsafeTransaction = useCallback ( async ( msafeTransaction : MSafeTxnInfo ) => {
987+ console . log ( 'Rejecting msafe transactions:' , msafeTransaction )
988+ if ( ! selectedAccount || ! account ?. address ) return
989+ try {
990+ const msafeAccount = await WalletConnectors [ 'Pontem' ] ( ) ;
991+ const msafeAccountInterface : IMultiSig = {
992+ address : new HexString ( selectedAccount . address ) ,
993+ }
994+ const rejectTransaction = await makeMSafeRevertTx (
995+ msafeAccountInterface ,
996+ { sn : msafeTransaction . sn } ,
997+ {
998+ maxGas : msafeTransaction . maxGas ,
999+ gasPrice : msafeTransaction . gasPrice ,
1000+ expirationRaw : msafeTransaction . expirationRaw , // expiration
1001+ chainID : msafeTransaction . chainID , // mainnet,
1002+ sequenceNumber : msafeTransaction . sn ,
1003+ estimateGasPrice : true ,
1004+ estimateMaxGas : true
1005+ }
1006+ )
1007+ console . log ( 'Reject transaction:' , rejectTransaction )
1008+ const [ p , s ] = await msafeAccount . getSigData ( rejectTransaction . raw )
1009+ console . log ( 'Payload:' , p )
1010+ console . log ( 'Signature:' , s )
1011+ const msafeInfo = await getMSafeInfo ( selectedAccount . address )
1012+ if ( ! msafeInfo ) {
1013+ throw new Error ( 'Failed to get MSafe information' )
1014+ }
1015+ // Find the index of the current account's public key
1016+ const currentAccountPubKey = account . publicKey ?. toString ( ) || ''
1017+ const pkIndex = msafeInfo . public_keys . findIndex ( ( pk ) =>
1018+ isHexEqual ( pk , currentAccountPubKey )
1019+ )
1020+
1021+ if ( pkIndex === - 1 ) {
1022+ throw new Error ( 'Current account is not an owner of this MSafe' )
1023+ }
1024+
1025+ console . log ( 'Found public key index:' , pkIndex , 'for public key:' , currentAccountPubKey )
1026+ const signerAccount : IAccount = {
1027+ address : new HexString ( account . address . toString ( ) ) ,
1028+ publicKey : ( ) => {
1029+ if ( ! account . publicKey ) {
1030+ throw new Error ( "Public key not available from wallet" ) ;
1031+ }
1032+ // Convert the public key string to Ed25519PublicKey
1033+ const publicKeyBytes = new HexString ( account . publicKey . toString ( ) ) . toUint8Array ( ) ;
1034+ return new TxnBuilderTypes . Ed25519PublicKey ( publicKeyBytes ) ;
1035+ }
1036+ } ;
1037+ const submitSignatureTx = await makeSubmitSignatureTxn (
1038+ signerAccount ,
1039+ msafeTransaction . hash . hex ( ) ,
1040+ pkIndex ,
1041+ new HexString ( selectedAccount . address ) ,
1042+ s ,
1043+ {
1044+ maxGas : 100000n ,
1045+ gasPrice : 100n ,
1046+ expirationSec : 30 , // 30 seconds
1047+ chainID : 1 , // mainnet,
1048+ sequenceNumber : await getAccountSequenceNumber ( account . address . toString ( ) ) ,
1049+ estimateGasPrice : true ,
1050+ estimateMaxGas : true
1051+ }
1052+ )
1053+
1054+ const signedTx = await msafeAccount . sign ( submitSignatureTx . raw )
1055+ const aptosClient = new ( await import ( 'aptos' ) ) . AptosClient ( 'https://fullnode.mainnet.aptoslabs.com' ) ;
1056+ const txRes = await aptosClient . submitSignedBCSTransaction ( signedTx )
1057+ console . log ( 'Transaction submitted:' , txRes )
1058+ const committedTx = await aptos . transaction . waitForTransaction ( {
1059+ transactionHash : txRes . hash
1060+ } )
1061+ console . log ( 'Committed transaction:' , committedTx )
1062+ await loadWithdrawalRequests ( )
1063+ await checkRegistration ( ) ;
1064+ return ;
1065+ } catch ( error ) {
1066+ console . error ( 'Failed to reject msafe transaction:' , error )
1067+ }
1068+ } , [ selectedAccount , account , loadWithdrawalRequests , checkRegistration , aptos . transaction , getMSafeInfo , getAccountSequenceNumber ] )
1069+
9861070 // Load balances for selected account
9871071 const loadAccountBalances = useCallback ( async ( account : MSafeAccount ) => {
9881072 if ( account . isLoadingBalances ) return
@@ -1351,6 +1435,7 @@ export function MSafeAccountList({ onAccountSelect }: MSafeAccountListProps) {
13511435 const token = request . fa_metadata ?. inner ;
13521436 const tokenData = getTokenData ( token ) ;
13531437 const amount = request . amount ? parseFloat ( request . amount ) / Math . pow ( 10 , tokenData ?. decimals || 8 ) : 0 ;
1438+ const isExecuted = request . status ?. __variant__ === 'Executed'
13541439
13551440 // Check if there's a pending transaction for this request
13561441 let hasPendingTx = false
@@ -1410,7 +1495,7 @@ export function MSafeAccountList({ onAccountSelect }: MSafeAccountListProps) {
14101495 < b > Sequence Number:</ b > { msafeTransactions . map ( tx => tx . sn ) . join ( ', ' ) }
14111496 </ div >
14121497 ) }
1413- { ( hasPayload && ! hasPendingTx && ! pendingTxInfo ) && (
1498+ { ( hasPayload && ! hasPendingTx && ! pendingTxInfo && ! isExecuted ) && (
14141499 < LoadingButton
14151500 size = "sm"
14161501 loading = { isSigning }
@@ -1548,7 +1633,6 @@ export function MSafeAccountList({ onAccountSelect }: MSafeAccountListProps) {
15481633 { transactions . map ( ( tx , txIndex ) => {
15491634 const threshold = registryData ?. threshold . get ( tx . sender . hex ( ) ) || 'N/A'
15501635 const isExpired = tx . expiration . getTime ( ) < new Date ( ) . getTime ( )
1551- console . log ( 'tx' , tx )
15521636
15531637 return (
15541638 < tr key = { `${ sn } -${ txIndex } ` } className = { `border-b ${ isExpired ? 'bg-red-50 dark:bg-red-950/20' : '' } ` } >
@@ -1603,9 +1687,21 @@ export function MSafeAccountList({ onAccountSelect }: MSafeAccountListProps) {
16031687 >
16041688 { tx . isSigned ? 'Completed' : isExpired ? 'Expired' : 'Sign & Send' }
16051689 </ LoadingButton >
1690+ { ! isExpired ? (
1691+ < LoadingButton
1692+ loading = { false }
1693+ size = "sm"
1694+ onClick = { ( ) => rejectMsafeTransaction ( tx ) }
1695+ disabled = { tx . isSigned }
1696+ className = "text-xs"
1697+ >
1698+ Reject
1699+ </ LoadingButton >
1700+ ) : (
16061701 < span className = "text-xs text-red-600 dark:text-red-400 text-center" >
16071702 Exp: { tx . expiration . toLocaleString ( ) }
16081703 </ span >
1704+ ) }
16091705 </ div >
16101706 </ td >
16111707 </ tr >
0 commit comments