From 52be22d635aec8e7657019437d1c5c0e1f60ba72 Mon Sep 17 00:00:00 2001 From: Georges KABBOUCHI Date: Thu, 26 Aug 2021 21:34:27 +0300 Subject: [PATCH] wip --- composables/useStrategy.ts | 5 +- core/strategies/helpers/index.ts | 7 +- core/strategies/helpers/strategy.ts | 8 ++ .../protocols/aave-v2/deposit-and-borrow.ts | 81 ++++++++++++++++++- 4 files changed, 95 insertions(+), 6 deletions(-) diff --git a/composables/useStrategy.ts b/composables/useStrategy.ts index 86c31bf..46b5d2e 100644 --- a/composables/useStrategy.ts +++ b/composables/useStrategy.ts @@ -9,7 +9,6 @@ import tokens from "~/constant/tokens"; import { buildStrategy, DefineStrategy, - IStrategy, StrategyProtocol } from "~/core/strategies"; import { position as aaveV2Position } from "./protocols/useAaveV2Position"; @@ -23,6 +22,8 @@ import { useNotification } from "./useNotification"; import { useSidebar } from "./useSidebar"; import { useToken } from "./useToken"; import { useWeb3 } from "./useWeb3"; +import { useBigNumber } from "./useBigNumber"; + export function useStrategy(defineStrategy: DefineStrategy) { const { web3, networkName, account } = useWeb3(); const { dsa } = useDSA(); @@ -30,6 +31,7 @@ export function useStrategy(defineStrategy: DefineStrategy) { const { close } = useSidebar(); const { valInt, getTokenByKey } = useToken(); const { emitEvent } = useEventBus(); + const { toBN } = useBigNumber(); const { showPendingTransaction, showConfirmedTransaction @@ -87,6 +89,7 @@ export function useStrategy(defineStrategy: DefineStrategy) { strategy.setProps({ convertTokenAmountToWei: valInt, getTokenByKey, + toBN, position }); }); diff --git a/core/strategies/helpers/index.ts b/core/strategies/helpers/index.ts index f9d9bc1..06ecb27 100644 --- a/core/strategies/helpers/index.ts +++ b/core/strategies/helpers/index.ts @@ -2,6 +2,7 @@ import DSA, { Spell } from "dsa-connect"; import Web3 from "web3"; import slugify from "slugify"; import { Strategy } from "./strategy"; +import BigNumber from "bignumber.js"; export interface IStrategyContext { dsa: DSA; web3: Web3; @@ -13,6 +14,7 @@ export interface IStrategyContext { getTokenByKey?: (key: string) => IStrategyToken; position?: any; variables?: { [key: string]: any }; + toBN?: (value: any) => BigNumber; } export interface IStrategyToken { @@ -66,7 +68,7 @@ export enum StrategyProtocol { AAVE_V2 = "aaveV2", COMPOUND = "compound", MAKERDAO = "makerdao", - LIQUITY = "liquity", + LIQUITY = "liquity" } export interface IStrategy { protocol: StrategyProtocol; @@ -81,6 +83,9 @@ export interface IStrategy { variables?: object; spells: (context: IStrategyContext) => Promise | Spell[]; + validate?: ( + context: IStrategyContext + ) => Promise | void | string; submitText?: string; } diff --git a/core/strategies/helpers/strategy.ts b/core/strategies/helpers/strategy.ts index cf3507e..c1c21bd 100644 --- a/core/strategies/helpers/strategy.ts +++ b/core/strategies/helpers/strategy.ts @@ -145,6 +145,14 @@ export class Strategy { throw new Error(result || "Error has occurred"); } } + + if (this.schema.validate) { + const result = await this.schema.validate(this.getContext()); + + if (typeof result === "string") { + throw new Error(result || "Error has occurred"); + } + } } setWeb3(web3: Web3) { diff --git a/core/strategies/protocols/aave-v2/deposit-and-borrow.ts b/core/strategies/protocols/aave-v2/deposit-and-borrow.ts index 37e6f93..7833a19 100644 --- a/core/strategies/protocols/aave-v2/deposit-and-borrow.ts +++ b/core/strategies/protocols/aave-v2/deposit-and-borrow.ts @@ -22,7 +22,7 @@ export default defineStrategy({ variables: { collateralTokenKey: "eth", debtTokenKey: "dai", - debtRateMode: 2, + debtRateMode: 2 }, inputs: [ @@ -31,7 +31,7 @@ export default defineStrategy({ name: "Collateral", placeholder: ({ input }) => input.token ? `${input.token.symbol} to Deposit` : "", - validate: ({ input, dsaBalances }) => { + validate: ({ input, dsaBalances, toBN }) => { if (!input.token) { return "Collateral token is required"; } @@ -40,11 +40,11 @@ export default defineStrategy({ return "Collateral amount is required"; } - const collateralBalance = new BigNumber( + const collateralBalance = toBN( dsaBalances[input.token.address]?.balance ); - if (new BigNumber(collateralBalance).lt(input.value)) { + if (toBN(collateralBalance).lt(input.value)) { const collateralBalanceFormatted = collateralBalance.toFixed(2); return `Your amount exceeds your maximum limit of ${collateralBalanceFormatted} ${input.token.symbol}`; } @@ -74,6 +74,79 @@ export default defineStrategy({ }) ], + validate: async ({ position, inputs, toBN }) => { + if (toBN(inputs[0].value).isZero() && toBN(inputs[0].value).isZero()) { + return; + } + + const newPositionData = position.data.map(position => { + const changedPosition = { ...position }; + if (inputs[1].token.key === position.key) { + changedPosition.borrow = BigNumber.max( + toBN(position.borrow).plus(inputs[1].value), + "0" + ).toFixed(); + } + + if (inputs[0].token.key === position.key) { + changedPosition.supply = BigNumber.max( + toBN(position.supply).plus(inputs[0].value), + "0" + ).toFixed(); + } + + return changedPosition; + }); + + const stats = newPositionData.reduce( + (stats, { key, supply, borrow, borrowStable, priceInEth, factor }) => { + if (key === "eth") { + stats.ethSupplied = supply; + } + + const borrowTotal = toBN(borrow).plus(borrowStable); + + stats.totalSupplyInEth = toBN(supply) + .times(priceInEth) + .plus(stats.totalSupplyInEth) + .toFixed(); + stats.totalBorrowInEth = toBN(borrowTotal) + .times(priceInEth) + .plus(stats.totalBorrowInEth) + .toFixed(); + + stats.totalMaxBorrowLimitInEth = toBN(priceInEth) + .times(factor) + .plus(stats.totalMaxBorrowLimitInEth) + .toFixed(); + + return stats; + }, + { + totalSupplyInEth: "0", + totalBorrowInEth: "0", + totalMaxBorrowLimitInEth: "0" + } + ); + + let liquidation = "0"; + if (!toBN(stats.totalSupplyInEth).isZero()) { + liquidation = BigNumber.max( + toBN(stats.totalMaxBorrowLimitInEth).div(stats.totalSupplyInEth), + "0" + ).toFixed(); + } + + const status = BigNumber.max( + toBN(stats.totalBorrowInEth).div(stats.totalSupplyInEth), + "0" + ); + + if (status.gt(toBN(liquidation).minus("0.0001"))) { + return "Position will liquidate."; + } + }, + spells: async ({ inputs, convertTokenAmountToWei, variables }) => { return [ {