Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve validator selection #353

Merged
merged 9 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions apps/beets-frontend-v3/wagmi.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,20 @@ export default defineConfig(() => {
},
],
}),
// etherscan({
// apiKey: env.SONICSCAN_API_KEY,
// chainId: 146, // forced generation of abi for sonic
// contracts: [
// {
// name: 'SonicStaking',
// address: sonicNetworkConfig.contracts.beets?.lstStaking,
// },
// ],
// }),
etherscan({
apiKey: env.SONICSCAN_API_KEY,
chainId: 146,
contracts: [
{
name: 'SonicStaking',
address: sonicNetworkConfig.contracts.beets?.lstStaking,
},
{
name: 'SFC',
address: sonicNetworkConfig.contracts.beets?.sfc,
},
],
}),
],
}
})
7 changes: 5 additions & 2 deletions packages/lib/config/config.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,11 @@ export interface ContractsConfig {
WeightedPool2TokensFactory?: Address
}
beets?: {
lstStaking?: Address
lstStakingProxy?: Address
lstStaking: Address
lstStakingProxy: Address
// TODO: make it required when fantom is removed
sfcProxy?: Address
sfc?: Address
}
feeDistributor?: Address
veDelegationProxy?: Address
Expand Down
1 change: 1 addition & 0 deletions packages/lib/config/networks/fantom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const networkConfig: NetworkConfig = {
beets: {
lstStaking: '0x310A1f7bd9dDE18CCFD701A796Ecb83CcbedE21A',
lstStakingProxy: '0xB458BfC855ab504a8a327720FcEF98886065529b',
sfc: '0xFC00FACE00000000000000000000000000000000',
},
},
pools: convertHexToLowerCase({ issues: {} }),
Expand Down
2 changes: 2 additions & 0 deletions packages/lib/config/networks/sonic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ const networkConfig: NetworkConfig = {
beets: {
lstStaking: '0xd5f7fc8ba92756a34693baa386edcc8dd5b3f141',
lstStakingProxy: '0xe5da20f15420ad15de0fa650600afc998bbe3955',
sfcProxy: '0xFC00FACE00000000000000000000000000000000',
sfc: '0x0aB8f3b709A52c096f33702fE8153776472305ed',
},
},
pools: convertHexToLowerCase({ issues: {} }),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
'use client'

import { getChainId, getNetworkConfig } from '@repo/lib/config/app.config'
import { useMulticall } from '@repo/lib/modules/web3/contracts/useMulticall'
import { useUserAccount } from '@repo/lib/modules/web3/UserAccountProvider'
import { GqlChain } from '@repo/lib/shared/services/api/generated/graphql'
import { useGetRate } from './useGetRate'
import { useGetStakedSonicData } from './useGetStakedSonicData'
import { useMemo } from 'react'
import { sfcAbi } from '@repo/lib/modules/web3/contracts/abi/beets/generated'
import { zeroAddress } from 'viem'

type Result = {
[key: string]: {
result: bigint
status: string
}
}

