Skip to content

Commit

Permalink
feat: add staked pools gauges request
Browse files Browse the repository at this point in the history
  • Loading branch information
alter-eggo committed Jul 28, 2023
1 parent 3eedf99 commit 918b47a
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 4 deletions.
35 changes: 33 additions & 2 deletions src/components/contextual/pages/pools/StakedPoolsTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import PortfolioSyncTip from '../vebal/cross-chain-boost/PortfolioSyncTip.vue';
*/
const showUnstakeModal = ref(false);
const poolToUnstake = ref<Pool | undefined>();
const showRestakeModal = ref(false);
const poolToRestake = ref<Pool | undefined>();
const showProceedModal = ref(false);
/**
Expand All @@ -28,8 +32,13 @@ providePoolStaking();
/**
* COMPOSABLES
*/
const { stakedPools, poolBoostsMap, stakedShares, isLoading } =
useUserStaking();
const {
stakedPools,
poolBoostsMap,
stakedShares,
isLoading,
hasNonPrefGaugesPoolsIds,
} = useUserStaking();
const { refetchAllUserPools } = useUserPools();
const { isWalletReady, isWalletConnecting } = useWeb3();
Expand Down Expand Up @@ -62,9 +71,15 @@ function handleUnstake(pool: Pool) {
poolToUnstake.value = pool;
}
function handleRestake(pool: Pool) {
showRestakeModal.value = true;
poolToRestake.value = pool;
}
function handleModalClose() {
refetchAllUserPools();
showUnstakeModal.value = false;
showRestakeModal.value = false;
}
async function handleUnstakeSuccess() {
Expand All @@ -77,6 +92,7 @@ async function handleUnstakeSuccess() {
<BalStack vertical spacing="sm">
<h5 class="px-4 xl:px-0">
{{ $t('staking.stakedPools') }}
{{ hasNonPrefGaugesPoolsIds }}
</h5>
<PortfolioSyncTip @show-proceed-modal="showProceedModal = true" />
<PoolsTable
Expand All @@ -91,10 +107,14 @@ async function handleUnstakeSuccess() {
:isLoading="isWalletReady && isLoading"
showPoolShares
showActions
showStakeActions
:showBoost="isPoolBoostsEnabled"
@trigger-unstake="handleUnstake"
@trigger-restake="handleRestake"
/>
</BalStack>

<!-- Unstake modal -->
<StakePreviewModal
v-if="poolToUnstake"
:pool="poolToUnstake"
Expand All @@ -103,6 +123,17 @@ async function handleUnstakeSuccess() {
@close="handleModalClose"
@success="handleUnstakeSuccess"
/>

<!-- Restake modal -->
<StakePreviewModal
v-if="poolToRestake"
:pool="poolToRestake"
:isVisible="showRestakeModal"
action="restake"
@close="handleModalClose"
@success="handleUnstakeSuccess"
/>

<ProceedToSyncModal
:isVisible="showProceedModal"
@close="showProceedModal = false"
Expand Down
22 changes: 21 additions & 1 deletion src/components/tables/PoolsTable/PoolsTableActionsCell.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Pool } from '@/services/pool/types';
*/
type Props = {
pool: Pool;
poolsType?: 'unstaked' | 'staked';
poolsType?: 'unstaked' | 'staked' | 'toRestake' | 'toUpdate';
};
/**
Expand All @@ -24,6 +24,8 @@ const props = withDefaults(defineProps<Props>(), {
const emit = defineEmits<{
(e: 'click:stake', value: Pool): void;
(e: 'click:unstake', value: Pool): void;
(e: 'click:restake', value: Pool): void;
(e: 'click:update', value: Pool): void;
(e: 'click:migrate', value: Pool): void;
}>();
/**
Expand Down Expand Up @@ -58,6 +60,24 @@ const showVeBalLock = computed(() => isVeBalPool(props.pool.id));
>
{{ $t('stake') }}
</BalBtn>
<BalBtn
v-else-if="poolsType === 'toRestake'"
color="gradient"
size="sm"
:disabled="isMigratablePool(pool)"
@click.prevent.stop="emit('click:stake', pool)"
>
{{ $t('restake') }}
</BalBtn>
<BalBtn
v-else-if="poolsType === 'toUpdate'"
color="gradient"
size="sm"
:disabled="isMigratablePool(pool)"
@click.prevent.stop="emit('click:stake', pool)"
>
{{ $t('Update') }}
</BalBtn>
<BalBtn
v-else-if="poolsType === 'staked'"
class="dark:text-gray-300 dark:border-gray-300"
Expand Down
95 changes: 95 additions & 0 deletions src/composables/queries/usePoolsGaugesQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { useQuery, UseQueryOptions } from '@tanstack/vue-query';

import QUERY_KEYS from '@/constants/queryKeys';
import { subgraphRequest } from '@/lib/utils/subgraph';
import { configService } from '@/services/config/config.service';

/**
* TYPES
*/
export type PoolsGauges = {
__name: 'PoolGauges';
pools: {
preferentialGauge: {
id: string | null;
};
gauges: {
id: string;
relativeWeightCap: string;
}[];
address: string;
}[];
};

type QueryOptions = UseQueryOptions<PoolsGauges>;

/**
* Fetches all gauges for a given pool and specifies which gauge is the
* preferential gauge.
*/
export default function usePoolsGaugesQuery(
poolAddresses: Ref<string[] | undefined>,
options: UseQueryOptions<PoolsGauges> = {}
) {
/**
* QUERY KEY
*/
const queryKey = reactive(QUERY_KEYS.Pools.Gauges(poolAddresses));

/**
* COMPUTED
*/
const enabled = computed((): boolean => !!poolAddresses?.value?.length);

const subgraphQuery = computed(() => ({
__name: 'PoolGauges',
pools: {
__args: {
where: {
address_in: poolAddresses.value?.map(address =>
address.toLowerCase()
),
},
},
preferentialGauge: {
id: true,
},
gauges: {
id: true,
relativeWeightCap: true,
},
address: true,
},
}));

/**
* QUERY FUNCTION
*/
const queryFn = async () => {
try {
return await subgraphRequest<PoolsGauges[]>({
url: configService.network.subgraphs.gauge,
query: subgraphQuery.value,
});
} catch (error) {
console.error(
`Failed to fetch pool gauge for pools: ${poolAddresses.value}`,
{
cause: error,
}
);
throw error;
}
};

/**
* QUERY OPTIONS
*/
const queryOptions = reactive({
enabled,
refetchOnWindowFocus: false,
...options,
});

return useQuery<PoolsGauges>(queryKey, queryFn, queryOptions as QueryOptions);

Check failure on line 94 in src/composables/queries/usePoolsGaugesQuery.ts

View workflow job for this annotation

GitHub Actions / Test

No overload matches this call.
}
2 changes: 2 additions & 0 deletions src/composables/queries/useUserGaugeSharesQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type GaugeShare = {
balance: string;
gauge: {
id: string;
poolAddress: string;
poolId: string;
totalSupply: string;
};
Expand Down Expand Up @@ -76,6 +77,7 @@ export default function useUserGaugeSharesQuery(
balance: true,
gauge: {
id: true,
poolAddress: true,
poolId: true,
totalSupply: true,
},
Expand Down
5 changes: 5 additions & 0 deletions src/constants/queryKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ const QUERY_KEYS = {
},
],
},
Gauges: (poolAddresses: Ref<string[] | undefined>) => [
'pools',
'gauges',
{ poolAddresses },
],
},
Pool: {
Gauges: (poolAddress: Ref<string | undefined>) => [
Expand Down
46 changes: 45 additions & 1 deletion src/providers/local/user-staking.provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { Pool } from '@/services/pool/types';
import { computed, InjectionKey, provide, reactive, ref } from 'vue';
import { safeInject } from '../inject';
import { useUserData } from '../user-data.provider';
import usePoolsGaugesQuery from '@/composables/queries/usePoolsGaugesQuery';
import { bnum, isSameAddress } from '@/lib/utils';

const provider = () => {
/**
Expand All @@ -27,10 +29,19 @@ const provider = () => {
// Array of all the pools a user has staked BPT for.
const stakedPoolIds = computed((): string[] => {
if (!userGaugeShares.value) return [];

console.log('userGaugeShares.value', userGaugeShares.value);
return userGaugeShares.value.map(gaugeShare => gaugeShare.gauge.poolId);
});

// Array of all the pools addresses a user has staked BPT for.
const stakedPoolAddresses = computed((): string[] => {
if (!userGaugeShares.value) return [];

return userGaugeShares.value.map(
gaugeShare => gaugeShare.gauge.poolAddress
);
});

const isPoolsQueryEnabled = computed(
(): boolean => stakedPoolIds.value.length > 0
);
Expand All @@ -45,6 +56,37 @@ const provider = () => {
pageSize: 999,
}
);

const { data: poolsGauges } = usePoolsGaugesQuery(
computed(() => stakedPoolAddresses.value)
);

// Map of user gauge addresses -> balance.
const userGaugeSharesMap = computed((): Record<string, string> => {
if (!userGaugeShares.value) return {};

return userGaugeShares.value.reduce((acc, share) => {
acc[share.gauge.id] = share.balance;
return acc;
}, {} as Record<string, string>);
});

const hasNonPrefGaugesPoolsIds = computed(() => {
return poolsGauges.value?.pools.reduce((acc: string[], pool) => {
const preferentialGaugeAddress = pool.preferentialGauge.id || '';
const hasNonPregGauge = pool.gauges.some(
gaugeAddress =>
!isSameAddress(gaugeAddress.id, preferentialGaugeAddress) &&
bnum(userGaugeSharesMap.value[gaugeAddress.id] || '0').gt(0)
);

if (hasNonPregGauge) {
acc.push(pool.address);
}
return acc;
}, []);
});

const { data: _stakedPools, refetch: refetchStakedPools } = stakedPoolsQuery;

// Pool records for all the pools where a user has staked BPT.
Expand Down Expand Up @@ -92,6 +134,8 @@ const provider = () => {
isLoading,
refetchStakedPools,
stakedSharesFor,
hasNonPrefGaugesPoolsIds,
poolsGauges,
};
};

Expand Down

0 comments on commit 918b47a

Please sign in to comment.