+
{{ subtitle }}
@@ -30,7 +30,7 @@
/>
- {{ indicator.value }}
+ {{ indicator.value || '-' }}
@@ -44,13 +44,17 @@
import { Icon } from '@/common'
import { type InfoBarType } from '@/types'
-defineProps<{
- subtitle: string
- status: 'public' | 'private'
- title: string
- description: string
- indicators: InfoBarType.Indicator[]
-}>()
+withDefaults(
+ defineProps<{
+ subtitle: string
+ status: 'public' | 'private'
+ title: string
+ description: string
+ indicators: InfoBarType.Indicator[]
+ isLoading?: boolean
+ }>(),
+ { isLoading: false },
+)
diff --git a/src/common/WalletBalances.vue b/src/common/WalletBalances.vue
index af96a43..73c3ee9 100644
--- a/src/common/WalletBalances.vue
+++ b/src/common/WalletBalances.vue
@@ -1,25 +1,29 @@
-
-
+
+
- {{ currentBalance.value }}
+ {{ selectedBalance.value }}
- {{ `${balance.value} ${balance.tokenTitle}` }}
+ {{ balance.value }}
diff --git a/src/composables/index.ts b/src/composables/index.ts
index c76ceaa..c91524a 100644
--- a/src/composables/index.ts
+++ b/src/composables/index.ts
@@ -1,4 +1,5 @@
export * from './use-context'
+export * from './use-contract'
export * from './use-form'
export * from './use-form-validation'
export * from './use-nav-links'
diff --git a/src/composables/use-contract.ts b/src/composables/use-contract.ts
new file mode 100644
index 0000000..11ff336
--- /dev/null
+++ b/src/composables/use-contract.ts
@@ -0,0 +1,78 @@
+import { type ETHEREUM_RPC_URLS } from '@/enums'
+import { useWeb3ProvidersStore } from '@/store'
+import { factories } from '@/types'
+import { providers } from 'ethers'
+import { computed, ref, type ComputedRef, type Ref, unref } from 'vue'
+
+type ContractFactoryKey = keyof typeof factories
+type ContractFactoryClass =
+ (typeof factories)[K]
+
+type Contract = ReturnType<
+ ContractFactoryClass['connect']
+>
+
+type ContractInterface =
+ ReturnType['createInterface']>
+
+export interface IUseContract<
+ K extends ContractFactoryKey = ContractFactoryKey,
+> {
+ provider: ComputedRef
+ signer: ComputedRef
+
+ contractInterface: ComputedRef>
+
+ contractWithProvider: ComputedRef>
+ contractWithSigner: ComputedRef>
+}
+
+export function useContract(
+ contractFactoryKey: K,
+ contractAddress: Ref | string,
+ rpcUrl?: ETHEREUM_RPC_URLS,
+): IUseContract {
+ type I = IUseContract
+
+ const web3ProvidersStore = useWeb3ProvidersStore()
+
+ const provider: I['provider'] = computed(() =>
+ rpcUrl
+ ? new providers.JsonRpcProvider(rpcUrl)
+ : new providers.Web3Provider(
+ web3ProvidersStore.provider.rawProvider as providers.ExternalProvider,
+ ),
+ )
+
+ const signer: I['signer'] = computed(() => provider.value.getSigner())
+
+ const _factoryClass = ref(factories[contractFactoryKey])
+
+ const contractInterface: I['contractInterface'] = computed(
+ () => _factoryClass.value.createInterface() as ContractInterface,
+ )
+
+ const contractWithProvider: I['contractWithProvider'] = computed(() => {
+ const unrefContractAddress = unref(contractAddress)
+ return _factoryClass.value.connect(
+ unrefContractAddress,
+ provider.value,
+ ) as Contract
+ })
+
+ const contractWithSigner: I['contractWithSigner'] = computed(() => {
+ const unrefContractAddress = unref(contractAddress)
+ return _factoryClass.value.connect(
+ unrefContractAddress,
+ signer.value,
+ ) as Contract
+ })
+
+ return {
+ provider,
+ signer,
+ contractInterface,
+ contractWithProvider,
+ contractWithSigner,
+ }
+}
diff --git a/src/composables/use-notifications.ts b/src/composables/use-notifications.ts
index 6672276..b5b85c6 100644
--- a/src/composables/use-notifications.ts
+++ b/src/composables/use-notifications.ts
@@ -6,8 +6,6 @@ import { TYPE, useToast } from 'vue-toastification'
import { DefaultToast } from '@/common'
import { CommonNotificationTypes, NotificationObjectPayload } from '@/types'
-const MINUTE = 60 * 1000
-
export const useNotifications = () => {
const toast = useToast()
@@ -32,7 +30,7 @@ export const useNotifications = () => {
[TYPE.INFO]: ICON_NAMES.exclamationCircle,
[TYPE.SUCCESS]: ICON_NAMES.checkCircle,
[TYPE.ERROR]: ICON_NAMES.xCircle,
- [TYPE.WARNING]: ICON_NAMES.shieldExclamation,
+ [TYPE.WARNING]: ICON_NAMES.exclamationCircle,
}
const showToast = (
@@ -81,8 +79,9 @@ export const useNotifications = () => {
warning: TYPE.WARNING,
}[messageType],
toastClassName: 'default-toast',
- timeout: MINUTE / 2,
+ timeout: 5000,
closeOnClick: false,
+ closeButton: false,
},
)
}
diff --git a/src/config.ts b/src/config.ts
index 615b728..7fc576f 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -4,11 +4,14 @@ import pickBy from 'lodash/pickBy'
import mapKeys from 'lodash/mapKeys'
export const config = {
- API_URL: import.meta.env.VITE_API_URL,
- APP_NAME: import.meta.env.VITE_APP_NAME,
- IS_TESTNET: import.meta.env.VITE_APP_IS_TESTNET === 'true',
+ NAME: import.meta.env.VITE_APP_NAME,
+ ERC1967_PROXY_CONTRACT_ADDRESS: import.meta.env
+ .VITE_APP_ERC1967_PROXY_CONTRACT_ADDRESS,
+ STETH_CONTRACT_ADDRESS: import.meta.env.VITE_APP_STETH_CONTRACT_ADDRESS,
+ MOR_CONTRACT_ADDRESS: import.meta.env.VITE_APP_MOR_CONTRACT_ADDRESS,
+ IS_MAINNET: import.meta.env.VITE_APP_IS_MAINNET,
LOG_LEVEL: 'trace' as LogLevelDesc,
- BUILD_VERSION: packageJson.version || import.meta.env.VITE_BUILD_VERSION,
+ BUILD_VERSION: packageJson.version || import.meta.env.VITE_APP_BUILD_VERSION,
} as const
Object.assign(config, _mapEnvCfg(import.meta.env))
@@ -18,7 +21,7 @@ function _mapEnvCfg(env: ImportMetaEnv | typeof document.ENV): {
[k: string]: string | boolean | undefined
} {
return mapKeys(
- pickBy(env, (v, k) => k.startsWith('VITE_')),
- (v, k) => k.replace(/^VITE_/, ''),
+ pickBy(env, (v, k) => k.startsWith('VITE_APP_')),
+ (v, k) => k.replace(/^VITE_APP_/, ''),
)
}
diff --git a/src/const/index.ts b/src/const/index.ts
index 74e984f..49025cc 100644
--- a/src/const/index.ts
+++ b/src/const/index.ts
@@ -1 +1,7 @@
+import { constants } from 'ethers'
+
+const { MaxUint256: MAX_UINT_256 } = constants
+
+export { MAX_UINT_256 }
export * from './network-configs'
+export * from './time.const'
diff --git a/src/const/network-configs.ts b/src/const/network-configs.ts
index aabf0fa..2fb9a31 100644
--- a/src/const/network-configs.ts
+++ b/src/const/network-configs.ts
@@ -1,4 +1,4 @@
-import { ETHEREUM_CHAINS } from '@/enums'
+import { ETHEREUM_CHAINS, ETHEREUM_RPC_URLS } from '@/enums'
import { type Web3ProviderType } from '@/types'
import { utils } from 'ethers'
@@ -11,26 +11,26 @@ export const ARBITRUM_NETWORK_CONFIG: Readonly =
symbol: 'ETH',
decimals: 18,
},
- rpcUrls: ['https://arb1.arbitrum.io/rpc'],
+ rpcUrls: [ETHEREUM_RPC_URLS.arbitrum],
blockExplorerUrls: ['https://arbiscan.io/'],
})
-export const ARBITRUM_GOERLI_NETWORK_CONFIG: Readonly =
+export const ARBITRUM_SEPOLIA_NETWORK_CONFIG: Readonly =
Object.freeze({
- chainId: utils.hexValue(Number(ETHEREUM_CHAINS.arbitrumGoerli)),
- chainName: 'Arbitrum Goerli (Testnet)',
+ chainId: utils.hexValue(Number(ETHEREUM_CHAINS.arbitrumSepolia)),
+ chainName: 'Arbitrum Sepolia (Testnet)',
nativeCurrency: {
name: 'ETH',
symbol: 'ETH',
decimals: 18,
},
- rpcUrls: ['https://goerli-rollup.arbitrum.io/rpc'],
- blockExplorerUrls: ['https://goerli.arbiscan.io'],
+ rpcUrls: [ETHEREUM_RPC_URLS.arbitrumSepolia],
+ blockExplorerUrls: ['https://sepolia.arbiscan.io'],
})
export const CHAINS_NETWORK_CONFIGS_MAP: Readonly<
Record
> = Object.freeze({
[ETHEREUM_CHAINS.arbitrum]: ARBITRUM_NETWORK_CONFIG,
- [ETHEREUM_CHAINS.arbitrumGoerli]: ARBITRUM_GOERLI_NETWORK_CONFIG,
+ [ETHEREUM_CHAINS.arbitrumSepolia]: ARBITRUM_SEPOLIA_NETWORK_CONFIG,
})
diff --git a/src/const/time.const.ts b/src/const/time.const.ts
new file mode 100644
index 0000000..c09212b
--- /dev/null
+++ b/src/const/time.const.ts
@@ -0,0 +1 @@
+export const DEFAULT_TIME_FORMAT = 'D MMM YYYY [at] HH:mm'
diff --git a/src/enums/chains.enum.ts b/src/enums/chains.enum.ts
index 456ddf6..1f0263e 100644
--- a/src/enums/chains.enum.ts
+++ b/src/enums/chains.enum.ts
@@ -1,6 +1,13 @@
export enum ETHEREUM_CHAINS {
ethereum = '1',
- goerli = '5',
+ sepolia = '11155111',
arbitrum = '42161',
- arbitrumGoerli = '421613',
+ arbitrumSepolia = '421614',
+}
+
+export enum ETHEREUM_RPC_URLS {
+ ethereum = 'https://ethereum.publicnode.com',
+ sepolia = 'https://rpc.sepolia.org/',
+ arbitrum = 'https://arb1.arbitrum.io/rpc',
+ arbitrumSepolia = 'https://sepolia-rollup.arbitrum.io/rpc',
}
diff --git a/src/enums/route-names.enum.ts b/src/enums/route-names.enum.ts
index 77e37d9..812e4cb 100644
--- a/src/enums/route-names.enum.ts
+++ b/src/enums/route-names.enum.ts
@@ -1,9 +1,7 @@
export enum ROUTE_NAMES {
app = 'app',
- appCommunity = 'app-community',
- appCoders = 'app-coders',
- appCompute = 'app-compute',
appCapital = 'app-capital',
+ appCommunity = 'app-community',
uiKit = 'ui-kit',
complexForm = 'complex-form',
}
diff --git a/src/env.d.ts b/src/env.d.ts
index 934cbb9..b08eabf 100644
--- a/src/env.d.ts
+++ b/src/env.d.ts
@@ -15,9 +15,12 @@ declare module '@vue/runtime-core' {
interface ImportMetaEnv {
VITE_ENVIRONMENT: string
VITE_PORT: string
- VITE_API_URL: string
VITE_APP_NAME: string
- VITE_APP_IS_TESTNET: string
+ VITE_APP_ERC1967_PROXY_CONTRACT_ADDRESS: string
+ VITE_APP_STETH_CONTRACT_ADDRESS: string
+ VITE_APP_MOR_CONTRACT_ADDRESS: string
+ VITE_APP_IS_MAINNET: string
+ VITE_APP_BUILD_VERSION: string
}
declare global {
diff --git a/src/fields/InputField.vue b/src/fields/InputField.vue
index a0c237f..9bc4552 100644
--- a/src/fields/InputField.vue
+++ b/src/fields/InputField.vue
@@ -79,6 +79,7 @@ const props = withDefaults(
type?: 'text' | 'number' | 'password'
errorMessage?: string
note?: string
+ isLoading?: boolean
}>(),
{
scheme: 'primary',
@@ -87,6 +88,7 @@ const props = withDefaults(
placeholder: '',
errorMessage: '',
note: '',
+ isLoading: false,
},
)
@@ -145,6 +147,7 @@ const inputClasses = computed(() => [
...(isDisabled.value ? ['input-field--disabled'] : []),
...(isReadonly.value ? ['input-field--readonly'] : []),
...(props.errorMessage ? ['input-field--error'] : []),
+ ...(props.isLoading ? ['input-field--loading'] : []),
`input-field--${props.scheme}`,
])
@@ -216,6 +219,18 @@ $z-index-side-nodes: 1;
position: relative;
width: 100%;
flex: 1;
+
+ &--loading {
+ &:before {
+ $z-index: 2;
+
+ z-index: $z-index;
+ }
+
+ @include skeleton;
+
+ border-radius: 0;
+ }
}
.input-field__label {
@@ -237,6 +252,7 @@ $z-index-side-nodes: 1;
&:disabled,
&:read-only {
+ cursor: not-allowed;
border-color: var(--field-border-disabled);
background: var(--field-bg-primary-disabled);
}
diff --git a/src/fields/SelectField.vue b/src/fields/SelectField.vue
index 7105045..373ae62 100644
--- a/src/fields/SelectField.vue
+++ b/src/fields/SelectField.vue
@@ -106,6 +106,7 @@ const props = withDefaults(
scheme?: 'primary'
modification?: 'dropdown' | 'dropup'
uid?: string
+ isLoading?: boolean
}>(),
{
valueOptions: () => [],
@@ -117,6 +118,7 @@ const props = withDefaults(
scheme: 'primary',
modification: 'dropdown',
uid: `select-field--${uuidv4()}`,
+ isLoading: false,
},
)
@@ -147,6 +149,7 @@ const selectFieldClasses = computed(() => ({
'select-field': true,
'select-field--error': props.errorMessage,
'select-field--filled': props.modelValue,
+ 'select-field--loading': props.isLoading,
'select-field--open': isDropMenuOpen.value,
'select-field--disabled': isDisabled.value,
'select-field--readonly': isReadonly.value,
@@ -206,6 +209,18 @@ $z-local-index: 2;
flex-direction: column;
position: relative;
flex: 1;
+
+ &--loading {
+ &:before {
+ $z-index: 1;
+
+ z-index: $z-index;
+ }
+
+ @include skeleton;
+
+ border-radius: 0;
+ }
}
.select-field__label {
@@ -232,7 +247,7 @@ $z-local-index: 2;
transition: var(--field-transition-duration) var(--field-transition-timing);
&:disabled {
- background: var(--field-bg-primary-disabled);
+ cursor: not-allowed;
color: var(--field-text-readonly);
}
diff --git a/src/forms/DepositForm.vue b/src/forms/DepositForm.vue
index cb87fc5..012516a 100644
--- a/src/forms/DepositForm.vue
+++ b/src/forms/DepositForm.vue
@@ -1,5 +1,9 @@
-
@@ -50,51 +63,206 @@
diff --git a/src/pages/HomePage/views/CodersView.vue b/src/pages/HomePage/views/CodersView.vue
deleted file mode 100644
index 38e0f0a..0000000
--- a/src/pages/HomePage/views/CodersView.vue
+++ /dev/null
@@ -1,70 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/pages/HomePage/views/CommunityView.vue b/src/pages/HomePage/views/CommunityView.vue
index 66b2f26..5d7ca35 100644
--- a/src/pages/HomePage/views/CommunityView.vue
+++ b/src/pages/HomePage/views/CommunityView.vue
@@ -1,50 +1,80 @@
@@ -58,54 +88,273 @@ import {
InfoDashboard,
WithdrawModal,
} from '@/common'
-import { useContext } from '@/composables'
-import { ICON_NAMES } from '@/enums'
-import type { InfoBarType, InfoDashboardType } from '@/types'
-import { ref } from 'vue'
+import { useContext, useContract } from '@/composables'
+import { DEFAULT_TIME_FORMAT } from '@/const'
+import { ETHEREUM_RPC_URLS, ICON_NAMES } from '@/enums'
+import { bus, BUS_EVENTS, ErrorHandler } from '@/helpers'
+import { useWeb3ProvidersStore } from '@/store'
+import type {
+ Erc1967ProxyType,
+ InfoBarType,
+ InfoDashboardType,
+ ProgressBarType,
+} from '@/types'
+import { BigNumber, formatEther, Time } from '@/utils'
+import { config } from '@config'
+import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
-const { $t } = useContext()
+const POOL_ID = 0
+
+const poolData = ref
(null)
+const dailyReward = ref(null)
+const userPoolData = ref(null)
+const currentUserReward = ref(null)
+const isInitializing = ref(false)
const isClaimModalShown = ref(false)
const isDepositModalShown = ref(false)
const isWithdrawModalShown = ref(false)
-const mockBarIndicators: InfoBarType.Indicator[] = [
+const { contractWithProvider: erc1967Proxy } = useContract(
+ 'ERC1967Proxy__factory',
+ config.ERC1967_PROXY_CONTRACT_ADDRESS,
+ config.IS_MAINNET ? ETHEREUM_RPC_URLS.ethereum : ETHEREUM_RPC_URLS.sepolia,
+)
+
+const { $t } = useContext()
+const web3ProvidersStore = useWeb3ProvidersStore()
+
+const barIndicators = computed(() => [
{
title: $t('home-page.community-view.total-invested-title'),
- value: '1 000.67 stETH',
+ value: poolData.value
+ ? `${formatEther(poolData.value.totalDeposited)} stETH`
+ : '',
},
{
title: $t('home-page.community-view.daily-reward-title'),
- value: '100 MOR',
+ value: dailyReward.value ? `${formatEther(dailyReward.value)} MOR` : '',
},
{
title: $t('home-page.community-view.started-at-title'),
- value: '15 Sep 2023 at 13:42',
+ value: poolData.value
+ ? new Time(poolData.value.payoutStart.toNumber() * 1000).format(
+ DEFAULT_TIME_FORMAT,
+ )
+ : '',
},
{
title: $t('home-page.community-view.withdraw-at-title'),
- value: '1 Jan 2024 at 05:12',
+ value: poolData.value
+ ? new Time(
+ (poolData.value.payoutStart.toNumber() +
+ poolData.value.withdrawLockPeriod.toNumber()) *
+ 1000,
+ ).format(DEFAULT_TIME_FORMAT)
+ : '',
note: $t('home-page.community-view.withdraw-at-note'),
},
{
title: $t('home-page.community-view.claim-at-title'),
- value: '1 Jan 2024 at 03:12',
+ value: poolData.value
+ ? new Time(
+ (poolData.value.payoutStart.toNumber() +
+ poolData.value.claimLockPeriod.toNumber()) *
+ 1000,
+ ).format(DEFAULT_TIME_FORMAT)
+ : '',
note: $t('home-page.community-view.claim-at-note'),
},
-]
+])
-const mockDashboardIndicators: InfoDashboardType.Indicator[] = [
+const dashboardIndicators = computed(() => [
{
iconName: ICON_NAMES.ethereum,
title: $t('home-page.community-view.user-invested-title'),
- value: '13 stETH',
+ value: userPoolData.value
+ ? `${formatEther(userPoolData.value.deposited)} stETH`
+ : '',
},
{
iconName: ICON_NAMES.arbitrum,
title: $t('home-page.community-view.available-to-claim-title'),
- value: '20 MOR',
+ value: currentUserReward.value
+ ? `${formatEther(currentUserReward.value)} MOR`
+ : '',
+ },
+])
+
+const dashboardProgress = computed(() => ({
+ value: userPoolData.value?.deposited || BigNumber.from('0'),
+ total: poolData.value?.totalDeposited || BigNumber.from('1'),
+}))
+
+const isDepositDisabled = computed(() => {
+ if (!web3ProvidersStore.balances.stEth) return true
+ return web3ProvidersStore.balances.stEth.isZero()
+})
+
+const isWithdrawDisabled = computed(() => {
+ if (!userPoolData.value?.deposited) return true
+ return userPoolData.value.deposited.isZero()
+})
+
+const isClaimDisabled = computed(() => {
+ if (!currentUserReward.value) return true
+ return currentUserReward.value.isZero()
+})
+
+const fetchPoolData = async (): Promise => {
+ const poolDataResponses = await Promise.all([
+ erc1967Proxy.value.poolsData(POOL_ID),
+ erc1967Proxy.value.pools(POOL_ID),
+ ])
+
+ return {
+ claimLockPeriod: poolDataResponses[1].claimLockPeriod,
+ decreaseInterval: poolDataResponses[1].decreaseInterval,
+ initialReward: poolDataResponses[1].initialReward,
+ isPublic: poolDataResponses[1].isPublic,
+ lastUpdate: poolDataResponses[0].lastUpdate,
+ minimalStake: poolDataResponses[1].minimalStake,
+ rate: poolDataResponses[0].rate,
+ payoutStart: poolDataResponses[1].payoutStart,
+ rewardDecrease: poolDataResponses[1].rewardDecrease,
+ totalDeposited: poolDataResponses[0].totalDeposited,
+ withdrawLockPeriod: poolDataResponses[1].withdrawLockPeriod,
+ withdrawLockPeriodAfterStake:
+ poolDataResponses[1].withdrawLockPeriodAfterStake,
+ }
+}
+
+const fetchDailyReward = async (): Promise => {
+ if (!poolData.value) throw new Error('poolData unavailable')
+
+ const currentTimestamp = new Time().timestamp
+ const decreaseIntervalTimestamp = poolData.value.decreaseInterval.toNumber()
+
+ const startTimestamp =
+ currentTimestamp - (currentTimestamp % decreaseIntervalTimestamp)
+ const endTimestamp = startTimestamp + decreaseIntervalTimestamp
+
+ return erc1967Proxy.value.getPeriodReward(
+ POOL_ID,
+ startTimestamp,
+ endTimestamp,
+ )
+}
+
+const fetchUserPoolData = async (): Promise => {
+ if (!web3ProvidersStore.provider.selectedAddress)
+ throw new Error('user address unavailable')
+
+ const response = await erc1967Proxy.value.usersData(
+ web3ProvidersStore.provider.selectedAddress,
+ POOL_ID,
+ )
+
+ return {
+ lastStake: response.lastStake,
+ deposited: response.deposited,
+ rate: response.rate,
+ pendingRewards: response.pendingRewards,
+ }
+}
+
+const fetchCurrentUserReward = async (): Promise => {
+ if (!web3ProvidersStore.provider.selectedAddress)
+ throw new Error('user address unavailable')
+
+ return erc1967Proxy.value.getCurrentUserReward(
+ POOL_ID,
+ web3ProvidersStore.provider.selectedAddress,
+ )
+}
+
+const updateUserData = async (): Promise => {
+ const [userDataResponse, currentUserRewardResponse] = await Promise.all([
+ fetchUserPoolData(),
+ fetchCurrentUserReward(),
+ ])
+
+ userPoolData.value = userDataResponse
+ currentUserReward.value = currentUserRewardResponse
+}
+
+watch(
+ () => web3ProvidersStore.provider.selectedAddress,
+ async newAddress => {
+ if (newAddress) {
+ try {
+ await updateUserData()
+ } catch (error) {
+ ErrorHandler.process(error)
+ }
+ }
},
-]
+)
+
+const init = async () => {
+ isInitializing.value = true
+
+ try {
+ if (web3ProvidersStore.provider.selectedAddress) {
+ const [pooDataResponse] = await Promise.all([
+ fetchPoolData(),
+ updateUserData(),
+ ])
+
+ poolData.value = pooDataResponse
+ } else {
+ poolData.value = await fetchPoolData()
+ }
+
+ if (poolData.value) dailyReward.value = await fetchDailyReward()
+ } catch (error) {
+ ErrorHandler.process(error)
+ }
+
+ isInitializing.value = false
+}
+
+const onChangePoolData = async (): Promise => {
+ try {
+ if (web3ProvidersStore.provider.selectedAddress) {
+ const [pooDataResponse] = await Promise.all([
+ fetchPoolData(),
+ updateUserData(),
+ ])
+
+ poolData.value = pooDataResponse
+ return
+ }
+
+ poolData.value = await fetchPoolData()
+ } catch (error) {
+ ErrorHandler.process(error)
+ }
+}
+
+const onChangeCurrentUserReward = async (): Promise => {
+ if (web3ProvidersStore.provider.selectedAddress) {
+ try {
+ currentUserReward.value = await fetchCurrentUserReward()
+ } catch (error) {
+ ErrorHandler.process(error)
+ }
+ }
+}
+
+onMounted(() => {
+ init()
+ bus.on(BUS_EVENTS.changedPoolData, onChangePoolData)
+ bus.on(BUS_EVENTS.changedCurrentUserReward, onChangeCurrentUserReward)
+})
+
+onBeforeUnmount(() => {
+ bus.off(BUS_EVENTS.changedPoolData, onChangePoolData)
+ bus.off(BUS_EVENTS.changedCurrentUserReward, onChangeCurrentUserReward)
+})