Skip to content

Commit 7ce6ef0

Browse files
committed
s11
1 parent c1fe24b commit 7ce6ef0

File tree

13 files changed

+1450
-117
lines changed

13 files changed

+1450
-117
lines changed

src/components/multisig/proxy/ProxyControl.tsx

Lines changed: 107 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ import ProxySpend from "./ProxySpend";
1414
import UTxOSelector from "@/components/pages/wallet/new-transaction/utxoSelector";
1515
import { getProvider } from "@/utils/get-provider";
1616
import { MeshTxBuilder, UTxO } from "@meshsdk/core";
17+
import { useProxy } from "@/hooks/useProxy";
1718

1819
import { Alert, AlertDescription } from "@/components/ui/alert";
1920
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
2021
import { Card, CardContent, CardHeader } from "@/components/ui/card";
2122
import { Button } from "@/components/ui/button";
2223
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
23-
import { AlertCircle, ChevronDown, ChevronUp, Wallet, TrendingUp, Info } from "lucide-react";
24+
import { AlertCircle, ChevronDown, ChevronUp, Wallet, TrendingUp, Info, UserCheck, UserX } from "lucide-react";
2425

2526
interface ProxyOutput {
2627
address: string;
@@ -43,6 +44,7 @@ export default function ProxyControl() {
4344
const { appWallet } = useAppWallet();
4445
const ctx = api.useUtils();
4546
const { newTransaction } = useTransaction();
47+
const { isProxyEnabled, selectedProxyId, setSelectedProxy, clearSelectedProxy, toggleProxy } = useProxy();
4648

4749

4850

@@ -90,10 +92,14 @@ export default function ProxyControl() {
9092
const [proxyBalance, setProxyBalance] = useState<Array<{ unit: string; quantity: string }>>([]);
9193
const [isProxySetup, setIsProxySetup] = useState<boolean>(false);
9294
const [loading, setLocalLoading] = useState<boolean>(false);
93-
const [selectedProxy, setSelectedProxy] = useState<string>("");
9495
const [selectedProxyBalance, setSelectedProxyBalance] = useState<Array<{ unit: string; quantity: string }>>([]);
9596
const [allProxyBalances, setAllProxyBalances] = useState<Record<string, Array<{ unit: string; quantity: string }>>>({});
9697
const [tvlLoading, setTvlLoading] = useState<boolean>(false);
98+
99+
// DRep information state
100+
const [selectedProxyDrepId, setSelectedProxyDrepId] = useState<string>("");
101+
const [selectedProxyDrepStatus, setSelectedProxyDrepStatus] = useState<any>(null);
102+
const [drepLoading, setDrepLoading] = useState<boolean>(false);
97103

98104
// Setup flow state
99105
const [setupStep, setSetupStep] = useState<number>(0);
@@ -133,6 +139,7 @@ export default function ProxyControl() {
133139
if (!utxos || utxos.length === 0) {
134140
throw new Error("No UTxOs found at multisig wallet address");
135141
}
142+
136143
console.log("utxos", utxos);
137144
console.log("walletAddress", appWallet.address);
138145
return { utxos, walletAddress: appWallet.address };
@@ -206,8 +213,8 @@ export default function ProxyControl() {
206213
// Reset proxy contract state to prevent policy ID conflicts
207214
proxyContract.reset();
208215

209-
// Use multisig wallet inputs: pass all UTxOs, first >=5 ADA as collateral, and ms wallet address
210-
const { utxos, collateral, walletAddress } = await getMsInputs();
216+
// Use multisig wallet inputs: pass all UTxOs and ms wallet address
217+
const { utxos, walletAddress } = await getMsInputs();
211218
const result: ProxySetupResult = await proxyContract.setupProxy(utxos, walletAddress);
212219

213220
setSetupData({
@@ -341,10 +348,10 @@ export default function ProxyControl() {
341348
}, []);
342349

343350
const handleStartSpending = useCallback(() => {
344-
if (selectedProxy) {
351+
if (selectedProxyId) {
345352
setShowSpendSection(true);
346353
}
347-
}, [selectedProxy]);
354+
}, [selectedProxyId]);
348355

349356
const handleCloseSetup = useCallback(() => {
350357
setShowSetupModal(false);
@@ -387,6 +394,40 @@ export default function ProxyControl() {
387394
}
388395
}, [proxyContract, network, wallet]);
389396

397+
// Get DRep information for a specific proxy
398+
const getProxyDrepInfo = useCallback(async (proxy: any) => {
399+
if (!proxy) return { drepId: "", status: null };
400+
401+
try {
402+
setDrepLoading(true);
403+
404+
// Create a temporary contract instance for this proxy
405+
const tempContract = new MeshProxyContract(
406+
{
407+
mesh: getTxBuilder(network),
408+
wallet: wallet,
409+
networkId: network,
410+
},
411+
{
412+
paramUtxo: JSON.parse(proxy.paramUtxo),
413+
},
414+
appWallet?.scriptCbor || undefined,
415+
);
416+
tempContract.proxyAddress = proxy.proxyAddress;
417+
418+
// Get DRep ID and status
419+
const drepId = await tempContract.getDrepId();
420+
const status = await tempContract.getDrepStatus();
421+
422+
return { drepId, status };
423+
} catch (error) {
424+
console.error("Get proxy DRep info error:", error);
425+
return { drepId: "", status: null };
426+
} finally {
427+
setDrepLoading(false);
428+
}
429+
}, [network, wallet, appWallet?.scriptCbor]);
430+
390431
// Fetch all proxy balances for TVL calculation
391432
const fetchAllProxyBalances = useCallback(async () => {
392433
if (!proxies || proxies.length === 0 || !proxyContract) return;
@@ -480,10 +521,17 @@ export default function ProxyControl() {
480521
setSelectedProxy(proxyId);
481522
const proxy = proxies?.find((p: any) => p.id === proxyId);
482523
if (proxy) {
483-
const balance = await getProxyBalance(proxy.proxyAddress);
524+
// Fetch both balance and DRep information
525+
const [balance, drepInfo] = await Promise.all([
526+
getProxyBalance(proxy.proxyAddress),
527+
getProxyDrepInfo(proxy)
528+
]);
529+
484530
setSelectedProxyBalance(balance);
531+
setSelectedProxyDrepId(drepInfo.drepId);
532+
setSelectedProxyDrepStatus(drepInfo.status);
485533
}
486-
}, [proxies, getProxyBalance]);
534+
}, [proxies, getProxyBalance, getProxyDrepInfo, setSelectedProxy]);
487535

488536

489537
// Spend from proxy
@@ -497,7 +545,7 @@ export default function ProxyControl() {
497545
return;
498546
}
499547

500-
if (!selectedProxy) {
548+
if (!selectedProxyId) {
501549
toast({
502550
title: "Error",
503551
description: "Please select a proxy to spend from",
@@ -525,7 +573,7 @@ export default function ProxyControl() {
525573
setLoading(true);
526574

527575
// Get the selected proxy
528-
const proxy = proxies?.find((p: any) => p.id === selectedProxy);
576+
const proxy = proxies?.find((p: any) => p.id === selectedProxyId);
529577
if (!proxy) {
530578
throw new Error("Selected proxy not found");
531579
}
@@ -558,7 +606,7 @@ export default function ProxyControl() {
558606
}
559607

560608
// Refresh balance after successful spend
561-
await handleProxySelection(selectedProxy);
609+
await handleProxySelection(selectedProxyId);
562610

563611
// Close the spend modal after successful transaction
564612
setTimeout(() => {
@@ -589,7 +637,7 @@ export default function ProxyControl() {
589637
setSpendLoading(false);
590638
setLoading(false);
591639
}
592-
}, [proxyContract, connected, spendOutputs, selectedProxy, proxies, network, wallet, setLoading, handleProxySelection]);
640+
}, [proxyContract, connected, spendOutputs, selectedProxyId, proxies, network, wallet, setLoading, handleProxySelection]);
593641

594642

595643
// Copy to clipboard
@@ -670,6 +718,48 @@ export default function ProxyControl() {
670718
</div>
671719
</div>
672720
<div className="flex items-center gap-2 sm:gap-4 flex-shrink-0">
721+
{/* Global Proxy Toggle */}
722+
<div className="flex items-center space-x-2">
723+
<div className="relative inline-block w-10 h-5">
724+
<input
725+
type="checkbox"
726+
id="global-proxy-toggle"
727+
checked={isProxyEnabled}
728+
onChange={(e) => {
729+
if (!e.target.checked) {
730+
clearSelectedProxy();
731+
}
732+
toggleProxy();
733+
}}
734+
className="sr-only"
735+
/>
736+
<label
737+
htmlFor="global-proxy-toggle"
738+
className={`block w-10 h-5 rounded-full cursor-pointer transition-colors duration-200 ease-in-out ${
739+
isProxyEnabled ? 'bg-primary' : 'bg-muted'
740+
}`}
741+
>
742+
<span
743+
className={`absolute top-0.5 left-0.5 w-4 h-4 bg-white rounded-full shadow-sm transform transition-transform duration-200 ease-in-out ${
744+
isProxyEnabled ? 'translate-x-5' : 'translate-x-0'
745+
}`}
746+
/>
747+
</label>
748+
</div>
749+
<TooltipProvider>
750+
<Tooltip>
751+
<TooltipTrigger asChild>
752+
<span className="text-xs text-muted-foreground cursor-help">
753+
Global Proxy
754+
</span>
755+
</TooltipTrigger>
756+
<TooltipContent>
757+
<p>Enable proxy functionality across the application</p>
758+
</TooltipContent>
759+
</Tooltip>
760+
</TooltipProvider>
761+
</div>
762+
673763
{/* TVL Display */}
674764
<TooltipProvider>
675765
<Tooltip>
@@ -739,10 +829,13 @@ export default function ProxyControl() {
739829
{/* Overview Section */}
740830
<ProxyOverview
741831
proxies={proxies}
742-
selectedProxy={selectedProxy}
832+
selectedProxy={selectedProxyId}
743833
selectedProxyBalance={selectedProxyBalance}
744834
proxyBalance={proxyBalance}
745835
isProxySetup={isProxySetup}
836+
selectedProxyDrepId={selectedProxyDrepId}
837+
selectedProxyDrepStatus={selectedProxyDrepStatus}
838+
drepLoading={drepLoading}
746839
onProxySelection={handleProxySelection}
747840
onCopyToClipboard={copyToClipboard}
748841
onStartSetup={handleStartSetup}
@@ -779,7 +872,7 @@ export default function ProxyControl() {
779872
</DialogHeader>
780873
<ProxySpend
781874
proxies={proxies}
782-
selectedProxy={selectedProxy}
875+
selectedProxy={selectedProxyId}
783876
selectedProxyBalance={selectedProxyBalance}
784877
spendOutputs={spendOutputs}
785878
spendLoading={spendLoading}

src/components/multisig/proxy/ProxyOverview.tsx

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ import {
2525
TrendingUp,
2626
Edit3,
2727
Save,
28-
X
28+
X,
29+
UserCheck,
30+
UserX,
31+
Users
2932
} from "lucide-react";
3033

3134
// ProxyCard Component
@@ -446,6 +449,9 @@ interface ProxyOverviewProps {
446449
selectedProxyBalance: Array<{ unit: string; quantity: string }>;
447450
proxyBalance: Array<{ unit: string; quantity: string }>;
448451
isProxySetup: boolean;
452+
selectedProxyDrepId: string;
453+
selectedProxyDrepStatus: any;
454+
drepLoading: boolean;
449455
onProxySelection: (proxyId: string) => void;
450456
onCopyToClipboard: (text: string) => void;
451457
onStartSetup: () => void;
@@ -461,6 +467,9 @@ const ProxyOverview = memo(function ProxyOverview({
461467
selectedProxyBalance,
462468
proxyBalance,
463469
isProxySetup,
470+
selectedProxyDrepId,
471+
selectedProxyDrepStatus,
472+
drepLoading,
464473
onProxySelection,
465474
onCopyToClipboard,
466475
onStartSetup,
@@ -490,6 +499,86 @@ const ProxyOverview = memo(function ProxyOverview({
490499
</CardContent>
491500
</Card>
492501
)}
502+
503+
{/* DRep Information Card - Only show when a proxy is selected */}
504+
{selectedProxy && (
505+
<Card>
506+
<CardContent className="p-4">
507+
<div className="flex items-center gap-3 mb-3">
508+
<div className="w-8 h-8 rounded-full bg-blue-500/10 flex items-center justify-center">
509+
<Users className="h-4 w-4 text-blue-500" />
510+
</div>
511+
<div>
512+
<p className="font-medium text-foreground">Proxy DRep Information</p>
513+
<p className="text-sm text-muted-foreground">Delegated Representative details</p>
514+
</div>
515+
</div>
516+
517+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
518+
{/* DRep ID */}
519+
<div className="space-y-2">
520+
<div className="flex items-center gap-2">
521+
<Hash className="h-3 w-3 text-muted-foreground" />
522+
<span className="text-xs font-medium">DRep ID</span>
523+
{selectedProxyDrepId && (
524+
<Button
525+
variant="ghost"
526+
size="sm"
527+
className="h-4 w-4 p-0 ml-auto"
528+
onClick={() => onCopyToClipboard(selectedProxyDrepId)}
529+
>
530+
<Copy className="h-3 w-3" />
531+
</Button>
532+
)}
533+
</div>
534+
<div className="p-2 bg-muted/50 rounded text-xs font-mono break-all">
535+
{drepLoading ? (
536+
<div className="h-4 bg-muted animate-pulse rounded"></div>
537+
) : selectedProxyDrepId ? (
538+
selectedProxyDrepId
539+
) : (
540+
<span className="text-muted-foreground">Not registered</span>
541+
)}
542+
</div>
543+
</div>
544+
545+
{/* DRep Status */}
546+
<div className="space-y-2">
547+
<div className="flex items-center gap-2">
548+
{selectedProxyDrepStatus?.active ? (
549+
<UserCheck className="h-3 w-3 text-green-500" />
550+
) : (
551+
<UserX className="h-3 w-3 text-muted-foreground" />
552+
)}
553+
<span className="text-xs font-medium">Status</span>
554+
</div>
555+
<div className="p-2 bg-muted/50 rounded text-xs">
556+
{drepLoading ? (
557+
<div className="h-4 bg-muted animate-pulse rounded"></div>
558+
) : selectedProxyDrepStatus ? (
559+
<div className="flex items-center gap-2">
560+
<span className={`px-2 py-1 rounded text-xs font-medium ${
561+
selectedProxyDrepStatus.active
562+
? 'bg-green-100 text-green-800 dark:bg-green-900/20 dark:text-green-400'
563+
: 'bg-gray-100 text-gray-800 dark:bg-gray-900/20 dark:text-gray-400'
564+
}`}>
565+
{selectedProxyDrepStatus.active ? 'Active' : 'Inactive'}
566+
</span>
567+
{selectedProxyDrepStatus.amount && (
568+
<span className="text-muted-foreground">
569+
{Math.round(Number(selectedProxyDrepStatus.amount) / 1000000).toLocaleString()}
570+
</span>
571+
)}
572+
</div>
573+
) : (
574+
<span className="text-muted-foreground">Not registered</span>
575+
)}
576+
</div>
577+
</div>
578+
</div>
579+
</CardContent>
580+
</Card>
581+
)}
493582
</div>
494583

495584
{/* Proxy Carousel */}

0 commit comments

Comments
 (0)