Files
solace-bg-dubai/frontend/app/settings/page.tsx
defiQUG c94eb595f8
Some checks failed
CI / lint-and-test (push) Has been cancelled
Initial commit: add .gitignore and README
2026-02-09 21:51:53 -08:00

194 lines
6.8 KiB
TypeScript

"use client";
import { useState } from "react";
import { useAccount, useWriteContract, useReadContract } from "wagmi";
import { WalletConnect } from "@/components/web3/WalletConnect";
import { TREASURY_WALLET_ABI, CONTRACT_ADDRESSES } from "@/lib/web3/contracts";
import { formatAddress, isAddress } from "@/lib/utils";
import { getAddress } from "viem";
export default function SettingsPage() {
const { isConnected } = useAccount();
const { writeContract } = useWriteContract();
const [newSigner, setNewSigner] = useState("");
const [signerToRemove, setSignerToRemove] = useState("");
const [newThreshold, setNewThreshold] = useState("");
// TODO: Fetch owners and threshold from contract
const { data: owners } = useReadContract({
address: CONTRACT_ADDRESSES.TreasuryWallet as `0x${string}`,
abi: TREASURY_WALLET_ABI,
functionName: "getOwners",
});
const { data: threshold } = useReadContract({
address: CONTRACT_ADDRESSES.TreasuryWallet as `0x${string}`,
abi: TREASURY_WALLET_ABI,
functionName: "threshold",
});
if (!isConnected) {
return (
<div className="min-h-screen p-8">
<div className="max-w-4xl mx-auto">
<WalletConnect />
</div>
</div>
);
}
const handleAddSigner = async () => {
if (!isAddress(newSigner) || !CONTRACT_ADDRESSES.TreasuryWallet) return;
await writeContract({
address: CONTRACT_ADDRESSES.TreasuryWallet as `0x${string}`,
abi: TREASURY_WALLET_ABI,
functionName: "addOwner",
args: [getAddress(newSigner)],
});
setNewSigner("");
};
const handleRemoveSigner = async () => {
if (!isAddress(signerToRemove) || !CONTRACT_ADDRESSES.TreasuryWallet) return;
await writeContract({
address: CONTRACT_ADDRESSES.TreasuryWallet as `0x${string}`,
abi: TREASURY_WALLET_ABI,
functionName: "removeOwner",
args: [getAddress(signerToRemove)],
});
setSignerToRemove("");
};
const handleChangeThreshold = async () => {
const thresholdNum = parseInt(newThreshold);
if (isNaN(thresholdNum) || !CONTRACT_ADDRESSES.TreasuryWallet) return;
await writeContract({
address: CONTRACT_ADDRESSES.TreasuryWallet as `0x${string}`,
abi: TREASURY_WALLET_ABI,
functionName: "changeThreshold",
args: [BigInt(thresholdNum)],
});
setNewThreshold("");
};
return (
<div className="min-h-screen p-8">
<div className="max-w-4xl mx-auto">
<header className="flex justify-between items-center mb-8">
<h1 className="text-3xl font-bold">Treasury Settings</h1>
<WalletConnect />
</header>
<div className="space-y-6">
{/* Current Configuration */}
<div className="bg-gray-900 rounded-xl p-8">
<h2 className="text-2xl font-semibold mb-4">Current Configuration</h2>
<div className="space-y-4">
<div>
<label className="block text-sm font-medium mb-2">Threshold</label>
<div className="text-lg">
{threshold?.toString()} of {owners?.length || 0} signers required
</div>
</div>
<div>
<label className="block text-sm font-medium mb-2">Signers</label>
<div className="space-y-2">
{owners?.map((owner, index) => (
<div
key={owner}
className="bg-gray-800 rounded-lg p-3 flex justify-between items-center"
>
<span className="font-mono text-sm">{formatAddress(owner)}</span>
{index === 0 && (
<span className="text-xs text-gray-400">(Deployer)</span>
)}
</div>
))}
</div>
</div>
</div>
</div>
{/* Add Signer */}
<div className="bg-gray-900 rounded-xl p-8">
<h2 className="text-2xl font-semibold mb-4">Add Signer</h2>
<div className="flex gap-4">
<input
type="text"
value={newSigner}
onChange={(e) => setNewSigner(e.target.value)}
placeholder="0x..."
className="flex-1 bg-gray-800 rounded-lg p-3 font-mono text-sm"
/>
<button
onClick={handleAddSigner}
disabled={!isAddress(newSigner)}
className="px-6 py-3 bg-green-600 hover:bg-green-700 disabled:bg-gray-700 disabled:cursor-not-allowed rounded-lg transition-colors"
>
Add
</button>
</div>
</div>
{/* Remove Signer */}
<div className="bg-gray-900 rounded-xl p-8">
<h2 className="text-2xl font-semibold mb-4">Remove Signer</h2>
<div className="bg-yellow-900/20 border border-yellow-600 rounded-lg p-4 mb-4">
<p className="text-sm text-yellow-300">
Warning: Removing a signer requires maintaining threshold validity. You
cannot remove a signer if it would break the current threshold.
</p>
</div>
<div className="flex gap-4">
<input
type="text"
value={signerToRemove}
onChange={(e) => setSignerToRemove(e.target.value)}
placeholder="0x..."
className="flex-1 bg-gray-800 rounded-lg p-3 font-mono text-sm"
/>
<button
onClick={handleRemoveSigner}
disabled={!isAddress(signerToRemove)}
className="px-6 py-3 bg-red-600 hover:bg-red-700 disabled:bg-gray-700 disabled:cursor-not-allowed rounded-lg transition-colors"
>
Remove
</button>
</div>
</div>
{/* Change Threshold */}
<div className="bg-gray-900 rounded-xl p-8">
<h2 className="text-2xl font-semibold mb-4">Change Threshold</h2>
<div className="flex gap-4">
<input
type="number"
value={newThreshold}
onChange={(e) => setNewThreshold(e.target.value)}
placeholder={`Current: ${threshold?.toString()}`}
min="1"
max={owners?.length || 1}
className="flex-1 bg-gray-800 rounded-lg p-3"
/>
<button
onClick={handleChangeThreshold}
disabled={!newThreshold}
className="px-6 py-3 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-700 disabled:cursor-not-allowed rounded-lg transition-colors"
>
Update
</button>
</div>
</div>
</div>
</div>
</div>
);
}