From 30d956549303bcc48a89304989aef90236930b86 Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Thu, 18 Apr 2024 18:50:24 +0200 Subject: [PATCH 01/17] fix: solve issues with swap calculations --- sdk/sdk-client/src/mocks/mockToken.ts | 20 + .../src/common/enums/TokenSymbol.ts | 2 + .../src/common/implementation/Price.ts | 24 ++ sdk/sdk-common/src/utils/PercentageUtils.ts | 9 +- ...refinanceMakerSparkAlreadyImported.test.ts | 5 +- .../tests/refinanceMakerSparkAnyPair.test.ts | 388 ++++++++++++++++++ .../simulator-engine/reducer/swapReducer.ts | 2 +- .../RefinanceLendingToLendingAnyPair.ts | 5 +- .../oneinch/OneInchSwapProvider.ts | 13 +- 9 files changed, 448 insertions(+), 20 deletions(-) create mode 100644 sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts diff --git a/sdk/sdk-client/src/mocks/mockToken.ts b/sdk/sdk-client/src/mocks/mockToken.ts index f634129798..dc5d81fee1 100644 --- a/sdk/sdk-client/src/mocks/mockToken.ts +++ b/sdk/sdk-client/src/mocks/mockToken.ts @@ -25,5 +25,25 @@ export async function getMockTokenBySymbol(params: { name: 'Wrapped Ether', decimals: 18, }) + case TokenSymbol.USDC: + return Token.createFrom({ + chainInfo: params.chainInfo, + address: Address.createFromEthereum({ + value: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + }), + symbol: params.symbol, + name: 'USD Coin', + decimals: 6, + }) + case TokenSymbol.WBTC: + return Token.createFrom({ + chainInfo: params.chainInfo, + address: Address.createFromEthereum({ + value: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', + }), + symbol: params.symbol, + name: 'Wrapped Bitcoin', + decimals: 8, + }) } } diff --git a/sdk/sdk-common/src/common/enums/TokenSymbol.ts b/sdk/sdk-common/src/common/enums/TokenSymbol.ts index 51ef6d6b16..20d07afd4c 100644 --- a/sdk/sdk-common/src/common/enums/TokenSymbol.ts +++ b/sdk/sdk-common/src/common/enums/TokenSymbol.ts @@ -6,4 +6,6 @@ export enum TokenSymbol { DAI = 'DAI', WETH = 'WETH', ETH = 'ETH', + USDC = 'USDC', + WBTC = 'WBTC', } diff --git a/sdk/sdk-common/src/common/implementation/Price.ts b/sdk/sdk-common/src/common/implementation/Price.ts index 0af1a313dd..7aceb13080 100644 --- a/sdk/sdk-common/src/common/implementation/Price.ts +++ b/sdk/sdk-common/src/common/implementation/Price.ts @@ -4,10 +4,12 @@ import { BigNumber } from 'bignumber.js' import { SerializationService } from '../../services/SerializationService' import { CurrencySymbol } from '../enums/CurrencySymbol' import { Token } from './Token' +import { isSameTokens } from '../utils/TokenUtils' /** * @class Price * @description Represents a price of a token (baseToken) in a given currency (quoteToken) + * @description Base / Quote e.q. 2000 ETH / DAI */ export class Price implements IPrice { readonly value: string @@ -37,6 +39,28 @@ export class Price implements IPrice { public toBN(): BigNumber { return new BigNumber(this.value) } + + public hasSameQuoteToken(b: Price): boolean { + if (isToken(this.quoteToken) && isToken(b.quoteToken)) { + return isSameTokens(this.quoteToken, b.quoteToken) + } + + return this.quoteToken === b.quoteToken + } + + public div(b: Price) { + if (!this.hasSameQuoteToken(b)) { + throw new Error('Token bases must be the same') + } + + return Price.createFrom({ + value: this.toBN().div(b.toBN()).toString(), + baseToken: this.baseToken, + quoteToken: b.baseToken, + }) + + // TODO: case when the quotes are the same + } } SerializationService.registerClass(Price) diff --git a/sdk/sdk-common/src/utils/PercentageUtils.ts b/sdk/sdk-common/src/utils/PercentageUtils.ts index f42f0de413..992486aef5 100644 --- a/sdk/sdk-common/src/utils/PercentageUtils.ts +++ b/sdk/sdk-common/src/utils/PercentageUtils.ts @@ -12,15 +12,20 @@ export function addPercentage(tokenAmount: TokenAmount, percentage: Percentage): const newAmount = amountBN.times(percentage.value).div(100) return TokenAmount.createFrom({ token: tokenAmount.token, - amount: amountBN.plus(newAmount).toFixed(0), + amount: amountBN.plus(newAmount).toString(), }) } export function subtractPercentage(tokenAmount: TokenAmount, percentage: Percentage): TokenAmount { const amountBN = tokenAmount.toBN() const newAmount = amountBN.times(percentage.value).div(100) + + console.log(percentage, 'percentage') + console.log(amountBN.toString(), 'amountBN') + console.log(newAmount.toString(), 'newAmount') + return TokenAmount.createFrom({ token: tokenAmount.token, - amount: amountBN.minus(newAmount).toFixed(0), + amount: amountBN.minus(newAmount).toString(), }) } diff --git a/sdk/sdk-e2e/tests/refinanceMakerSparkAlreadyImported.test.ts b/sdk/sdk-e2e/tests/refinanceMakerSparkAlreadyImported.test.ts index 28b3bcadea..1e0186d8e4 100644 --- a/sdk/sdk-e2e/tests/refinanceMakerSparkAlreadyImported.test.ts +++ b/sdk/sdk-e2e/tests/refinanceMakerSparkAlreadyImported.test.ts @@ -50,9 +50,8 @@ import { jest.setTimeout(300000) -const SDKAPiUrl = 'https://zmjmtfsocb.execute-api.us-east-1.amazonaws.com/api/sdk' -const TenderlyForkUrl = - 'https://virtual.mainnet.rpc.tenderly.co/d4cb5af8-8015-4342-b95d-26e5b05a6525' +const SDKAPiUrl = 'https://nkllstfoy8.execute-api.us-east-1.amazonaws.com/api/sdk' +const TenderlyForkUrl = 'https://rpc.tenderly.co/fork/50e01944-8635-4d67-9569-004d72113328' describe.skip('Refinance Maker Spark | SDK', () => { it('should allow refinance Maker -> Spark with same pair', async () => { diff --git a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts new file mode 100644 index 0000000000..0e003a6220 --- /dev/null +++ b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts @@ -0,0 +1,388 @@ +import { + Percentage, + PositionId, + Token, + TokenAmount, + Position, + Address, + type Maybe, + ChainFamilyMap, + AddressValue, + newEmptyPositionFromPool, + PositionType, +} from '@summerfi/sdk-common/common' + +import { ProtocolName, isLendingPool } from '@summerfi/sdk-common/protocols' +import { makeSDK, type Chain, type User, Protocol } from '@summerfi/sdk-client' +import { TokenSymbol } from '@summerfi/sdk-common/common/enums' +import { IPositionsManager, IRefinanceParameters, Order } from '@summerfi/sdk-common/orders' +import { ISimulation, SimulationType } from '@summerfi/sdk-common/simulation' +import { TransactionUtils } from './utils/TransactionUtils' +import { + decodeActionCalldata, + decodePositionsManagerCalldata, + decodeStrategyExecutorCalldata, +} from '@summerfi/testing-utils' +import { Deployments } from '@summerfi/core-contracts' +import { DeploymentIndex } from '@summerfi/deployment-utils' + +import { Hex, createPublicClient } from 'viem' +import assert from 'assert' +import { + EmodeType, + FlashloanAction, + SendTokenAction, + SetApprovalAction, + PositionCreatedAction, +} from '@summerfi/protocol-plugins/plugins/common' +import { + ILKType, + MakerPaybackAction, + MakerPoolId, + MakerWithdrawAction, +} from '@summerfi/protocol-plugins/plugins/maker' +import { + SparkBorrowAction, + SparkDepositAction, + SparkPoolId, + isSparkPoolId, +} from '@summerfi/protocol-plugins/plugins/spark' + +jest.setTimeout(300000) + +const SDKAPiUrl = 'https://nkllstfoy8.execute-api.us-east-1.amazonaws.com/api/sdk' +const TenderlyForkUrl = 'https://virtual.mainnet.rpc.tenderly.co/dff10c5c-3f1d-4a78-9132-de17d2768c13' + +describe.only('Refinance Maker Spark | SDK', () => { + it('should allow refinance Maker -> Spark with same pair', async () => { + // SDK + const sdk = makeSDK({ apiURL: SDKAPiUrl }) + + // Chain + const chain: Maybe = await sdk.chains.getChain({ + chainInfo: ChainFamilyMap.Ethereum.Mainnet, + }) + + assert(chain, 'Chain not found') + + // Deployment + const deploymentName = `${chain.chainInfo.name}.standard` + const deployments = Deployments as DeploymentIndex + const deployment = deployments[deploymentName] + + // Strategy Executor + const strategyExecutorAddress = Address.createFromEthereum({ + value: deployment.contracts.OperationExecutor.address as AddressValue, + }) + + // User + const walletAddress = Address.createFromEthereum({ + value: '0x34314adbfBb5d239bb67f0265c9c45EB8b834412', + }) + const user: User = await sdk.users.getUser({ + chainInfo: chain.chainInfo, + walletAddress: walletAddress, + }) + expect(user).toBeDefined() + expect(user.wallet.address).toEqual(walletAddress) + expect(user.chainInfo).toEqual(chain.chainInfo) + + // Positions Manager + const positionsManager: IPositionsManager = { + address: Address.createFromEthereum({ + value: '0x7f65e7326f22963e2039734ddff61958d5d284ca', + }), + } + + // Tokens + const WETH: Maybe = await chain.tokens.getTokenBySymbol({ symbol: TokenSymbol.WETH }) + assert(WETH, 'WETH not found') + + const DAI: Maybe = await chain.tokens.getTokenBySymbol({ symbol: TokenSymbol.DAI }) + assert(DAI, 'DAI not found') + + const USDC: Maybe = await chain.tokens.getTokenBySymbol({ symbol: TokenSymbol.USDC }) + assert(USDC, 'USDC not found') + + const WBTC: Maybe = await chain.tokens.getTokenBySymbol({ symbol: TokenSymbol.WBTC }) + assert(WBTC, 'WBTC not found') + + const maker = await chain.protocols.getProtocol({ name: ProtocolName.Maker }) + assert(maker, 'Maker protocol not found') + + const makerPoolId: MakerPoolId = { + protocol: { + name: ProtocolName.Maker, + chainInfo: chain.chainInfo, + }, + ilkType: ILKType.ETH_C, + vaultId: '31690', + } + + const makerPool = await maker.getPool({ + poolId: makerPoolId, + }) + assert(makerPool, 'Maker pool not found') + + if (!isLendingPool(makerPool)) { + assert(false, 'Maker pool type is not lending') + } + + // Source position + const makerPosition: Position = Position.createFrom({ + type: PositionType.Multiply, + positionId: PositionId.createFrom({ id: '31690' }), + debtAmount: TokenAmount.createFromBaseUnit({ + token: DAI, + amount: '5000000000000000000001', + }), + collateralAmount: TokenAmount.createFromBaseUnit({ + token: WETH, + amount: '100000000000000000000', + }), + pool: makerPool, + }) + + // Target protocol + // TODO: this should have spark protocol type so we don't need to cast, derive it from the protocol name + const spark: Maybe = await chain.protocols.getProtocol({ + name: ProtocolName.Spark, + }) + assert(spark, 'Spark not found') + + const poolId: SparkPoolId = { + protocol: { + name: ProtocolName.Spark, + chainInfo: chain.chainInfo, + }, + emodeType: EmodeType.None, + } + + const sparkPool = await spark.getPool({ + poolId, + }) + + assert(sparkPool, 'Pool not found') + + if (!isSparkPoolId(sparkPool.poolId)) { + assert(false, 'Pool ID is not a Spark one') + } + + if (!isLendingPool(sparkPool)) { + assert(false, 'Spark pool type is not lending') + } + + const emptyTargetPosition = newEmptyPositionFromPool( + sparkPool, + USDC, + WBTC, + ) + const refinanceSimulation: ISimulation = + await sdk.simulator.refinance.simulateRefinancePosition({ + sourcePosition: makerPosition, + targetPosition: emptyTargetPosition, + slippage: Percentage.createFrom({ value: 0.2 }), + } as IRefinanceParameters) + + expect(refinanceSimulation).toBeDefined() + + expect(refinanceSimulation.sourcePosition?.positionId).toEqual(makerPosition.positionId) + expect(refinanceSimulation.targetPosition.pool.poolId).toEqual(sparkPool.poolId) + expect(refinanceSimulation.steps.length).toBe(8) + + const refinanceOrder: Maybe = await user.newOrder({ + positionsManager, + simulation: refinanceSimulation, + }) + + assert(refinanceOrder, 'Order not found') + + expect(refinanceOrder.simulation.simulationType).toEqual(refinanceSimulation.simulationType) + assert(refinanceOrder.simulation.sourcePosition, 'Source position not found') + + expect(refinanceOrder.simulation.sourcePosition.positionId).toEqual( + refinanceSimulation.sourcePosition?.positionId, + ) + expect(refinanceOrder.simulation.targetPosition.pool.poolId).toEqual(sparkPool.poolId) + expect(refinanceOrder.simulation.steps.length).toEqual(refinanceSimulation.steps.length) + + for (let i = 0; i < refinanceOrder.simulation.steps.length; i++) { + expect(refinanceOrder.simulation.steps[i].type).toEqual(refinanceSimulation.steps[i].type) + } + + expect(refinanceOrder.transactions.length).toEqual(1) + expect(refinanceOrder.transactions[0].transaction.target.value).toEqual( + positionsManager.address.value, + ) + + const positionsManagerParams = decodePositionsManagerCalldata({ + calldata: refinanceOrder.transactions[0].transaction.calldata, + }) + + assert(positionsManagerParams, 'Cannot decode Positions Manager calldata') + expect(positionsManagerParams.target.value).toEqual(strategyExecutorAddress.value) + + // Decode calldata + const strategyExecutorParams = decodeStrategyExecutorCalldata(positionsManagerParams.calldata) + + const strategyName = `${refinanceOrder.simulation.simulationType}${refinanceOrder.simulation.sourcePosition?.pool.protocol.name}${refinanceOrder.simulation.targetPosition.pool.protocol.name}` + + assert(strategyExecutorParams, 'Cannot decode Strategy Executor calldata') + expect(strategyExecutorParams.strategyName).toEqual(strategyName) + expect(strategyExecutorParams.actionCalls.length).toEqual(3) + + // // Decode Flashloan action + // const flashloanParams = decodeActionCalldata({ + // action: new FlashloanAction(), + // calldata: strategyExecutorParams.actionCalls[0].callData, + // }) + + // const sourcePosition = Position.createFrom(refinanceOrder.simulation.sourcePosition) + // const targetPosition = Position.createFrom(refinanceOrder.simulation.targetPosition) + + // assert(flashloanParams, 'Cannot decode Flashloan action calldata') + + // const FlashloanMargin = 1.001 + // const flashloanAmount = sourcePosition.debtAmount.multiply(FlashloanMargin) + + // expect(flashloanParams.args[0].amount).toBe(BigInt(flashloanAmount.toBaseUnit())) + // expect(flashloanParams.args[0].asset).toBe(sourcePosition.debtAmount.token.address.value) + // expect(flashloanParams.args[0].isProxyFlashloan).toBe(true) + // expect(flashloanParams.args[0].isDPMProxy).toBe(true) + // expect(flashloanParams.args[0].provider).toBe(0) + // /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ + // const flashloanSubcalls = flashloanParams.args[0].calls as Array + // expect(flashloanSubcalls.length).toBe(6) + + // // Decode Maker Payback action + // const makerPaybackAction = decodeActionCalldata({ + // action: new MakerPaybackAction(), + // calldata: flashloanSubcalls[0].callData, + // }) + + // const paybackAmount = TokenAmount.createFrom({ + // amount: Number.MAX_SAFE_INTEGER.toString(), + // token: sourcePosition.debtAmount.token, + // }).toBaseUnit() + + // assert(makerPaybackAction, 'Cannot decode Maker Payback action calldata') + // expect(makerPaybackAction.args[0].vaultId).toBe( + // BigInt((sourcePosition.pool.poolId as MakerPoolId).vaultId), + // ) + // expect(makerPaybackAction.args[0].userAddress).toBe(positionsManager.address.value) + // expect(makerPaybackAction.args[0].amount).toBe(BigInt(paybackAmount)) + // expect(makerPaybackAction.args[0].paybackAll).toBe(true) + + // // Decode Maker Withdraw action + // const makerWithdrawAction = decodeActionCalldata({ + // action: new MakerWithdrawAction(), + // calldata: flashloanSubcalls[1].callData, + // }) + + // assert(makerWithdrawAction, 'Cannot decode Maker Withdraw action calldata') + + // expect(makerWithdrawAction.args[0].vaultId).toBe( + // BigInt((sourcePosition.pool.poolId as MakerPoolId).vaultId), + // ) + // expect(makerWithdrawAction.args[0].userAddress).toBe(positionsManager.address.value) + // expect(makerWithdrawAction.args[0].joinAddr).toBe( + // deployment.dependencies.MCD_JOIN_ETH_C.address, + // ) + // expect(makerWithdrawAction.args[0].amount).toBe( + // BigInt(sourcePosition.collateralAmount.toBaseUnit()), + // ) + + // // Set Approval + // const setApprovalAction = decodeActionCalldata({ + // action: new SetApprovalAction(), + // calldata: flashloanSubcalls[2].callData, + // }) + + // assert(setApprovalAction, 'Cannot decode Set Approval action calldata') + + // const sparkLendingPool = Address.createFromEthereum({ + // value: deployment.dependencies.SparkLendingPool.address as AddressValue, + // }) + // expect(setApprovalAction.args[0].asset).toBe( + // sourcePosition.collateralAmount.token.address.value, + // ) + // expect(setApprovalAction.args[0].delegate).toBe(sparkLendingPool.value) + // expect(setApprovalAction.args[0].amount).toBe( + // BigInt(sourcePosition.collateralAmount.toBaseUnit()), + // ) + // expect(setApprovalAction.args[0].sumAmounts).toBe(false) + + // // Decode Spark Deposit action + // const sparkDepositAction = decodeActionCalldata({ + // action: new SparkDepositAction(), + // calldata: flashloanSubcalls[3].callData, + // }) + + // assert(sparkDepositAction, 'Cannot decode Spark Deposit action calldata') + + // expect(sparkDepositAction.args[0].asset).toBe( + // targetPosition.collateralAmount.token.address.value, + // ) + // expect(sparkDepositAction.args[0].amount).toBe( + // BigInt(sourcePosition.collateralAmount.toBaseUnit()), + // ) + // expect(sparkDepositAction.args[0].sumAmounts).toBe(false) + // expect(sparkDepositAction.args[0].setAsCollateral).toBe(true) + + // // Decode Spark Borrow action + // const sparkBorrowAction = decodeActionCalldata({ + // action: new SparkBorrowAction(), + // calldata: flashloanSubcalls[4].callData, + // }) + + // assert(sparkBorrowAction, 'Cannot decode Spark Borrow action calldata') + + // expect(sparkBorrowAction.args[0].asset).toBe(targetPosition.debtAmount.token.address.value) + // expect(sparkBorrowAction.args[0].amount).toBe(BigInt(targetPosition.debtAmount.toBaseUnit())) + // expect(sparkBorrowAction.args[0].to).toBe(positionsManager.address.value) + + // // Decode Send Token action + // const sendTokenAction = decodeActionCalldata({ + // action: new SendTokenAction(), + // calldata: flashloanSubcalls[5].callData, + // }) + + // assert(sendTokenAction, 'Cannot decode Send Token action calldata') + + // expect(sendTokenAction.args[0].asset).toBe(sourcePosition.debtAmount.token.address.value) + // expect(sendTokenAction.args[0].to).toBe(strategyExecutorAddress.value) + // expect(sendTokenAction.args[0].amount).toBe(BigInt(flashloanAmount.toBaseUnit())) + + // // Decode Position Created event action + // const positionCreatedParams = decodeActionCalldata({ + // action: new PositionCreatedAction(), + // calldata: strategyExecutorParams.actionCalls[1].callData, + // }) + + // assert(positionCreatedParams, 'Cannot decode Position Created action calldata') + + // expect(positionCreatedParams.args[0].protocol).toBe(targetPosition.pool.protocol.name) + // expect(positionCreatedParams.args[0].positionType).toBe(sourcePosition.type) + // expect(positionCreatedParams.args[0].collateralToken).toBe( + // targetPosition.collateralAmount.token.address.value, + // ) + // expect(positionCreatedParams.args[0].debtToken).toBe( + // targetPosition.debtAmount.token.address.value, + // ) + + // Send transaction + console.log('Sending transaction...') + + const privateKey = process.env.DEPLOYER_PRIVATE_KEY as Hex + const transactionUtils = new TransactionUtils({ + rpcUrl: TenderlyForkUrl, + walletPrivateKey: privateKey, + }) + + const receipt = await transactionUtils.sendTransaction({ + transaction: refinanceOrder.transactions[0].transaction, + }) + + console.log('Transaction sent:', receipt) + }) +}) diff --git a/sdk/simulator-service/src/implementation/simulator-engine/reducer/swapReducer.ts b/sdk/simulator-service/src/implementation/simulator-engine/reducer/swapReducer.ts index ea8c38eb95..f7b1d0348d 100644 --- a/sdk/simulator-service/src/implementation/simulator-engine/reducer/swapReducer.ts +++ b/sdk/simulator-service/src/implementation/simulator-engine/reducer/swapReducer.ts @@ -12,7 +12,7 @@ export function swapReducer(step: steps.SwapStep, state: ISimulationState): ISim // We require both from & to be at similar decimal precisions const offerPrice = Price.createFrom({ - value: step.inputs.toTokenAmount.divide(step.inputs.fromTokenAmount.amount).toString(), + value: step.inputs.toTokenAmount.divide(step.inputs.fromTokenAmount.amount).amount, baseToken, quoteToken, }) diff --git a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts index ae8dc540db..420ef56b8a 100644 --- a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts +++ b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts @@ -82,10 +82,7 @@ export async function refinanceLendingToLendingAnyPair( amount: Number.MAX_SAFE_INTEGER.toString(), token: position.debtAmount.token, }), - withdrawAmount: TokenAmount.createFrom({ - amount: Number.MAX_SAFE_INTEGER.toString(), - token: position.collateralAmount.token, - }), + withdrawAmount: position.collateralAmount, position: position, }, })) diff --git a/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts b/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts index edaffce8e2..b9e813b31d 100644 --- a/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts +++ b/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts @@ -96,7 +96,7 @@ export class OneInchSwapProvider implements ISwapProvider { return { provider: SwapProviderType.OneInch, fromTokenAmount: params.fromAmount, - toTokenAmount: TokenAmount.createFrom({ + toTokenAmount: TokenAmount.createFromBaseUnit({ token: params.toToken, amount: responseData.toTokenAmount, }), @@ -135,7 +135,7 @@ export class OneInchSwapProvider implements ISwapProvider { return { provider: SwapProviderType.OneInch, fromTokenAmount: params.fromAmount, - toTokenAmount: TokenAmount.createFrom({ + toTokenAmount: TokenAmount.createFromBaseUnit({ token: params.toToken, amount: responseData.toTokenAmount, }), @@ -201,14 +201,7 @@ export class OneInchSwapProvider implements ISwapProvider { return { provider: SwapProviderType.OneInch, - price: Price.createFrom({ - value: baseTokenPriceQuotedInCurrencySymbol - .toBN() - .div(quoteTokenPriceQuoteInCurrencySymbol.toBN()) - .toString(), - baseToken: baseToken, - quoteToken: quoteToken, - }), + price: baseTokenPriceQuotedInCurrencySymbol.div(quoteTokenPriceQuoteInCurrencySymbol), } } else { const quoteCurrency = params.quoteToken ?? CurrencySymbol.USD From 4da002ca43efd8c1e4ce8a718a5c8fb001acf345 Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Fri, 19 Apr 2024 17:09:15 +0200 Subject: [PATCH 02/17] chore: refactor take under account that amounts swapped and send to exchange are different --- pnpm-lock.yaml | 3 - .../common/builders/SwapActionBuilder.ts | 2 +- sdk/sdk-common/package.json | 5 +- .../src/common/implementation/TokenAmount.ts | 19 +- sdk/sdk-common/src/simulation/Steps.ts | 3 + sdk/sdk-common/src/utils/PercentageUtils.ts | 8 +- .../implementation/utils/GetSwapStepData.ts | 50 ++++++ .../src/implementation/utils/index.ts | 1 + .../RefinanceLendingToLendingAnyPair.ts | 165 ++++++------------ .../src/interfaces/ISwapManager.ts | 6 +- .../src/implementation/SwapManager.ts | 9 +- .../src/mocks/SwapManagerMock.ts | 2 +- 12 files changed, 139 insertions(+), 134 deletions(-) create mode 100644 sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 23da170bb7..65b01b6d05 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -938,9 +938,6 @@ importers: '@summerfi/common': specifier: workspace:* version: link:../../packages/common - bignumber.js: - specifier: 9.0.1 - version: 9.0.1 superjson: specifier: ^1.13.3 version: 1.13.3 diff --git a/sdk/protocol-plugins/src/plugins/common/builders/SwapActionBuilder.ts b/sdk/protocol-plugins/src/plugins/common/builders/SwapActionBuilder.ts index fedd888bcd..d1cc8751d8 100644 --- a/sdk/protocol-plugins/src/plugins/common/builders/SwapActionBuilder.ts +++ b/sdk/protocol-plugins/src/plugins/common/builders/SwapActionBuilder.ts @@ -11,7 +11,7 @@ export const SwapActionBuilder: ActionBuilder = async (params): const swapData = await swapManager.getSwapDataExactInput({ chainInfo: params.user.chainInfo, - fromAmount: step.inputs.fromTokenAmount, + fromAmount: step.inputs.swappedAmount, toToken: step.inputs.toTokenAmount.token, recipient: Address.createFromEthereum({ value: swapContractInfo.address as HexData }), slippage: step.inputs.slippage, diff --git a/sdk/sdk-common/package.json b/sdk/sdk-common/package.json index 8cb14d6b65..6c40a744b2 100644 --- a/sdk/sdk-common/package.json +++ b/sdk/sdk-common/package.json @@ -26,9 +26,8 @@ "publish:npm": "pnpm bundle:npm && cd bundle && npm publish && cd .." }, "dependencies": { - "bignumber.js": "9.0.1", - "superjson": "^1.13.3", - "@summerfi/common": "workspace:*" + "@summerfi/common": "workspace:*", + "superjson": "^1.13.3" }, "devDependencies": { "@summerfi/eslint-config": "workspace:*", diff --git a/sdk/sdk-common/src/common/implementation/TokenAmount.ts b/sdk/sdk-common/src/common/implementation/TokenAmount.ts index f727dd84f3..f14e2af577 100644 --- a/sdk/sdk-common/src/common/implementation/TokenAmount.ts +++ b/sdk/sdk-common/src/common/implementation/TokenAmount.ts @@ -3,6 +3,8 @@ import { Percentage } from './Percentage' import { Token } from './Token' import { SerializationService } from '../../services/SerializationService' import { ITokenAmount } from '../interfaces/ITokenAmount' +import { Price } from '.' +import { isSameTokens } from '..' /** * @class TokenAmount @@ -61,7 +63,7 @@ export class TokenAmount implements ITokenAmount { }) } - public multiply(multiplier: Percentage | string | number): TokenAmount { + public multiply(multiplier: Percentage | string | number | Price): TokenAmount { if (multiplier instanceof Percentage) { return new TokenAmount({ token: this.token, @@ -69,6 +71,21 @@ export class TokenAmount implements ITokenAmount { }) } + if (multiplier instanceof Price) { + if (isSameTokens(this.token, multiplier.baseToken)) { + throw new Error('Token symbols do not match') + } + + if (!(multiplier.quoteToken instanceof Token)) { + throw new Error('Quote token is not a Token, (Currently currency is not supported)') + } + + return new TokenAmount({ + token: multiplier.quoteToken, + amount: this.amountBN.times(multiplier.toBN()).toString(), + }) + } + return new TokenAmount({ token: this.token, amount: this.amountBN.times(multiplier).toString(), diff --git a/sdk/sdk-common/src/simulation/Steps.ts b/sdk/sdk-common/src/simulation/Steps.ts index 4f544b1fec..f277089c58 100644 --- a/sdk/sdk-common/src/simulation/Steps.ts +++ b/sdk/sdk-common/src/simulation/Steps.ts @@ -65,7 +65,10 @@ export interface SwapStep provider: SwapProviderType routes: SwapRoute[] spotPrice: Price + // Amount that will be send to our Swap service which then deducts our fee fromTokenAmount: TokenAmount + // This amount has our fee already dedducted, and it will be send to exchange provider + swappedAmount: TokenAmount toTokenAmount: TokenAmount slippage: Percentage summerFee: Percentage diff --git a/sdk/sdk-common/src/utils/PercentageUtils.ts b/sdk/sdk-common/src/utils/PercentageUtils.ts index 992486aef5..f25e06747a 100644 --- a/sdk/sdk-common/src/utils/PercentageUtils.ts +++ b/sdk/sdk-common/src/utils/PercentageUtils.ts @@ -3,8 +3,8 @@ import { TokenAmount } from '../common/implementation/TokenAmount' export function applyPercentage(tokenAmount: TokenAmount, percentage: Percentage): TokenAmount { const amountBN = tokenAmount.toBN() - const newAmount = amountBN.times(percentage.value).div(100) - return TokenAmount.createFrom({ token: tokenAmount.token, amount: newAmount.toFixed(0) }) + const newAmountBN = amountBN.times(percentage.value).div(100) + return TokenAmount.createFrom({ token: tokenAmount.token, amount: newAmountBN.toString() }) } export function addPercentage(tokenAmount: TokenAmount, percentage: Percentage): TokenAmount { @@ -19,10 +19,6 @@ export function addPercentage(tokenAmount: TokenAmount, percentage: Percentage): export function subtractPercentage(tokenAmount: TokenAmount, percentage: Percentage): TokenAmount { const amountBN = tokenAmount.toBN() const newAmount = amountBN.times(percentage.value).div(100) - - console.log(percentage, 'percentage') - console.log(amountBN.toString(), 'amountBN') - console.log(newAmount.toString(), 'newAmount') return TokenAmount.createFrom({ token: tokenAmount.token, diff --git a/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts b/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts new file mode 100644 index 0000000000..aa03042b1b --- /dev/null +++ b/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts @@ -0,0 +1,50 @@ +import { applyPercentage } from "@summerfi/sdk-common/utils" +import type { ChainInfo, Percentage, Token, TokenAmount } from "@summerfi/sdk-common/common/implementation" +import { steps } from "@summerfi/sdk-common/simulation" +import type { ISwapManager } from "@summerfi/swap-common/interfaces" + +export async function getSwapStepData(params: { + chainInfo: ChainInfo + fromAmount: TokenAmount + toToken: Token + slippage: Percentage + swapManager: ISwapManager + }): Promise { + const summerFee = await params.swapManager.getSummerFee({ + from: { token: params.fromAmount.token }, + to: { token: params.toToken } + }) + + const summerFeeAmount = applyPercentage(params.fromAmount, summerFee) + const amountAfterSummerFee = params.fromAmount.subtract(summerFeeAmount) + + // Deduct summer fee from fromAmount + // Call swapProvider with new amount + // at last we need to return from amount with summer fee + // + + const [ + quote, + spotPrice, + ] = await Promise.all([ + params.swapManager.getSwapQuoteExactInput({ + chainInfo: params.chainInfo, + fromAmount: amountAfterSummerFee, + toToken: params.toToken, + }), + params.swapManager.getSpotPrice({ + chainInfo: params.chainInfo, + baseToken: params.toToken, + quoteToken: params.fromAmount.token, + }) + ]) + + return { + ...quote, + fromTokenAmount: params.fromAmount, + swappedAmount: amountAfterSummerFee, + summerFee, + spotPrice: spotPrice.price, + slippage: params.slippage, + } + } \ No newline at end of file diff --git a/sdk/simulator-service/src/implementation/utils/index.ts b/sdk/simulator-service/src/implementation/utils/index.ts index 297bef7257..addadd9726 100644 --- a/sdk/simulator-service/src/implementation/utils/index.ts +++ b/sdk/simulator-service/src/implementation/utils/index.ts @@ -1,2 +1,3 @@ export { getTokenBalance, addBalance, subtractBalance } from './BalanceUtils' export { makeStrategy, isValueReference, getReferencedValue, tail, head } from './SimulatorUtils' +export { getSwapStepData } from './GetSwapStepData' diff --git a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts index 420ef56b8a..fc3e7ec2d6 100644 --- a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts +++ b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts @@ -1,4 +1,4 @@ -import { subtractPercentage } from '@summerfi/sdk-common/utils' +import { applyPercentage, subtractPercentage } from '@summerfi/sdk-common/utils' import { FlashloanProvider, ISimulation, @@ -8,12 +8,15 @@ import { getValueFromReference, } from '@summerfi/sdk-common/simulation' import { Simulator } from '../../implementation/simulator-engine' -import { Position, TokenAmount, Percentage, Price } from '@summerfi/sdk-common/common' +import { Position, TokenAmount, Percentage, Price, Token } from '@summerfi/sdk-common/common' import { newEmptyPositionFromPool } from '@summerfi/sdk-common/common/utils' import { IRefinanceParameters } from '@summerfi/sdk-common/orders' import { isLendingPool } from '@summerfi/sdk-common/protocols' import { refinanceLendingToLendingAnyPairStrategy } from './Strategy' import { type IRefinanceDependencies } from '../common/Types' +import { getSwapStepData } from '../../implementation/utils/GetSwapStepData' +import { ISwapManager } from '@summerfi/swap-common/interfaces' +import { isSameTokens } from '@summerfi/sdk-common' export async function refinanceLendingToLendingAnyPair( args: IRefinanceParameters, @@ -48,23 +51,6 @@ export async function refinanceLendingToLendingAnyPair( ) const isDebtSwapSkipped = targetDebtConfig.token.address.equals(position.debtAmount.token.address) - const debtSpotPrice = ( - await dependencies.swapManager.getSpotPrice({ - chainInfo: position.pool.protocol.chainInfo, - baseToken: targetDebtConfig.token, - quoteToken: position.debtAmount.token, - }) - ).price - - const collateralSwapSummerFee = dependencies.swapManager.getSummerFee({ - from: { token: position.collateralAmount.token, protocol: position.pool.protocol }, - to: { token: targetCollateralConfig.token, protocol: targetPool.protocol }, - }) - const debtSwapSummerFee = dependencies.swapManager.getSummerFee({ - from: { token: position.debtAmount.token, protocol: position.pool.protocol }, - to: { token: targetDebtConfig.token, protocol: targetPool.protocol }, - }) - const simulation = await simulator .next(async () => ({ name: 'Flashloan', @@ -90,27 +76,13 @@ export async function refinanceLendingToLendingAnyPair( async () => ({ name: 'CollateralSwap', type: SimulationSteps.Swap, - inputs: { - ...(await dependencies.swapManager.getSwapQuoteExactInput({ - chainInfo: position.pool.protocol.chainInfo, - fromAmount: subtractPercentage( - position.collateralAmount, - Percentage.createFrom({ - value: collateralSwapSummerFee.value, - }), - ), - toToken: targetCollateralConfig.token, - })), - spotPrice: ( - await dependencies.swapManager.getSpotPrice({ - chainInfo: position.pool.protocol.chainInfo, - baseToken: targetCollateralConfig.token, - quoteToken: position.collateralAmount.token, - }) - ).price, + inputs: await getSwapStepData({ + chainInfo: position.pool.protocol.chainInfo, + fromAmount: position.collateralAmount, + toToken: targetCollateralConfig.token, slippage: Percentage.createFrom({ value: args.slippage.value }), - summerFee: collateralSwapSummerFee, - }, + swapManager: dependencies.swapManager, + }) }), isCollateralSwapSkipped, ) @@ -118,12 +90,12 @@ export async function refinanceLendingToLendingAnyPair( name: 'DepositBorrowToTarget', type: SimulationSteps.DepositBorrow, inputs: { - borrowAmount: await calculateBorrowAmount({ - isDebtSwapSkipped, - prevDebtAmount: position.debtAmount, - debtSpotPrice, + // refactor + borrowAmount: await estimateTokenAmountAfterSwap({ + sourceAmount: position.debtAmount, + targetToken: targetDebtConfig.token, slippage: Percentage.createFrom(args.slippage), - summerFee: debtSwapSummerFee, + swapManager: dependencies.swapManager, }), depositAmount: ctx.getReference( isCollateralSwapSkipped @@ -142,22 +114,13 @@ export async function refinanceLendingToLendingAnyPair( async (ctx) => ({ name: 'DebtSwap', type: SimulationSteps.Swap, - inputs: { - ...(await dependencies.swapManager.getSwapQuoteExactInput({ - chainInfo: args.sourcePosition.pool.protocol.chainInfo, - fromAmount: subtractPercentage( - // TODO: this should have better semantics. There was a bug where `getReferencedValue` was used instead of `getValueFromReference`, the names are too similar - getValueFromReference(ctx.getReference(['DepositBorrowToTarget', 'borrowAmount'])), - Percentage.createFrom({ - value: debtSwapSummerFee.value, - }), - ), - toToken: flashloanAmount.token, - })), - spotPrice: debtSpotPrice, + inputs: await getSwapStepData({ + chainInfo: position.pool.protocol.chainInfo, + fromAmount: getValueFromReference(ctx.getReference(['DepositBorrowToTarget', 'borrowAmount'])), + toToken: flashloanAmount.token, slippage: Percentage.createFrom({ value: args.slippage.value }), - summerFee: debtSwapSummerFee, - }, + swapManager: dependencies.swapManager, + }) }), isDebtSwapSkipped, ) @@ -219,62 +182,46 @@ export async function refinanceLendingToLendingAnyPair( } /** - * CalculateBorrowAmount - * @description Determines how much to borrow. - * When the DebtSwap step is skipped we simply return the previous position's debt amount - * When a DebtSwap is required we need to borrow enough to cover the original flashloan after - * accounting the swap and assuming the worst case scenario on slippage IE max slippage. - * - * We also need to factor in Summer fees ahead of time + * EstimateTokenAmountAfterSwap + * @description Estimates how much you will recive after swap. + * If target token is the same as source token, we return the same amount. + * When we perform a swap, we need to account for the summer fee, + * and we assume maximum slippage. */ -function calculateBorrowAmount(params: { - isDebtSwapSkipped: boolean - prevDebtAmount: TokenAmount - debtSpotPrice: Price +async function estimateTokenAmountAfterSwap(params: { + sourceAmount: TokenAmount + targetToken: Token slippage: Percentage - summerFee: Percentage -}): TokenAmount { - const { isDebtSwapSkipped, prevDebtAmount, debtSpotPrice, slippage, summerFee } = params - - /** - * If no swap is required we simply borrow the same amount of debt, and the same asset, - * on the target protocol - */ - if (isDebtSwapSkipped) { - return prevDebtAmount + swapManager: ISwapManager +}): Promise { + const { sourceAmount, slippage } = params + + if (isSameTokens(sourceAmount.token, params.targetToken)) { + return sourceAmount } - /** - * Worked Example - * @description 3 ETH/ 5000 DAI -> X WTBC / Y USDC - * 5000 DAI * (0.98 USDC/DAI) = 4900 USDC - * but this assumes zero price impact - * - * 5000 DAI * (0.98 USDC/DAI) / (1 - 0.01) = 4949.49 USDC (slippage adjusted borrow amount) - * where 0.01 is 1% slippage - * - * (5000 DAI * (0.98 USDC/DAI) / (1 - 0.01)) / (1 - 0.002) = 4959.41 USDC (slippage + summer fee adjusted borrow amount) - * where 0.002 is 20 basis pt fee as an example - * - * More generally we'd write this as - * (sourcePositionDebt * targetDebtQuotedInSourceDebtPrice / (one - slippage)) / (one - summer fee) = borrowAmount - */ - const borrowAmount = prevDebtAmount.multiply(debtSpotPrice.value) - const borrowAmountAdjustedForSlippage = subtractPercentage( - borrowAmount, + const spotPrice = ( + await params.swapManager.getSpotPrice({ + chainInfo: sourceAmount.token.chainInfo, + baseToken: params.targetToken, + quoteToken: sourceAmount.token, + }) + ).price + + const summerFee = await params.swapManager.getSummerFee({ + from: { token: sourceAmount.token }, + to: { token: params.targetToken }, + }) + + const summerFeeAmount = applyPercentage(sourceAmount, summerFee) + const prevAmountAfterFee = sourceAmount.subtract(summerFeeAmount) + const amountInTagetToken = prevAmountAfterFee.multiply(spotPrice) + + const amountAfterSlippage = subtractPercentage( + amountInTagetToken, Percentage.createFrom({ value: slippage.value, }), ) - const borrowAmountAdjustedForSlippageAndSummerFee = subtractPercentage( - borrowAmountAdjustedForSlippage, - Percentage.createFrom({ - value: summerFee.value, - }), - ) - - return TokenAmount.createFrom({ - amount: borrowAmountAdjustedForSlippageAndSummerFee.amount, - token: debtSpotPrice.baseToken, - }) + return amountAfterSlippage } diff --git a/sdk/swap-common/src/interfaces/ISwapManager.ts b/sdk/swap-common/src/interfaces/ISwapManager.ts index 5fcc0aff26..ea306057c7 100644 --- a/sdk/swap-common/src/interfaces/ISwapManager.ts +++ b/sdk/swap-common/src/interfaces/ISwapManager.ts @@ -6,7 +6,6 @@ import type { Address, CurrencySymbol, } from '@summerfi/sdk-common/common' -import { IProtocol } from '@summerfi/sdk-common/protocols' import type { QuoteData, SwapData, SpotData } from '@summerfi/sdk-common/swap' /** @@ -63,18 +62,15 @@ export interface ISwapManager { /** * @name getSummerFee * @description Returns the Summer fee to charge on the swap - * @param protocol The protocol name and chain info * @param fromToken The source token * @param toToken The target token */ getSummerFee(params: { from: { - protocol: IProtocol token: Token } to: { - protocol: IProtocol token: Token } - }): Percentage + }): Promise } diff --git a/sdk/swap-service/src/implementation/SwapManager.ts b/sdk/swap-service/src/implementation/SwapManager.ts index f724b40648..fde9b9392a 100644 --- a/sdk/swap-service/src/implementation/SwapManager.ts +++ b/sdk/swap-service/src/implementation/SwapManager.ts @@ -1,7 +1,6 @@ import type { Maybe } from '@summerfi/sdk-common/common/aliases' import type { ChainInfo, TokenAmount, Token, Address } from '@summerfi/sdk-common/common' import { ChainId, CurrencySymbol, Percentage } from '@summerfi/sdk-common/common' -import { IProtocol } from '@summerfi/sdk-common/protocols' import { ISwapProvider, ISwapManager } from '@summerfi/swap-common/interfaces' import type { QuoteData, SwapData, SwapProviderType, SpotData } from '@summerfi/sdk-common/swap' @@ -68,10 +67,10 @@ export class SwapManager implements ISwapManager { } // eslint-disable-next-line @typescript-eslint/no-unused-vars - getSummerFee(params: { - from: { protocol: IProtocol; token: Token } - to: { protocol: IProtocol; token: Token } - }): Percentage { + async getSummerFee(params: { + from: { token: Token } + to: { token: Token } + }): Promise { // TODO: Implement with appropriate logic return Percentage.createFrom({ value: 0.2, diff --git a/sdk/testing-utils/src/mocks/SwapManagerMock.ts b/sdk/testing-utils/src/mocks/SwapManagerMock.ts index 29a59c8291..06ecd04467 100644 --- a/sdk/testing-utils/src/mocks/SwapManagerMock.ts +++ b/sdk/testing-utils/src/mocks/SwapManagerMock.ts @@ -39,7 +39,7 @@ export class SwapManagerMock implements ISwapManager { return this._spotDataReturnValue } - getSummerFee(): Percentage { + async getSummerFee(): Promise { return this._summerFeeValue } From 71cee4b99ccaa9f1516fb8bc869cdcdcb7f325d8 Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Mon, 22 Apr 2024 16:13:35 +0200 Subject: [PATCH 03/17] fix: tx sucessful --- .../src/plugins/common/actions/SwapAction.ts | 2 +- .../src/common/implementation/TokenAmount.ts | 19 +----- sdk/sdk-common/src/common/utils/TokenUtils.ts | 21 ++++++- sdk/sdk-common/tests/TokenUtils.test.ts | 61 +++++++++++++++++++ .../tests/refinanceMakerSparkAnyPair.test.ts | 10 +-- .../implementation/utils/GetSwapStepData.ts | 1 + .../RefinanceLendingToLendingAnyPair.ts | 61 +++++++++++-------- .../src/interfaces/ISwapManager.ts | 1 + .../src/interfaces/ISwapProvider.ts | 1 + .../src/implementation/SwapManager.ts | 1 + .../oneinch/OneInchSwapProvider.ts | 11 +++- 11 files changed, 136 insertions(+), 53 deletions(-) create mode 100644 sdk/sdk-common/tests/TokenUtils.test.ts diff --git a/sdk/protocol-plugins/src/plugins/common/actions/SwapAction.ts b/sdk/protocol-plugins/src/plugins/common/actions/SwapAction.ts index be9a28c8ee..a35935b3fc 100644 --- a/sdk/protocol-plugins/src/plugins/common/actions/SwapAction.ts +++ b/sdk/protocol-plugins/src/plugins/common/actions/SwapAction.ts @@ -29,7 +29,7 @@ export class SwapAction extends BaseAction { toAsset: params.toMinimumAmount.token.address.value, amount: params.fromAmount.toBaseUnit(), receiveAtLeast: params.toMinimumAmount.toBaseUnit(), - fee: params.fee.toBaseUnit({ decimals: 8 }), + fee: params.fee.toBaseUnit({ decimals: 2 }), withData: params.withData, collectFeeFromToken: params.collectFeeInFromToken, }, diff --git a/sdk/sdk-common/src/common/implementation/TokenAmount.ts b/sdk/sdk-common/src/common/implementation/TokenAmount.ts index f14e2af577..27e1a55212 100644 --- a/sdk/sdk-common/src/common/implementation/TokenAmount.ts +++ b/sdk/sdk-common/src/common/implementation/TokenAmount.ts @@ -63,26 +63,11 @@ export class TokenAmount implements ITokenAmount { }) } - public multiply(multiplier: Percentage | string | number | Price): TokenAmount { + public multiply(multiplier: Percentage | string | number): TokenAmount { if (multiplier instanceof Percentage) { return new TokenAmount({ token: this.token, - amount: this.amountBN.times(multiplier.value).toString(), - }) - } - - if (multiplier instanceof Price) { - if (isSameTokens(this.token, multiplier.baseToken)) { - throw new Error('Token symbols do not match') - } - - if (!(multiplier.quoteToken instanceof Token)) { - throw new Error('Quote token is not a Token, (Currently currency is not supported)') - } - - return new TokenAmount({ - token: multiplier.quoteToken, - amount: this.amountBN.times(multiplier.toBN()).toString(), + amount: this.amountBN.times(multiplier.toProportion()).toString(), }) } diff --git a/sdk/sdk-common/src/common/utils/TokenUtils.ts b/sdk/sdk-common/src/common/utils/TokenUtils.ts index fa1c12c699..15eafe53b1 100644 --- a/sdk/sdk-common/src/common/utils/TokenUtils.ts +++ b/sdk/sdk-common/src/common/utils/TokenUtils.ts @@ -1,8 +1,25 @@ -import { IToken } from '../interfaces/IToken' +import { Token } from "../implementation/Token"; +import { Price } from "../implementation/Price"; +import { TokenAmount } from "../implementation/TokenAmount"; -export function isSameTokens(a: IToken, b: IToken): boolean { +export function isSameTokens(a: Token, b: Token): boolean { return ( a.address.value.toLowerCase() === b.address.value.toLowerCase() && a.chainInfo.chainId === b.chainInfo.chainId ) } + +export function exchange(tokenAmount: TokenAmount, price: Price) { + if (!(price.quoteToken instanceof Token)) { + throw new Error('Quote token is not a Token, (Currently currency is not supported)') + } + + if (!isSameTokens(tokenAmount.token, price.quoteToken)) { + throw new Error('Price needs to be quoted in the same token as the tokenAmount') + } + + return TokenAmount.createFrom({ + token: price.baseToken, + amount: tokenAmount.toBN().div(price.toBN()).toString(), + }) +} \ No newline at end of file diff --git a/sdk/sdk-common/tests/TokenUtils.test.ts b/sdk/sdk-common/tests/TokenUtils.test.ts new file mode 100644 index 0000000000..a13c0d5216 --- /dev/null +++ b/sdk/sdk-common/tests/TokenUtils.test.ts @@ -0,0 +1,61 @@ +import { Token } from '../src/common/implementation/Token' +import { TokenAmount } from '../src/common/implementation/TokenAmount' +import { Address } from '../src/common/implementation/Address' +import { AddressType } from '../src/common/enums/AddressType' +import { Price } from '../src/common/implementation/Price' +import { exchange } from '../src/common/utils/TokenUtils' +import { describe } from 'node:test' + +describe('TokenUtils', () => { + describe('exchange', () => { + const DAI = Token.createFrom({ + address: Address.createFrom({type: AddressType.Ethereum, value: '0x6b175474e89094c44da98b954eedeac495271d0f' }), chainInfo: { chainId: 1, name: 'eth' }, + symbol: 'DAI', + name: 'Dai', + decimals: 18 + }) + const ETH = Token.createFrom({ + address: Address.createFrom({type: AddressType.Ethereum, value: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' }), chainInfo: { chainId: 1, name: 'eth' }, + symbol: 'ETH', + name: 'Ethereium', + decimals: 18 + }) + describe("When the quote token is a Token", () => { + const tokenAmount = TokenAmount.createFrom({ + token: DAI, + amount: '300', + }) + const price = Price.createFrom({ + value: '3000', + baseToken: ETH, + quoteToken: DAI, + }) + + const result = exchange(tokenAmount, price) + + it('Should return an amount in base token', () => { + expect(result.token).toEqual(ETH) + }) + + it('Should return the correct amount', () => { + expect(result.amount).toEqual('0.1') + }) + }) + + describe("When the quote token does not match the tokenAmount token", () => { + const tokenAmount = TokenAmount.createFrom({ + token: DAI, + amount: '300', + }) + const price = Price.createFrom({ + value: '0.000333', + baseToken: DAI, + quoteToken: ETH, + }) + + it('Should throw an error when price is quoted in different token', () => { + expect(() => exchange(tokenAmount, price)).toThrow('Price needs to be quoted in the same token as the tokenAmount') + }) + }) + }) +}) diff --git a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts index 0e003a6220..528574f9f7 100644 --- a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts +++ b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts @@ -51,7 +51,7 @@ import { jest.setTimeout(300000) const SDKAPiUrl = 'https://nkllstfoy8.execute-api.us-east-1.amazonaws.com/api/sdk' -const TenderlyForkUrl = 'https://virtual.mainnet.rpc.tenderly.co/dff10c5c-3f1d-4a78-9132-de17d2768c13' +const TenderlyForkUrl = 'https://virtual.mainnet.rpc.tenderly.co/616d2e18-f889-4857-abc0-fa423dc91519' describe.only('Refinance Maker Spark | SDK', () => { it('should allow refinance Maker -> Spark with same pair', async () => { @@ -90,7 +90,7 @@ describe.only('Refinance Maker Spark | SDK', () => { // Positions Manager const positionsManager: IPositionsManager = { address: Address.createFromEthereum({ - value: '0x7f65e7326f22963e2039734ddff61958d5d284ca', + value: '0x8c6322eaa8e3a5fe1b813d5fa266318bea3b44aa', }), } @@ -116,7 +116,7 @@ describe.only('Refinance Maker Spark | SDK', () => { chainInfo: chain.chainInfo, }, ilkType: ILKType.ETH_C, - vaultId: '31690', + vaultId: '31696', } const makerPool = await maker.getPool({ @@ -131,10 +131,10 @@ describe.only('Refinance Maker Spark | SDK', () => { // Source position const makerPosition: Position = Position.createFrom({ type: PositionType.Multiply, - positionId: PositionId.createFrom({ id: '31690' }), + positionId: PositionId.createFrom({ id: '31696' }), debtAmount: TokenAmount.createFromBaseUnit({ token: DAI, - amount: '5000000000000000000001', + amount: '5000000000000000000000', }), collateralAmount: TokenAmount.createFromBaseUnit({ token: WETH, diff --git a/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts b/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts index aa03042b1b..d8a1ba0663 100644 --- a/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts +++ b/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts @@ -31,6 +31,7 @@ export async function getSwapStepData(params: { chainInfo: params.chainInfo, fromAmount: amountAfterSummerFee, toToken: params.toToken, + slippage: params.slippage, }), params.swapManager.getSpotPrice({ chainInfo: params.chainInfo, diff --git a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts index fc3e7ec2d6..fc3f9270e4 100644 --- a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts +++ b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts @@ -9,7 +9,7 @@ import { } from '@summerfi/sdk-common/simulation' import { Simulator } from '../../implementation/simulator-engine' import { Position, TokenAmount, Percentage, Price, Token } from '@summerfi/sdk-common/common' -import { newEmptyPositionFromPool } from '@summerfi/sdk-common/common/utils' +import { exchange, newEmptyPositionFromPool } from '@summerfi/sdk-common/common/utils' import { IRefinanceParameters } from '@summerfi/sdk-common/orders' import { isLendingPool } from '@summerfi/sdk-common/protocols' import { refinanceLendingToLendingAnyPairStrategy } from './Strategy' @@ -17,6 +17,7 @@ import { type IRefinanceDependencies } from '../common/Types' import { getSwapStepData } from '../../implementation/utils/GetSwapStepData' import { ISwapManager } from '@summerfi/swap-common/interfaces' import { isSameTokens } from '@summerfi/sdk-common' +import BigNumber from 'bignumber.js' export async function refinanceLendingToLendingAnyPair( args: IRefinanceParameters, @@ -51,6 +52,8 @@ export async function refinanceLendingToLendingAnyPair( ) const isDebtSwapSkipped = targetDebtConfig.token.address.equals(position.debtAmount.token.address) + console.log(`WE ARE FLASHLOANING ${flashloanAmount.toString()}`) + const simulation = await simulator .next(async () => ({ name: 'Flashloan', @@ -91,9 +94,11 @@ export async function refinanceLendingToLendingAnyPair( type: SimulationSteps.DepositBorrow, inputs: { // refactor - borrowAmount: await estimateTokenAmountAfterSwap({ - sourceAmount: position.debtAmount, - targetToken: targetDebtConfig.token, + borrowAmount: isDebtSwapSkipped + ? ctx.getReference(['PaybackWithdrawFromSource', 'paybackAmount']) + : await estimateSwapFromAmount({ + receiveAtLeast: flashloanAmount, + fromToken: targetDebtConfig.token, slippage: Percentage.createFrom(args.slippage), swapManager: dependencies.swapManager, }), @@ -143,7 +148,6 @@ export async function refinanceLendingToLendingAnyPair( token: position.debtAmount.token, }, }), - isDebtSwapSkipped, ) .next(async (ctx) => { // TODO: we should have a way to get the target position more easily and realiably, @@ -181,6 +185,7 @@ export async function refinanceLendingToLendingAnyPair( } satisfies ISimulation } + /** * EstimateTokenAmountAfterSwap * @description Estimates how much you will recive after swap. @@ -188,40 +193,42 @@ export async function refinanceLendingToLendingAnyPair( * When we perform a swap, we need to account for the summer fee, * and we assume maximum slippage. */ -async function estimateTokenAmountAfterSwap(params: { - sourceAmount: TokenAmount - targetToken: Token +async function estimateSwapFromAmount(params: { + receiveAtLeast: TokenAmount + fromToken: Token slippage: Percentage swapManager: ISwapManager }): Promise { - const { sourceAmount, slippage } = params + const { receiveAtLeast, slippage } = params - if (isSameTokens(sourceAmount.token, params.targetToken)) { - return sourceAmount + if (isSameTokens(receiveAtLeast.token, params.fromToken)) { + return receiveAtLeast } const spotPrice = ( await params.swapManager.getSpotPrice({ - chainInfo: sourceAmount.token.chainInfo, - baseToken: params.targetToken, - quoteToken: sourceAmount.token, + chainInfo: receiveAtLeast.token.chainInfo, + baseToken: params.fromToken, + quoteToken: receiveAtLeast.token, }) ).price + const summerFee = await params.swapManager.getSummerFee({ - from: { token: sourceAmount.token }, - to: { token: params.targetToken }, + from: { token: receiveAtLeast.token }, + to: { token: params.fromToken }, }) - const summerFeeAmount = applyPercentage(sourceAmount, summerFee) - const prevAmountAfterFee = sourceAmount.subtract(summerFeeAmount) - const amountInTagetToken = prevAmountAfterFee.multiply(spotPrice) - - const amountAfterSlippage = subtractPercentage( - amountInTagetToken, - Percentage.createFrom({ - value: slippage.value, - }), - ) - return amountAfterSlippage + const ONE = new BigNumber(1) + /* + TargetAmt = SourceAmt * (1 - SummerFee) / (SpotPrice * (1 + Slippage)) + SourceAmt = TargetAmt * SpotPrice * (1 + Slippage) / (1 - SummerFee) + */ + + const sourceAmount = params.receiveAtLeast.toBN().multipliedBy(spotPrice.toBN().times(ONE.plus(slippage.toProportion()))).div(ONE.minus(summerFee.toProportion())) + + return TokenAmount.createFrom({ + amount: sourceAmount.toString(), + token: params.fromToken, + }) } diff --git a/sdk/swap-common/src/interfaces/ISwapManager.ts b/sdk/swap-common/src/interfaces/ISwapManager.ts index ea306057c7..11c50f4c63 100644 --- a/sdk/swap-common/src/interfaces/ISwapManager.ts +++ b/sdk/swap-common/src/interfaces/ISwapManager.ts @@ -43,6 +43,7 @@ export interface ISwapManager { chainInfo: ChainInfo fromAmount: TokenAmount toToken: Token + slippage: Percentage }): Promise /** diff --git a/sdk/swap-common/src/interfaces/ISwapProvider.ts b/sdk/swap-common/src/interfaces/ISwapProvider.ts index a8bbb34641..610e1a7a8a 100644 --- a/sdk/swap-common/src/interfaces/ISwapProvider.ts +++ b/sdk/swap-common/src/interfaces/ISwapProvider.ts @@ -39,6 +39,7 @@ export interface ISwapProvider { chainInfo: ChainInfo fromAmount: TokenAmount toToken: Token + slippage: Percentage }): Promise /** diff --git a/sdk/swap-service/src/implementation/SwapManager.ts b/sdk/swap-service/src/implementation/SwapManager.ts index fde9b9392a..c9cc39512c 100644 --- a/sdk/swap-service/src/implementation/SwapManager.ts +++ b/sdk/swap-service/src/implementation/SwapManager.ts @@ -42,6 +42,7 @@ export class SwapManager implements ISwapManager { chainInfo: ChainInfo fromAmount: TokenAmount toToken: Token + slippage: Percentage forceUseProvider?: SwapProviderType }): Promise { const provider: Maybe = this._getBestProvider(params) diff --git a/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts b/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts index b9e813b31d..4e31f0f663 100644 --- a/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts +++ b/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts @@ -111,6 +111,7 @@ export class OneInchSwapProvider implements ISwapProvider { chainInfo: ChainInfo fromAmount: TokenAmount toToken: Token + slippage: Percentage }): Promise { const swapUrl = this._formatOneInchQuoteUrl({ chainInfo: params.chainInfo, @@ -132,13 +133,21 @@ export class OneInchSwapProvider implements ISwapProvider { const responseData = (await response.json()) as OneInchQuoteResponse + const One = Percentage.createFrom({ value: 100 }) + + console.log('SLIPPAGE', One.subtract(params.slippage).toProportion()) + console.log(`amount: ${TokenAmount.createFromBaseUnit({ + token: params.toToken, + amount: responseData.toTokenAmount, + }).multiply(One.subtract(params.slippage))}`) + return { provider: SwapProviderType.OneInch, fromTokenAmount: params.fromAmount, toTokenAmount: TokenAmount.createFromBaseUnit({ token: params.toToken, amount: responseData.toTokenAmount, - }), + }).multiply(One.subtract(params.slippage)), routes: this._extractSwapRoutes(responseData.protocols), estimatedGas: responseData.estimatedGas, } From 71e1932f4fae0301b72e38eb9e8a65c011427500 Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Mon, 22 Apr 2024 17:04:31 +0200 Subject: [PATCH 04/17] refactor: clean up --- sdk/sdk-common/src/common/utils/TokenUtils.ts | 21 +- sdk/sdk-common/tests/TokenUtils.test.ts | 61 ----- .../tests/refinanceMakerSparkAnyPair.test.ts | 224 +----------------- .../RefinanceLendingToLendingAnyPair.ts | 6 +- .../oneinch/OneInchSwapProvider.ts | 6 - 5 files changed, 14 insertions(+), 304 deletions(-) delete mode 100644 sdk/sdk-common/tests/TokenUtils.test.ts diff --git a/sdk/sdk-common/src/common/utils/TokenUtils.ts b/sdk/sdk-common/src/common/utils/TokenUtils.ts index 15eafe53b1..06755d3653 100644 --- a/sdk/sdk-common/src/common/utils/TokenUtils.ts +++ b/sdk/sdk-common/src/common/utils/TokenUtils.ts @@ -1,25 +1,8 @@ -import { Token } from "../implementation/Token"; -import { Price } from "../implementation/Price"; -import { TokenAmount } from "../implementation/TokenAmount"; +import { IToken } from "../interfaces/IToken"; -export function isSameTokens(a: Token, b: Token): boolean { +export function isSameTokens(a: IToken, b: IToken): boolean { return ( a.address.value.toLowerCase() === b.address.value.toLowerCase() && a.chainInfo.chainId === b.chainInfo.chainId ) } - -export function exchange(tokenAmount: TokenAmount, price: Price) { - if (!(price.quoteToken instanceof Token)) { - throw new Error('Quote token is not a Token, (Currently currency is not supported)') - } - - if (!isSameTokens(tokenAmount.token, price.quoteToken)) { - throw new Error('Price needs to be quoted in the same token as the tokenAmount') - } - - return TokenAmount.createFrom({ - token: price.baseToken, - amount: tokenAmount.toBN().div(price.toBN()).toString(), - }) -} \ No newline at end of file diff --git a/sdk/sdk-common/tests/TokenUtils.test.ts b/sdk/sdk-common/tests/TokenUtils.test.ts deleted file mode 100644 index a13c0d5216..0000000000 --- a/sdk/sdk-common/tests/TokenUtils.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Token } from '../src/common/implementation/Token' -import { TokenAmount } from '../src/common/implementation/TokenAmount' -import { Address } from '../src/common/implementation/Address' -import { AddressType } from '../src/common/enums/AddressType' -import { Price } from '../src/common/implementation/Price' -import { exchange } from '../src/common/utils/TokenUtils' -import { describe } from 'node:test' - -describe('TokenUtils', () => { - describe('exchange', () => { - const DAI = Token.createFrom({ - address: Address.createFrom({type: AddressType.Ethereum, value: '0x6b175474e89094c44da98b954eedeac495271d0f' }), chainInfo: { chainId: 1, name: 'eth' }, - symbol: 'DAI', - name: 'Dai', - decimals: 18 - }) - const ETH = Token.createFrom({ - address: Address.createFrom({type: AddressType.Ethereum, value: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' }), chainInfo: { chainId: 1, name: 'eth' }, - symbol: 'ETH', - name: 'Ethereium', - decimals: 18 - }) - describe("When the quote token is a Token", () => { - const tokenAmount = TokenAmount.createFrom({ - token: DAI, - amount: '300', - }) - const price = Price.createFrom({ - value: '3000', - baseToken: ETH, - quoteToken: DAI, - }) - - const result = exchange(tokenAmount, price) - - it('Should return an amount in base token', () => { - expect(result.token).toEqual(ETH) - }) - - it('Should return the correct amount', () => { - expect(result.amount).toEqual('0.1') - }) - }) - - describe("When the quote token does not match the tokenAmount token", () => { - const tokenAmount = TokenAmount.createFrom({ - token: DAI, - amount: '300', - }) - const price = Price.createFrom({ - value: '0.000333', - baseToken: DAI, - quoteToken: ETH, - }) - - it('Should throw an error when price is quoted in different token', () => { - expect(() => exchange(tokenAmount, price)).toThrow('Price needs to be quoted in the same token as the tokenAmount') - }) - }) - }) -}) diff --git a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts index 528574f9f7..6373e384a4 100644 --- a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts +++ b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts @@ -7,7 +7,6 @@ import { Address, type Maybe, ChainFamilyMap, - AddressValue, newEmptyPositionFromPool, PositionType, } from '@summerfi/sdk-common/common' @@ -18,32 +17,13 @@ import { TokenSymbol } from '@summerfi/sdk-common/common/enums' import { IPositionsManager, IRefinanceParameters, Order } from '@summerfi/sdk-common/orders' import { ISimulation, SimulationType } from '@summerfi/sdk-common/simulation' import { TransactionUtils } from './utils/TransactionUtils' -import { - decodeActionCalldata, - decodePositionsManagerCalldata, - decodeStrategyExecutorCalldata, -} from '@summerfi/testing-utils' -import { Deployments } from '@summerfi/core-contracts' -import { DeploymentIndex } from '@summerfi/deployment-utils' - -import { Hex, createPublicClient } from 'viem' + +import { Hex } from 'viem' import assert from 'assert' +import { EmodeType } from '@summerfi/protocol-plugins/plugins/common' +import { ILKType, MakerPoolId } from '@summerfi/protocol-plugins/plugins/maker' import { - EmodeType, - FlashloanAction, - SendTokenAction, - SetApprovalAction, - PositionCreatedAction, -} from '@summerfi/protocol-plugins/plugins/common' -import { - ILKType, - MakerPaybackAction, - MakerPoolId, - MakerWithdrawAction, -} from '@summerfi/protocol-plugins/plugins/maker' -import { - SparkBorrowAction, - SparkDepositAction, + SparkPoolId, isSparkPoolId, } from '@summerfi/protocol-plugins/plugins/spark' @@ -51,7 +31,7 @@ import { jest.setTimeout(300000) const SDKAPiUrl = 'https://nkllstfoy8.execute-api.us-east-1.amazonaws.com/api/sdk' -const TenderlyForkUrl = 'https://virtual.mainnet.rpc.tenderly.co/616d2e18-f889-4857-abc0-fa423dc91519' +const TenderlyForkUrl = 'https://virtual.mainnet.rpc.tenderly.co/7bebdd10-2878-4830-833d-aba2710f3dc0' describe.only('Refinance Maker Spark | SDK', () => { it('should allow refinance Maker -> Spark with same pair', async () => { @@ -65,16 +45,6 @@ describe.only('Refinance Maker Spark | SDK', () => { assert(chain, 'Chain not found') - // Deployment - const deploymentName = `${chain.chainInfo.name}.standard` - const deployments = Deployments as DeploymentIndex - const deployment = deployments[deploymentName] - - // Strategy Executor - const strategyExecutorAddress = Address.createFromEthereum({ - value: deployment.contracts.OperationExecutor.address as AddressValue, - }) - // User const walletAddress = Address.createFromEthereum({ value: '0x34314adbfBb5d239bb67f0265c9c45EB8b834412', @@ -90,7 +60,7 @@ describe.only('Refinance Maker Spark | SDK', () => { // Positions Manager const positionsManager: IPositionsManager = { address: Address.createFromEthereum({ - value: '0x8c6322eaa8e3a5fe1b813d5fa266318bea3b44aa', + value: '0x1858b76756d19f8cb7c7756a0f96e0d7673285ed', }), } @@ -116,7 +86,7 @@ describe.only('Refinance Maker Spark | SDK', () => { chainInfo: chain.chainInfo, }, ilkType: ILKType.ETH_C, - vaultId: '31696', + vaultId: '31697', } const makerPool = await maker.getPool({ @@ -131,7 +101,7 @@ describe.only('Refinance Maker Spark | SDK', () => { // Source position const makerPosition: Position = Position.createFrom({ type: PositionType.Multiply, - positionId: PositionId.createFrom({ id: '31696' }), + positionId: PositionId.createFrom({ id: '31697' }), debtAmount: TokenAmount.createFromBaseUnit({ token: DAI, amount: '5000000000000000000000', @@ -188,7 +158,6 @@ describe.only('Refinance Maker Spark | SDK', () => { expect(refinanceSimulation.sourcePosition?.positionId).toEqual(makerPosition.positionId) expect(refinanceSimulation.targetPosition.pool.poolId).toEqual(sparkPool.poolId) - expect(refinanceSimulation.steps.length).toBe(8) const refinanceOrder: Maybe = await user.newOrder({ positionsManager, @@ -196,180 +165,7 @@ describe.only('Refinance Maker Spark | SDK', () => { }) assert(refinanceOrder, 'Order not found') - - expect(refinanceOrder.simulation.simulationType).toEqual(refinanceSimulation.simulationType) - assert(refinanceOrder.simulation.sourcePosition, 'Source position not found') - - expect(refinanceOrder.simulation.sourcePosition.positionId).toEqual( - refinanceSimulation.sourcePosition?.positionId, - ) - expect(refinanceOrder.simulation.targetPosition.pool.poolId).toEqual(sparkPool.poolId) - expect(refinanceOrder.simulation.steps.length).toEqual(refinanceSimulation.steps.length) - - for (let i = 0; i < refinanceOrder.simulation.steps.length; i++) { - expect(refinanceOrder.simulation.steps[i].type).toEqual(refinanceSimulation.steps[i].type) - } - - expect(refinanceOrder.transactions.length).toEqual(1) - expect(refinanceOrder.transactions[0].transaction.target.value).toEqual( - positionsManager.address.value, - ) - - const positionsManagerParams = decodePositionsManagerCalldata({ - calldata: refinanceOrder.transactions[0].transaction.calldata, - }) - - assert(positionsManagerParams, 'Cannot decode Positions Manager calldata') - expect(positionsManagerParams.target.value).toEqual(strategyExecutorAddress.value) - - // Decode calldata - const strategyExecutorParams = decodeStrategyExecutorCalldata(positionsManagerParams.calldata) - - const strategyName = `${refinanceOrder.simulation.simulationType}${refinanceOrder.simulation.sourcePosition?.pool.protocol.name}${refinanceOrder.simulation.targetPosition.pool.protocol.name}` - - assert(strategyExecutorParams, 'Cannot decode Strategy Executor calldata') - expect(strategyExecutorParams.strategyName).toEqual(strategyName) - expect(strategyExecutorParams.actionCalls.length).toEqual(3) - - // // Decode Flashloan action - // const flashloanParams = decodeActionCalldata({ - // action: new FlashloanAction(), - // calldata: strategyExecutorParams.actionCalls[0].callData, - // }) - - // const sourcePosition = Position.createFrom(refinanceOrder.simulation.sourcePosition) - // const targetPosition = Position.createFrom(refinanceOrder.simulation.targetPosition) - - // assert(flashloanParams, 'Cannot decode Flashloan action calldata') - - // const FlashloanMargin = 1.001 - // const flashloanAmount = sourcePosition.debtAmount.multiply(FlashloanMargin) - - // expect(flashloanParams.args[0].amount).toBe(BigInt(flashloanAmount.toBaseUnit())) - // expect(flashloanParams.args[0].asset).toBe(sourcePosition.debtAmount.token.address.value) - // expect(flashloanParams.args[0].isProxyFlashloan).toBe(true) - // expect(flashloanParams.args[0].isDPMProxy).toBe(true) - // expect(flashloanParams.args[0].provider).toBe(0) - // /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ - // const flashloanSubcalls = flashloanParams.args[0].calls as Array - // expect(flashloanSubcalls.length).toBe(6) - - // // Decode Maker Payback action - // const makerPaybackAction = decodeActionCalldata({ - // action: new MakerPaybackAction(), - // calldata: flashloanSubcalls[0].callData, - // }) - - // const paybackAmount = TokenAmount.createFrom({ - // amount: Number.MAX_SAFE_INTEGER.toString(), - // token: sourcePosition.debtAmount.token, - // }).toBaseUnit() - - // assert(makerPaybackAction, 'Cannot decode Maker Payback action calldata') - // expect(makerPaybackAction.args[0].vaultId).toBe( - // BigInt((sourcePosition.pool.poolId as MakerPoolId).vaultId), - // ) - // expect(makerPaybackAction.args[0].userAddress).toBe(positionsManager.address.value) - // expect(makerPaybackAction.args[0].amount).toBe(BigInt(paybackAmount)) - // expect(makerPaybackAction.args[0].paybackAll).toBe(true) - - // // Decode Maker Withdraw action - // const makerWithdrawAction = decodeActionCalldata({ - // action: new MakerWithdrawAction(), - // calldata: flashloanSubcalls[1].callData, - // }) - - // assert(makerWithdrawAction, 'Cannot decode Maker Withdraw action calldata') - - // expect(makerWithdrawAction.args[0].vaultId).toBe( - // BigInt((sourcePosition.pool.poolId as MakerPoolId).vaultId), - // ) - // expect(makerWithdrawAction.args[0].userAddress).toBe(positionsManager.address.value) - // expect(makerWithdrawAction.args[0].joinAddr).toBe( - // deployment.dependencies.MCD_JOIN_ETH_C.address, - // ) - // expect(makerWithdrawAction.args[0].amount).toBe( - // BigInt(sourcePosition.collateralAmount.toBaseUnit()), - // ) - - // // Set Approval - // const setApprovalAction = decodeActionCalldata({ - // action: new SetApprovalAction(), - // calldata: flashloanSubcalls[2].callData, - // }) - - // assert(setApprovalAction, 'Cannot decode Set Approval action calldata') - - // const sparkLendingPool = Address.createFromEthereum({ - // value: deployment.dependencies.SparkLendingPool.address as AddressValue, - // }) - // expect(setApprovalAction.args[0].asset).toBe( - // sourcePosition.collateralAmount.token.address.value, - // ) - // expect(setApprovalAction.args[0].delegate).toBe(sparkLendingPool.value) - // expect(setApprovalAction.args[0].amount).toBe( - // BigInt(sourcePosition.collateralAmount.toBaseUnit()), - // ) - // expect(setApprovalAction.args[0].sumAmounts).toBe(false) - - // // Decode Spark Deposit action - // const sparkDepositAction = decodeActionCalldata({ - // action: new SparkDepositAction(), - // calldata: flashloanSubcalls[3].callData, - // }) - - // assert(sparkDepositAction, 'Cannot decode Spark Deposit action calldata') - - // expect(sparkDepositAction.args[0].asset).toBe( - // targetPosition.collateralAmount.token.address.value, - // ) - // expect(sparkDepositAction.args[0].amount).toBe( - // BigInt(sourcePosition.collateralAmount.toBaseUnit()), - // ) - // expect(sparkDepositAction.args[0].sumAmounts).toBe(false) - // expect(sparkDepositAction.args[0].setAsCollateral).toBe(true) - - // // Decode Spark Borrow action - // const sparkBorrowAction = decodeActionCalldata({ - // action: new SparkBorrowAction(), - // calldata: flashloanSubcalls[4].callData, - // }) - - // assert(sparkBorrowAction, 'Cannot decode Spark Borrow action calldata') - - // expect(sparkBorrowAction.args[0].asset).toBe(targetPosition.debtAmount.token.address.value) - // expect(sparkBorrowAction.args[0].amount).toBe(BigInt(targetPosition.debtAmount.toBaseUnit())) - // expect(sparkBorrowAction.args[0].to).toBe(positionsManager.address.value) - - // // Decode Send Token action - // const sendTokenAction = decodeActionCalldata({ - // action: new SendTokenAction(), - // calldata: flashloanSubcalls[5].callData, - // }) - - // assert(sendTokenAction, 'Cannot decode Send Token action calldata') - - // expect(sendTokenAction.args[0].asset).toBe(sourcePosition.debtAmount.token.address.value) - // expect(sendTokenAction.args[0].to).toBe(strategyExecutorAddress.value) - // expect(sendTokenAction.args[0].amount).toBe(BigInt(flashloanAmount.toBaseUnit())) - - // // Decode Position Created event action - // const positionCreatedParams = decodeActionCalldata({ - // action: new PositionCreatedAction(), - // calldata: strategyExecutorParams.actionCalls[1].callData, - // }) - - // assert(positionCreatedParams, 'Cannot decode Position Created action calldata') - - // expect(positionCreatedParams.args[0].protocol).toBe(targetPosition.pool.protocol.name) - // expect(positionCreatedParams.args[0].positionType).toBe(sourcePosition.type) - // expect(positionCreatedParams.args[0].collateralToken).toBe( - // targetPosition.collateralAmount.token.address.value, - // ) - // expect(positionCreatedParams.args[0].debtToken).toBe( - // targetPosition.debtAmount.token.address.value, - // ) - + // Send transaction console.log('Sending transaction...') diff --git a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts index fc3f9270e4..54d1cd9613 100644 --- a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts +++ b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts @@ -8,8 +8,8 @@ import { getValueFromReference, } from '@summerfi/sdk-common/simulation' import { Simulator } from '../../implementation/simulator-engine' -import { Position, TokenAmount, Percentage, Price, Token } from '@summerfi/sdk-common/common' -import { exchange, newEmptyPositionFromPool } from '@summerfi/sdk-common/common/utils' +import { Position, TokenAmount, Percentage, Token } from '@summerfi/sdk-common/common' +import { newEmptyPositionFromPool } from '@summerfi/sdk-common/common/utils' import { IRefinanceParameters } from '@summerfi/sdk-common/orders' import { isLendingPool } from '@summerfi/sdk-common/protocols' import { refinanceLendingToLendingAnyPairStrategy } from './Strategy' @@ -52,8 +52,6 @@ export async function refinanceLendingToLendingAnyPair( ) const isDebtSwapSkipped = targetDebtConfig.token.address.equals(position.debtAmount.token.address) - console.log(`WE ARE FLASHLOANING ${flashloanAmount.toString()}`) - const simulation = await simulator .next(async () => ({ name: 'Flashloan', diff --git a/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts b/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts index 4e31f0f663..e29e4d1844 100644 --- a/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts +++ b/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts @@ -135,12 +135,6 @@ export class OneInchSwapProvider implements ISwapProvider { const One = Percentage.createFrom({ value: 100 }) - console.log('SLIPPAGE', One.subtract(params.slippage).toProportion()) - console.log(`amount: ${TokenAmount.createFromBaseUnit({ - token: params.toToken, - amount: responseData.toTokenAmount, - }).multiply(One.subtract(params.slippage))}`) - return { provider: SwapProviderType.OneInch, fromTokenAmount: params.fromAmount, From 32ad242bc96bca31e14a74873da129bc06b6c38a Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Mon, 22 Apr 2024 17:09:03 +0200 Subject: [PATCH 05/17] chore: format --- .../src/common/implementation/Price.ts | 2 +- sdk/sdk-common/src/common/utils/TokenUtils.ts | 2 +- sdk/sdk-common/src/utils/PercentageUtils.ts | 2 +- .../tests/refinanceMakerSparkAnyPair.test.ts | 17 +--- .../implementation/utils/GetSwapStepData.ts | 92 ++++++++++--------- .../RefinanceLendingToLendingAnyPair.ts | 55 +++++------ 6 files changed, 83 insertions(+), 87 deletions(-) diff --git a/sdk/sdk-common/src/common/implementation/Price.ts b/sdk/sdk-common/src/common/implementation/Price.ts index 7aceb13080..f21db51df9 100644 --- a/sdk/sdk-common/src/common/implementation/Price.ts +++ b/sdk/sdk-common/src/common/implementation/Price.ts @@ -59,7 +59,7 @@ export class Price implements IPrice { quoteToken: b.baseToken, }) - // TODO: case when the quotes are the same + // TODO: case when the quotes are the same } } diff --git a/sdk/sdk-common/src/common/utils/TokenUtils.ts b/sdk/sdk-common/src/common/utils/TokenUtils.ts index 06755d3653..fa1c12c699 100644 --- a/sdk/sdk-common/src/common/utils/TokenUtils.ts +++ b/sdk/sdk-common/src/common/utils/TokenUtils.ts @@ -1,4 +1,4 @@ -import { IToken } from "../interfaces/IToken"; +import { IToken } from '../interfaces/IToken' export function isSameTokens(a: IToken, b: IToken): boolean { return ( diff --git a/sdk/sdk-common/src/utils/PercentageUtils.ts b/sdk/sdk-common/src/utils/PercentageUtils.ts index f25e06747a..4414e964b3 100644 --- a/sdk/sdk-common/src/utils/PercentageUtils.ts +++ b/sdk/sdk-common/src/utils/PercentageUtils.ts @@ -19,7 +19,7 @@ export function addPercentage(tokenAmount: TokenAmount, percentage: Percentage): export function subtractPercentage(tokenAmount: TokenAmount, percentage: Percentage): TokenAmount { const amountBN = tokenAmount.toBN() const newAmount = amountBN.times(percentage.value).div(100) - + return TokenAmount.createFrom({ token: tokenAmount.token, amount: amountBN.minus(newAmount).toString(), diff --git a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts index 6373e384a4..e2236688f8 100644 --- a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts +++ b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts @@ -22,16 +22,13 @@ import { Hex } from 'viem' import assert from 'assert' import { EmodeType } from '@summerfi/protocol-plugins/plugins/common' import { ILKType, MakerPoolId } from '@summerfi/protocol-plugins/plugins/maker' -import { - - SparkPoolId, - isSparkPoolId, -} from '@summerfi/protocol-plugins/plugins/spark' +import { SparkPoolId, isSparkPoolId } from '@summerfi/protocol-plugins/plugins/spark' jest.setTimeout(300000) const SDKAPiUrl = 'https://nkllstfoy8.execute-api.us-east-1.amazonaws.com/api/sdk' -const TenderlyForkUrl = 'https://virtual.mainnet.rpc.tenderly.co/7bebdd10-2878-4830-833d-aba2710f3dc0' +const TenderlyForkUrl = + 'https://virtual.mainnet.rpc.tenderly.co/7bebdd10-2878-4830-833d-aba2710f3dc0' describe.only('Refinance Maker Spark | SDK', () => { it('should allow refinance Maker -> Spark with same pair', async () => { @@ -142,11 +139,7 @@ describe.only('Refinance Maker Spark | SDK', () => { assert(false, 'Spark pool type is not lending') } - const emptyTargetPosition = newEmptyPositionFromPool( - sparkPool, - USDC, - WBTC, - ) + const emptyTargetPosition = newEmptyPositionFromPool(sparkPool, USDC, WBTC) const refinanceSimulation: ISimulation = await sdk.simulator.refinance.simulateRefinancePosition({ sourcePosition: makerPosition, @@ -165,7 +158,7 @@ describe.only('Refinance Maker Spark | SDK', () => { }) assert(refinanceOrder, 'Order not found') - + // Send transaction console.log('Sending transaction...') diff --git a/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts b/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts index d8a1ba0663..c89468d832 100644 --- a/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts +++ b/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts @@ -1,51 +1,53 @@ -import { applyPercentage } from "@summerfi/sdk-common/utils" -import type { ChainInfo, Percentage, Token, TokenAmount } from "@summerfi/sdk-common/common/implementation" -import { steps } from "@summerfi/sdk-common/simulation" -import type { ISwapManager } from "@summerfi/swap-common/interfaces" +import { applyPercentage } from '@summerfi/sdk-common/utils' +import type { + ChainInfo, + Percentage, + Token, + TokenAmount, +} from '@summerfi/sdk-common/common/implementation' +import { steps } from '@summerfi/sdk-common/simulation' +import type { ISwapManager } from '@summerfi/swap-common/interfaces' export async function getSwapStepData(params: { - chainInfo: ChainInfo - fromAmount: TokenAmount - toToken: Token - slippage: Percentage - swapManager: ISwapManager - }): Promise { - const summerFee = await params.swapManager.getSummerFee({ - from: { token: params.fromAmount.token }, - to: { token: params.toToken } - }) + chainInfo: ChainInfo + fromAmount: TokenAmount + toToken: Token + slippage: Percentage + swapManager: ISwapManager +}): Promise { + const summerFee = await params.swapManager.getSummerFee({ + from: { token: params.fromAmount.token }, + to: { token: params.toToken }, + }) - const summerFeeAmount = applyPercentage(params.fromAmount, summerFee) - const amountAfterSummerFee = params.fromAmount.subtract(summerFeeAmount) + const summerFeeAmount = applyPercentage(params.fromAmount, summerFee) + const amountAfterSummerFee = params.fromAmount.subtract(summerFeeAmount) - // Deduct summer fee from fromAmount - // Call swapProvider with new amount - // at last we need to return from amount with summer fee - // - - const [ - quote, - spotPrice, - ] = await Promise.all([ - params.swapManager.getSwapQuoteExactInput({ - chainInfo: params.chainInfo, - fromAmount: amountAfterSummerFee, - toToken: params.toToken, - slippage: params.slippage, - }), - params.swapManager.getSpotPrice({ - chainInfo: params.chainInfo, - baseToken: params.toToken, - quoteToken: params.fromAmount.token, - }) - ]) + // Deduct summer fee from fromAmount + // Call swapProvider with new amount + // at last we need to return from amount with summer fee + // - return { - ...quote, - fromTokenAmount: params.fromAmount, - swappedAmount: amountAfterSummerFee, - summerFee, - spotPrice: spotPrice.price, + const [quote, spotPrice] = await Promise.all([ + params.swapManager.getSwapQuoteExactInput({ + chainInfo: params.chainInfo, + fromAmount: amountAfterSummerFee, + toToken: params.toToken, slippage: params.slippage, - } - } \ No newline at end of file + }), + params.swapManager.getSpotPrice({ + chainInfo: params.chainInfo, + baseToken: params.toToken, + quoteToken: params.fromAmount.token, + }), + ]) + + return { + ...quote, + fromTokenAmount: params.fromAmount, + swappedAmount: amountAfterSummerFee, + summerFee, + spotPrice: spotPrice.price, + slippage: params.slippage, + } +} diff --git a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts index 54d1cd9613..487a76e9e4 100644 --- a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts +++ b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts @@ -83,7 +83,7 @@ export async function refinanceLendingToLendingAnyPair( toToken: targetCollateralConfig.token, slippage: Percentage.createFrom({ value: args.slippage.value }), swapManager: dependencies.swapManager, - }) + }), }), isCollateralSwapSkipped, ) @@ -92,14 +92,14 @@ export async function refinanceLendingToLendingAnyPair( type: SimulationSteps.DepositBorrow, inputs: { // refactor - borrowAmount: isDebtSwapSkipped - ? ctx.getReference(['PaybackWithdrawFromSource', 'paybackAmount']) + borrowAmount: isDebtSwapSkipped + ? ctx.getReference(['PaybackWithdrawFromSource', 'paybackAmount']) : await estimateSwapFromAmount({ - receiveAtLeast: flashloanAmount, - fromToken: targetDebtConfig.token, - slippage: Percentage.createFrom(args.slippage), - swapManager: dependencies.swapManager, - }), + receiveAtLeast: flashloanAmount, + fromToken: targetDebtConfig.token, + slippage: Percentage.createFrom(args.slippage), + swapManager: dependencies.swapManager, + }), depositAmount: ctx.getReference( isCollateralSwapSkipped ? ['PaybackWithdrawFromSource', 'withdrawAmount'] @@ -119,11 +119,13 @@ export async function refinanceLendingToLendingAnyPair( type: SimulationSteps.Swap, inputs: await getSwapStepData({ chainInfo: position.pool.protocol.chainInfo, - fromAmount: getValueFromReference(ctx.getReference(['DepositBorrowToTarget', 'borrowAmount'])), + fromAmount: getValueFromReference( + ctx.getReference(['DepositBorrowToTarget', 'borrowAmount']), + ), toToken: flashloanAmount.token, slippage: Percentage.createFrom({ value: args.slippage.value }), swapManager: dependencies.swapManager, - }) + }), }), isDebtSwapSkipped, ) @@ -134,19 +136,17 @@ export async function refinanceLendingToLendingAnyPair( amount: flashloanAmount, }, })) - .next( - async () => ({ - name: 'ReturnFunds', - type: SimulationSteps.ReturnFunds, - inputs: { - /* - * We swap back to the original position's debt in order to repay the flashloan. - * Therefore, the dust amount will be in the original position's debt - * */ - token: position.debtAmount.token, - }, - }), - ) + .next(async () => ({ + name: 'ReturnFunds', + type: SimulationSteps.ReturnFunds, + inputs: { + /* + * We swap back to the original position's debt in order to repay the flashloan. + * Therefore, the dust amount will be in the original position's debt + * */ + token: position.debtAmount.token, + }, + })) .next(async (ctx) => { // TODO: we should have a way to get the target position more easily and realiably, const targetPosition = Object.values(ctx.state.positions).find( @@ -183,7 +183,6 @@ export async function refinanceLendingToLendingAnyPair( } satisfies ISimulation } - /** * EstimateTokenAmountAfterSwap * @description Estimates how much you will recive after swap. @@ -198,7 +197,7 @@ async function estimateSwapFromAmount(params: { swapManager: ISwapManager }): Promise { const { receiveAtLeast, slippage } = params - + if (isSameTokens(receiveAtLeast.token, params.fromToken)) { return receiveAtLeast } @@ -211,7 +210,6 @@ async function estimateSwapFromAmount(params: { }) ).price - const summerFee = await params.swapManager.getSummerFee({ from: { token: receiveAtLeast.token }, to: { token: params.fromToken }, @@ -223,7 +221,10 @@ async function estimateSwapFromAmount(params: { SourceAmt = TargetAmt * SpotPrice * (1 + Slippage) / (1 - SummerFee) */ - const sourceAmount = params.receiveAtLeast.toBN().multipliedBy(spotPrice.toBN().times(ONE.plus(slippage.toProportion()))).div(ONE.minus(summerFee.toProportion())) + const sourceAmount = params.receiveAtLeast + .toBN() + .multipliedBy(spotPrice.toBN().times(ONE.plus(slippage.toProportion()))) + .div(ONE.minus(summerFee.toProportion())) return TokenAmount.createFrom({ amount: sourceAmount.toString(), From 54622b973fc047a5dfef0612259bced91f152f64 Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Mon, 22 Apr 2024 17:15:40 +0200 Subject: [PATCH 06/17] chore: lint --- sdk/sdk-common/src/common/implementation/TokenAmount.ts | 2 -- sdk/sdk-server/src/handlers/getSwapQuote.ts | 3 +++ .../refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/sdk-common/src/common/implementation/TokenAmount.ts b/sdk/sdk-common/src/common/implementation/TokenAmount.ts index 27e1a55212..be1d5afa74 100644 --- a/sdk/sdk-common/src/common/implementation/TokenAmount.ts +++ b/sdk/sdk-common/src/common/implementation/TokenAmount.ts @@ -3,8 +3,6 @@ import { Percentage } from './Percentage' import { Token } from './Token' import { SerializationService } from '../../services/SerializationService' import { ITokenAmount } from '../interfaces/ITokenAmount' -import { Price } from '.' -import { isSameTokens } from '..' /** * @class TokenAmount diff --git a/sdk/sdk-server/src/handlers/getSwapQuote.ts b/sdk/sdk-server/src/handlers/getSwapQuote.ts index 8da0d294ef..7b159533c4 100644 --- a/sdk/sdk-server/src/handlers/getSwapQuote.ts +++ b/sdk/sdk-server/src/handlers/getSwapQuote.ts @@ -2,6 +2,7 @@ import { z } from 'zod' import { ChainInfo, Token, TokenAmount } from '@summerfi/sdk-common/common' import { QuoteData } from '@summerfi/sdk-common/swap' import { publicProcedure } from '../TRPC' +import { Percentage } from '@summerfi/sdk-common' export const getSwapQuoteExactInput = publicProcedure .input( @@ -9,6 +10,7 @@ export const getSwapQuoteExactInput = publicProcedure chainInfo: z.custom((chainInfo) => chainInfo !== undefined), fromAmount: z.custom((tokenAmount) => tokenAmount !== undefined), toToken: z.custom((token) => token !== undefined), + slippage: z.custom((tokenAmount) => tokenAmount !== undefined), }), ) .query(async (opts): Promise => { @@ -16,5 +18,6 @@ export const getSwapQuoteExactInput = publicProcedure chainInfo: opts.input.chainInfo, fromAmount: opts.input.fromAmount, toToken: opts.input.toToken, + slippage: opts.input.slippage, }) }) diff --git a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts index 487a76e9e4..8d5dedd12a 100644 --- a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts +++ b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts @@ -1,4 +1,3 @@ -import { applyPercentage, subtractPercentage } from '@summerfi/sdk-common/utils' import { FlashloanProvider, ISimulation, From 7cbddc0cf8a96a1b1774c196ccd372626f5beae4 Mon Sep 17 00:00:00 2001 From: James Tuckett Date: Tue, 23 Apr 2024 12:25:18 +0100 Subject: [PATCH 07/17] fix: util import --- .../refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts index 8d5dedd12a..897d98dc05 100644 --- a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts +++ b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts @@ -15,7 +15,7 @@ import { refinanceLendingToLendingAnyPairStrategy } from './Strategy' import { type IRefinanceDependencies } from '../common/Types' import { getSwapStepData } from '../../implementation/utils/GetSwapStepData' import { ISwapManager } from '@summerfi/swap-common/interfaces' -import { isSameTokens } from '@summerfi/sdk-common' +import {isSameTokens} from "@summerfi/sdk-common/common"; import BigNumber from 'bignumber.js' export async function refinanceLendingToLendingAnyPair( From a199ad8164582e3af5785b49bb801a87a3bac7ff Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Tue, 23 Apr 2024 15:59:20 +0200 Subject: [PATCH 08/17] chore: apply requested chnages --- .../src/plugins/common/builders/SwapActionBuilder.ts | 2 +- sdk/sdk-common/src/common/implementation/Price.ts | 2 ++ sdk/sdk-common/src/simulation/Steps.ts | 2 +- sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts | 2 +- .../src/implementation/utils/GetSwapStepData.ts | 7 +------ 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/sdk/protocol-plugins/src/plugins/common/builders/SwapActionBuilder.ts b/sdk/protocol-plugins/src/plugins/common/builders/SwapActionBuilder.ts index d1cc8751d8..8cdd68cda9 100644 --- a/sdk/protocol-plugins/src/plugins/common/builders/SwapActionBuilder.ts +++ b/sdk/protocol-plugins/src/plugins/common/builders/SwapActionBuilder.ts @@ -11,7 +11,7 @@ export const SwapActionBuilder: ActionBuilder = async (params): const swapData = await swapManager.getSwapDataExactInput({ chainInfo: params.user.chainInfo, - fromAmount: step.inputs.swappedAmount, + fromAmount: step.inputs.amountAfterFee, toToken: step.inputs.toTokenAmount.token, recipient: Address.createFromEthereum({ value: swapContractInfo.address as HexData }), slippage: step.inputs.slippage, diff --git a/sdk/sdk-common/src/common/implementation/Price.ts b/sdk/sdk-common/src/common/implementation/Price.ts index f21db51df9..8742b936c2 100644 --- a/sdk/sdk-common/src/common/implementation/Price.ts +++ b/sdk/sdk-common/src/common/implementation/Price.ts @@ -10,6 +10,8 @@ import { isSameTokens } from '../utils/TokenUtils' * @class Price * @description Represents a price of a token (baseToken) in a given currency (quoteToken) * @description Base / Quote e.q. 2000 ETH / DAI + * @description The financial reprezentation (x ETH/DAI, Base/Quote) might be confusing as mathematically it is (x DAI/ETH, Quote/Base witch means x DAI per 1 ETH) + * @description x amount of quoted token for one unit of base token */ export class Price implements IPrice { readonly value: string diff --git a/sdk/sdk-common/src/simulation/Steps.ts b/sdk/sdk-common/src/simulation/Steps.ts index f277089c58..379a07a314 100644 --- a/sdk/sdk-common/src/simulation/Steps.ts +++ b/sdk/sdk-common/src/simulation/Steps.ts @@ -68,7 +68,7 @@ export interface SwapStep // Amount that will be send to our Swap service which then deducts our fee fromTokenAmount: TokenAmount // This amount has our fee already dedducted, and it will be send to exchange provider - swappedAmount: TokenAmount + amountAfterFee: TokenAmount toTokenAmount: TokenAmount slippage: Percentage summerFee: Percentage diff --git a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts index e2236688f8..7132928797 100644 --- a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts +++ b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts @@ -30,7 +30,7 @@ const SDKAPiUrl = 'https://nkllstfoy8.execute-api.us-east-1.amazonaws.com/api/sd const TenderlyForkUrl = 'https://virtual.mainnet.rpc.tenderly.co/7bebdd10-2878-4830-833d-aba2710f3dc0' -describe.only('Refinance Maker Spark | SDK', () => { +describe('Refinance Maker Spark | SDK', () => { it('should allow refinance Maker -> Spark with same pair', async () => { // SDK const sdk = makeSDK({ apiURL: SDKAPiUrl }) diff --git a/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts b/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts index c89468d832..204e044c46 100644 --- a/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts +++ b/sdk/simulator-service/src/implementation/utils/GetSwapStepData.ts @@ -23,11 +23,6 @@ export async function getSwapStepData(params: { const summerFeeAmount = applyPercentage(params.fromAmount, summerFee) const amountAfterSummerFee = params.fromAmount.subtract(summerFeeAmount) - // Deduct summer fee from fromAmount - // Call swapProvider with new amount - // at last we need to return from amount with summer fee - // - const [quote, spotPrice] = await Promise.all([ params.swapManager.getSwapQuoteExactInput({ chainInfo: params.chainInfo, @@ -45,7 +40,7 @@ export async function getSwapStepData(params: { return { ...quote, fromTokenAmount: params.fromAmount, - swappedAmount: amountAfterSummerFee, + amountAfterFee: amountAfterSummerFee, summerFee, spotPrice: spotPrice.price, slippage: params.slippage, From 890d607e82cba8eb680cacce72a5bb39320aa405 Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Tue, 23 Apr 2024 17:05:47 +0200 Subject: [PATCH 09/17] feat: register different flavours of refinance --- sdk/sdk-common/src/simulation/Enums.ts | 3 ++ .../tests/refinanceMakerSparkAnyPair.test.ts | 7 +++-- .../RefinanceLendingToLendingAnyPair.ts | 31 +++++++++++++++++-- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/sdk/sdk-common/src/simulation/Enums.ts b/sdk/sdk-common/src/simulation/Enums.ts index 01eaa98543..0d0f86674e 100644 --- a/sdk/sdk-common/src/simulation/Enums.ts +++ b/sdk/sdk-common/src/simulation/Enums.ts @@ -7,6 +7,9 @@ export enum SimulationType { Migrate = 'Migrate', CreatePosition = 'CreatePosition', Refinance = 'Refinance', + RefinanceDifferentPair = 'RefinanceDifPair', + RefinanceDifferentDebt = 'RefinanceDifDebt', + RefinanceDifferentCollateral = 'RefinanceDifCol', } export enum SimulationSteps { diff --git a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts index 7132928797..2ffab37d53 100644 --- a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts +++ b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts @@ -28,7 +28,7 @@ jest.setTimeout(300000) const SDKAPiUrl = 'https://nkllstfoy8.execute-api.us-east-1.amazonaws.com/api/sdk' const TenderlyForkUrl = - 'https://virtual.mainnet.rpc.tenderly.co/7bebdd10-2878-4830-833d-aba2710f3dc0' + 'https://virtual.mainnet.rpc.tenderly.co/8ffae4ec-575d-40a5-87d4-295669e8a24b' describe('Refinance Maker Spark | SDK', () => { it('should allow refinance Maker -> Spark with same pair', async () => { @@ -74,6 +74,9 @@ describe('Refinance Maker Spark | SDK', () => { const WBTC: Maybe = await chain.tokens.getTokenBySymbol({ symbol: TokenSymbol.WBTC }) assert(WBTC, 'WBTC not found') + const WSTETH: Maybe = await chain.tokens.getTokenBySymbol({ symbol: TokenSymbol.WSTETH }) + assert(WSTETH, 'WSTETH not found') + const maker = await chain.protocols.getProtocol({ name: ProtocolName.Maker }) assert(maker, 'Maker protocol not found') @@ -139,7 +142,7 @@ describe('Refinance Maker Spark | SDK', () => { assert(false, 'Spark pool type is not lending') } - const emptyTargetPosition = newEmptyPositionFromPool(sparkPool, USDC, WBTC) + const emptyTargetPosition = newEmptyPositionFromPool(sparkPool, DAI, WSTETH) const refinanceSimulation: ISimulation = await sdk.simulator.refinance.simulateRefinancePosition({ sourcePosition: makerPosition, diff --git a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts index 897d98dc05..1aa8ef4654 100644 --- a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts +++ b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts @@ -18,10 +18,16 @@ import { ISwapManager } from '@summerfi/swap-common/interfaces' import {isSameTokens} from "@summerfi/sdk-common/common"; import BigNumber from 'bignumber.js' +type RefinanceSimulationTypes = + | SimulationType.Refinance + | SimulationType.RefinanceDifferentPair + | SimulationType.RefinanceDifferentCollateral + | SimulationType.RefinanceDifferentDebt + export async function refinanceLendingToLendingAnyPair( args: IRefinanceParameters, dependencies: IRefinanceDependencies, -): Promise> { +): Promise> { // args validation if (!isLendingPool(args.targetPosition.pool)) { throw new Error('Target pool is not a lending pool') @@ -174,12 +180,31 @@ export async function refinanceLendingToLendingAnyPair( } return { - simulationType: SimulationType.Refinance, + simulationType: getSimulationType(!isCollateralSwapSkipped, !isDebtSwapSkipped), sourcePosition: position, targetPosition, swaps: Object.values(simulation.swaps), steps: Object.values(simulation.steps), - } satisfies ISimulation + } satisfies ISimulation +} + +function getSimulationType( + hasCollateralSwap: boolean, + hasDebtSwap: boolean, +): RefinanceSimulationTypes { + if (hasCollateralSwap && hasDebtSwap) { + return SimulationType.RefinanceDifferentPair + } + + if (hasCollateralSwap) { + return SimulationType.RefinanceDifferentCollateral + } + + if (hasDebtSwap) { + return SimulationType.RefinanceDifferentDebt + } + + return SimulationType.Refinance } /** From ab8b72960d8525f656a4be3aad101f714716204d Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Tue, 23 Apr 2024 17:07:48 +0200 Subject: [PATCH 10/17] chore: skip test --- sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts index 2ffab37d53..e36de762a6 100644 --- a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts +++ b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts @@ -30,7 +30,7 @@ const SDKAPiUrl = 'https://nkllstfoy8.execute-api.us-east-1.amazonaws.com/api/sd const TenderlyForkUrl = 'https://virtual.mainnet.rpc.tenderly.co/8ffae4ec-575d-40a5-87d4-295669e8a24b' -describe('Refinance Maker Spark | SDK', () => { +describe.skip('Refinance Maker Spark | SDK', () => { it('should allow refinance Maker -> Spark with same pair', async () => { // SDK const sdk = makeSDK({ apiURL: SDKAPiUrl }) From f42490de072a3f6347b052a046688fe16ab3cba8 Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Tue, 23 Apr 2024 17:16:48 +0200 Subject: [PATCH 11/17] chore: lint fix --- sdk/sdk-server/src/handlers/getRefinanceSimulation.ts | 3 ++- .../RefinanceLendingToLendingAnyPair.ts | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sdk/sdk-server/src/handlers/getRefinanceSimulation.ts b/sdk/sdk-server/src/handlers/getRefinanceSimulation.ts index bd21be09a3..005167ef29 100644 --- a/sdk/sdk-server/src/handlers/getRefinanceSimulation.ts +++ b/sdk/sdk-server/src/handlers/getRefinanceSimulation.ts @@ -4,6 +4,7 @@ import { refinanceLendingToLendingSamePair, type IRefinanceDependencies, refinanceLendingToLendingAnyPair, + RefinanceSimulationTypes, } from '@summerfi/simulator-service/strategies' import type { IRefinanceParameters } from '@summerfi/sdk-common/orders' import { publicProcedure } from '../TRPC' @@ -26,7 +27,7 @@ function isToSamePair(parameters: IRefinanceParameters): boolean { export const getRefinanceSimulation = publicProcedure .input(inputSchema) - .query(async (opts): Promise> => { + .query(async (opts): Promise> => { const args: IRefinanceParameters = opts.input const dependencies: IRefinanceDependencies = { diff --git a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts index 1aa8ef4654..834520e5c0 100644 --- a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts +++ b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts @@ -15,13 +15,13 @@ import { refinanceLendingToLendingAnyPairStrategy } from './Strategy' import { type IRefinanceDependencies } from '../common/Types' import { getSwapStepData } from '../../implementation/utils/GetSwapStepData' import { ISwapManager } from '@summerfi/swap-common/interfaces' -import {isSameTokens} from "@summerfi/sdk-common/common"; +import { isSameTokens } from '@summerfi/sdk-common/common' import BigNumber from 'bignumber.js' -type RefinanceSimulationTypes = - | SimulationType.Refinance - | SimulationType.RefinanceDifferentPair - | SimulationType.RefinanceDifferentCollateral +export type RefinanceSimulationTypes = + | SimulationType.Refinance + | SimulationType.RefinanceDifferentPair + | SimulationType.RefinanceDifferentCollateral | SimulationType.RefinanceDifferentDebt export async function refinanceLendingToLendingAnyPair( From c0e97f3eb2d75d983c33c36aa502e9a91b1f6d8b Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Tue, 23 Apr 2024 17:41:24 +0200 Subject: [PATCH 12/17] chore: move refinance union type to common --- .../simulations/RefinanceSimulationManager.ts | 4 ++-- sdk/sdk-common/src/simulation/Enums.ts | 6 ++++++ sdk/sdk-server/src/handlers/getRefinanceSimulation.ts | 3 +-- .../refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts | 7 +------ 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sdk/sdk-client/src/implementation/simulations/RefinanceSimulationManager.ts b/sdk/sdk-client/src/implementation/simulations/RefinanceSimulationManager.ts index 3ca16e3e96..62f5e7eeb4 100644 --- a/sdk/sdk-client/src/implementation/simulations/RefinanceSimulationManager.ts +++ b/sdk/sdk-client/src/implementation/simulations/RefinanceSimulationManager.ts @@ -1,5 +1,5 @@ import { IRefinanceParameters } from '@summerfi/sdk-common/orders' -import { ISimulation, SimulationType } from '@summerfi/sdk-common/simulation' +import { ISimulation, RefinanceSimulationTypes } from '@summerfi/sdk-common/simulation' import { RPCClientType } from '../../rpc/SDKClient' import { IRPCClient } from '../../interfaces/IRPCClient' @@ -10,7 +10,7 @@ export class RefinanceSimulationManager extends IRPCClient { public async simulateRefinancePosition( params: IRefinanceParameters, - ): Promise> { + ): Promise> { const refinanceParameters: IRefinanceParameters = { sourcePosition: { type: params.sourcePosition.type, diff --git a/sdk/sdk-common/src/simulation/Enums.ts b/sdk/sdk-common/src/simulation/Enums.ts index 0d0f86674e..56149450e9 100644 --- a/sdk/sdk-common/src/simulation/Enums.ts +++ b/sdk/sdk-common/src/simulation/Enums.ts @@ -33,3 +33,9 @@ export enum TokenTransferTargetType { PositionsManager = 1, StrategyExecutor = 0, } + +export type RefinanceSimulationTypes = + | SimulationType.Refinance + | SimulationType.RefinanceDifferentPair + | SimulationType.RefinanceDifferentCollateral + | SimulationType.RefinanceDifferentDebt diff --git a/sdk/sdk-server/src/handlers/getRefinanceSimulation.ts b/sdk/sdk-server/src/handlers/getRefinanceSimulation.ts index 005167ef29..0076f18402 100644 --- a/sdk/sdk-server/src/handlers/getRefinanceSimulation.ts +++ b/sdk/sdk-server/src/handlers/getRefinanceSimulation.ts @@ -1,10 +1,9 @@ import { z } from 'zod' -import type { ISimulation, SimulationType } from '@summerfi/sdk-common/simulation' +import type { ISimulation, RefinanceSimulationTypes } from '@summerfi/sdk-common/simulation' import { refinanceLendingToLendingSamePair, type IRefinanceDependencies, refinanceLendingToLendingAnyPair, - RefinanceSimulationTypes, } from '@summerfi/simulator-service/strategies' import type { IRefinanceParameters } from '@summerfi/sdk-common/orders' import { publicProcedure } from '../TRPC' diff --git a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts index 834520e5c0..2dfe8d1ed4 100644 --- a/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts +++ b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts @@ -1,6 +1,7 @@ import { FlashloanProvider, ISimulation, + RefinanceSimulationTypes, SimulationSteps, SimulationType, TokenTransferTargetType, @@ -18,12 +19,6 @@ import { ISwapManager } from '@summerfi/swap-common/interfaces' import { isSameTokens } from '@summerfi/sdk-common/common' import BigNumber from 'bignumber.js' -export type RefinanceSimulationTypes = - | SimulationType.Refinance - | SimulationType.RefinanceDifferentPair - | SimulationType.RefinanceDifferentCollateral - | SimulationType.RefinanceDifferentDebt - export async function refinanceLendingToLendingAnyPair( args: IRefinanceParameters, dependencies: IRefinanceDependencies, From bf2a331cd969abefd090c6c651be63174875c87b Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Tue, 23 Apr 2024 17:54:44 +0200 Subject: [PATCH 13/17] fix: types --- sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts index e36de762a6..c0f9c2f1c2 100644 --- a/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts +++ b/sdk/sdk-e2e/tests/refinanceMakerSparkAnyPair.test.ts @@ -15,7 +15,7 @@ import { ProtocolName, isLendingPool } from '@summerfi/sdk-common/protocols' import { makeSDK, type Chain, type User, Protocol } from '@summerfi/sdk-client' import { TokenSymbol } from '@summerfi/sdk-common/common/enums' import { IPositionsManager, IRefinanceParameters, Order } from '@summerfi/sdk-common/orders' -import { ISimulation, SimulationType } from '@summerfi/sdk-common/simulation' +import { ISimulation } from '@summerfi/sdk-common/simulation' import { TransactionUtils } from './utils/TransactionUtils' import { Hex } from 'viem' @@ -23,6 +23,7 @@ import assert from 'assert' import { EmodeType } from '@summerfi/protocol-plugins/plugins/common' import { ILKType, MakerPoolId } from '@summerfi/protocol-plugins/plugins/maker' import { SparkPoolId, isSparkPoolId } from '@summerfi/protocol-plugins/plugins/spark' +import { RefinanceSimulationTypes } from '@summerfi/sdk-common' jest.setTimeout(300000) @@ -143,7 +144,7 @@ describe.skip('Refinance Maker Spark | SDK', () => { } const emptyTargetPosition = newEmptyPositionFromPool(sparkPool, DAI, WSTETH) - const refinanceSimulation: ISimulation = + const refinanceSimulation: ISimulation = await sdk.simulator.refinance.simulateRefinancePosition({ sourcePosition: makerPosition, targetPosition: emptyTargetPosition, From b35c9c31f4d6af96327a5454cd5a269565235aa1 Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Tue, 23 Apr 2024 18:03:08 +0200 Subject: [PATCH 14/17] fix types --- sdk/simulator-service/tests/simulator.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/simulator-service/tests/simulator.test.ts b/sdk/simulator-service/tests/simulator.test.ts index 05ec078b2b..eb9b743e38 100644 --- a/sdk/simulator-service/tests/simulator.test.ts +++ b/sdk/simulator-service/tests/simulator.test.ts @@ -1,7 +1,6 @@ import { ISimulation, SimulationSteps, - SimulationType, steps, } from '@summerfi/sdk-common/simulation' import { @@ -18,10 +17,11 @@ import { } from './mocks/testSourcePosition' import { mockRefinanceContext, mockRefinanceContextRequiredSwaps } from './mocks/contextMock' import assert from 'assert' +import { RefinanceSimulationTypes } from '@summerfi/sdk-common' describe('Refinance', () => { describe('to the position with the same collateral and debt (no swaps)', () => { - let simulation: ISimulation + let simulation: ISimulation beforeAll(async () => { simulation = await refinanceLendingToLendingSamePair( { @@ -83,7 +83,7 @@ describe('Refinance', () => { }) describe('to the position with the different collateral and debt (with swaps)', () => { - let simulation: ISimulation + let simulation: ISimulation beforeAll(async () => { simulation = await refinanceLendingToLendingAnyPair( { From 44b72624e4274f3d8d51f4b0d682e878d3a7d473 Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Tue, 23 Apr 2024 18:10:23 +0200 Subject: [PATCH 15/17] fix: types --- sdk/sdk-e2e/tests/refinanceMakerSparkAlreadyImported.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sdk/sdk-e2e/tests/refinanceMakerSparkAlreadyImported.test.ts b/sdk/sdk-e2e/tests/refinanceMakerSparkAlreadyImported.test.ts index 1e0186d8e4..4ffba45f08 100644 --- a/sdk/sdk-e2e/tests/refinanceMakerSparkAlreadyImported.test.ts +++ b/sdk/sdk-e2e/tests/refinanceMakerSparkAlreadyImported.test.ts @@ -16,7 +16,7 @@ import { ProtocolName, isLendingPool } from '@summerfi/sdk-common/protocols' import { makeSDK, type Chain, type User, Protocol } from '@summerfi/sdk-client' import { TokenSymbol } from '@summerfi/sdk-common/common/enums' import { IPositionsManager, IRefinanceParameters, Order } from '@summerfi/sdk-common/orders' -import { ISimulation, SimulationType } from '@summerfi/sdk-common/simulation' +import { ISimulation } from '@summerfi/sdk-common/simulation' import { TransactionUtils } from './utils/TransactionUtils' import { decodeActionCalldata, @@ -47,6 +47,7 @@ import { SparkPoolId, isSparkPoolId, } from '@summerfi/protocol-plugins/plugins/spark' +import { RefinanceSimulationTypes } from '@summerfi/sdk-common' jest.setTimeout(300000) @@ -171,7 +172,7 @@ describe.skip('Refinance Maker Spark | SDK', () => { makerPosition.debtAmount.token, makerPosition.collateralAmount.token, ) - const refinanceSimulation: ISimulation = + const refinanceSimulation: ISimulation = await sdk.simulator.refinance.simulateRefinancePosition({ sourcePosition: makerPosition, targetPosition: emptyTargetPosition, From 6774a6ed6928c51e9067b421ee7250b67605a35b Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Tue, 23 Apr 2024 18:16:38 +0200 Subject: [PATCH 16/17] format --- sdk/simulator-service/tests/simulator.test.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sdk/simulator-service/tests/simulator.test.ts b/sdk/simulator-service/tests/simulator.test.ts index eb9b743e38..0628f238f7 100644 --- a/sdk/simulator-service/tests/simulator.test.ts +++ b/sdk/simulator-service/tests/simulator.test.ts @@ -1,8 +1,4 @@ -import { - ISimulation, - SimulationSteps, - steps, -} from '@summerfi/sdk-common/simulation' +import { ISimulation, SimulationSteps, steps } from '@summerfi/sdk-common/simulation' import { refinanceLendingToLendingAnyPair, refinanceLendingToLendingSamePair, From 3833a3c71466f3329c7c77cff331972540f5137e Mon Sep 17 00:00:00 2001 From: Damian Paszkowski Date: Wed, 24 Apr 2024 12:03:14 +0200 Subject: [PATCH 17/17] fix: typo --- sdk/sdk-common/src/common/implementation/Price.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/sdk-common/src/common/implementation/Price.ts b/sdk/sdk-common/src/common/implementation/Price.ts index 8742b936c2..612d90c178 100644 --- a/sdk/sdk-common/src/common/implementation/Price.ts +++ b/sdk/sdk-common/src/common/implementation/Price.ts @@ -10,7 +10,7 @@ import { isSameTokens } from '../utils/TokenUtils' * @class Price * @description Represents a price of a token (baseToken) in a given currency (quoteToken) * @description Base / Quote e.q. 2000 ETH / DAI - * @description The financial reprezentation (x ETH/DAI, Base/Quote) might be confusing as mathematically it is (x DAI/ETH, Quote/Base witch means x DAI per 1 ETH) + * @description The financial representation (x ETH/DAI, Base/Quote) might be confusing as mathematically it is (x DAI/ETH, Quote/Base which means x DAI per 1 ETH) * @description x amount of quoted token for one unit of base token */ export class Price implements IPrice {