Skip to content
Closed
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
5 changes: 5 additions & 0 deletions .changeset/yield-plus-pr05-data-hooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@venusprotocol/evm": patch
---

add Yield+ position, asset, and simulation queries plus the hooks that feed the feature UI
13 changes: 12 additions & 1 deletion apps/evm/src/__mocks__/models/swap.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ExactInSwapQuote } from 'types';
import type { ApproximateOutSwapQuote, ExactInSwapQuote } from 'types';
import { lisUsd, usdc } from './tokens';

export const exactInSwapQuote: ExactInSwapQuote = {
Expand All @@ -11,3 +11,14 @@ export const exactInSwapQuote: ExactInSwapQuote = {
minimumToTokenAmountReceivedMantissa: 100000000n,
callData: '0x',
};

export const approximateOutSwapQuote: ApproximateOutSwapQuote = {
fromToken: lisUsd,
toToken: usdc,
direction: 'approximate-out',
priceImpactPercentage: 0.1,
fromTokenAmountSoldMantissa: 100000000n,
expectedToTokenAmountReceivedMantissa: 100000000n,
minimumToTokenAmountReceivedMantissa: 100000000n,
callData: '0x',
};
119 changes: 119 additions & 0 deletions apps/evm/src/clients/api/__mocks__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { primeEstimationData } from '__mocks__/models/primeEstimation';
import { transactions } from '__mocks__/models/transactions';
import { fixedRatedVaults, vaults } from '__mocks__/models/vaults';
import voters from '__mocks__/models/voters';
import { yieldPlusPositions } from '__mocks__/models/yieldPlus';

import FunctionKey from 'constants/functionKey';

Expand Down Expand Up @@ -53,6 +54,30 @@ export const useGetVaiTreasuryPercentage = vi.fn(() =>
}),
);

export const getProportionalCloseTolerancePercentage = vi.fn(() => ({
proportionalCloseTolerancePercentage: 2,
}));
export const useGetProportionalCloseTolerancePercentage = vi.fn(() =>
useQuery({
queryKey: [FunctionKey.GET_PROPORTIONAL_CLOSE_TOLERANCE_PERCENTAGE],
queryFn: getProportionalCloseTolerancePercentage,
}),
);

export const getDsaVTokens = vi.fn(async () => ({
dsaVTokenAddresses: [
poolData[0].assets[0].vToken.address,
poolData[0].assets[1].vToken.address,
poolData[0].assets[2].vToken.address,
],
}));
export const useGetDsaVTokens = vi.fn(() =>
useQuery({
queryKey: [FunctionKey.GET_DSA_V_TOKENS],
queryFn: getDsaVTokens,
}),
);

