-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into feat/vote-list
- Loading branch information
Showing
8 changed files
with
301 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
packages/lib/modules/pool/__mocks__/pool-examples/boosted.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { GqlChain } from '@repo/lib/shared/services/api/generated/graphql' | ||
import { PoolExample } from './flat' | ||
|
||
export const v3SepoliaNestedBoosted: PoolExample = { | ||
description: 'Edge case: V3 Nested Boosted', | ||
poolId: '0x693cc6a39bbf35464f53d6a5dbf7d6c2fa93741c', | ||
poolChain: GqlChain.Sepolia, | ||
version: 2, | ||
} | ||
|
||
export const morphoStakeHouse: PoolExample = { | ||
description: 'Edge case: boosted with custom morpho stuff', | ||
poolId: '0x5dd88b3aa3143173eb26552923922bdf33f50949', | ||
poolChain: GqlChain.Mainnet, | ||
version: 3, | ||
} | ||
|
||
export const sDAIBoosted: PoolExample = { | ||
description: | ||
'Edge case: BOOSTED with 2 ERC4626 tokens but one of them (sDAI) has isBufferAllowed == false', | ||
poolId: '0xd1d7fa8871d84d0e77020fc28b7cd5718c446522', | ||
poolChain: GqlChain.Gnosis, | ||
version: 3, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { GqlChain } from '@repo/lib/shared/services/api/generated/graphql' | ||
import { Address } from 'viem' | ||
import { ProtocolVersion } from '../../pool.types' | ||
|
||
export type PoolExample = { | ||
description?: string | ||
// Explicit pool prefix to make tests more readable | ||
poolId: Address | ||
poolAddress?: Address | ||
poolChain: GqlChain | ||
version: ProtocolVersion | ||
} | ||
|
||
export const balWeth8020: PoolExample = { | ||
description: 'Weighted OG', | ||
poolId: '0x5c6ee304399dbdb9c8ef030ab642b10820db8f56000200000000000000000014', | ||
poolAddress: '0x5c6ee304399dbdb9c8ef030ab642b10820db8f56', | ||
poolChain: GqlChain.Mainnet, | ||
version: 2, | ||
} | ||
|
||
export const osETHPhantom: PoolExample = { | ||
description: | ||
'Edge case: Phantom composable stable where the pool itself appears in one of the tokens', | ||
poolId: '0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635', | ||
poolChain: GqlChain.Mainnet, | ||
version: 2, | ||
} | ||
|
||
// TODO: use it in actionable tests | ||
// THIS is A WRONG TEST CAUSE IT IS V2, we need V3 | ||
export const sDAIWeighted: PoolExample = { | ||
description: 'Edge case: sDAI is ERC4626 but has isBufferAllowed == false', | ||
poolId: '0xbc2acf5e821c5c9f8667a36bb1131dad26ed64f9000200000000000000000063', | ||
poolChain: GqlChain.Gnosis, | ||
version: 2, | ||
} | ||
|
||
export const v2SepoliaStableWithERC4626: PoolExample = { | ||
description: 'It has ERC4626 (usdc-aave and dai-aave) tokens but it is V2 so it is not boosted', | ||
poolId: '0x6c3966874f49a2f6a8f2f791f82f65b214e90ccb0000000000000000000001a6', | ||
poolChain: GqlChain.Sepolia, | ||
version: 3, | ||
} |
16 changes: 16 additions & 0 deletions
16
packages/lib/modules/pool/__mocks__/pool-examples/nested.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { GqlChain } from '@repo/lib/shared/services/api/generated/graphql' | ||
import { PoolExample } from './flat' | ||
|
||
export const staBALv2Nested: PoolExample = { | ||
description: 'V2 Nested supporting nested actions (default)', | ||
poolId: '0x66888e4f35063ad8bb11506a6fde5024fb4f1db0000100000000000000000053', | ||
poolChain: GqlChain.Gnosis, | ||
version: 2, | ||
} | ||
|
||
export const auraBal: PoolExample = { | ||
description: 'Edge case: Must use nested 8020 BPT to add (does not support nested actions)', | ||
poolId: '0x3dd0843a028c86e0b760b1a76929d1c5ef93a2dd000200000000000000000249', | ||
poolChain: GqlChain.Mainnet, | ||
version: 2, | ||
} |
10 changes: 10 additions & 0 deletions
10
packages/lib/modules/pool/__mocks__/pool-examples/pool-example-helpers.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { ApiToken } from '../../pool.types' | ||
|
||
// TODO: move to testing utils | ||
export function tokenSymbols(apiTokens: ApiToken[]): string[] { | ||
return apiTokens.map(token => token.symbol).sort() | ||
} | ||
|
||
export function underlyingTokenSymbols(apiTokens: ApiToken[]): string[] { | ||
return apiTokens.map(token => token.underlyingToken?.symbol || '-').sort() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
196 changes: 196 additions & 0 deletions
196
packages/lib/modules/pool/pool.utils.integration.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
import { GqlNestedPool } from '@repo/lib/shared/services/api/generated/graphql' | ||
import { isSameAddress } from '@repo/lib/shared/utils/addresses' | ||
import { sortBy } from 'lodash' | ||
import { Address } from 'viem' | ||
import { PoolToken } from '../tokens/token.helpers' | ||
import { getPoolForTest } from './__mocks__/getPoolMock' | ||
import { | ||
morphoStakeHouse, | ||
sDAIBoosted, | ||
v3SepoliaNestedBoosted, | ||
} from './__mocks__/pool-examples/boosted' | ||
import { | ||
balWeth8020, | ||
osETHPhantom, | ||
PoolExample, | ||
sDAIWeighted, | ||
v2SepoliaStableWithERC4626, | ||
} from './__mocks__/pool-examples/flat' | ||
import { auraBal, staBALv2Nested } from './__mocks__/pool-examples/nested' | ||
import { | ||
tokenSymbols, | ||
underlyingTokenSymbols, | ||
} from './__mocks__/pool-examples/pool-example-helpers' | ||
import { isV3Pool } from './pool.helpers' | ||
import { ApiToken } from './pool.types' | ||
import { getPoolDisplayTokensWithPossibleNestedPools } from './pool.utils' | ||
import { Pool } from './PoolProvider' | ||
|
||
function isPool(pool: any): pool is Pool { | ||
return (pool as Pool).poolTokens !== undefined | ||
} | ||
|
||
function isGqlNestedPool(pool: any): pool is GqlNestedPool { | ||
return (pool as GqlNestedPool).tokens !== undefined | ||
} | ||
|
||
function getPoolTokens(pool: Pool | GqlNestedPool) { | ||
if (isPool(pool)) { | ||
return pool.poolTokens | ||
} | ||
if (isGqlNestedPool(pool)) { | ||
return pool.tokens | ||
} | ||
throw new Error('Invalid pool type: poolTokens or tokens but be defined') | ||
} | ||
|
||
// TODO: extract this pool helpers or utils | ||
function getDisplayTokens(pool: Pool | GqlNestedPool): ApiToken[] { | ||
const tokens = getPoolTokens(pool).map(token => { | ||
if (token.hasNestedPool && token.nestedPool) { | ||
return { | ||
...token, | ||
nestedTokens: getDisplayTokens(token.nestedPool as GqlNestedPool), | ||
} as ApiToken | ||
} | ||
return token as ApiToken | ||
}) | ||
|
||
return sortBy(excludeNestedBptTokens(tokens as ApiToken[], pool.address), 'symbol') | ||
} | ||
|
||
function getHeaderDisplayTokens(pool: Pool): ApiToken[] { | ||
// excludeNestedBptTokens(pool.poolTokens, pool.address) //TODO: do we need this case?? How is Panthom displayed after API fix? | ||
if (isV3Pool(pool) && pool.hasErc4626 && pool.hasAnyAllowedBuffer) { | ||
return pool.poolTokens.map(token => | ||
token.isErc4626 && token.isBufferAllowed | ||
? ({ ...token, ...token.underlyingToken } as ApiToken) | ||
: (token as ApiToken) | ||
) | ||
} | ||
// Is this correct? | ||
return getDisplayTokens(pool) | ||
} | ||
|
||
function excludeNestedBptTokens(tokens: PoolToken[] | ApiToken[], poolAddress: string): ApiToken[] { | ||
return tokens | ||
.filter(token => !isSameAddress(token.address, poolAddress as Address)) // Exclude the BPT pool token itself | ||
.filter(token => token !== undefined) as ApiToken[] | ||
} | ||
|
||
// Testing utils that can be kept in the test: | ||
async function getDisplaySymbols(poolExample: PoolExample): Promise<string[]> { | ||
const pool = await getPoolForTest(poolExample) | ||
|
||
return tokenSymbols(getDisplayTokens(pool)) | ||
} | ||
|
||
async function getDisplayTokensFromPoolExample(poolExample: PoolExample): Promise<ApiToken[]> { | ||
const pool = await getPoolForTest(poolExample) | ||
return getDisplayTokens(pool) | ||
} | ||
|
||
async function getHeaderDisplaySymbols(poolExample: PoolExample): Promise<string[]> { | ||
const pool = await getPoolForTest(poolExample) | ||
|
||
return tokenSymbols(getHeaderDisplayTokens(pool)) | ||
} | ||
|
||
async function getBoostedUnderlyingTokenSymbols(poolExample: PoolExample): Promise<string[]> { | ||
const displayTokens = await getDisplayTokensFromPoolExample(poolExample) | ||
|
||
return underlyingTokenSymbols(displayTokens) | ||
} | ||
|
||
async function getNestedTokenSymbols(poolExample: PoolExample): Promise<string[]> { | ||
const displayTokens = await getDisplayTokensFromPoolExample(poolExample) | ||
|
||
return displayTokens | ||
.filter(token => token.nestedTokens) | ||
.flatMap(token => token.nestedTokens?.map(t => t.symbol) || []) | ||
} | ||
|
||
async function getOldCompositionDisplaySymbols(poolExample: PoolExample): Promise<string[]> { | ||
const pool = await getPoolForTest(poolExample) | ||
|
||
return tokenSymbols(getPoolDisplayTokensWithPossibleNestedPools(pool) as ApiToken[]) | ||
} | ||
|
||
describe('getDisplayTokens for flat pools', () => { | ||
it('BAL WETH 80 20', async () => { | ||
expect(await getDisplaySymbols(balWeth8020)).toEqual(['BAL', 'WETH']) | ||
}) | ||
|
||
it('osETH Phantom Composable Stable', async () => { | ||
expect(await getDisplaySymbols(osETHPhantom)).toEqual(['WETH', 'osETH']) | ||
}) | ||
|
||
it('sDAI weighted', async () => { | ||
expect(await getDisplaySymbols(sDAIWeighted)).toEqual(['sDAI', 'wstETH']) | ||
}) | ||
|
||
it.skip('v2 stable with ERC4626 tokens (V2 so no boosted)', async () => { | ||
expect(await getDisplaySymbols(v2SepoliaStableWithERC4626)).toEqual(['dai-aave', 'usdc-aave']) | ||
}) | ||
}) | ||
|
||
describe('getDisplayTokens for NESTED pools', () => { | ||
it('v2 nested', async () => { | ||
expect(await getDisplaySymbols(staBALv2Nested)).toEqual(['WBTC', 'WETH', 'staBAL3']) | ||
|
||
expect(await getHeaderDisplaySymbols(staBALv2Nested)).toEqual(['WBTC', 'WETH', 'staBAL3']) | ||
|
||
// TODO: merge this function logic into getDisplayTokens above and getPoolDisplayTokens(pool: Pool | PoolListItem) in pool.utils | ||
expect(await getOldCompositionDisplaySymbols(staBALv2Nested)).toEqual([ | ||
'USDC', | ||
'USDT', | ||
'WBTC', | ||
'WETH', | ||
'WXDAI', | ||
'staBAL3', | ||
]) | ||
|
||
expect(await getNestedTokenSymbols(staBALv2Nested)).toEqual(['USDC', 'USDT', 'WXDAI']) | ||
}) | ||
|
||
it('aura bal (Nested with supportsNestedActions false)', async () => { | ||
expect(await getDisplaySymbols(auraBal)).toEqual(['B-80BAL-20WETH', 'auraBAL']) | ||
}) | ||
}) | ||
|
||
describe('getDisplayTokens for BOOSTED pools', () => { | ||
it('Morpho boosted', async () => { | ||
expect(await getDisplaySymbols(morphoStakeHouse)).toEqual(['csUSDL', 'steakUSDC']) | ||
|
||
// Only case where pool composition and header do not match | ||
expect(await getHeaderDisplaySymbols(morphoStakeHouse)).toEqual(['USDC', 'wUSDL']) | ||
|
||
expect(await getBoostedUnderlyingTokenSymbols(morphoStakeHouse)).toEqual(['USDC', 'wUSDL']) | ||
}) | ||
|
||
it('sDAI boosted', async () => { | ||
expect(await getDisplaySymbols(sDAIBoosted)).toEqual(['sDAI', 'waGnoGNO']) | ||
// Only case where pool composition and header do not match | ||
expect(await getHeaderDisplaySymbols(sDAIBoosted)).toEqual(['GNO', 'sDAI']) | ||
}) | ||
|
||
// unskip when we have a non-sepolia nested v3 | ||
it.skip('v3 nested boosted', async () => { | ||
expect(await getDisplaySymbols(v3SepoliaNestedBoosted)).toEqual(['WETH', 'bb-a-USD']) | ||
|
||
expect(await getHeaderDisplaySymbols(v3SepoliaNestedBoosted)).toEqual(['WETH', 'bb-a-USD']) // DO WE WANT THIS in the header? | ||
|
||
const lpToken = getDisplayTokens(await getPoolForTest(v3SepoliaNestedBoosted))[1] | ||
expect(tokenSymbols(lpToken.nestedTokens as ApiToken[])).toEqual([ | ||
'stataEthUSDC', | ||
'stataEthUSDT', | ||
]) | ||
|
||
// TODO: merge this function logic into getDisplayTokens above and getPoolDisplayTokens(pool: Pool | PoolListItem) in pool.utils | ||
expect(await getOldCompositionDisplaySymbols(v3SepoliaNestedBoosted)).toEqual([ | ||
'WETH', | ||
'stataEthUSDC', | ||
'stataEthUSDT', | ||
]) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters