Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/morpho blue + fix optimizers #6

Closed
wants to merge 7 commits into from
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
"dotenv": "^16.3.1",
"ethers": "^6.7.1",
"evm-maths": "^6.0.0",
"pino": "^8.15.0"
"pino": "^8.15.0",
"zod": "^3.22.4"
}
}
4 changes: 2 additions & 2 deletions src/adapters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ import { IZiswapAdapter } from './iziswap/products/iziswap/iZiswapAdapter'
import { LidoStEthAdapter } from './lido/products/st-eth/lidoStEthAdapter'
import { LidoWstEthAdapter } from './lido/products/wst-eth/lidoWstEthAdapter'
import { SDaiAdapter } from './maker/products/yield/sDaiAdapter'
import { MendiFinanceBorrowAdapter } from './mendi-finance/products/borrow/mendiFinanceBorrowAdapter'
import { MendiFinanceSupplyAdapter } from './mendi-finance/products/supply/mendiFinanceSupplyAdapter'
import { MorphoAaveV2OptimizerBorrowAdapter } from './morpho-aave-v2/products/optimizer-borrow/morphoAaveV2OptimizerBorrowAdapter'
import { MorphoAaveV2OptimizerSupplyAdapter } from './morpho-aave-v2/products/optimizer-supply/morphoAaveV2OptimizerSupplyAdapter'
import { MorphoAaveV3ETHOptimizerBorrowAdapter } from './morpho-aave-v3-eth/products/optimizer-borrow/morphoAaveV3ETHOptimizerBorrowAdapter'
import { MorphoAaveV3ETHOptimizerSupplyAdapter } from './morpho-aave-v3-eth/products/optimizer-supply/morphoAaveV3ETHOptimizerSupplyAdapter'
import { MorphoCompoundV2OptimizerBorrowAdapter } from './morpho-compound-v2/products/optimizer-borrow/morphoCompoundV2OptimizerBorrowAdapter'
import { MorphoCompoundV2OptimizerSupplyAdapter } from './morpho-compound-v2/products/optimizer-supply/morphoCompoundV2OptimizerSupplyAdapter'
import { MendiFinanceBorrowAdapter } from './mendi-finance/products/borrow/mendiFinanceBorrowAdapter'
import { MendiFinanceSupplyAdapter } from './mendi-finance/products/supply/mendiFinanceSupplyAdapter'
import { PricesUSDAdapter } from './prices/products/usd/pricesUSDAdapter'
import { Protocol } from './protocols'
import { StargatePoolAdapter } from './stargate/products/pool/stargatePoolAdapter'
Expand Down
2 changes: 1 addition & 1 deletion src/adapters/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import { testCases as gMXTestCases } from './gmx/tests/testCases'
import { testCases as iZiSwapTestCases } from './iziswap/tests/testCases'
import { testCases as lidoTestCases } from './lido/tests/testCases'
import { testCases as makerTestCases } from './maker/tests/testCases'
import { testCases as mendiFinanceTestCases } from './mendi-finance/tests/testCases'
import { testCases as morphoAaveV2TestCases } from './morpho-aave-v2/tests/testCases'
import { testCases as morphoAaveV3ETHOptimizerTestCases } from './morpho-aave-v3-eth/tests/testCases'
import { testCases as morphoCompoundV2OptimizerTestCases } from './morpho-compound-v2/tests/testCases'
import { testCases as mendiFinanceTestCases } from './mendi-finance/tests/testCases'
import { testCases as pricesTestCases } from './prices/tests/testCases'
import { Protocol } from './protocols'
import { testCases as stargateTestCases } from './stargate/tests/testCases'
Expand Down
145 changes: 10 additions & 135 deletions src/adapters/morpho-aave-v2/common/morphoBasePoolAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import { formatUnits } from 'ethers'
import { AdaptersController } from '../../../core/adaptersController'
import { Chain } from '../../../core/constants/chains'
import { RAY } from '../../../core/constants/RAY'
import { SECONDS_PER_YEAR } from '../../../core/constants/SECONDS_PER_YEAR'
import { ZERO_ADDRESS } from '../../../core/constants/ZERO_ADDRESS'
import { IMetadataBuilder } from '../../../core/decorators/cacheToFile'
import { NotImplementedError } from '../../../core/errors/errors'
import { aggregateTrades } from '../../../core/utils/aggregateTrades'
import { aprToApy } from '../../../core/utils/aprToApy'
import { CustomJsonRpcProvider } from '../../../core/utils/customJsonRpcProvider'
import { getTokenMetadata } from '../../../core/utils/getTokenMetadata'
import { logger } from '../../../core/utils/logger'
import { formatProtocolTokenArrayToMap } from '../../../core/utils/protocolTokenToMap'
import {
GetPositionsInput,
GetEventsInput,
GetApyInput,
GetAprInput,
GetTotalValueLockedInput,
GetProfitsInput,
GetConversionRateInput,
MovementsByBlock,
PositionType,
Expand All @@ -27,14 +23,12 @@ import {
ProtocolTokenApr,
ProtocolTokenApy,
ProtocolTokenUnderlyingRate,
ProfitsWithRange,
ProtocolTokenTvl,
ProtocolPosition,
TokenBalance,
TokenType,
Underlying,
UnderlyingTokenRate,
BaseTokenMovement,
} from '../../../types/adapter'
import { Erc20Metadata } from '../../../types/erc20Metadata'
import { Protocol } from '../../protocols'
Expand Down Expand Up @@ -334,124 +328,6 @@ export abstract class MorphoBasePoolAdapter implements IMetadataBuilder {
})
}

