11"use client" ;
22
3- import React , { useState } from "react" ;
3+ import React , { useEffect , useState } from "react" ;
4+ import Image from "next/image" ;
45import { Button } from "../ui/button" ;
56import { Dialog , DialogContent , DialogTitle , DialogTrigger } from "../ui/dialog" ;
67import { Input } from "../ui/input" ;
78import { ConfirmDialog } from "./Confirm" ;
89import { TxType , encodeAddSigner , encodeRemoveSigner , encodeUpdateThreshold } from "@polypay/shared" ;
910import { Copy , Repeat , Trash2 , X } from "lucide-react" ;
10- import { useMetaMultiSigWallet , useUpdateAccount , useUpdateWallet } from "~~/hooks" ;
11- import { useCreateTransaction , useReserveNonce } from "~~/hooks/api/useTransaction" ;
11+ import { useMetaMultiSigWallet , useUpdateWallet , useWalletCommitments , useWalletThreshold } from "~~/hooks" ;
12+ import { useCreateTransaction } from "~~/hooks/api/useTransaction" ;
1213import { useGenerateProof } from "~~/hooks/app/useGenerateProof" ;
1314import { useIdentityStore , useWalletStore } from "~~/services/store" ;
1415import { notification } from "~~/utils/scaffold-eth" ;
1516
1617interface EditAccountModalProps {
1718 children : React . ReactNode ;
18- signers : string [ ] ; // commitments
19- threshold : number ;
20- accountName ?: string ;
2119}
2220
23- export const EditAccountModal : React . FC < EditAccountModalProps > = ( {
24- children,
25- signers = [ ] ,
26- threshold = 0 ,
27- accountName = "" ,
28- } ) => {
21+ export const EditAccountModal : React . FC < EditAccountModalProps > = ( { children } ) => {
2922 const [ isOpen , setIsOpen ] = useState ( false ) ;
30- const [ editThreshold , setEditThreshold ] = useState ( threshold ) ;
23+ const [ editThreshold , setEditThreshold ] = useState ( 0 ) ;
3124 const [ newSignerCommitment , setNewSignerCommitment ] = useState ( "" ) ;
3225 const [ loading , setLoading ] = useState ( false ) ;
3326 const [ loadingState , setLoadingState ] = useState ( "" ) ;
34- const [ editName , setEditName ] = useState ( accountName || "" ) ;
27+ const [ editName , setEditName ] = useState ( "" ) ;
3528 const { commitment } = useIdentityStore ( ) ;
3629 const { mutateAsync : updateWallet , isPending : isUpdatingWallet } = useUpdateWallet ( ) ;
37-
3830 const { currentWallet, setCurrentWallet } = useWalletStore ( ) ;
39-
4031 const metaMultiSigWallet = useMetaMultiSigWallet ( ) ;
4132 const { generateProof } = useGenerateProof ( {
4233 onLoadingStateChange : setLoadingState ,
4334 } ) ;
44- const { mutateAsync : reserveNonce } = useReserveNonce ( ) ;
4535 const { mutateAsync : createTransaction } = useCreateTransaction ( ) ;
4636
47- const newThresholdForAdd = editThreshold ;
48- const newThresholdForRemove = editThreshold ;
37+ const { data : thresholdData , refetch : refetchThreshold } = useWalletThreshold ( ) ;
38+ const { data : commitmentsData , refetch : refetchCommitments } = useWalletCommitments ( ) ;
39+
40+ const threshold = Number ( thresholdData ?? 0 ) ;
41+ const signers = commitmentsData ? commitmentsData . map ( ( c : bigint ) => c . toString ( ) ) : [ ] ;
42+ const accountName = currentWallet ?. name ?? "Default" ;
4943
5044 const handleGenerateName = ( ) => {
5145 const randomName = `Wallet-${ Math . random ( ) . toString ( 36 ) . substring ( 2 , 8 ) } ` ;
5246 setEditName ( randomName ) ;
5347 } ;
5448
55- // ============ Update Account Name ============
5649 const handleUpdateName = async ( ) => {
5750 if ( ! commitment || ! editName . trim ( ) ) return ;
5851
@@ -75,54 +68,46 @@ export const EditAccountModal: React.FC<EditAccountModalProps> = ({
7568 }
7669 } ;
7770
78- // ============ Add Signer ============
7971 const handleAddSigner = async ( ) => {
8072 if ( ! metaMultiSigWallet || ! newSignerCommitment . trim ( ) ) return ;
8173
82- // Validate
83- if ( newThresholdForAdd < 1 || newThresholdForAdd > signers . length + 1 ) {
74+ if ( editThreshold < 1 || editThreshold > signers . length + 1 ) {
8475 notification . error ( "Invalid threshold value" ) ;
8576 return ;
8677 }
8778
8879 setLoading ( true ) ;
8980 try {
90- // 1. Reserve nonce from backend
91- const { nonce } = await reserveNonce ( metaMultiSigWallet . address ) ;
92-
93- // 2. Get current threshold
81+ const currentNonce = await metaMultiSigWallet . read . nonce ( ) ;
9482 const currentThreshold = await metaMultiSigWallet . read . signaturesRequired ( ) ;
95-
96- // 3. Build callData for addSigner
97- const callData = encodeAddSigner ( newSignerCommitment , newThresholdForAdd ) ;
98-
99- // 4. Get txHash from contract
83+ const callData = encodeAddSigner ( newSignerCommitment , editThreshold ) ;
10084 const txHash = ( await metaMultiSigWallet . read . getTransactionHash ( [
101- BigInt ( nonce ) ,
85+ currentNonce ,
10286 metaMultiSigWallet . address ,
10387 0n ,
10488 callData ,
10589 ] ) ) as `0x${string } `;
10690
107- // 5. Generate proof
10891 const { proof, publicInputs, nullifier, commitment : myCommitment } = await generateProof ( txHash ) ;
10992
110- // 6. Submit to backend
11193 setLoadingState ( "Submitting to backend..." ) ;
11294 await createTransaction ( {
113- nonce,
95+ nonce : Number ( currentNonce ) ,
11496 type : TxType . ADD_SIGNER ,
11597 walletAddress : metaMultiSigWallet . address ,
11698 threshold : Number ( currentThreshold ) ,
11799 totalSigners : signers . length ,
118100 signerCommitment : newSignerCommitment . trim ( ) ,
119- newThreshold : newThresholdForAdd ,
101+ newThreshold : editThreshold ,
120102 creatorCommitment : myCommitment ,
121103 proof,
122104 publicInputs,
123105 nullifier,
124106 } ) ;
125107
108+ await refetchCommitments ( ) ;
109+ await refetchThreshold ( ) ;
110+
126111 notification . success ( "Add signer transaction created!" ) ;
127112 setNewSignerCommitment ( "" ) ;
128113 setIsOpen ( false ) ;
@@ -134,7 +119,7 @@ export const EditAccountModal: React.FC<EditAccountModalProps> = ({
134119 setLoadingState ( "" ) ;
135120 }
136121 } ;
137- // ============ Remove Signer ============
122+
138123 const handleRemoveSigner = async ( signerCommitment : string ) => {
139124 if ( ! metaMultiSigWallet ) return ;
140125
@@ -143,43 +128,33 @@ export const EditAccountModal: React.FC<EditAccountModalProps> = ({
143128 return ;
144129 }
145130
146- let newThreshold = newThresholdForRemove ;
131+ let newThreshold = editThreshold ;
147132 if ( newThreshold > signers . length - 1 ) {
148133 newThreshold = signers . length - 1 ;
149134 }
150135
151- // Validate threshold
152136 if ( newThreshold < 1 || newThreshold > signers . length - 1 ) {
153137 notification . error ( "Invalid threshold value for removal" ) ;
154138 return ;
155139 }
156140
157141 setLoading ( true ) ;
158142 try {
159- // 1. Reserve nonce from backend
160- const { nonce } = await reserveNonce ( metaMultiSigWallet . address ) ;
161-
162- // 2. Get current threshold
143+ const currentNonce = await metaMultiSigWallet . read . nonce ( ) ;
163144 const currentThreshold = await metaMultiSigWallet . read . signaturesRequired ( ) ;
164-
165- // 3. Build callData for removeSigner
166145 const callData = encodeRemoveSigner ( signerCommitment , newThreshold ) ;
167-
168- // 4. Get txHash
169146 const txHash = ( await metaMultiSigWallet . read . getTransactionHash ( [
170- BigInt ( nonce ) ,
147+ currentNonce ,
171148 metaMultiSigWallet . address ,
172149 0n ,
173150 callData ,
174151 ] ) ) as `0x${string } `;
175152
176- // 5. Generate proof
177153 const { proof, publicInputs, nullifier, commitment : myCommitment } = await generateProof ( txHash ) ;
178154
179- // 6. Submit to backend
180155 setLoadingState ( "Submitting to backend..." ) ;
181156 await createTransaction ( {
182- nonce,
157+ nonce : Number ( currentNonce ) ,
183158 type : TxType . REMOVE_SIGNER ,
184159 walletAddress : metaMultiSigWallet . address ,
185160 threshold : Number ( currentThreshold ) ,
@@ -192,6 +167,9 @@ export const EditAccountModal: React.FC<EditAccountModalProps> = ({
192167 nullifier,
193168 } ) ;
194169
170+ await refetchCommitments ( ) ;
171+ await refetchThreshold ( ) ;
172+
195173 notification . success ( "Remove signer transaction created!" ) ;
196174 setIsOpen ( false ) ;
197175 } catch ( error : any ) {
@@ -203,7 +181,6 @@ export const EditAccountModal: React.FC<EditAccountModalProps> = ({
203181 }
204182 } ;
205183
206- // ============ Update Threshold ============
207184 const handleUpdateThreshold = async ( ) => {
208185 if ( ! metaMultiSigWallet ) return ;
209186
@@ -219,30 +196,21 @@ export const EditAccountModal: React.FC<EditAccountModalProps> = ({
219196
220197 setLoading ( true ) ;
221198 try {
222- // 1. Reserve nonce from backend
223- const { nonce } = await reserveNonce ( metaMultiSigWallet . address ) ;
224-
225- // 2. Get current threshold
199+ const currentNonce = await metaMultiSigWallet . read . nonce ( ) ;
226200 const currentThreshold = await metaMultiSigWallet . read . signaturesRequired ( ) ;
227-
228- // 3. Build callData for updateSignaturesRequired
229201 const callData = encodeUpdateThreshold ( editThreshold ) ;
230-
231- // 4. Get txHash
232202 const txHash = ( await metaMultiSigWallet . read . getTransactionHash ( [
233- BigInt ( nonce ) ,
203+ currentNonce ,
234204 metaMultiSigWallet . address ,
235205 0n ,
236206 callData ,
237207 ] ) ) as `0x${string } `;
238208
239- // 5. Generate proof
240209 const { proof, publicInputs, nullifier, commitment : myCommitment } = await generateProof ( txHash ) ;
241210
242- // 6. Submit to backend
243211 setLoadingState ( "Submitting to backend..." ) ;
244212 await createTransaction ( {
245- nonce,
213+ nonce : Number ( currentNonce ) ,
246214 type : TxType . SET_THRESHOLD ,
247215 walletAddress : metaMultiSigWallet . address ,
248216 threshold : Number ( currentThreshold ) ,
@@ -254,6 +222,8 @@ export const EditAccountModal: React.FC<EditAccountModalProps> = ({
254222 nullifier,
255223 } ) ;
256224
225+ await refetchThreshold ( ) ;
226+
257227 notification . success ( "Update threshold transaction created!" ) ;
258228 setIsOpen ( false ) ;
259229 } catch ( error : any ) {
@@ -265,31 +235,35 @@ export const EditAccountModal: React.FC<EditAccountModalProps> = ({
265235 }
266236 } ;
267237
268- // ============ Copy to Clipboard ============
269238 const copyToClipboard = ( text : string ) => {
270239 navigator . clipboard . writeText ( text ) ;
271240 notification . success ( "Copied to clipboard" ) ;
272241 } ;
273242
274- React . useEffect ( ( ) => {
243+ useEffect ( ( ) => {
244+ if ( isOpen ) {
245+ refetchThreshold ( ) ;
246+ refetchCommitments ( ) ;
247+ }
248+ } , [ isOpen , refetchThreshold , refetchCommitments ] ) ;
249+
250+ useEffect ( ( ) => {
275251 if ( isOpen ) {
276252 setEditThreshold ( threshold ) ;
277253 setEditName ( accountName || "" ) ;
278254 }
279255 } , [ isOpen , threshold , accountName ] ) ;
280256
281- // ============ Render ============
282257 return (
283258 < Dialog open = { isOpen } onOpenChange = { setIsOpen } >
284259 < DialogTrigger asChild > { children } </ DialogTrigger >
285260 < DialogContent className = "sm:max-w-[600px] max-h-[80vh] p-0 overflow-hidden" showCloseButton = { false } >
286261 < DialogTitle hidden > </ DialogTitle >
287262 < div className = "flex flex-col h-full bg-white rounded-lg" >
288- { /* Header */ }
289263 < div className = "flex flex-row items-center justify-between p-3 m-1 border-b bg-[#EDEDED] rounded-xl" >
290264 < div className = "flex items-center gap-3" >
291265 < div className = "rounded-full bg-gray-200 flex items-center justify-center" >
292- < img src = { "/common/edit-wallet.svg" } alt = "Edit wallet" />
266+ < Image src = "/common/edit-wallet.svg" alt = "Edit wallet" width = { 40 } height = { 40 } />
293267 </ div >
294268 < span className = "flex flex-col" >
295269 < span className = "text-lg font-semibold text-black" > EDIT YOUR WALLET</ span >
@@ -315,14 +289,11 @@ export const EditAccountModal: React.FC<EditAccountModalProps> = ({
315289 </ Button >
316290 </ div >
317291
318- { /* Loading State */ }
319292 { loading && loadingState && (
320293 < div className = "px-6 py-2 bg-blue-50 text-blue-700 text-sm text-center" > { loadingState } </ div >
321294 ) }
322295
323- { /* Content */ }
324296 < div className = "flex-1 overflow-y-auto p-6 pt-3 space-y-6" >
325- { /* Account Name Section */ }
326297 < div className = "mb-6" >
327298 < h3 className = "font-semibold text-gray-900" > ACCOUNT NAME</ h3 >
328299 < p className = "text-sm text-gray-500 mb-4" > Give your account a name to easily identify it.</ p >
@@ -366,15 +337,13 @@ export const EditAccountModal: React.FC<EditAccountModalProps> = ({
366337 </ Button >
367338 </ div >
368339
369- { /* Wallet Signers Section */ }
370340 < div >
371341 < h3 className = "font-semibold text-gray-900" > WALLET SIGNERS</ h3 >
372342 < p className = "text-sm text-gray-500 mb-4" >
373343 Commitments added to the signers list below will be able to approve transactions. Each signer is
374344 identified by their commitment (hash of secret).
375345 </ p >
376346
377- { /* Existing Signers */ }
378347 < div className = "space-y-3 mb-4" >
379348 { signers . map ( ( signer , index ) => (
380349 < div key = { index } className = "flex items-center justify-between p-3 border rounded" >
@@ -389,7 +358,6 @@ export const EditAccountModal: React.FC<EditAccountModalProps> = ({
389358 < Copy className = "h-4 w-4" />
390359 </ Button >
391360
392- { /* Remove Signer with Threshold Input */ }
393361 < ConfirmDialog
394362 title = "Remove Signer"
395363 description = "Are you sure you want to remove this signer?"
@@ -408,7 +376,6 @@ export const EditAccountModal: React.FC<EditAccountModalProps> = ({
408376 ) ) }
409377 </ div >
410378
411- { /* Add New Signer */ }
412379 < div className = "space-y-3 p-3 border border-dashed border-gray-300 rounded-lg" >
413380 < Input
414381 placeholder = "Enter new signer commitment"
@@ -429,7 +396,6 @@ export const EditAccountModal: React.FC<EditAccountModalProps> = ({
429396 </ div >
430397 </ div >
431398
432- { /* Threshold Section */ }
433399 < div >
434400 < h3 className = "font-semibold text-gray-900 mb-2" > THRESHOLD</ h3 >
435401 < p className = "text-sm text-gray-500 mb-4" >
0 commit comments