Skip to content

Commit

Permalink
feat: creating AaveLike openDepositBorrow strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
zerotucks committed Aug 25, 2023
1 parent d9076f6 commit f293a45
Show file tree
Hide file tree
Showing 19 changed files with 346 additions and 171 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const resolveProtocolKeyConfig = (
export function isAaveOperation(op: any): op is AaveBorrowOperations | AaveMultiplyOperations {
return op && ('v2' in op || 'v3' in op)
}

export function resolveAaveLikeOperations(
protocolType: AaveLikeProtocol,
positionType: PositionType,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
export { depositBorrow } from './deposit-borrow'
export { AaveLikeDepositBorrow, AaveLikeDepositBorrowDependencies } from './types'
export {
AaveLikeDepositBorrow,
AaveLikeDepositBorrowArgs,
AaveLikeDepositBorrowDependencies,
} from './types'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export { openDepositBorrow } from './open-deposit-borrow'
export {
AaveLikeOpenDepositBorrow,
AaveLikeOpenDepositBorrowArgs,
AaveLikeOpenDepositBorrowDependencies,
} from './types'
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { CollectFeeFrom } from '@dma-common/types'
import { BorrowArgs, DepositArgs } from '@dma-library/operations'
import { resolveAaveLikeOperations } from '@dma-library/operations/aave-like'
import * as AaveCommon from '@dma-library/strategies/aave/common'
import { getAaveTokenAddress } from '@dma-library/strategies/aave/common'
import { IOperation } from '@dma-library/types'
import { AaveVersion } from '@dma-library/types/aave'
import * as SwapUtils from '@dma-library/utils/swap'
import { isAaveView, resolveAavelikeViews } from '@dma-library/views/aave-like'
import { IPosition } from '@domain'

import {
AaveLikeOpenDepositBorrow,
AaveLikeOpenDepositBorrowArgs,
AaveLikeOpenDepositBorrowDependencies,
} from './types'

export const openDepositBorrow: AaveLikeOpenDepositBorrow = async (args, dependencies) => {
const {
collateralToken,
debtToken,
entryToken,
slippage,
amountCollateralToDepositInBaseUnit: depositAmount,
amountDebtToBorrowInBaseUnit: borrowAmount,
} = args

const currentPosition = await resolveCurrentPositionForProtocol(args, dependencies)
const entryTokenAddress = getAaveTokenAddress(entryToken, dependencies.addresses)
const collateralTokenAddress = getAaveTokenAddress(collateralToken, dependencies.addresses)

const isSwapNeeded = SwapUtils.getIsSwapNeeded(
entryTokenAddress,
collateralTokenAddress,
dependencies.addresses.tokens.ETH,
dependencies.addresses.tokens.WETH,
)

const alwaysReturnDepositArgs = true
const deposit = await AaveCommon.buildDepositArgs(
entryToken,
collateralToken,
collateralTokenAddress,
depositAmount,
slippage,
dependencies,
alwaysReturnDepositArgs,
)

const alwaysReturnBorrowArgs = true
const borrow = await AaveCommon.buildBorrowArgs(
borrowAmount,
debtToken,
dependencies,
alwaysReturnBorrowArgs,
)

if (!deposit.args) throw new Error('Deposit args must be defined when opening position')
if (!borrow.args) throw new Error('Borrow args must be defined when opening position')
const operation = await buildOperation(deposit.args, borrow.args, dependencies)

const finalPosition: IPosition = currentPosition
.deposit(deposit.collateralDelta)
.borrow(borrow.debtDelta)

const transaction = AaveCommon.buildTransaction(operation)
const simulation = AaveCommon.buildSimulation(
borrow.debtDelta,
deposit.collateralDelta,
finalPosition,
)

const collectFeeFrom: CollectFeeFrom = 'sourceToken'
if (isSwapNeeded) {
if (!deposit.swap) {
throw new Error('Swap data is missing')
}

return {
transaction,
simulation: {
...simulation,
swap: AaveCommon.buildSwap(deposit.swap, entryToken, collateralToken, collectFeeFrom),
},
}
}

return {
transaction,
simulation,
}
}

async function buildOperation(
depositArgs: DepositArgs,
borrowArgs: BorrowArgs,
dependencies: AaveLikeOpenDepositBorrowDependencies,
): Promise<IOperation> {
const positionType = dependencies.positionType
const aaveLikeBorrowOperations = resolveAaveLikeOperations(
dependencies.protocolType,
positionType,
)

return aaveLikeBorrowOperations.openDepositBorrow(
depositArgs,
borrowArgs,
{
positionType: dependencies.positionType,
protocol: dependencies.protocolType,
},
dependencies.addresses,
dependencies.network,
)
}

/**
* Resolves the current position for the given protocol version
* Used on open to account for dust issues when reopening a position
* With same proxy
*/
async function resolveCurrentPositionForProtocol(
args: AaveLikeOpenDepositBorrowArgs,
dependencies: AaveLikeOpenDepositBorrowDependencies,
) {
const { view, version } = resolveAavelikeViews(dependencies.protocolType)

if (isAaveView(view)) {
if (!version) throw new Error('Version must be defined when using Aave view')
return await view.getCurrentPosition(
{ ...args, proxy: dependencies.proxy },
{ ...dependencies, protocolVersion: version as AaveVersion },
)
}
return await view.getCurrentPosition({ ...args, proxy: dependencies.proxy }, { ...dependencies })
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { IDepositBorrowStrategy } from '@dma-library/strategies/aave/borrow/deposit-borrow/types'
import {
AaveLikeDepositBorrowArgs,
AaveLikeDepositBorrowDependencies,
} from '@dma-library/strategies/aave-like/borrow/deposit-borrow'
import * as StrategyParams from '@dma-library/types/strategy-params'

export type AaveLikeOpenDepositBorrowArgs = AaveLikeDepositBorrowArgs

type IOpenDepositBorrowStrategy = IDepositBorrowStrategy

export type AaveLikeOpenDepositBorrowDependencies = Omit<
AaveLikeDepositBorrowDependencies,
'currentPosition'
> &
StrategyParams.WithOptionalSwap &
StrategyParams.WithPositionType

export type AaveLikeOpenDepositBorrow = (
args: AaveLikeOpenDepositBorrowArgs,
dependencies: AaveLikeOpenDepositBorrowDependencies,
) => Promise<IOpenDepositBorrowStrategy>
3 changes: 3 additions & 0 deletions packages/dma-library/src/strategies/aave-like/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { AaveLikeDepositBorrow, depositBorrow } from './borrow/deposit-borrow'
import { AaveLikeOpenDepositBorrow, openDepositBorrow } from './borrow/open-deposit-borrow'

type AaveLike = {
borrow: {
depositBorrow: AaveLikeDepositBorrow
openDepositBorrow: AaveLikeOpenDepositBorrow
}
}

export const aaveLike: AaveLike = {
borrow: {
depositBorrow,
openDepositBorrow,
},
}
Original file line number Diff line number Diff line change
@@ -1,154 +1,26 @@
import { CollectFeeFrom } from '@dma-common/types'
import { BorrowArgs, DepositArgs, operations } from '@dma-library/operations'
import * as AaveCommon from '@dma-library/strategies/aave/common'
import { getAaveTokenAddress } from '@dma-library/strategies/aave/common'
import { IOperation } from '@dma-library/types'
import { AaveVersion } from '@dma-library/types/aave'
import * as SwapUtils from '@dma-library/utils/swap'
import { getCurrentPosition } from '@dma-library/views/aave'
import { IPosition } from '@domain'
import { aaveLike } from '@dma-library/strategies/aave-like'

import {
AaveOpenDepositBorrow,
AaveOpenDepositBorrowArgs,
AaveOpenDepositBorrowDependencies,
AaveV3OpenDepositBorrowDependencies,
AaveV2OpenDepositBorrowDependencies,
} from './types'

export const openDepositBorrow: AaveOpenDepositBorrow = async (args, dependencies) => {
const {
collateralToken,
debtToken,
entryToken,
slippage,
amountCollateralToDepositInBaseUnit: depositAmount,
amountDebtToBorrowInBaseUnit: borrowAmount,
} = args

const currentPosition = await resolveCurrentPositionForProtocol(args, dependencies)
const entryTokenAddress = getAaveTokenAddress(entryToken, dependencies.addresses)
const collateralTokenAddress = getAaveTokenAddress(collateralToken, dependencies.addresses)

const isSwapNeeded = SwapUtils.getIsSwapNeeded(
entryTokenAddress,
collateralTokenAddress,
dependencies.addresses.tokens.ETH,
dependencies.addresses.tokens.WETH,
)

const alwaysReturnDepositArgs = true
const deposit = await AaveCommon.buildDepositArgs(
entryToken,
collateralToken,
collateralTokenAddress,
depositAmount,
slippage,
dependencies,
alwaysReturnDepositArgs,
)

const alwaysReturnBorrowArgs = true
const borrow = await AaveCommon.buildBorrowArgs(
borrowAmount,
debtToken,
dependencies,
alwaysReturnBorrowArgs,
)

if (!deposit.args) throw new Error('Deposit args must be defined when opening position')
if (!borrow.args) throw new Error('Borrow args must be defined when opening position')
const operation = await buildOperation(deposit.args, borrow.args, dependencies)

const finalPosition: IPosition = currentPosition
.deposit(deposit.collateralDelta)
.borrow(borrow.debtDelta)

const transaction = AaveCommon.buildTransaction(operation)
const simulation = AaveCommon.buildSimulation(
borrow.debtDelta,
deposit.collateralDelta,
finalPosition,
)

const collectFeeFrom: CollectFeeFrom = 'sourceToken'
if (isSwapNeeded) {
if (!deposit.swap) {
throw new Error('Swap data is missing')
}

return {
transaction,
simulation: {
...simulation,
swap: AaveCommon.buildSwap(deposit.swap, entryToken, collateralToken, collectFeeFrom),
},
}
}

return {
transaction,
simulation,
}
}

async function buildOperation(
depositArgs: DepositArgs,
borrowArgs: BorrowArgs,
dependencies: AaveOpenDepositBorrowDependencies,
): Promise<IOperation> {
if (
AaveCommon.isV3<AaveOpenDepositBorrowDependencies, AaveV3OpenDepositBorrowDependencies>(
AaveCommon.isV2<AaveOpenDepositBorrowDependencies, AaveV2OpenDepositBorrowDependencies>(
dependencies,
)
) {
return await operations.aave.v3.openDepositBorrow(
depositArgs,
borrowArgs,
{
positionType: dependencies.positionType,
protocol: 'AAVE_V3',
},
dependencies.addresses,
dependencies.network,
)
}
if (AaveCommon.isV2(dependencies)) {
return await operations.aave.v2.openDepositAndBorrow(
depositArgs,
borrowArgs,
{
positionType: dependencies.positionType,
protocol: 'AAVE',
},
dependencies.addresses,
dependencies.network,
)
const protocolType = 'AAVE' as const
return await aaveLike.borrow.openDepositBorrow(args, { ...dependencies, protocolType })
}

throw new Error('No operation found for Aave protocol version')
}

async function resolveCurrentPositionForProtocol(
args: AaveOpenDepositBorrowArgs,
dependencies: AaveOpenDepositBorrowDependencies,
) {
if (
AaveCommon.isV3<AaveOpenDepositBorrowDependencies, AaveV3OpenDepositBorrowDependencies>(
dependencies,
)
) {
return await getCurrentPosition(
{ ...args, proxy: dependencies.proxy },
{ ...dependencies, protocolVersion: AaveVersion.v3 },
)
}

if (AaveCommon.isV2(dependencies)) {
return await getCurrentPosition(
{ ...args, proxy: dependencies.proxy },
{ ...dependencies, protocolVersion: AaveVersion.v2 },
)
if (AaveCommon.isV3(dependencies)) {
const protocolType = 'AAVE_V3' as const
return await aaveLike.borrow.openDepositBorrow(args, { ...dependencies, protocolType })
}

throw new Error('No current position resolver found for Aave protocol version')
throw new Error('Unsupported protocol')
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { openDepositBorrow } from './open-deposit-borrow'
export { SparkOpenDepositBorrow } from './types'
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { aaveLike } from '@dma-library/strategies/aave-like'

import { SparkOpenDepositBorrow } from './types'

export const openDepositBorrow: SparkOpenDepositBorrow = async (args, dependencies) => {
const protocolType = 'Spark' as const
return await aaveLike.borrow.openDepositBorrow(args, { ...dependencies, protocolType })
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { IDepositBorrowStrategy } from '@dma-library/strategies/aave/borrow/deposit-borrow/types'
import {
SparkDepositBorrowArgs,
SparkDepositBorrowDependencies,
} from '@dma-library/strategies/spark/borrow/deposit-borrow/types'
import * as StrategyParams from '@dma-library/types/strategy-params'

export type SparkOpenDepositBorrowArgs = SparkDepositBorrowArgs

type IOpenDepositBorrowStrategy = IDepositBorrowStrategy

export type SparkOpenDepositBorrowDependencies = SparkDepositBorrowDependencies &
StrategyParams.WithPositionType
export type SparkOpenDepositBorrow = (
args: SparkOpenDepositBorrowArgs,
dependencies: SparkOpenDepositBorrowDependencies,
) => Promise<IOpenDepositBorrowStrategy>
Loading

0 comments on commit f293a45

Please sign in to comment.