export function useGetAmountDelegatedPerValidator(chain: GqlChain) {
const { isConnected } = useUserAccount()
const { rate } = useGetRate(chain)
const { data, loading } = useGetStakedSonicData()

const chainId = getChainId(chain)
const config = getNetworkConfig(chainId)

const validatorIds = useMemo(() => {
if (!loading && data) {
return data.stsGetGqlStakedSonicData.delegatedValidators.map(v => v.validatorId)
}

return []
}, [data, loading])

const getStakeRequests = validatorIds.map(validatorId => {
return {
chainId,
id: validatorId,
abi: sfcAbi,
address: config.contracts.beets?.sfcProxy || zeroAddress,
functionName: 'getStake',
args: [config.contracts.beets?.lstStakingProxy, validatorId],
enabled: isConnected,
}
})

const {
results: stakeRequests,
refetchAll,
isLoading,
} = useMulticall(getStakeRequests, {
enabled: isConnected,
})

const amountResults = useMemo(() => {
const results = stakeRequests[chainId]
if (results?.isSuccess) {
return results?.data as Result
}

return {}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [stakeRequests, isLoading])

const amountDelegatedPerValidator = validatorIds.map(validatorId => ({
validatorId,
amountDelegated: amountResults[validatorId]?.result ?? 0n,
}))

function chooseValidatorsForUnstakeAmount(unstakeAmountShares: bigint) {
const unstakeAmountAssets = (unstakeAmountShares * rate) / 10n ** 18n

const validator = amountDelegatedPerValidator.find(
validator => validator.amountDelegated > unstakeAmountAssets
)

// TODO: we should split the unstake amount across several validators down the line
return [
{
validatorId: validator?.validatorId || '1',
unstakeAmountShares,
},
]
}

return {
amountDelegatedPerValidator,
stakeRequests,
refetchAll,
isLoading,
chooseValidatorsForUnstakeAmount,
}
}
3 changes: 1 addition & 2 deletions packages/lib/modules/beets/lst/hooks/useGetRate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { useUserAccount } from '@repo/lib/modules/web3/UserAccountProvider'
import { useReadContract } from 'wagmi'
import { sonicStakingAbi } from '@repo/lib/modules/web3/contracts/abi/beets/generated'
import { GqlChain } from '@repo/lib/shared/services/api/generated/graphql'
import { formatUnits } from 'viem'

export function useGetRate(chain: GqlChain) {
const { isConnected } = useUserAccount()
Expand All @@ -27,6 +26,6 @@ export function useGetRate(chain: GqlChain) {

return {
...query,
rate: formatUnits(query.data ?? 1n, 18),
rate: query.data ?? 1n,
}
}
9 changes: 8 additions & 1 deletion packages/lib/modules/beets/lst/hooks/useLstUnstakeStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@ import { GqlChain } from '@repo/lib/shared/services/api/generated/graphql'
import { useTokenBalances } from '@repo/lib/modules/tokens/TokenBalancesProvider'
import { useGetUserWithdraws } from './useGetUserWithdraws'
import { useGetUserNumWithdraws } from './useGetUserNumWithdraws'
import { useGetAmountDelegatedPerValidator } from './useGetAmountDelegatedPerValidator'

export function useLstUnstakeStep(sharesAmount: string, chain: GqlChain, enabled: boolean) {
const { getTransaction } = useTransactionState()
const { isConnected } = useUserAccount()
const { refetchBalances } = useTokenBalances()
const { userNumWithdraws, refetch: refetchUserNumWithdraws } = useGetUserNumWithdraws(chain)
const { refetch: refetchWithdrawals } = useGetUserWithdraws(chain, userNumWithdraws)
const { chooseValidatorsForUnstakeAmount } = useGetAmountDelegatedPerValidator(chain)
const validators = chooseValidatorsForUnstakeAmount(parseUnits(sharesAmount, 18))

function onSuccess() {
refetchBalances()
Expand All @@ -51,7 +54,11 @@ export function useLstUnstakeStep(sharesAmount: string, chain: GqlChain, enabled
contractId: 'beets.lstStaking',
contractAddress: networkConfigs[chain].contracts.beets?.lstStakingProxy || '',
functionName: 'undelegateMany',
args: [[BigInt(1)], [parseUnits(sharesAmount, 18)]], // TODO: make dynamic
//args: [[BigInt(1)], [parseUnits(sharesAmount, 18)]], // TODO: make dynamic
args: [
validators.map(validator => BigInt(validator.validatorId)),
validators.map(validator => validator.unstakeAmountShares),
],
enabled: isConnected && !!sharesAmount && enabled,
txSimulationMeta,
}
Expand Down
3 changes: 2 additions & 1 deletion packages/lib/modules/web3/contracts/AbiMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
veDelegationProxyAbi,
} from './abi/generated'
import { VeDelegationProxyL2Abi } from './abi/veDelegationProxyL2'
import { sonicStakingAbi } from './abi/beets/generated'
import { sfcAbi, sonicStakingAbi } from './abi/beets/generated'

export const AbiMap = {
'balancer.vaultV2': balancerV2VaultAbi,
Expand All @@ -28,6 +28,7 @@ export const AbiMap = {
'balancer.LiquidityGauge': LiquidityGaugeAbi,
'balancer.omniVotingEscrowAbi': OmniVotingEscrowAbi,
'beets.lstStaking': sonicStakingAbi,
'beets.sfc': sfcAbi,
}

export type AbiMapType = keyof typeof AbiMap | undefined
Loading
Loading