Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m18s
CI/CD Pipeline / Security Scanning (push) Successful in 2m53s
CI/CD Pipeline / Lint and Format (push) Failing after 49s
CI/CD Pipeline / Terraform Validation (push) Failing after 24s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 26s
Deploy ChainID 138 / Deploy ChainID 138 (push) Failing after 42s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 39s
Validation / validate-genesis (push) Successful in 33s
Validation / validate-terraform (push) Failing after 28s
Validation / validate-kubernetes (push) Failing after 12s
Validation / validate-smart-contracts (push) Failing after 13s
Validation / validate-security (push) Failing after 1m21s
Validation / validate-documentation (push) Failing after 22s
Verify Deployment / Verify Deployment (push) Failing after 1m0s
181 lines
5.9 KiB
TypeScript
181 lines
5.9 KiB
TypeScript
/**
|
|
* WalletDeployment Component - Deploy new Safe wallets for admin use
|
|
*/
|
|
|
|
import { useState } from 'react'
|
|
import { useAccount } from 'wagmi'
|
|
import { useAdmin } from '../../contexts/AdminContext'
|
|
import toast from 'react-hot-toast'
|
|
|
|
interface WalletConfig {
|
|
owners: string[]
|
|
threshold: number
|
|
name: string
|
|
}
|
|
|
|
export default function WalletDeployment() {
|
|
const { address } = useAccount()
|
|
const { addAuditLog } = useAdmin()
|
|
const [config, setConfig] = useState<WalletConfig>({
|
|
owners: address ? [address] : [],
|
|
threshold: 1,
|
|
name: '',
|
|
})
|
|
const [newOwner, setNewOwner] = useState('')
|
|
const [isDeploying, setIsDeploying] = useState(false)
|
|
|
|
const addOwner = () => {
|
|
if (!newOwner || !/^0x[a-fA-F0-9]{40}$/.test(newOwner)) {
|
|
toast.error('Invalid address')
|
|
return
|
|
}
|
|
if (config.owners.includes(newOwner)) {
|
|
toast.error('Owner already added')
|
|
return
|
|
}
|
|
setConfig((prev) => ({
|
|
...prev,
|
|
owners: [...prev.owners, newOwner],
|
|
}))
|
|
setNewOwner('')
|
|
}
|
|
|
|
const removeOwner = (owner: string) => {
|
|
if (config.owners.length <= 1) {
|
|
toast.error('Must have at least one owner')
|
|
return
|
|
}
|
|
setConfig((prev) => ({
|
|
...prev,
|
|
owners: prev.owners.filter((o) => o !== owner),
|
|
threshold: Math.min(prev.threshold, prev.owners.length - 1),
|
|
}))
|
|
}
|
|
|
|
const handleDeploy = async () => {
|
|
if (config.owners.length === 0) {
|
|
toast.error('Add at least one owner')
|
|
return
|
|
}
|
|
if (config.threshold > config.owners.length) {
|
|
toast.error('Threshold cannot exceed owner count')
|
|
return
|
|
}
|
|
if (!config.name) {
|
|
toast.error('Enter a wallet name')
|
|
return
|
|
}
|
|
|
|
setIsDeploying(true)
|
|
// Simulate deployment (in production, this would call Safe SDK)
|
|
setTimeout(() => {
|
|
toast.success(`Wallet "${config.name}" deployment initiated`)
|
|
addAuditLog({
|
|
user: address || 'admin',
|
|
action: 'deploy_wallet',
|
|
resourceType: 'wallet',
|
|
resourceId: `wallet_${Date.now()}`,
|
|
details: { name: config.name, owners: config.owners.length, threshold: config.threshold },
|
|
status: 'success',
|
|
})
|
|
setIsDeploying(false)
|
|
setConfig({
|
|
owners: address ? [address] : [],
|
|
threshold: 1,
|
|
name: '',
|
|
})
|
|
}, 2000)
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div className="bg-black/20 rounded-xl p-6 border border-white/10">
|
|
<h2 className="text-xl font-bold text-white mb-4">Deploy Safe Wallet</h2>
|
|
<p className="text-white/70 text-sm mb-4">
|
|
Deploy a new Gnosis Safe wallet for admin operations.
|
|
</p>
|
|
|
|
<div className="space-y-4">
|
|
<div>
|
|
<label className="block text-white/70 text-sm mb-2">Wallet Name</label>
|
|
<input
|
|
type="text"
|
|
value={config.name}
|
|
onChange={(e) => setConfig({ ...config, name: e.target.value })}
|
|
placeholder="My Admin Wallet"
|
|
className="w-full px-4 py-2 bg-white/10 border border-white/20 rounded-lg text-white placeholder-white/40 focus:outline-none focus:border-green-500"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-white/70 text-sm mb-2">Owners</label>
|
|
<div className="space-y-2">
|
|
{config.owners.map((owner, index) => (
|
|
<div
|
|
key={index}
|
|
className="flex items-center justify-between bg-white/5 rounded-lg p-3"
|
|
>
|
|
<span className="text-white font-mono text-sm">{owner}</span>
|
|
{config.owners.length > 1 && (
|
|
<button
|
|
onClick={() => removeOwner(owner)}
|
|
className="text-red-400 hover:text-red-300 text-sm"
|
|
>
|
|
Remove
|
|
</button>
|
|
)}
|
|
</div>
|
|
))}
|
|
<div className="flex gap-2">
|
|
<input
|
|
type="text"
|
|
value={newOwner}
|
|
onChange={(e) => setNewOwner(e.target.value)}
|
|
placeholder="0x..."
|
|
className="flex-1 px-4 py-2 bg-white/10 border border-white/20 rounded-lg text-white placeholder-white/40 focus:outline-none focus:border-green-500 font-mono text-sm"
|
|
/>
|
|
<button
|
|
onClick={addOwner}
|
|
className="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-semibold transition-colors"
|
|
>
|
|
Add
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-white/70 text-sm mb-2">
|
|
Threshold ({config.owners.length} owners)
|
|
</label>
|
|
<input
|
|
type="number"
|
|
value={config.threshold}
|
|
onChange={(e) =>
|
|
setConfig({
|
|
...config,
|
|
threshold: Math.max(1, Math.min(parseInt(e.target.value) || 1, config.owners.length)),
|
|
})
|
|
}
|
|
min="1"
|
|
max={config.owners.length}
|
|
className="w-full px-4 py-2 bg-white/10 border border-white/20 rounded-lg text-white focus:outline-none focus:border-green-500"
|
|
/>
|
|
<p className="text-white/60 text-xs mt-1">
|
|
Requires {config.threshold} of {config.owners.length} owners to approve transactions
|
|
</p>
|
|
</div>
|
|
|
|
<button
|
|
onClick={handleDeploy}
|
|
disabled={isDeploying || config.owners.length === 0 || !config.name}
|
|
className="w-full px-6 py-3 bg-green-600 hover:bg-green-700 disabled:bg-gray-600 disabled:cursor-not-allowed text-white rounded-lg font-semibold transition-colors"
|
|
>
|
|
{isDeploying ? 'Deploying...' : 'Deploy Wallet'}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|