async getProfits({
userAddress,
fromBlock,
toBlock,
}: GetProfitsInput): Promise<ProfitsWithRange> {
// Fetch end and start position values
const positionType = this.getProtocolDetails().positionType

const [endPositionValues, startPositionValues] = await Promise.all([
this.getPositions({
userAddress,
blockNumber: toBlock,
}).then(formatProtocolTokenArrayToMap),
this.getPositions({
userAddress,
blockNumber: fromBlock,
}).then(formatProtocolTokenArrayToMap),
])

// Fetch and process each token's movements
const tokens = await Promise.all(
Object.values(endPositionValues).map(
async ({
protocolTokenMetadata,
underlyingTokenPositions: underlyingEndPositions,
}) => {
const getEventsInput: GetEventsInput = {
userAddress,
protocolTokenAddress: protocolTokenMetadata.address,
fromBlock,
toBlock,
}
let eventsOut: Record<string, bigint>
let eventsIn: Record<string, bigint>

if (positionType === PositionType.Supply) {
;[eventsOut, eventsIn] = await Promise.all([
this.getWithdrawals(getEventsInput).then(aggregateTrades),
this.getDeposits(getEventsInput).then(aggregateTrades),
])
} else {
;[eventsOut, eventsIn] = await Promise.all([
this.getBorrows(getEventsInput).then(aggregateTrades),
this.getRepays(getEventsInput).then(aggregateTrades),
])
}

return {
...protocolTokenMetadata,
type: TokenType.Protocol,
tokens: Object.values(underlyingEndPositions).map(
({
address,
name,
symbol,
decimals,
balanceRaw: endPositionValueRaw,
}) => {
const startPositionValueRaw =
startPositionValues[protocolTokenMetadata.address]
?.underlyingTokenPositions[address]?.balanceRaw ?? 0n

const calculationData = {
outRaw: eventsOut[address] ?? 0n,
inRaw: eventsIn[address] ?? 0n,
endPositionValueRaw: endPositionValueRaw ?? 0n,
startPositionValueRaw,
}

let profitRaw =
calculationData.endPositionValueRaw +
calculationData.outRaw -
calculationData.inRaw -
calculationData.startPositionValueRaw

if (
this.getProtocolDetails().positionType === PositionType.Borrow
) {
profitRaw *= -1n
}

return {
address,
name,
symbol,
decimals,
profitRaw,
type: TokenType.Underlying,
calculationData: {
withdrawalsRaw: eventsOut[address] ?? 0n,
withdrawals: formatUnits(
eventsOut[address] ?? 0n,
decimals,
),
depositsRaw: eventsIn[address] ?? 0n,
deposits: formatUnits(eventsIn[address] ?? 0n, decimals),
startPositionValueRaw: startPositionValueRaw ?? 0n,
startPositionValue: formatUnits(
startPositionValueRaw ?? 0n,
decimals,
),
endPositionValueRaw,
endPositionValue: formatUnits(
endPositionValueRaw ?? 0n,
decimals,
),
},
}
},
),
}
},
),
)

return { tokens, fromBlock, toBlock }
}