export const getMarketHistory = vi.fn();
export const useGetMarketHistory = vi.fn(() =>
useQuery({
Expand All @@ -69,6 +94,16 @@ export const useGetTopMarkets = vi.fn(() =>
}),
);

export const getTokenPairKLineCandles = vi.fn(() => ({
candles: [],
}));
export const useGetTokenPairKLineCandles = vi.fn(() =>
useQuery({
queryKey: [FunctionKey.GET_TOKEN_PAIR_K_LINE_CANDLES],
queryFn: getTokenPairKLineCandles,
}),
);

export const getMintableVai = vi.fn();
export const useGetMintableVai = vi.fn(() =>
useQuery({
Expand Down Expand Up @@ -681,6 +716,18 @@ export const useGetProposalCount = vi.fn(() =>
}),
);

export const getRawYieldPlusPositions = vi.fn(async () => ({
positions: yieldPlusPositions,
}));
export const useGetRawYieldPlusPositions = vi.fn(() =>
useQuery({
queryKey: [FunctionKey.GET_RAW_YIELD_PLUS_POSITIONS],
queryFn: getRawYieldPlusPositions,
}),
);

export const useKLineWebSocket = vi.fn();

// Mutations
export const useApproveToken = vi.fn((_variables: never, options?: MutationObserverOptions) =>
useMutation({
Expand Down Expand Up @@ -753,6 +800,78 @@ export const useOpenLeveragedPosition = vi.fn(
}),
);

export const useOpenYieldPlusPosition = vi.fn(
(_variables: never, options?: MutationObserverOptions) =>
useMutation({
mutationFn: vi.fn(),
...options,
}),
);

export const useCloseYieldPlusPosition = vi.fn(
(_variables: never, options?: MutationObserverOptions) =>
useMutation({
mutationFn: vi.fn(),
...options,
}),
);

export const useCloseYieldPlusPositionWithLoss = vi.fn(
(_variables: never, options?: MutationObserverOptions) =>
useMutation({
mutationFn: vi.fn(),
...options,
}),
);

export const useCloseYieldPlusPositionWithProfit = vi.fn(
(_variables: never, options?: MutationObserverOptions) =>
useMutation({
mutationFn: vi.fn(),
...options,
}),
);

export const useReduceYieldPlusPositionWithProfit = vi.fn(
(_variables: never, options?: MutationObserverOptions) =>
useMutation({
mutationFn: vi.fn(),
...options,
}),
);

export const useReduceYieldPlusPositionWithLoss = vi.fn(
(_variables: never, options?: MutationObserverOptions) =>
useMutation({
mutationFn: vi.fn(),
...options,
}),
);

export const useIncreaseYieldPlusPosition = vi.fn(
(_variables: never, options?: MutationObserverOptions) =>
useMutation({
mutationFn: vi.fn(),
...options,
}),
);

export const useSupplyYieldPlusPositionCollateral = vi.fn(
(_variables: never, options?: MutationObserverOptions) =>
useMutation({
mutationFn: vi.fn(),
...options,
}),
);

export const useWithdrawYieldPlusPositionCollateral = vi.fn(
(_variables: never, options?: MutationObserverOptions) =>
useMutation({
mutationFn: vi.fn(),
...options,
}),
);

export const useRepayWithCollateral = vi.fn(
(_variables: never, options?: MutationObserverOptions) =>
useMutation({
Expand Down
8 changes: 8 additions & 0 deletions apps/evm/src/clients/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,16 @@ export * from './queries/getSimulatedPool/useGetSimulatedPool';
export * from './queries/getSwapQuote';
export * from './queries/getSwapQuote/useGetSwapQuote';

export * from './queries/getDsaVTokens';
export * from './queries/getDsaVTokens/useGetDsaVTokens';

export * from './queries/getProportionalCloseTolerancePercentage';
export * from './queries/getProportionalCloseTolerancePercentage/useGetProportionalCloseTolerancePercentage';

export * from './queries/getProposalCount';
export * from './queries/getProposalCount/useGetProposalCount';
export * from './queries/getRawYieldPlusPositions';
export * from './queries/getRawYieldPlusPositions/useGetRawYieldPlusPositions';

export * from './queries/getFixedRatedVaults';
export * from './queries/getFixedRatedVaults/useGetFixedRatedVaults';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import fakeAccountAddress, {
altAddress as fakePoolComptrollerAddress,
} from '__mocks__/models/address';
import BigNumber from 'bignumber.js';
import { queryClient } from 'clients/api';
import { queryClient } from 'clients/api/queryClient';
import type { PendleContractDepositCallParams } from 'clients/api';
import { useGetContractAddress } from 'hooks/useGetContractAddress';
import { useSendTransaction } from 'hooks/useSendTransaction';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,41 @@
import { fireEvent, waitFor } from '@testing-library/react';
import { vai, xvs } from '__mocks__/models/tokens';
import BigNumber from 'bignumber.js';
import { useStakeInVaiVault, useStakeInXvsVault } from 'clients/api';
import { useStakeInVaiVault } from 'clients/api/mutations/useStakeInVaiVault';
import { useStakeInXvsVault } from 'clients/api/mutations/useStakeInXvsVault';
import { renderComponent } from 'testUtils/render';
import type { Mock } from 'vitest';
import { useStakeInVault } from '..';

vi.mock('clients/api/mutations/useStakeInVaiVault', () => ({
useStakeInVaiVault: vi.fn(),
}));

vi.mock('clients/api/mutations/useStakeInXvsVault', () => ({
useStakeInXvsVault: vi.fn(),
}));

const fakeAmountMantissa = new BigNumber('10000000000000000');
const fakeStakeButtonLabel = 'Stake';

describe('useStakeInVault', () => {
beforeEach(() => {
(useStakeInXvsVault as Mock).mockReturnValue({
mutateAsync: vi.fn(),
isPending: false,
});

(useStakeInVaiVault as Mock).mockReturnValue({
mutateAsync: vi.fn(),
isPending: false,
});
});

it('calls stakeInXvsVault with correct parameters when calling stake a poolIndex', async () => {
const mockStakeInXvsVault = vi.fn();
(useStakeInXvsVault as Mock).mockReturnValue({
mutateAsync: mockStakeInXvsVault,
isPending: false,
});

const fakePoolIndex = 6;
Expand Down Expand Up @@ -58,6 +80,7 @@ describe('useStakeInVault', () => {
const mockStakeInVaiVault = vi.fn();
(useStakeInVaiVault as Mock).mockReturnValue({
mutateAsync: mockStakeInVaiVault,
isPending: false,
});

const TestComponent: React.FC = () => {
Expand Down
3 changes: 2 additions & 1 deletion apps/evm/src/clients/api/mutations/useStakeInVault/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type BigNumber from 'bignumber.js';

import { useStakeInVaiVault, useStakeInXvsVault } from 'clients/api';
import { useStakeInVaiVault } from 'clients/api/mutations/useStakeInVaiVault';
import { useStakeInXvsVault } from 'clients/api/mutations/useStakeInXvsVault';
import { VError } from 'libs/errors';
import { useGetToken } from 'libs/tokens';
import type { Token } from 'types';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import fakeAccountAddress, {
altAddress as fakePoolComptrollerAddress,
} from '__mocks__/models/address';
import BigNumber from 'bignumber.js';
import { queryClient } from 'clients/api';
import { queryClient } from 'clients/api/queryClient';
import type { PendleContractWithdrawCallParams } from 'clients/api';
import { useGetContractAddress } from 'hooks/useGetContractAddress';
import { useSendTransaction } from 'hooks/useSendTransaction';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { PublicClient } from 'viem';

import fakeAddress from '__mocks__/models/address';
import { relativePositionManagerAbi } from 'libs/contracts';
import { getDsaVTokens } from '..';

describe('getDsaVTokens', () => {
test('returns DSA vToken addresses', async () => {
const fakeDsaVTokenAddresses = [fakeAddress, '0x0000000000000000000000000000000000000001'];

const readContractMock = vi.fn().mockResolvedValue(fakeDsaVTokenAddresses);

const fakePublicClient = {
readContract: readContractMock,
} as unknown as PublicClient;

const response = await getDsaVTokens({
publicClient: fakePublicClient,
relativePositionManagerAddress: fakeAddress,
});

expect(readContractMock).toHaveBeenCalledTimes(1);
expect(readContractMock).toHaveBeenCalledWith({
address: fakeAddress,
abi: relativePositionManagerAbi,
functionName: 'getDsaVTokens',
});

expect(response).toEqual({
dsaVTokenAddresses: fakeDsaVTokenAddresses,
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { QueryClient } from '@tanstack/react-query';
import { waitFor } from '@testing-library/react';
import fakeAddress from '__mocks__/models/address';
import FunctionKey from 'constants/functionKey';
import { useGetContractAddress } from 'hooks/useGetContractAddress';
import { usePublicClient } from 'libs/wallet';
import { renderHook } from 'testUtils/render';
import { ChainId } from 'types';
import type { Address } from 'viem';
import type { Mock } from 'vitest';
import * as getDsaVTokensQueries from '..';
import { useGetDsaVTokens } from '../useGetDsaVTokens';

describe('useGetDsaVTokens', () => {
it('uses the expected query key and calls getDsaVTokens with the right parameters', async () => {
const fakePublicClient = {
readContract: vi.fn(),
};

const fakeOutput = {
dsaVTokenAddresses: [fakeAddress as Address],
};

const getDsaVTokensSpy = vi
.spyOn(getDsaVTokensQueries, 'getDsaVTokens')
.mockResolvedValue(fakeOutput);

(usePublicClient as Mock).mockImplementation(() => ({
publicClient: fakePublicClient,
}));

const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
gcTime: 0,
},
},
});

const { result } = renderHook(() => useGetDsaVTokens(), {
chainId: ChainId.BSC_MAINNET,
queryClient,
});

await waitFor(() => expect(result.current.isSuccess).toBe(true));

expect(getDsaVTokensSpy).toHaveBeenCalledWith({
publicClient: fakePublicClient,
relativePositionManagerAddress: '0xfakeRelativePositionManagerContractAddress',
});

expect(
queryClient.getQueryData([FunctionKey.GET_DSA_V_TOKENS, { chainId: ChainId.BSC_MAINNET }]),
).toEqual(fakeOutput);
});

it('throws when relativePositionManagerAddress is missing', async () => {
const getDsaVTokensSpy = vi.spyOn(getDsaVTokensQueries, 'getDsaVTokens');

(useGetContractAddress as Mock).mockImplementation(() => ({ address: undefined }));

const { result } = renderHook(() => useGetDsaVTokens());

await waitFor(() => expect(result.current.isError).toBe(true));

expect(result.current.error?.message).toBe('couldNotRetrieveSigner');
expect(getDsaVTokensSpy).not.toHaveBeenCalled();
});
});
Loading
Loading