Skip to content

Commit bc00729

Browse files
authored
Merge pull request #190 from MeshJS/feature/UX-info-page
Refactor wallet authorization and session handling
2 parents ef325eb + fb11e7d commit bc00729

File tree

18 files changed

+694
-122
lines changed

18 files changed

+694
-122
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"db:studio": "prisma studio",
1313
"db:update": "prisma format && prisma db push && prisma generate",
1414
"dev": "next dev",
15-
"postinstall": "prisma format && prisma generate",
15+
"postinstall": "prisma generate",
1616
"lint": "next lint",
1717
"start": "next start",
1818
"test": "jest",

src/components/common/modals/WalletAuthModal.tsx

Lines changed: 79 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState } from "react";
1+
import { useState, useEffect, useCallback } from "react";
22
import { useWallet } from "@meshsdk/react";
33
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog";
44
import { Button } from "@/components/ui/button";
@@ -9,14 +9,16 @@ interface WalletAuthModalProps {
99
open: boolean;
1010
onClose: () => void;
1111
onAuthorized?: () => void;
12+
autoAuthorize?: boolean; // If true, automatically trigger authorization when modal opens
1213
}
1314

14-
export function WalletAuthModal({ address, open, onClose, onAuthorized }: WalletAuthModalProps) {
15+
export function WalletAuthModal({ address, open, onClose, onAuthorized, autoAuthorize = false }: WalletAuthModalProps) {
1516
const { wallet, connected } = useWallet();
1617
const { toast } = useToast();
1718
const [submitting, setSubmitting] = useState(false);
19+
const [hasAutoAuthorized, setHasAutoAuthorized] = useState(false);
1820

19-
const handleAuthorize = async () => {
21+
const handleAuthorize = useCallback(async () => {
2022
if (!wallet || !connected) {
2123
toast({
2224
title: "No wallet connected",
@@ -27,11 +29,33 @@ export function WalletAuthModal({ address, open, onClose, onAuthorized }: Wallet
2729
}
2830
setSubmitting(true);
2931
try {
30-
// Resolve the payment address the wallet uses (match Swagger flow)
31-
const usedAddresses = await wallet.getUsedAddresses();
32-
const signingAddress = usedAddresses[0];
32+
// Resolve the payment address the wallet uses
33+
// Try used addresses first, fall back to unused addresses if needed
34+
let signingAddress: string | undefined;
35+
try {
36+
const usedAddresses = await wallet.getUsedAddresses();
37+
signingAddress = usedAddresses[0];
38+
} catch (error) {
39+
if (error instanceof Error && error.message.includes("account changed")) {
40+
throw error;
41+
}
42+
// If getUsedAddresses fails for other reasons, try unused addresses
43+
}
44+
45+
// Fall back to unused addresses if no used addresses found
46+
if (!signingAddress) {
47+
try {
48+
const unusedAddresses = await wallet.getUnusedAddresses();
49+
signingAddress = unusedAddresses[0];
50+
} catch (error) {
51+
if (error instanceof Error && error.message.includes("account changed")) {
52+
throw error;
53+
}
54+
}
55+
}
56+
3357
if (!signingAddress) {
34-
throw new Error("No used addresses found for wallet");
58+
throw new Error("No addresses found for wallet");
3559
}
3660

3761
// 1) Get nonce from existing endpoint
@@ -100,7 +124,6 @@ export function WalletAuthModal({ address, open, onClose, onAuthorized }: Wallet
100124
onAuthorized?.();
101125
onClose();
102126
} catch (error: any) {
103-
console.error("WalletAuthModal authorize error:", error);
104127
toast({
105128
title: "Authorization failed",
106129
description: error?.message || "Unable to authorize wallet. Please try again.",
@@ -109,16 +132,56 @@ export function WalletAuthModal({ address, open, onClose, onAuthorized }: Wallet
109132
} finally {
110133
setSubmitting(false);
111134
}
112-
};
135+
}, [wallet, connected, toast, onAuthorized, onClose]);
136+
137+
// Auto-authorize when modal opens if autoAuthorize is true (only once)
138+
useEffect(() => {
139+
if (open && autoAuthorize && !hasAutoAuthorized && wallet && connected && !submitting) {
140+
// Small delay to ensure modal is fully rendered before triggering wallet prompt
141+
const timeoutId = setTimeout(() => {
142+
setHasAutoAuthorized(true);
143+
void handleAuthorize();
144+
}, 100);
145+
146+
return () => clearTimeout(timeoutId);
147+
}
148+
}, [open, autoAuthorize, hasAutoAuthorized, wallet, connected, submitting, handleAuthorize]);
149+
150+
// Reset auto-authorize flag when modal closes
151+
useEffect(() => {
152+
if (!open) {
153+
setHasAutoAuthorized(false);
154+
}
155+
}, [open]);
113156

114157
return (
115-
<Dialog open={open} onOpenChange={(open) => !open && !submitting && onClose()}>
116-
<DialogContent>
158+
<Dialog open={open} onOpenChange={(open) => {
159+
// Prevent closing during authorization
160+
if (!open && !submitting) {
161+
onClose();
162+
}
163+
}}>
164+
<DialogContent onPointerDownOutside={(e) => {
165+
// Prevent closing by clicking outside during authorization
166+
if (submitting) {
167+
e.preventDefault();
168+
}
169+
}} onEscapeKeyDown={(e) => {
170+
// Prevent closing with Escape key during authorization
171+
if (submitting) {
172+
e.preventDefault();
173+
}
174+
}}>
117175
<DialogHeader>
118176
<DialogTitle>Authorize this wallet</DialogTitle>
119177
<DialogDescription>
120178
To use this wallet with multisig, we need to confirm you control it by signing a
121179
short message. This does not move any funds or create a transaction.
180+
{autoAuthorize && !hasAutoAuthorized && (
181+
<span className="block mt-2 text-sm font-medium">
182+
Please approve the signing request in your wallet.
183+
</span>
184+
)}
122185
</DialogDescription>
123186
</DialogHeader>
124187
<div className="mt-4 space-y-2 text-sm text-muted-foreground break-all">
@@ -127,9 +190,11 @@ export function WalletAuthModal({ address, open, onClose, onAuthorized }: Wallet
127190
</div>
128191
</div>
129192
<div className="mt-6 flex justify-end gap-2">
130-
<Button variant="outline" onClick={onClose} disabled={submitting}>
131-
Cancel
132-
</Button>
193+
{!autoAuthorize && (
194+
<Button variant="outline" onClick={onClose} disabled={submitting}>
195+
Cancel
196+
</Button>
197+
)}
133198
<Button onClick={handleAuthorize} disabled={submitting}>
134199
{submitting ? "Authorizing..." : "Authorize"}
135200
</Button>

0 commit comments

Comments
 (0)