diff --git a/apps/beets-frontend-v3/wagmi.config.ts b/apps/beets-frontend-v3/wagmi.config.ts index 2ab90fef0..4a6509787 100644 --- a/apps/beets-frontend-v3/wagmi.config.ts +++ b/apps/beets-frontend-v3/wagmi.config.ts @@ -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, + }, + ], + }), ], } }) diff --git a/packages/lib/config/config.types.ts b/packages/lib/config/config.types.ts index 7c50d0d46..10ece9783 100644 --- a/packages/lib/config/config.types.ts +++ b/packages/lib/config/config.types.ts @@ -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 diff --git a/packages/lib/config/networks/fantom.ts b/packages/lib/config/networks/fantom.ts index daa366ead..98b35e623 100644 --- a/packages/lib/config/networks/fantom.ts +++ b/packages/lib/config/networks/fantom.ts @@ -45,6 +45,7 @@ const networkConfig: NetworkConfig = { beets: { lstStaking: '0x310A1f7bd9dDE18CCFD701A796Ecb83CcbedE21A', lstStakingProxy: '0xB458BfC855ab504a8a327720FcEF98886065529b', + sfc: '0xFC00FACE00000000000000000000000000000000', }, }, pools: convertHexToLowerCase({ issues: {} }), diff --git a/packages/lib/config/networks/sonic.ts b/packages/lib/config/networks/sonic.ts index c2dd5787b..25f427d96 100644 --- a/packages/lib/config/networks/sonic.ts +++ b/packages/lib/config/networks/sonic.ts @@ -47,6 +47,8 @@ const networkConfig: NetworkConfig = { beets: { lstStaking: '0xd5f7fc8ba92756a34693baa386edcc8dd5b3f141', lstStakingProxy: '0xe5da20f15420ad15de0fa650600afc998bbe3955', + sfcProxy: '0xFC00FACE00000000000000000000000000000000', + sfc: '0x0aB8f3b709A52c096f33702fE8153776472305ed', }, }, pools: convertHexToLowerCase({ issues: {} }), diff --git a/packages/lib/modules/beets/lst/hooks/useGetAmountDelegatedPerValidator.tsx b/packages/lib/modules/beets/lst/hooks/useGetAmountDelegatedPerValidator.tsx new file mode 100644 index 000000000..ec4dd0751 --- /dev/null +++ b/packages/lib/modules/beets/lst/hooks/useGetAmountDelegatedPerValidator.tsx @@ -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, + } +} diff --git a/packages/lib/modules/beets/lst/hooks/useGetRate.tsx b/packages/lib/modules/beets/lst/hooks/useGetRate.tsx index 4d3d392a5..a4e474e26 100644 --- a/packages/lib/modules/beets/lst/hooks/useGetRate.tsx +++ b/packages/lib/modules/beets/lst/hooks/useGetRate.tsx @@ -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() @@ -27,6 +26,6 @@ export function useGetRate(chain: GqlChain) { return { ...query, - rate: formatUnits(query.data ?? 1n, 18), + rate: query.data ?? 1n, } } diff --git a/packages/lib/modules/beets/lst/hooks/useLstUnstakeStep.tsx b/packages/lib/modules/beets/lst/hooks/useLstUnstakeStep.tsx index 42b8b9c15..740323e0d 100644 --- a/packages/lib/modules/beets/lst/hooks/useLstUnstakeStep.tsx +++ b/packages/lib/modules/beets/lst/hooks/useLstUnstakeStep.tsx @@ -18,6 +18,7 @@ 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() @@ -25,6 +26,8 @@ export function useLstUnstakeStep(sharesAmount: string, chain: GqlChain, enabled 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() @@ -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, } diff --git a/packages/lib/modules/web3/contracts/AbiMap.ts b/packages/lib/modules/web3/contracts/AbiMap.ts index d4416369e..f000396e8 100644 --- a/packages/lib/modules/web3/contracts/AbiMap.ts +++ b/packages/lib/modules/web3/contracts/AbiMap.ts @@ -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, @@ -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 diff --git a/packages/lib/modules/web3/contracts/abi/beets/generated.ts b/packages/lib/modules/web3/contracts/abi/beets/generated.ts index 6ae8e4f8a..e2c23435b 100644 --- a/packages/lib/modules/web3/contracts/abi/beets/generated.ts +++ b/packages/lib/modules/web3/contracts/abi/beets/generated.ts @@ -3891,12 +3891,1004 @@ export const balancerV2WeightedPoolV4Config = { abi: balancerV2WeightedPoolV4Abi, } as const +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SFC +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * [__View Contract on Sonic Sonic Explorer__](https://explorer.soniclabs.com/address/0x0aB8f3b709A52c096f33702fE8153776472305ed) + */ +export const sfcAbi = [ + { type: 'constructor', inputs: [], stateMutability: 'nonpayable' }, + { + type: 'error', + inputs: [{ name: 'target', internalType: 'address', type: 'address' }], + name: 'AddressEmptyCode', + }, + { type: 'error', inputs: [], name: 'AlreadyRedirected' }, + { + type: 'error', + inputs: [{ name: 'implementation', internalType: 'address', type: 'address' }], + name: 'ERC1967InvalidImplementation', + }, + { type: 'error', inputs: [], name: 'ERC1967NonPayable' }, + { type: 'error', inputs: [], name: 'FailedCall' }, + { type: 'error', inputs: [], name: 'InsufficientSelfStake' }, + { type: 'error', inputs: [], name: 'InvalidInitialization' }, + { type: 'error', inputs: [], name: 'MalformedPubkey' }, + { type: 'error', inputs: [], name: 'NoUnresolvedTreasuryFees' }, + { type: 'error', inputs: [], name: 'NotAuthorized' }, + { type: 'error', inputs: [], name: 'NotDeactivatedStatus' }, + { type: 'error', inputs: [], name: 'NotDriverAuth' }, + { type: 'error', inputs: [], name: 'NotEnoughEpochsPassed' }, + { type: 'error', inputs: [], name: 'NotEnoughTimePassed' }, + { type: 'error', inputs: [], name: 'NotInitializing' }, + { type: 'error', inputs: [], name: 'NothingToStash' }, + { + type: 'error', + inputs: [{ name: 'owner', internalType: 'address', type: 'address' }], + name: 'OwnableInvalidOwner', + }, + { + type: 'error', + inputs: [{ name: 'account', internalType: 'address', type: 'address' }], + name: 'OwnableUnauthorizedAccount', + }, + { type: 'error', inputs: [], name: 'PubkeyUsedByOtherValidator' }, + { type: 'error', inputs: [], name: 'Redirected' }, + { type: 'error', inputs: [], name: 'RefundRatioTooHigh' }, + { type: 'error', inputs: [], name: 'RequestExists' }, + { type: 'error', inputs: [], name: 'RequestNotExists' }, + { type: 'error', inputs: [], name: 'SameAddress' }, + { type: 'error', inputs: [], name: 'SameRedirectionAuthorizer' }, + { type: 'error', inputs: [], name: 'StakeIsFullySlashed' }, + { type: 'error', inputs: [], name: 'StakeSubscriberFailed' }, + { type: 'error', inputs: [], name: 'TransferFailed' }, + { type: 'error', inputs: [], name: 'TransfersNotAllowed' }, + { type: 'error', inputs: [], name: 'TreasuryNotSet' }, + { type: 'error', inputs: [], name: 'UUPSUnauthorizedCallContext' }, + { + type: 'error', + inputs: [{ name: 'slot', internalType: 'bytes32', type: 'bytes32' }], + name: 'UUPSUnsupportedProxiableUUID', + }, + { type: 'error', inputs: [], name: 'ValidatorDelegationLimitExceeded' }, + { type: 'error', inputs: [], name: 'ValidatorExists' }, + { type: 'error', inputs: [], name: 'ValidatorNotActive' }, + { type: 'error', inputs: [], name: 'ValidatorNotExists' }, + { type: 'error', inputs: [], name: 'ValidatorNotSlashed' }, + { type: 'error', inputs: [], name: 'ValueTooLarge' }, + { type: 'error', inputs: [], name: 'ZeroAddress' }, + { type: 'error', inputs: [], name: 'ZeroAmount' }, + { type: 'error', inputs: [], name: 'ZeroRewards' }, + { + type: 'event', + anonymous: false, + inputs: [ + { name: 'from', internalType: 'address', type: 'address', indexed: true }, + { name: 'to', internalType: 'address', type: 'address', indexed: true }, + ], + name: 'AnnouncedRedirection', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'amount', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + ], + name: 'BurntNativeTokens', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'validatorID', + internalType: 'uint256', + type: 'uint256', + indexed: true, + }, + { + name: 'status', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + ], + name: 'ChangedValidatorStatus', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'delegator', + internalType: 'address', + type: 'address', + indexed: true, + }, + { + name: 'toValidatorID', + internalType: 'uint256', + type: 'uint256', + indexed: true, + }, + { + name: 'rewards', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + ], + name: 'ClaimedRewards', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'validatorID', + internalType: 'uint256', + type: 'uint256', + indexed: true, + }, + { name: 'auth', internalType: 'address', type: 'address', indexed: true }, + { + name: 'createdEpoch', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + { + name: 'createdTime', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + ], + name: 'CreatedValidator', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'validatorID', + internalType: 'uint256', + type: 'uint256', + indexed: true, + }, + { + name: 'deactivatedEpoch', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + { + name: 'deactivatedTime', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + ], + name: 'DeactivatedValidator', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'delegator', + internalType: 'address', + type: 'address', + indexed: true, + }, + { + name: 'toValidatorID', + internalType: 'uint256', + type: 'uint256', + indexed: true, + }, + { + name: 'amount', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + ], + name: 'Delegated', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'version', + internalType: 'uint64', + type: 'uint64', + indexed: false, + }, + ], + name: 'Initialized', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'previousOwner', + internalType: 'address', + type: 'address', + indexed: true, + }, + { + name: 'newOwner', + internalType: 'address', + type: 'address', + indexed: true, + }, + ], + name: 'OwnershipTransferred', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'delegator', + internalType: 'address', + type: 'address', + indexed: true, + }, + { + name: 'validatorID', + internalType: 'uint256', + type: 'uint256', + indexed: true, + }, + { + name: 'amount', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + ], + name: 'RefundedSlashedLegacyDelegation', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'delegator', + internalType: 'address', + type: 'address', + indexed: true, + }, + { + name: 'toValidatorID', + internalType: 'uint256', + type: 'uint256', + indexed: true, + }, + { + name: 'rewards', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + ], + name: 'RestakedRewards', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'amount', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + ], + name: 'TreasuryFeesResolved', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'delegator', + internalType: 'address', + type: 'address', + indexed: true, + }, + { + name: 'toValidatorID', + internalType: 'uint256', + type: 'uint256', + indexed: true, + }, + { name: 'wrID', internalType: 'uint256', type: 'uint256', indexed: true }, + { + name: 'amount', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + ], + name: 'Undelegated', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'validatorID', + internalType: 'uint256', + type: 'uint256', + indexed: true, + }, + { + name: 'refundRatio', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + ], + name: 'UpdatedSlashingRefundRatio', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'implementation', + internalType: 'address', + type: 'address', + indexed: true, + }, + ], + name: 'Upgraded', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'delegator', + internalType: 'address', + type: 'address', + indexed: true, + }, + { + name: 'toValidatorID', + internalType: 'uint256', + type: 'uint256', + indexed: true, + }, + { name: 'wrID', internalType: 'uint256', type: 'uint256', indexed: true }, + { + name: 'amount', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + { + name: 'penalty', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + ], + name: 'Withdrawn', + }, + { + type: 'function', + inputs: [], + name: 'UPGRADE_INTERFACE_VERSION', + outputs: [{ name: '', internalType: 'string', type: 'string' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + { name: 'syncPubkey', internalType: 'bool', type: 'bool' }, + ], + name: '_syncValidator', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'to', internalType: 'address', type: 'address' }], + name: 'announceRedirection', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [], + name: 'burnNativeTokens', + outputs: [], + stateMutability: 'payable', + }, + { + type: 'function', + inputs: [{ name: 'toValidatorID', internalType: 'uint256', type: 'uint256' }], + name: 'claimRewards', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [], + name: 'constsAddress', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'pubkey', internalType: 'bytes', type: 'bytes' }], + name: 'createValidator', + outputs: [], + stateMutability: 'payable', + }, + { + type: 'function', + inputs: [], + name: 'currentEpoch', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'currentSealedEpoch', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + { name: 'status', internalType: 'uint256', type: 'uint256' }, + ], + name: 'deactivateValidator', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'toValidatorID', internalType: 'uint256', type: 'uint256' }], + name: 'delegate', + outputs: [], + stateMutability: 'payable', + }, + { + type: 'function', + inputs: [ + { name: 'epoch', internalType: 'uint256', type: 'uint256' }, + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + ], + name: 'getEpochAccumulatedOriginatedTxsFee', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'epoch', internalType: 'uint256', type: 'uint256' }, + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + ], + name: 'getEpochAccumulatedRewardPerToken', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'epoch', internalType: 'uint256', type: 'uint256' }, + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + ], + name: 'getEpochAccumulatedUptime', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'epoch', internalType: 'uint256', type: 'uint256' }, + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + ], + name: 'getEpochAverageUptime', + outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'epoch', internalType: 'uint256', type: 'uint256' }], + name: 'getEpochEndBlock', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'epoch', internalType: 'uint256', type: 'uint256' }, + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + ], + name: 'getEpochOfflineBlocks', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'epoch', internalType: 'uint256', type: 'uint256' }, + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + ], + name: 'getEpochOfflineTime', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'epoch', internalType: 'uint256', type: 'uint256' }, + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + ], + name: 'getEpochReceivedStake', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'epoch', internalType: 'uint256', type: 'uint256' }], + name: 'getEpochSnapshot', + outputs: [ + { name: 'endTime', internalType: 'uint256', type: 'uint256' }, + { name: 'endBlock', internalType: 'uint256', type: 'uint256' }, + { name: 'epochFee', internalType: 'uint256', type: 'uint256' }, + { name: 'baseRewardPerSecond', internalType: 'uint256', type: 'uint256' }, + { name: 'totalStake', internalType: 'uint256', type: 'uint256' }, + { name: 'totalSupply', internalType: 'uint256', type: 'uint256' }, + ], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'epoch', internalType: 'uint256', type: 'uint256' }], + name: 'getEpochValidatorIDs', + outputs: [{ name: '', internalType: 'uint256[]', type: 'uint256[]' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'delegator', internalType: 'address', type: 'address' }], + name: 'getRedirection', + outputs: [{ name: 'receiver', internalType: 'address', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'delegator', internalType: 'address', type: 'address' }], + name: 'getRedirectionRequest', + outputs: [{ name: 'receiver', internalType: 'address', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'validatorID', internalType: 'uint256', type: 'uint256' }], + name: 'getSelfStake', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'delegator', internalType: 'address', type: 'address' }, + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + ], + name: 'getStake', + outputs: [{ name: 'stake', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'validatorID', internalType: 'uint256', type: 'uint256' }], + name: 'getValidator', + outputs: [ + { name: 'status', internalType: 'uint256', type: 'uint256' }, + { name: 'receivedStake', internalType: 'uint256', type: 'uint256' }, + { name: 'auth', internalType: 'address', type: 'address' }, + { name: 'createdEpoch', internalType: 'uint256', type: 'uint256' }, + { name: 'createdTime', internalType: 'uint256', type: 'uint256' }, + { name: 'deactivatedTime', internalType: 'uint256', type: 'uint256' }, + { name: 'deactivatedEpoch', internalType: 'uint256', type: 'uint256' }, + ], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'auth', internalType: 'address', type: 'address' }], + name: 'getValidatorID', + outputs: [{ name: 'validatorID', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'validatorID', internalType: 'uint256', type: 'uint256' }], + name: 'getValidatorPubkey', + outputs: [{ name: 'pubkey', internalType: 'bytes', type: 'bytes' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'delegator', internalType: 'address', type: 'address' }, + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + { name: 'wrID', internalType: 'uint256', type: 'uint256' }, + ], + name: 'getWithdrawalRequest', + outputs: [ + { name: 'epoch', internalType: 'uint256', type: 'uint256' }, + { name: 'time', internalType: 'uint256', type: 'uint256' }, + { name: 'amount', internalType: 'uint256', type: 'uint256' }, + ], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'sealedEpoch', internalType: 'uint256', type: 'uint256' }, + { name: '_totalSupply', internalType: 'uint256', type: 'uint256' }, + { name: 'nodeDriver', internalType: 'address', type: 'address' }, + { name: '_c', internalType: 'address', type: 'address' }, + { name: 'owner', internalType: 'address', type: 'address' }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'from', internalType: 'address', type: 'address' }, + { name: 'to', internalType: 'address', type: 'address' }, + ], + name: 'initiateRedirection', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'validatorID', internalType: 'uint256', type: 'uint256' }], + name: 'isSlashed', + outputs: [{ name: '', internalType: 'bool', type: 'bool' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'amount', internalType: 'uint256', type: 'uint256' }], + name: 'issueTokens', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [], + name: 'lastValidatorID', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'owner', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'delegator', internalType: 'address', type: 'address' }, + { name: 'toValidatorID', internalType: 'uint256', type: 'uint256' }, + ], + name: 'pendingRewards', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'proxiableUUID', + outputs: [{ name: '', internalType: 'bytes32', type: 'bytes32' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'pubkeyAddress', internalType: 'address', type: 'address' }], + name: 'pubkeyAddressToValidatorID', + outputs: [{ name: 'validatorID', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'to', internalType: 'address', type: 'address' }], + name: 'redirect', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [], + name: 'redirectionAuthorizer', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'renounceOwnership', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [], + name: 'resolveTreasuryFees', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'toValidatorID', internalType: 'uint256', type: 'uint256' }], + name: 'restakeRewards', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'delegator', internalType: 'address', type: 'address' }, + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + ], + name: 'rewardsStash', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'offlineTime', internalType: 'uint256[]', type: 'uint256[]' }, + { name: 'offlineBlocks', internalType: 'uint256[]', type: 'uint256[]' }, + { name: 'uptimes', internalType: 'uint256[]', type: 'uint256[]' }, + { + name: 'originatedTxsFee', + internalType: 'uint256[]', + type: 'uint256[]', + }, + ], + name: 'sealEpoch', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { + name: 'nextValidatorIDs', + internalType: 'uint256[]', + type: 'uint256[]', + }, + ], + name: 'sealEpochValidators', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'delegator', internalType: 'address', type: 'address' }, + { name: 'toValidatorID', internalType: 'uint256', type: 'uint256' }, + { name: 'stake', internalType: 'uint256', type: 'uint256' }, + ], + name: 'setGenesisDelegation', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'auth', internalType: 'address', type: 'address' }, + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + { name: 'pubkey', internalType: 'bytes', type: 'bytes' }, + { name: 'createdTime', internalType: 'uint256', type: 'uint256' }, + ], + name: 'setGenesisValidator', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'v', internalType: 'address', type: 'address' }], + name: 'setRedirectionAuthorizer', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'validatorID', internalType: 'uint256', type: 'uint256' }], + name: 'slashingRefundRatio', + outputs: [{ name: 'refundRatio', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'stakeSubscriberAddress', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'delegator', internalType: 'address', type: 'address' }, + { name: 'toValidatorID', internalType: 'uint256', type: 'uint256' }, + ], + name: 'stashRewards', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'delegator', internalType: 'address', type: 'address' }, + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + ], + name: 'stashedRewardsUntilEpoch', + outputs: [{ name: 'epoch', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'totalActiveStake', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'totalStake', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'totalSupply', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'newOwner', internalType: 'address', type: 'address' }], + name: 'transferOwnership', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [], + name: 'treasuryAddress', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'toValidatorID', internalType: 'uint256', type: 'uint256' }, + { name: 'wrID', internalType: 'uint256', type: 'uint256' }, + { name: 'amount', internalType: 'uint256', type: 'uint256' }, + ], + name: 'undelegate', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [], + name: 'unresolvedTreasuryFees', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'v', internalType: 'address', type: 'address' }], + name: 'updateConstsAddress', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'validatorID', internalType: 'uint256', type: 'uint256' }, + { name: 'refundRatio', internalType: 'uint256', type: 'uint256' }, + ], + name: 'updateSlashingRefundRatio', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'v', internalType: 'address', type: 'address' }], + name: 'updateStakeSubscriberAddress', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'v', internalType: 'address', type: 'address' }], + name: 'updateTreasuryAddress', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'newImplementation', internalType: 'address', type: 'address' }, + { name: 'data', internalType: 'bytes', type: 'bytes' }, + ], + name: 'upgradeToAndCall', + outputs: [], + stateMutability: 'payable', + }, + { + type: 'function', + inputs: [], + name: 'version', + outputs: [{ name: '', internalType: 'bytes3', type: 'bytes3' }], + stateMutability: 'pure', + }, + { + type: 'function', + inputs: [ + { name: 'toValidatorID', internalType: 'uint256', type: 'uint256' }, + { name: 'wrID', internalType: 'uint256', type: 'uint256' }, + ], + name: 'withdraw', + outputs: [], + stateMutability: 'nonpayable', + }, + { type: 'receive', stateMutability: 'payable' }, +] as const + +/** + * [__View Contract on Sonic Sonic Explorer__](https://explorer.soniclabs.com/address/0x0aB8f3b709A52c096f33702fE8153776472305ed) + */ +export const sfcAddress = { + 146: '0x0aB8f3b709A52c096f33702fE8153776472305ed', +} as const + +/** + * [__View Contract on Sonic Sonic Explorer__](https://explorer.soniclabs.com/address/0x0aB8f3b709A52c096f33702fE8153776472305ed) + */ +export const sfcConfig = { address: sfcAddress, abi: sfcAbi } as const + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SonicStaking ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** - * + * [__View Contract on Sonic Sonic Explorer__](https://explorer.soniclabs.com/address/0xd5f7fc8ba92756a34693baa386edcc8dd5b3f141) */ export const sonicStakingAbi = [ { type: 'constructor', inputs: [], stateMutability: 'nonpayable' }, @@ -5168,14 +6160,14 @@ export const sonicStakingAbi = [ ] as const /** - * + * [__View Contract on Sonic Sonic Explorer__](https://explorer.soniclabs.com/address/0xd5f7fc8ba92756a34693baa386edcc8dd5b3f141) */ export const sonicStakingAddress = { - 146: '0xBF46AeF3c4c119495245e6b1911A4a961859038d', + 146: '0xD5F7FC8ba92756a34693bAA386Edcc8Dd5B3F141', } as const /** - * + * [__View Contract on Sonic Sonic Explorer__](https://explorer.soniclabs.com/address/0xd5f7fc8ba92756a34693baa386edcc8dd5b3f141) */ export const sonicStakingConfig = { address: sonicStakingAddress, diff --git a/packages/lib/modules/web3/contracts/useMulticall.ts b/packages/lib/modules/web3/contracts/useMulticall.ts index cfe319cce..74895ed12 100644 --- a/packages/lib/modules/web3/contracts/useMulticall.ts +++ b/packages/lib/modules/web3/contracts/useMulticall.ts @@ -7,6 +7,7 @@ import { useConfig } from 'wagmi' import { SupportedChainId } from '@repo/lib/config/config.types' import { GqlChain } from '@repo/lib/shared/services/api/generated/graphql' import sonicNetworkConfig from '@repo/lib/config/networks/sonic' +import { getChainId } from '@repo/lib/config/app.config' export type ChainContractConfig = ContractFunctionParameters & { chainId: SupportedChainId @@ -35,7 +36,7 @@ export function useMulticall(multicallRequests: ChainContractConfig[], options: const results = await multicall(config, { contracts: multicalls, chainId: Number(chain), - ...(chain === GqlChain.Sonic && { + ...(Number(chain) === getChainId(GqlChain.Sonic) && { multicallAddress: sonicNetworkConfig.contracts.multicall3, }), })