async getTotalValueLocked({
blockNumber,
}: GetTotalValueLockedInput): Promise<ProtocolTokenTvl[]> {
Expand Down Expand Up @@ -605,24 +481,23 @@ export abstract class MorphoBasePoolAdapter implements IMetadataBuilder {
eventData._poolToken,
)

const underlyingTokensMovement: Record<string, BaseTokenMovement> = {}
underlyingTokens.forEach((underlyingToken) => {
underlyingTokensMovement[underlyingToken.address] = {
const tokens: Underlying[] = underlyingTokens.map(
(underlyingToken) => ({
...underlyingToken,
transactionHash: event.transactionHash,
movementValueRaw: eventData._amount,
}
})
balanceRaw: eventData._amount,
type: TokenType.Underlying,
}),
)

return {
protocolToken: {
...protocolToken,
},
underlyingTokensMovement,
protocolToken,
tokens,
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
}
}),
)

return movements.filter(
(movement): movement is MovementsByBlock => movement !== null,
) as MovementsByBlock[]
Expand Down
107 changes: 12 additions & 95 deletions src/adapters/morpho-aave-v2/tests/snapshots/ethereum.profits.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,13 @@
"positionType": "borrow",
"chainId": 1,
"productId": "optimizer-borrow",
"success": true,
"tokens": [
{
"address": "0x030ba81f1c18d280636f32af80b9aad02cf0854e",
"name": "Aave interest bearing WETH",
"symbol": "aWETH",
"decimals": 18,
"type": "protocol",
"tokens": [
{
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"name": "Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"profitRaw": "-95602153837365848n",
"type": "underlying",
"calculationData": {
"withdrawalsRaw": "0n",
"withdrawals": "0.0",
"depositsRaw": "0n",
"deposits": "0.0",
"startPositionValueRaw": "1500251298264201313462n",
"startPositionValue": "1500.251298264201313462",
"endPositionValueRaw": "1500346900418038679310n",
"endPositionValue": "1500.34690041803867931"
},
"profit": "-0.095602153837365848",
"iconUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"
}
]
"success": false,
"error": {
"message": "Unable to calculate profits, missing USD price for token position 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"details": {
"name": "Error"
}
],
"fromBlock": 18725934,
"toBlock": 18733080
}
},
{
"protocolId": "morpho-aave-v2",
Expand All @@ -54,69 +27,13 @@
"positionType": "supply",
"chainId": 1,
"productId": "optimizer-supply",
"success": true,
"tokens": [
{
"address": "0x3ed3b47dd13ec9a98b44e6204a523e766b225811",
"name": "Aave interest bearing USDT",
"symbol": "aUSDT",
"decimals": 6,
"type": "protocol",
"tokens": [
{
"address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"profitRaw": "313n",
"type": "underlying",
"calculationData": {
"withdrawalsRaw": "0n",
"withdrawals": "0.0",
"depositsRaw": "0n",
"deposits": "0.0",
"startPositionValueRaw": "1198908n",
"startPositionValue": "1.198908",
"endPositionValueRaw": "1199221n",
"endPositionValue": "1.199221"
},
"profit": "0.000313",
"iconUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"
}
]
},
{
"address": "0xbcca60bb61934080951369a648fb03df4f96263c",
"name": "Aave interest bearing USDC",
"symbol": "aUSDC",
"decimals": 6,
"type": "protocol",
"tokens": [
{
"address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"profitRaw": "901109849n",
"type": "underlying",
"calculationData": {
"withdrawalsRaw": "0n",
"withdrawals": "0.0",
"depositsRaw": "0n",
"deposits": "0.0",
"startPositionValueRaw": "4849837112609n",
"startPositionValue": "4849837.112609",
"endPositionValueRaw": "4850738222458n",
"endPositionValue": "4850738.222458"
},
"profit": "901.109849",
"iconUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
}
]
"success": false,
"error": {
"message": "Unable to calculate profits, missing USD price for token position 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"details": {
"name": "Error"
}
],
"fromBlock": 18725934,
"toBlock": 18733080
}
}
]
}
Loading
Loading