Skip to content

Commit

Permalink
Add Eigen support optionality to register operator form
Browse files Browse the repository at this point in the history
  • Loading branch information
ccali11 committed Oct 24, 2023
1 parent 08d7837 commit ef909ff
Show file tree
Hide file tree
Showing 3 changed files with 230 additions and 39 deletions.
72 changes: 51 additions & 21 deletions apps/web/src/composables/operators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ let defaultManager: CasimirManager
let defaultRegistry: CasimirRegistry
let defaultViews: CasimirViews

// let eigenManager: CasimirManager
// let eigenRegistry: CasimirRegistry
// let eigenViews: CasimirViews
let eigenManager: CasimirManager
let eigenRegistry: CasimirRegistry
let eigenViews: CasimirViews

const { getContracts } = useContracts()
const { ethereumUrl, ssvNetworkAddress, ssvViewsAddress, usersUrl } = useEnvironment()
Expand All @@ -35,8 +35,10 @@ export default function useOperators() {
const loadingRegisteredOperators = ref(false)
const loadingRegisteredOperatorsError = ref(false)

const nonregisteredOperators = ref<Operator[]>([])
const registeredOperators = ref<Operator[]>([])
const nonregisteredDefaultOperators = ref<Operator[]>([])
const nonregisteredEigenOperators = ref<Operator[]>([])
const registeredDefaultOperators = ref<Operator[]>([])
const registeredEigenOperators = ref<Operator[]>([])

async function addOperator({ address, nodeUrl }: { address: string, nodeUrl: string }) {
try {
Expand Down Expand Up @@ -73,12 +75,32 @@ export default function useOperators() {
ssvOperators.push(...userOperators)
}

const defaultCasimirOperators = await _getRegisteredOperators(ssvOperators, 'default')
const eigenCasimirOperators = await _getRegisteredOperators(ssvOperators, 'eigen')

const nonregDefaultOperators = ssvOperators.filter((operator: any) => {
const idRegistered = defaultCasimirOperators.find((registeredOperator: any) => registeredOperator.id === operator.id)
return !idRegistered
})
const nonregEigenOperators = ssvOperators.filter((operator: any) => {
const idRegistered = eigenCasimirOperators.find((registeredOperator: any) => registeredOperator.id === operator.id)
return !idRegistered
})

nonregisteredDefaultOperators.value = nonregDefaultOperators as Array<Operator>
nonregisteredEigenOperators.value = nonregEigenOperators as Array<Operator>
registeredDefaultOperators.value = defaultCasimirOperators as Array<RegisteredOperator>
registeredEigenOperators.value = eigenCasimirOperators as Array<RegisteredOperator>
}

async function _getRegisteredOperators(ssvOperators: Operator[], type: 'default' | 'eigen'): Promise<RegisteredOperator[]> {
const casimirOperators: RegisteredOperator[] = []
const registry = type === 'default' ? defaultRegistry : eigenRegistry
for (const operator of ssvOperators) {
const { active, collateral, poolCount, resharing } = await (defaultRegistry as CasimirRegistry).getOperator(operator.id)
const { active, collateral, poolCount, resharing } = await (registry as CasimirRegistry).getOperator(operator.id)
const registered = active || collateral.gt(0) || poolCount.gt(0) || resharing
if (registered) {
const pools = await _getPools(operator.id)
const pools = await _getPools(operator.id, type)
// TODO: Replace these Public Nodes URLs once we have this working again
const operatorStore = {
'208': 'https://nodes.casimir.co/eth/goerli/dkg/1',
Expand All @@ -102,26 +124,26 @@ export default function useOperators() {
})
}
}

const nonregOperators = ssvOperators.filter((operator: any) => {
const idRegistered = casimirOperators.find((registeredOperator: any) => registeredOperator.id === operator.id)
return !idRegistered
})

nonregisteredOperators.value = nonregOperators as Array<Operator>
registeredOperators.value = casimirOperators as Array<RegisteredOperator>
return casimirOperators
}

async function _getPools(operatorId: number): Promise<PoolConfig[]> {
async function _getPools(operatorId: number, type: 'default' | 'eigen'): Promise<PoolConfig[]> {
const pools: PoolConfig[] = []

const poolIds = [
const defaultPoolIds = [
...await (defaultManager as CasimirManager).getPendingPoolIds(),
...await (defaultManager as CasimirManager).getStakedPoolIds()
]
const eigenPoolIds = [
...await (eigenManager as CasimirManager).getPendingPoolIds(),
...await (eigenManager as CasimirManager).getStakedPoolIds()
]

const poolIds = type === 'default' ? defaultPoolIds : eigenPoolIds
const views = type === 'default' ? defaultViews : eigenViews

for (const poolId of poolIds) {
const poolConfig = await (defaultViews as CasimirViews).getPoolConfig(poolId)
const poolConfig = await (views as CasimirViews).getPoolConfig(poolId)
const pool = {
...poolConfig,
operatorIds: poolConfig.operatorIds.map(id => id.toNumber()),
Expand All @@ -138,9 +160,13 @@ export default function useOperators() {
try {
/* Get Manager, Views, and Registry */
const { defaultManager: managerContract, defaultRegistry: registryContract, defaultViews: viewsContract } = await getContracts()
const { eigenManager: eigenManagerContract, eigenRegistry: eigenRegistryContract, eigenViews: eigenViewsContract } = await getContracts()
defaultManager = managerContract
defaultRegistry = registryContract
defaultViews = viewsContract
eigenManager = eigenManagerContract
eigenRegistry = eigenRegistryContract
eigenViews = eigenViewsContract

loadingInitializeOperators.value = true
listenForContractEvents()
Expand All @@ -155,7 +181,9 @@ export default function useOperators() {

function listenForContractEvents() {
try {
(defaultRegistry as CasimirRegistry).on('OperatorRegistered', () => getUserOperators())
(defaultRegistry as CasimirRegistry).on('OperatorRegistered', () => getUserOperators());
(eigenRegistry as CasimirRegistry).on('OperatorRegistered', () => getUserOperators())

// (registry as CasimirRegistry).on('OperatorDeregistered', getUserOperators)
// (registry as CasimirRegistry).on('DeregistrationRequested', getUserOperators)
} catch (err) {
Expand Down Expand Up @@ -192,8 +220,10 @@ export default function useOperators() {
}

return {
nonregisteredOperators: readonly(nonregisteredOperators),
registeredOperators: readonly(registeredOperators),
nonregisteredDefaultOperators: readonly(nonregisteredDefaultOperators),
nonregisteredEigenOperators: readonly(nonregisteredEigenOperators),
registeredDefaultOperators: readonly(registeredDefaultOperators),
registeredEigenOperators: readonly(registeredEigenOperators),
loadingAddOperator: readonly(loadingAddOperator),
loadingAddOperatorError: readonly(loadingAddOperatorError),
loadingInitializeOperators: readonly(loadingInitializeOperators),
Expand Down
171 changes: 166 additions & 5 deletions apps/web/src/pages/operators/Operator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,16 @@ const { loadingSessionLogin } = useAuth()
// const { detectActiveWalletAddress } = useEthers()
const { exportFile } = useFiles()
const { convertString } = useFormat()
const {initializeOperatorComposable, nonregisteredOperators, registeredOperators, registerOperatorWithCasimir, loadingInitializeOperators, loadingAddOperator } = useOperators()
const {
initializeOperatorComposable,
registerOperatorWithCasimir,
nonregisteredDefaultOperators,
nonregisteredEigenOperators,
registeredDefaultOperators,
registeredEigenOperators,
loadingInitializeOperators,
loadingAddOperator
} = useOperators()
const { user } = useUser()
// Form inputs
Expand All @@ -24,6 +33,28 @@ const onSelectWalletBlur = () => {
openSelectWalletOptions.value = false
}, 200)
}
const operatorType = ref<'default' | 'eigen'>('default')
const eigenIsShining = ref(true) // Determines if the shine effect is active
const eigenIsToggled = ref(false) // Determines the toggle state
const toggleBackgroundColor = ref('#eee') // Initial color
function toggleEigenLayerSupport() {
eigenIsToggled.value = !eigenIsToggled.value
toggleBackgroundColor.value = eigenIsToggled.value ? 'green' : '#eee'
operatorType.value = eigenIsToggled.value ? 'eigen' : 'default'
console.log('nonregisteredDefaultOperators.value :>> ', nonregisteredDefaultOperators.value)
console.log('registeredDefaultOperators.value :>> ', registeredDefaultOperators.value)
console.log('nonregisteredEigenOperators.value :>> ', nonregisteredEigenOperators.value)
console.log('registeredEigenOperators.value :>> ', registeredEigenOperators.value)
console.log('operatorType.value :>> ', operatorType.value)
// Update stakeType
// stakeType.value = eigenIsToggled.value ? 'eigen' : 'default'
}
const selectedOperatorID = ref()
const openSelectOperatorID = ref(false)
const onSelectOperatorIDBlur = () => {
Expand Down Expand Up @@ -121,13 +152,34 @@ watch(selectedWallet, async () =>{
if (selectedWallet.value.address === '') {
availableOperatorIDs.value = []
} else if(nonregisteredOperators.value && nonregisteredOperators.value.length > 0) {
availableOperatorIDs.value = [...nonregisteredOperators.value].filter((operator: any) => operator.ownerAddress === selectedWallet.value.address).map((operator: any) => operator.id)}
} else if(operatorType.value === 'default') {
if (nonregisteredDefaultOperators.value && nonregisteredDefaultOperators.value.length > 0) {
availableOperatorIDs.value = [...nonregisteredDefaultOperators.value].filter((operator: any) => operator.ownerAddress === selectedWallet.value.address).map((operator: any) => operator.id)
} else if (nonregisteredEigenOperators.value && nonregisteredEigenOperators.value.length > 0) {
availableOperatorIDs.value = [...nonregisteredEigenOperators.value].filter((operator: any) => operator.ownerAddress === selectedWallet.value.address).map((operator: any) => operator.id)
} else {
availableOperatorIDs.value = []
}
}
})
watch(registeredDefaultOperators, () => {
openAddOperatorModal.value = false
tableData.value = [...registeredDefaultOperators.value].map((operator: any) => {
return {
id: operator.id,
walletAddress: operator.ownerAddress,
collateral: operator.collateral + ' ETH',
poolCount: operator.poolCount,
nodeURL: operator.url
}
})
filterData()
})
watch(registeredOperators, () => {
watch(registeredEigenOperators, () => {
openAddOperatorModal.value = false
tableData.value = [...registeredOperators.value].map((operator: any) => {
tableData.value = [...registeredEigenOperators.value].map((operator: any) => {
return {
id: operator.id,
walletAddress: operator.ownerAddress,
Expand Down Expand Up @@ -406,6 +458,29 @@ watch([loadingSessionLogin || loadingInitializeOperators], () =>{
Select your SSV owner address
</div>

<div
ref="confettiButton"
class="toggle_container mt-10 w-full max-w-[400px] relative"
@click="toggleEigenLayerSupport"
>
<img
class="eigen-logo"
src="/eigen.svg"
>
Enable EigenLayer Support
<span
v-if="eigenIsShining"
class="shine-effect"
/>
<div
class="toggle-button"
:style="{ 'background-color': toggleBackgroundColor }"
:class="{ 'toggle-on': eigenIsToggled }"
>
<div class="toggle-circle" />
</div>
</div>

<!-- operator id input -->
<h6 class="text-[12px] font-[500] mt-[15px] mb-[4px] pl-[5px]">
Operator ID
Expand Down Expand Up @@ -913,4 +988,90 @@ watch([loadingSessionLogin || loadingInitializeOperators], () =>{
letter-spacing: -0.03em;
color: #FFFFFF;
}
/* Eigen Button */
.toggle_container {
display: flex;
align-items: center;
justify-content: flex-start;
padding-left: 10px; /* space from the left edge */
position: relative;
height: 44px; /* adjust as needed if required */
background-color: rgb(26 12 109);
overflow: hidden;
text-align: center;
color: #fff; /* or any suitable color for better visibility */
font-size: 14px; /* adjust based on preference */
border-radius: 8px;
transition: background-color 0.3s; /* This will animate the color change */
}
.toggle_container:disabled {
background-color: rgba(26, 12, 109, 0.5); /* This makes the purple color lighter (grayed out) */
/* cursor: not-allowed; This changes the cursor to indicate the button is not clickable */
}
.shine-effect {
content: '';
position: absolute;
top: -50%;
left: -150%;
width: 200%;
height: 200%;
background: rgba(255, 255, 255, 0.5);
transform: rotate(30deg);
pointer-events: none;
animation: shine 2.5s infinite;
}
@keyframes shine {
0% {
left: -150%;
}
50% {
left: 150%;
}
100% {
left: 150%;
}
}
/* Eigen Button */
.toggle-button {
position: absolute;
top: 50%;
right: 10px; /* space from the right edge */
transform: translateY(-50%);
width: 50px;
height: 25px;
background-color: #eee;
border-radius: 15px;
cursor: pointer;
overflow: hidden;
}
.card_container .toggle_container.toggle-on .toggle-button {
background-color: green !important;
}
.toggle-circle {
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
width: 30px;
height: 30px;
background-color: #fff;
border-radius: 50%;
transition: left 0.3s;
}
.toggle-on .toggle-circle {
left: calc(100% - 30px);
}
.eigen-logo {
height: 20px;
margin-right: 10px;
}
</style>@/composables/files@/composables/user
Loading

0 comments on commit ef909ff

Please sign in to comment.