From 86703fedcddfe683b3ef9cdd3c1a95fd7405101a Mon Sep 17 00:00:00 2001 From: Roberto Cano <3525807+robercano@users.noreply.github.com> Date: Thu, 4 Apr 2024 18:28:00 +0200 Subject: [PATCH] feat: add position created to refinance simulator (#154) --- package.json | 2 +- .../src/config/Config.ts | 2 + .../tests/utils/MakerSourcePosition.ts | 4 +- .../tests/utils/SparkTargetPosition.ts | 4 +- .../tests/ExecutionStorageMapper.spec.ts | 4 +- .../tests/StepBuilderContext.spec.ts | 4 +- .../common/actions/PositionCreatedAction.ts | 27 ++++ .../src/plugins/common/actions/index.ts | 1 + .../builders/PositionCreatedActionBuilder.ts | 19 +++ .../src/plugins/common/builders/index.ts | 1 + .../src/plugins/maker/types/MakerPoolId.ts | 8 +- .../actions/PositionCreatedAction.spec.ts | 96 ++++++++++++++ .../DepositBorrowActionBuilder.spec.ts | 4 +- .../PaybackWithdrawActionBuilder.spec.ts | 4 +- .../simulations/RefinanceSimulationManager.ts | 1 + .../tests/queries/newOrder.subtest.ts | 3 + .../queries/simulateRefinance.subtest.ts | 3 + .../src/common/enums/PositionType.ts | 4 + sdk/sdk-common/src/common/enums/index.ts | 1 + .../src/common/implementation/Position.ts | 5 +- .../src/common/interfaces/IPosition.ts | 2 + .../src/common/utils/PositionUtils.ts | 16 ++- sdk/sdk-common/src/simulation/Enums.ts | 1 + sdk/sdk-common/src/simulation/Steps.ts | 9 ++ sdk/sdk-e2e/tests/refinanceMakerSpark.test.ts | 26 +++- .../src/handlers/getRefinanceSimulation.ts | 4 +- .../reducer/newPositionEventReducer.ts | 15 +++ .../simulator-engine/reducer/stateReducers.ts | 2 + .../stepProcessor/newPositionEvent.ts | 11 ++ .../stepProcessor/stepOutputProcessors.ts | 2 + .../src/implementation/utils/BalanceUtils.ts | 15 +-- .../src/interfaces/simulation.ts | 12 +- .../strategies/{refinance => common}/Types.ts | 0 .../src/strategies/common/index.ts | 1 + sdk/simulator-service/src/strategies/index.ts | 4 +- .../src/strategies/refinance/index.ts | 3 - .../RefinanceLendingToLendingAnyPair.ts} | 25 +++- .../Strategy.ts | 6 +- .../src/strategies/refinanceAnyPair/index.ts | 2 + .../RefinanceLendingToLendingSamePair.ts | 120 ++++++++++++++++++ .../strategies/refinanceSamePair/Strategy.ts | 25 ++++ .../src/strategies/refinanceSamePair/index.ts | 2 + sdk/simulator-service/src/types/Types.ts | 10 ++ sdk/simulator-service/tests/simulator.test.ts | 26 +++- .../oneinch/OneInchSwapProvider.ts | 2 +- turbo.json | 5 +- 46 files changed, 488 insertions(+), 55 deletions(-) create mode 100644 sdk/protocol-plugins/src/plugins/common/actions/PositionCreatedAction.ts create mode 100644 sdk/protocol-plugins/src/plugins/common/builders/PositionCreatedActionBuilder.ts create mode 100644 sdk/protocol-plugins/tests/actions/PositionCreatedAction.spec.ts create mode 100644 sdk/sdk-common/src/common/enums/PositionType.ts create mode 100644 sdk/simulator-service/src/implementation/simulator-engine/reducer/newPositionEventReducer.ts create mode 100644 sdk/simulator-service/src/implementation/simulator-engine/stepProcessor/newPositionEvent.ts rename sdk/simulator-service/src/strategies/{refinance => common}/Types.ts (100%) create mode 100644 sdk/simulator-service/src/strategies/common/index.ts delete mode 100644 sdk/simulator-service/src/strategies/refinance/index.ts rename sdk/simulator-service/src/strategies/{refinance/RefinanceLendingToLending.ts => refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts} (87%) rename sdk/simulator-service/src/strategies/{refinance => refinanceAnyPair}/Strategy.ts (84%) create mode 100644 sdk/simulator-service/src/strategies/refinanceAnyPair/index.ts create mode 100644 sdk/simulator-service/src/strategies/refinanceSamePair/RefinanceLendingToLendingSamePair.ts create mode 100644 sdk/simulator-service/src/strategies/refinanceSamePair/Strategy.ts create mode 100644 sdk/simulator-service/src/strategies/refinanceSamePair/index.ts create mode 100644 sdk/simulator-service/src/types/Types.ts diff --git a/package.json b/package.json index b0735fbb73..5975cee78f 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "test": "turbo run test --cache-dir=.turbo", "test:integration": "turbo run test:integration --cache-dir=.turbo", "check-circular": "turbo run check-circular --cache-dir=.turbo", - "cicheck": "turbo run cicheck --cache-dir=.turbo && pnpm format", + "cicheck": "turbo run cicheck --cache-dir=.turbo", "sst:dev": "sst dev", "sst:build": "sst build", "sst:deploy:staging": "sst deploy --stage staging", diff --git a/sdk/order-planner-service/src/config/Config.ts b/sdk/order-planner-service/src/config/Config.ts index d27177a395..03657eb3cc 100644 --- a/sdk/order-planner-service/src/config/Config.ts +++ b/sdk/order-planner-service/src/config/Config.ts @@ -4,6 +4,7 @@ import { DepositBorrowActionBuilder, FlashloanActionBuilder, PaybackWithdrawActionBuilder, + PositionCreatedActionBuilder, PullTokenActionBuilder, RepayFlashloanActionBuilder, ReturnFundsActionBuilder, @@ -18,4 +19,5 @@ export const ActionBuildersConfig: ActionBuildersMap = { [SimulationSteps.DepositBorrow]: DepositBorrowActionBuilder, [SimulationSteps.PaybackWithdraw]: PaybackWithdrawActionBuilder, [SimulationSteps.ReturnFunds]: ReturnFundsActionBuilder, + [SimulationSteps.NewPositionEvent]: PositionCreatedActionBuilder, } diff --git a/sdk/order-planner-service/tests/utils/MakerSourcePosition.ts b/sdk/order-planner-service/tests/utils/MakerSourcePosition.ts index ddc14574fa..54d3d932a2 100644 --- a/sdk/order-planner-service/tests/utils/MakerSourcePosition.ts +++ b/sdk/order-planner-service/tests/utils/MakerSourcePosition.ts @@ -9,6 +9,7 @@ import { } from '@summerfi/sdk-common/common' import { PoolType, ProtocolName } from '@summerfi/sdk-common/protocols' import { ILKType, MakerPoolId } from '@summerfi/protocol-plugins/plugins/maker' +import { PositionType } from '@summerfi/sdk-common/common' export function getMakerPosition(): Position { const chainInfo: ChainInfo = ChainFamilyMap.Ethereum.Mainnet @@ -56,7 +57,8 @@ export function getMakerPosition(): Position { poolId, } - const position = new Position({ + const position = Position.createFrom({ + type: PositionType.Multiply, positionId: PositionId.createFrom({ id: 'makerPosition' }), debtAmount, collateralAmount, diff --git a/sdk/order-planner-service/tests/utils/SparkTargetPosition.ts b/sdk/order-planner-service/tests/utils/SparkTargetPosition.ts index 0fbb9d068c..c46d5c3ed1 100644 --- a/sdk/order-planner-service/tests/utils/SparkTargetPosition.ts +++ b/sdk/order-planner-service/tests/utils/SparkTargetPosition.ts @@ -6,6 +6,7 @@ import { ChainInfo, Position, PositionId, + PositionType, Token, TokenAmount, } from '@summerfi/sdk-common/common' @@ -56,7 +57,8 @@ export function getSparkPosition(): Position { poolId, } - const position = new Position({ + const position = Position.createFrom({ + type: PositionType.Multiply, positionId: PositionId.createFrom({ id: 'sparkPosition' }), debtAmount, collateralAmount, diff --git a/sdk/protocol-plugins-common/tests/ExecutionStorageMapper.spec.ts b/sdk/protocol-plugins-common/tests/ExecutionStorageMapper.spec.ts index 56d2650e69..2d3a85ed2b 100644 --- a/sdk/protocol-plugins-common/tests/ExecutionStorageMapper.spec.ts +++ b/sdk/protocol-plugins-common/tests/ExecutionStorageMapper.spec.ts @@ -6,6 +6,7 @@ import { ChainInfo, Position, PositionId, + PositionType, Token, TokenAmount, } from '@summerfi/sdk-common/common' @@ -78,7 +79,8 @@ describe('Execution Storage Mapper', () => { poolId, } - const position = new Position({ + const position = Position.createFrom({ + type: PositionType.Multiply, positionId: PositionId.createFrom({ id: 'someposition' }), debtAmount: borrowAmount, collateralAmount: depositAmount, diff --git a/sdk/protocol-plugins-common/tests/StepBuilderContext.spec.ts b/sdk/protocol-plugins-common/tests/StepBuilderContext.spec.ts index 5aab163057..16d3364e1b 100644 --- a/sdk/protocol-plugins-common/tests/StepBuilderContext.spec.ts +++ b/sdk/protocol-plugins-common/tests/StepBuilderContext.spec.ts @@ -4,6 +4,7 @@ import { ChainInfo, Position, PositionId, + PositionType, Token, TokenAmount, } from '@summerfi/sdk-common/common' @@ -87,7 +88,8 @@ describe('Step Builder Context', () => { poolId, } - const position = new Position({ + const position = Position.createFrom({ + type: PositionType.Multiply, positionId: PositionId.createFrom({ id: 'someposition' }), debtAmount: borrowAmount, collateralAmount: depositAmount, diff --git a/sdk/protocol-plugins/src/plugins/common/actions/PositionCreatedAction.ts b/sdk/protocol-plugins/src/plugins/common/actions/PositionCreatedAction.ts new file mode 100644 index 0000000000..7d10271d3f --- /dev/null +++ b/sdk/protocol-plugins/src/plugins/common/actions/PositionCreatedAction.ts @@ -0,0 +1,27 @@ +import { ActionCall, BaseAction, InputSlotsMapping } from '@summerfi/protocol-plugins-common' +import { Position } from '@summerfi/sdk-common/common' + +export class PositionCreatedAction extends BaseAction { + public readonly config = { + name: 'PositionCreated', + version: 0, + parametersAbi: + '(string protocol, string positionType, address collateralToken, address debtToken)', + storageInputs: [], + storageOutputs: [], + } as const + + public encodeCall(params: { position: Position }, paramsMapping?: InputSlotsMapping): ActionCall { + return this._encodeCall({ + arguments: [ + { + protocol: params.position.pool.protocol.name, + positionType: params.position.type, + collateralToken: params.position.collateralAmount.token.address.value, + debtToken: params.position.debtAmount.token.address.value, + }, + ], + mapping: paramsMapping, + }) + } +} diff --git a/sdk/protocol-plugins/src/plugins/common/actions/index.ts b/sdk/protocol-plugins/src/plugins/common/actions/index.ts index 31831ac2eb..d996f9a68b 100644 --- a/sdk/protocol-plugins/src/plugins/common/actions/index.ts +++ b/sdk/protocol-plugins/src/plugins/common/actions/index.ts @@ -4,3 +4,4 @@ export { ReturnFundsAction } from './ReturnFundsAction' export { SendTokenAction } from './SendTokenAction' export { SetApprovalAction } from './SetApprovalAction' export { SwapAction } from './SwapAction' +export { PositionCreatedAction } from './PositionCreatedAction' diff --git a/sdk/protocol-plugins/src/plugins/common/builders/PositionCreatedActionBuilder.ts b/sdk/protocol-plugins/src/plugins/common/builders/PositionCreatedActionBuilder.ts new file mode 100644 index 0000000000..5505dafbfc --- /dev/null +++ b/sdk/protocol-plugins/src/plugins/common/builders/PositionCreatedActionBuilder.ts @@ -0,0 +1,19 @@ +import { steps } from '@summerfi/sdk-common/simulation' +import { ActionBuilder } from '@summerfi/protocol-plugins-common' +import { PositionCreatedAction } from '../actions/PositionCreatedAction' + +export const PositionCreatedActionBuilder: ActionBuilder = async ( + params, +): Promise => { + const { context, step } = params + + context.addActionCall({ + step: step, + action: new PositionCreatedAction(), + arguments: { + position: step.inputs.position, + }, + connectedInputs: {}, + connectedOutputs: {}, + }) +} diff --git a/sdk/protocol-plugins/src/plugins/common/builders/index.ts b/sdk/protocol-plugins/src/plugins/common/builders/index.ts index 7667aca905..e2d8f5d9bc 100644 --- a/sdk/protocol-plugins/src/plugins/common/builders/index.ts +++ b/sdk/protocol-plugins/src/plugins/common/builders/index.ts @@ -9,3 +9,4 @@ export { } from './RepayFlashloanActionBuilder' export { ReturnFundsActionBuilder } from './ReturnFundsActionBuilder' export { SwapActionBuilder } from './SwapActionBuilder' +export { PositionCreatedActionBuilder } from './PositionCreatedActionBuilder' diff --git a/sdk/protocol-plugins/src/plugins/maker/types/MakerPoolId.ts b/sdk/protocol-plugins/src/plugins/maker/types/MakerPoolId.ts index 44dd35b377..2220ec6d28 100644 --- a/sdk/protocol-plugins/src/plugins/maker/types/MakerPoolId.ts +++ b/sdk/protocol-plugins/src/plugins/maker/types/MakerPoolId.ts @@ -1,12 +1,8 @@ -import { ChainInfo } from '@summerfi/sdk-common/common' -import { IPoolId, ProtocolName, isPoolId } from '@summerfi/sdk-common/protocols' +import { IPoolId, IProtocol, ProtocolName, isPoolId } from '@summerfi/sdk-common/protocols' import { ILKType } from '../enums/ILKType' export interface MakerPoolId extends IPoolId { - protocol: { - name: ProtocolName.Maker - chainInfo: ChainInfo - } + protocol: IProtocol ilkType: ILKType // TODO: vaultId does not belong in the poolId vaultId: string diff --git a/sdk/protocol-plugins/tests/actions/PositionCreatedAction.spec.ts b/sdk/protocol-plugins/tests/actions/PositionCreatedAction.spec.ts new file mode 100644 index 0000000000..5e2e6a6b98 --- /dev/null +++ b/sdk/protocol-plugins/tests/actions/PositionCreatedAction.spec.ts @@ -0,0 +1,96 @@ +import { Address, Position, Token, TokenAmount, PositionType } from '@summerfi/sdk-common/common' +import { decodeActionCalldata, getTargetHash } from '@summerfi/testing-utils' +import { PositionCreatedAction } from '../../src/plugins/common/actions/PositionCreatedAction' +import { IProtocol, PoolType, ProtocolName } from '@summerfi/sdk-common/protocols' +import { MakerPoolId } from '../../src/plugins/maker/types/MakerPoolId' +import { ILKType } from '../../src/plugins/maker' + +describe('PositionCreated Action', () => { + const action = new PositionCreatedAction() + const contractNameWithVersion = `${action.config.name}` + + const DAI = Token.createFrom({ + chainInfo: { + name: 'Mainnet', + chainId: 1, + }, + address: Address.createFromEthereum({ value: '0x6B175474E89094C44Da98b954EedeAC495271d0F' }), + decimals: 18, + name: 'Dai Stablecoin', + symbol: 'DAI', + }) + + const WETH = Token.createFrom({ + chainInfo: { + name: 'Mainnet', + chainId: 1, + }, + address: Address.createFromEthereum({ value: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' }), + decimals: 18, + name: 'Wrapped Ether', + symbol: 'WETH', + }) + + const protocol: IProtocol = { + name: ProtocolName.Spark, + chainInfo: { + name: 'Mainnet', + chainId: 1, + }, + } + + const position = Position.createFrom({ + type: PositionType.Multiply, + positionId: { + id: '0x123', + }, + pool: { + type: PoolType.Lending, + protocol: protocol, + poolId: { + protocol: protocol, + vaultId: '0x123', + ilkType: ILKType.ETH_A, + } as MakerPoolId, + }, + debtAmount: TokenAmount.createFrom({ + token: DAI, + amount: '100', + }), + collateralAmount: TokenAmount.createFrom({ + token: WETH, + amount: '100', + }), + }) + + it('should return the versioned name', () => { + expect(action.getVersionedName()).toBe(contractNameWithVersion) + }) + + it('should encode calls', async () => { + const call = action.encodeCall( + { + position: position, + }, + [8, 9, 1, 3], + ) + + expect(call.targetHash).toBe(getTargetHash(action)) + + const actionDecodedArgs = decodeActionCalldata({ + action, + calldata: call.callData, + }) + + expect(actionDecodedArgs).toBeDefined() + expect(actionDecodedArgs?.args).toEqual([ + { + protocol: protocol.name, + positionType: position.type, + collateralToken: WETH.address.value, + debtToken: DAI.address.value, + }, + ]) + expect(actionDecodedArgs?.mapping).toEqual([8, 9, 1, 3]) + }) +}) diff --git a/sdk/protocol-plugins/tests/builders/DepositBorrowActionBuilder.spec.ts b/sdk/protocol-plugins/tests/builders/DepositBorrowActionBuilder.spec.ts index d5c68613b9..fa6b846340 100644 --- a/sdk/protocol-plugins/tests/builders/DepositBorrowActionBuilder.spec.ts +++ b/sdk/protocol-plugins/tests/builders/DepositBorrowActionBuilder.spec.ts @@ -4,6 +4,7 @@ import { ChainInfo, Position, PositionId, + PositionType, Token, TokenAmount, } from '@summerfi/sdk-common/common' @@ -65,7 +66,8 @@ describe('Deposit Borrow Action Builder', () => { poolId, } - const position = new Position({ + const position = Position.createFrom({ + type: PositionType.Multiply, positionId: PositionId.createFrom({ id: 'someposition' }), debtAmount: borrowAmount, collateralAmount: depositAmount, diff --git a/sdk/protocol-plugins/tests/builders/PaybackWithdrawActionBuilder.spec.ts b/sdk/protocol-plugins/tests/builders/PaybackWithdrawActionBuilder.spec.ts index 341323a109..afe11cdb6e 100644 --- a/sdk/protocol-plugins/tests/builders/PaybackWithdrawActionBuilder.spec.ts +++ b/sdk/protocol-plugins/tests/builders/PaybackWithdrawActionBuilder.spec.ts @@ -4,6 +4,7 @@ import { ChainInfo, Position, PositionId, + PositionType, Token, TokenAmount, } from '@summerfi/sdk-common/common' @@ -65,7 +66,8 @@ describe('Payback Withdraw Action Builder', () => { poolId, } - const position = new Position({ + const position = Position.createFrom({ + type: PositionType.Multiply, positionId: PositionId.createFrom({ id: 'someposition' }), debtAmount: withdrawAmount, collateralAmount: paybackAmount, diff --git a/sdk/sdk-client/src/implementation/simulations/RefinanceSimulationManager.ts b/sdk/sdk-client/src/implementation/simulations/RefinanceSimulationManager.ts index c81f61c734..f35e014f39 100644 --- a/sdk/sdk-client/src/implementation/simulations/RefinanceSimulationManager.ts +++ b/sdk/sdk-client/src/implementation/simulations/RefinanceSimulationManager.ts @@ -13,6 +13,7 @@ export class RefinanceSimulationManager extends IRPCClient { ): Promise> { const refinanceParameters: IRefinanceParameters = { position: { + type: params.position.type, positionId: params.position.positionId, debtAmount: params.position.debtAmount, collateralAmount: params.position.collateralAmount, diff --git a/sdk/sdk-client/tests/queries/newOrder.subtest.ts b/sdk/sdk-client/tests/queries/newOrder.subtest.ts index 61a147a1a3..8132bc43ff 100644 --- a/sdk/sdk-client/tests/queries/newOrder.subtest.ts +++ b/sdk/sdk-client/tests/queries/newOrder.subtest.ts @@ -12,6 +12,7 @@ import { Percentage, Position, PositionId, + PositionType, RiskRatio, Token, TokenAmount, @@ -56,6 +57,7 @@ export default async function simulateNewOrder() { } as MakerLendingPool const prevPosition: Position = { + type: PositionType.Multiply, pool: pool, debtAmount: TokenAmount.createFrom({ token: DAI, amount: '56.78' }), collateralAmount: TokenAmount.createFrom({ token: WETH, amount: '105.98' }), @@ -82,6 +84,7 @@ export default async function simulateNewOrder() { sourcePosition: prevPosition, swaps: [], targetPosition: { + type: PositionType.Multiply, positionId: PositionId.createFrom({ id: '1234567890' }), debtAmount: TokenAmount.createFrom({ token: DAI, amount: '56.78' }), collateralAmount: TokenAmount.createFrom({ token: WETH, amount: '105.98' }), diff --git a/sdk/sdk-client/tests/queries/simulateRefinance.subtest.ts b/sdk/sdk-client/tests/queries/simulateRefinance.subtest.ts index 5dc1f70ebc..53771e63cf 100644 --- a/sdk/sdk-client/tests/queries/simulateRefinance.subtest.ts +++ b/sdk/sdk-client/tests/queries/simulateRefinance.subtest.ts @@ -11,6 +11,7 @@ import { Percentage, Position, PositionId, + PositionType, RiskRatio, Token, TokenAmount, @@ -25,6 +26,7 @@ export default async function simulateRefinanceTest() { sourcePosition: params.position, swaps: [], targetPosition: { + type: params.position.type, positionId: PositionId.createFrom({ id: '0987654321' }), debtAmount: params.position.debtAmount, collateralAmount: params.position.collateralAmount, @@ -82,6 +84,7 @@ export default async function simulateRefinanceTest() { } as MakerLendingPool const prevPosition: Position = { + type: PositionType.Multiply, pool: pool, debtAmount: TokenAmount.createFrom({ token: DAI, amount: '56.78' }), collateralAmount: TokenAmount.createFrom({ token: WETH, amount: '105.98' }), diff --git a/sdk/sdk-common/src/common/enums/PositionType.ts b/sdk/sdk-common/src/common/enums/PositionType.ts new file mode 100644 index 0000000000..3d5d712b15 --- /dev/null +++ b/sdk/sdk-common/src/common/enums/PositionType.ts @@ -0,0 +1,4 @@ +export enum PositionType { + Borrow = 'Borrow', + Multiply = 'Multiply', +} diff --git a/sdk/sdk-common/src/common/enums/index.ts b/sdk/sdk-common/src/common/enums/index.ts index 3e8ca3f03e..ebdbbc0659 100644 --- a/sdk/sdk-common/src/common/enums/index.ts +++ b/sdk/sdk-common/src/common/enums/index.ts @@ -9,3 +9,4 @@ export { EthereumChainNames, OptimismChainNames, } from './ChainNames' +export { PositionType } from './PositionType' diff --git a/sdk/sdk-common/src/common/implementation/Position.ts b/sdk/sdk-common/src/common/implementation/Position.ts index 342b4a34df..744b9f773f 100644 --- a/sdk/sdk-common/src/common/implementation/Position.ts +++ b/sdk/sdk-common/src/common/implementation/Position.ts @@ -4,15 +4,18 @@ import { SerializationService } from '../../services/SerializationService' import { PositionId } from './PositionId' import { RiskRatio } from './RiskRatio' import { TokenAmount } from './TokenAmount' +import { PositionType } from '../enums/PositionType' // we should add assests prop instead of the amounts export class Position implements IPosition { + readonly type: PositionType readonly positionId: PositionId readonly debtAmount: TokenAmount readonly collateralAmount: TokenAmount readonly pool: IPool - constructor(params: IPosition) { + private constructor(params: IPosition) { + this.type = params.type this.positionId = params.positionId this.debtAmount = TokenAmount.createFrom(params.debtAmount) this.collateralAmount = TokenAmount.createFrom(params.collateralAmount) diff --git a/sdk/sdk-common/src/common/interfaces/IPosition.ts b/sdk/sdk-common/src/common/interfaces/IPosition.ts index bfec7badc1..8048d1e3c2 100644 --- a/sdk/sdk-common/src/common/interfaces/IPosition.ts +++ b/sdk/sdk-common/src/common/interfaces/IPosition.ts @@ -1,8 +1,10 @@ import { IPool } from '../../protocols/interfaces/IPool' +import { PositionType } from '../enums/PositionType' import { PositionId } from '../implementation/PositionId' import { ITokenAmount } from './ITokenAmount' export interface IPosition { + readonly type: PositionType readonly positionId: PositionId readonly debtAmount: ITokenAmount readonly collateralAmount: ITokenAmount diff --git a/sdk/sdk-common/src/common/utils/PositionUtils.ts b/sdk/sdk-common/src/common/utils/PositionUtils.ts index d6500ba641..63d4be51d6 100644 --- a/sdk/sdk-common/src/common/utils/PositionUtils.ts +++ b/sdk/sdk-common/src/common/utils/PositionUtils.ts @@ -2,6 +2,7 @@ import { LendingPool } from '../../protocols/implementation/LendingPool' import { TokenAmount } from '../implementation/TokenAmount' import { Position } from '../implementation/Position' import { Token } from '../implementation/Token' +import { PositionType } from '../enums/PositionType' export function newEmptyPositionFromPool( pool: LendingPool, @@ -18,7 +19,8 @@ export function newEmptyPositionFromPool( throw new Error('Collateral token not supported by pool') } - return new Position({ + return Position.createFrom({ + type: PositionType.Multiply, positionId: { id: 'newEmptyPositionFromPool', }, @@ -29,7 +31,8 @@ export function newEmptyPositionFromPool( } export function depositToPosition(position: Position, amount: TokenAmount): Position { - return new Position({ + return Position.createFrom({ + type: PositionType.Multiply, positionId: position.positionId, debtAmount: position.debtAmount, collateralAmount: position.collateralAmount.add(amount), @@ -38,7 +41,8 @@ export function depositToPosition(position: Position, amount: TokenAmount): Posi } export function withdrawFromPosition(position: Position, amount: TokenAmount): Position { - return new Position({ + return Position.createFrom({ + type: PositionType.Multiply, positionId: position.positionId, debtAmount: position.debtAmount, collateralAmount: position.collateralAmount.subtract(amount), @@ -47,7 +51,8 @@ export function withdrawFromPosition(position: Position, amount: TokenAmount): P } export function borrowFromPosition(position: Position, amount: TokenAmount): Position { - return new Position({ + return Position.createFrom({ + type: PositionType.Multiply, positionId: position.positionId, debtAmount: position.debtAmount.add(amount), collateralAmount: position.collateralAmount, @@ -56,7 +61,8 @@ export function borrowFromPosition(position: Position, amount: TokenAmount): Pos } export function repayPositionDebt(position: Position, amount: TokenAmount): Position { - return new Position({ + return Position.createFrom({ + type: PositionType.Multiply, positionId: position.positionId, debtAmount: position.debtAmount.subtract(amount), collateralAmount: position.collateralAmount, diff --git a/sdk/sdk-common/src/simulation/Enums.ts b/sdk/sdk-common/src/simulation/Enums.ts index 9f6dab6096..f98b48921e 100644 --- a/sdk/sdk-common/src/simulation/Enums.ts +++ b/sdk/sdk-common/src/simulation/Enums.ts @@ -17,6 +17,7 @@ export enum SimulationSteps { PullToken = 'PullToken', ReturnFunds = 'ReturnFunds', RepayFlashloan = 'RepayFlashloan', + NewPositionEvent = 'NewPositionEvent', } export enum FlashloanProvider { diff --git a/sdk/sdk-common/src/simulation/Steps.ts b/sdk/sdk-common/src/simulation/Steps.ts index e6e74941b1..7fa8a9360a 100644 --- a/sdk/sdk-common/src/simulation/Steps.ts +++ b/sdk/sdk-common/src/simulation/Steps.ts @@ -84,6 +84,14 @@ export interface RepayFlashloan } > {} +export interface NewPositionEvent + extends Step< + SimulationSteps.NewPositionEvent, + { + position: Position + } + > {} + export type Steps = | FlashloanStep | PullTokenStep @@ -92,3 +100,4 @@ export type Steps = | SwapStep | ReturnFunds | RepayFlashloan + | NewPositionEvent diff --git a/sdk/sdk-e2e/tests/refinanceMakerSpark.test.ts b/sdk/sdk-e2e/tests/refinanceMakerSpark.test.ts index 2f64f82f58..0ff5b3415c 100644 --- a/sdk/sdk-e2e/tests/refinanceMakerSpark.test.ts +++ b/sdk/sdk-e2e/tests/refinanceMakerSpark.test.ts @@ -8,6 +8,7 @@ import { type Maybe, ChainFamilyMap, AddressValue, + PositionType, } from '@summerfi/sdk-common/common' import { ProtocolName, isLendingPool } from '@summerfi/sdk-common/protocols' @@ -31,6 +32,7 @@ import { FlashloanAction, SendTokenAction, SetApprovalAction, + PositionCreatedAction, } from '@summerfi/protocol-plugins/plugins/common' import { ILKType, @@ -48,7 +50,7 @@ import { jest.setTimeout(300000) const SDKAPiUrl = 'https://zmjmtfsocb.execute-api.us-east-1.amazonaws.com/api/sdk' -const TenderlyForkUrl = 'https://rpc.tenderly.co/fork/47a20a20-3aa1-4d21-afd7-6a230b12a0cc' +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 () => { @@ -121,6 +123,7 @@ describe.skip('Refinance Maker Spark | SDK', () => { // Source position const makerPosition: Position = Position.createFrom({ + type: PositionType.Multiply, positionId: PositionId.createFrom({ id: '31646' }), debtAmount: TokenAmount.createFromBaseUnit({ token: DAI, @@ -173,7 +176,7 @@ describe.skip('Refinance Maker Spark | SDK', () => { expect(refinanceSimulation.sourcePosition?.positionId).toEqual(makerPosition.positionId) expect(refinanceSimulation.targetPosition.pool.poolId).toEqual(sparkPool.poolId) - expect(refinanceSimulation.steps.length).toBe(4) + expect(refinanceSimulation.steps.length).toBe(5) const refinanceOrder: Maybe = await user.newOrder({ positionsManager: { @@ -218,7 +221,7 @@ describe.skip('Refinance Maker Spark | SDK', () => { assert(strategyExecutorParams, 'Cannot decode Strategy Executor calldata') expect(strategyExecutorParams.strategyName).toEqual(strategyName) - expect(strategyExecutorParams.actionCalls.length).toEqual(1) + expect(strategyExecutorParams.actionCalls.length).toEqual(2) // Decode Flashloan action const flashloanParams = decodeActionCalldata({ @@ -342,6 +345,23 @@ describe.skip('Refinance Maker Spark | SDK', () => { 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/sdk-server/src/handlers/getRefinanceSimulation.ts b/sdk/sdk-server/src/handlers/getRefinanceSimulation.ts index 21a8f49a4b..0c763d1ab6 100644 --- a/sdk/sdk-server/src/handlers/getRefinanceSimulation.ts +++ b/sdk/sdk-server/src/handlers/getRefinanceSimulation.ts @@ -2,7 +2,7 @@ import { z } from 'zod' import { Percentage } from '@summerfi/sdk-common/common' import type { ISimulation, SimulationType } from '@summerfi/sdk-common/simulation' import { - refinanceLendingToLending, + refinanceLendingToLendingSamePair, type IRefinanceDependencies, } from '@summerfi/simulator-service/strategies' import type { IRefinanceParameters } from '@summerfi/sdk-common/orders' @@ -22,5 +22,5 @@ export const getRefinanceSimulation = publicProcedure getSummerFee: () => Percentage.createFrom({ value: 0 }), } - return await refinanceLendingToLending(args, dependencies) + return await refinanceLendingToLendingSamePair(args, dependencies) }) diff --git a/sdk/simulator-service/src/implementation/simulator-engine/reducer/newPositionEventReducer.ts b/sdk/simulator-service/src/implementation/simulator-engine/reducer/newPositionEventReducer.ts new file mode 100644 index 0000000000..9606b40429 --- /dev/null +++ b/sdk/simulator-service/src/implementation/simulator-engine/reducer/newPositionEventReducer.ts @@ -0,0 +1,15 @@ +import { steps } from '@summerfi/sdk-common/simulation' +import { ISimulationState } from '../../../interfaces/simulation' + +export function newPositionEventReducer( + step: steps.NewPositionEvent, + state: ISimulationState, +): ISimulationState { + return { + ...state, + steps: { + ...state.steps, + [step.name]: step, + }, + } +} diff --git a/sdk/simulator-service/src/implementation/simulator-engine/reducer/stateReducers.ts b/sdk/simulator-service/src/implementation/simulator-engine/reducer/stateReducers.ts index d88692759b..34a60bb046 100644 --- a/sdk/simulator-service/src/implementation/simulator-engine/reducer/stateReducers.ts +++ b/sdk/simulator-service/src/implementation/simulator-engine/reducer/stateReducers.ts @@ -8,6 +8,7 @@ import { swapReducer } from './swapReducer' import { returnFundsReducer } from './returnFundsReducer' import { repayFlashloanReducer } from './repayFlashloanReducer' import { pullTokenReducer } from './pullTokenReducer' +import { newPositionEventReducer } from './newPositionEventReducer' const stateReducers: StateReducers = { [SimulationSteps.Flashloan]: flashloanReducer, @@ -17,6 +18,7 @@ const stateReducers: StateReducers = { [SimulationSteps.ReturnFunds]: returnFundsReducer, [SimulationSteps.RepayFlashloan]: repayFlashloanReducer, [SimulationSteps.PullToken]: pullTokenReducer, + [SimulationSteps.NewPositionEvent]: newPositionEventReducer, } export function stateReducer(step: steps.Steps, state: ISimulationState): ISimulationState { diff --git a/sdk/simulator-service/src/implementation/simulator-engine/stepProcessor/newPositionEvent.ts b/sdk/simulator-service/src/implementation/simulator-engine/stepProcessor/newPositionEvent.ts new file mode 100644 index 0000000000..8817014f6f --- /dev/null +++ b/sdk/simulator-service/src/implementation/simulator-engine/stepProcessor/newPositionEvent.ts @@ -0,0 +1,11 @@ +import { steps } from '@summerfi/sdk-common/simulation' +import type { StepOutputProcessor } from '../../../interfaces/steps' + +export const newPositionEventProcessor: StepOutputProcessor = async ( + step, +) => { + return { + ...step, + outputs: undefined, + } +} diff --git a/sdk/simulator-service/src/implementation/simulator-engine/stepProcessor/stepOutputProcessors.ts b/sdk/simulator-service/src/implementation/simulator-engine/stepProcessor/stepOutputProcessors.ts index 9637a00dff..9f16f2bf39 100644 --- a/sdk/simulator-service/src/implementation/simulator-engine/stepProcessor/stepOutputProcessors.ts +++ b/sdk/simulator-service/src/implementation/simulator-engine/stepProcessor/stepOutputProcessors.ts @@ -11,6 +11,7 @@ import { paybackWithdrawOutputProcessor } from './paybackWithdrawOutputProcessor import { swapOutputProcessor } from './swapOutputProcessor' import { returnFundsOutputProcessor } from './returnFundsOutputProcessor' import { repayFlashloanOutputProcessor } from './repayFlashloanOutputProcessor' +import { newPositionEventProcessor } from './newPositionEvent' const stepOutputProcessors: StepOutputProcessors = { [SimulationSteps.Flashloan]: flashloanOutputProcessor, @@ -20,6 +21,7 @@ const stepOutputProcessors: StepOutputProcessors = { [SimulationSteps.ReturnFunds]: returnFundsOutputProcessor, [SimulationSteps.RepayFlashloan]: repayFlashloanOutputProcessor, [SimulationSteps.PullToken]: pullTokenOutputProcessor, + [SimulationSteps.NewPositionEvent]: newPositionEventProcessor, } export async function processStepOutput(step: StepsWithoutOutputs): Promise { diff --git a/sdk/simulator-service/src/implementation/utils/BalanceUtils.ts b/sdk/simulator-service/src/implementation/utils/BalanceUtils.ts index 6a80c95fd9..c87d075227 100644 --- a/sdk/simulator-service/src/implementation/utils/BalanceUtils.ts +++ b/sdk/simulator-service/src/implementation/utils/BalanceUtils.ts @@ -1,13 +1,13 @@ import { TokenAmount, type Token } from '@summerfi/sdk-common/common' +import { BalancesRecord } from '../../types/Types' -export function getTokenBalance(token: Token, balances: Record): TokenAmount { +// TODO: This should be transformed into a proper class, as we are passing the balances record +// TODO: to each call +export function getTokenBalance(token: Token, balances: BalancesRecord): TokenAmount { return balances[token.address.value] || TokenAmount.createFrom({ amount: '0', token }) } -export function addBalance( - amount: TokenAmount, - balance: Record, -): Record { +export function addBalance(amount: TokenAmount, balance: BalancesRecord): BalancesRecord { return { ...balance, [amount.token.address.value]: balance[amount.token.address.value] @@ -16,10 +16,7 @@ export function addBalance( } } -export function subtractBalance( - amount: TokenAmount, - balance: Record, -): Record { +export function subtractBalance(amount: TokenAmount, balance: BalancesRecord): BalancesRecord { return { ...balance, [amount.token.address.value]: balance[amount.token.address.value] diff --git a/sdk/simulator-service/src/interfaces/simulation.ts b/sdk/simulator-service/src/interfaces/simulation.ts index a9ad7e21d3..fd1581b6f6 100644 --- a/sdk/simulator-service/src/interfaces/simulation.ts +++ b/sdk/simulator-service/src/interfaces/simulation.ts @@ -1,10 +1,8 @@ -import type { steps } from '@summerfi/sdk-common/simulation' -import type { TokenAmount, Position } from '@summerfi/sdk-common/common' -import type { SimulatedSwapData } from '@summerfi/sdk-common/swap' +import { BalancesRecord, PositionsRecord, StepsRecord, SwapsRecord } from '../types/Types' export interface ISimulationState { - swaps: Record - balances: Record - positions: Record - steps: Record + swaps: SwapsRecord + balances: BalancesRecord + positions: PositionsRecord + steps: StepsRecord } diff --git a/sdk/simulator-service/src/strategies/refinance/Types.ts b/sdk/simulator-service/src/strategies/common/Types.ts similarity index 100% rename from sdk/simulator-service/src/strategies/refinance/Types.ts rename to sdk/simulator-service/src/strategies/common/Types.ts diff --git a/sdk/simulator-service/src/strategies/common/index.ts b/sdk/simulator-service/src/strategies/common/index.ts new file mode 100644 index 0000000000..cf701220bd --- /dev/null +++ b/sdk/simulator-service/src/strategies/common/index.ts @@ -0,0 +1 @@ +export * from './Types' diff --git a/sdk/simulator-service/src/strategies/index.ts b/sdk/simulator-service/src/strategies/index.ts index 0ee38d8f24..3c006d5c2d 100644 --- a/sdk/simulator-service/src/strategies/index.ts +++ b/sdk/simulator-service/src/strategies/index.ts @@ -1 +1,3 @@ -export * from './refinance' +export * from './refinanceSamePair' +export * from './refinanceAnyPair' +export * from './common' diff --git a/sdk/simulator-service/src/strategies/refinance/index.ts b/sdk/simulator-service/src/strategies/refinance/index.ts deleted file mode 100644 index 3b6c974181..0000000000 --- a/sdk/simulator-service/src/strategies/refinance/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './RefinanceLendingToLending' -export * from './Strategy' -export * from './Types' diff --git a/sdk/simulator-service/src/strategies/refinance/RefinanceLendingToLending.ts b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts similarity index 87% rename from sdk/simulator-service/src/strategies/refinance/RefinanceLendingToLending.ts rename to sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts index 5ca9642c0f..167ce53859 100644 --- a/sdk/simulator-service/src/strategies/refinance/RefinanceLendingToLending.ts +++ b/sdk/simulator-service/src/strategies/refinanceAnyPair/RefinanceLendingToLendingAnyPair.ts @@ -11,10 +11,10 @@ import { newEmptyPositionFromPool } from '@summerfi/sdk-common/common/utils' import { IRefinanceParameters } from '@summerfi/sdk-common/orders' import { isLendingPool } from '@summerfi/sdk-common/protocols' import { getReferencedValue } from '../../implementation/utils' -import { refinanceLendingToLendingStrategy } from './Strategy' -import { type IRefinanceDependencies } from './Types' +import { refinanceLendingToLendingAnyPairStrategy } from './Strategy' +import { type IRefinanceDependencies } from '../common/Types' -export async function refinanceLendingToLending( +export async function refinanceLendingToLendingAnyPair( args: IRefinanceParameters, dependencies: IRefinanceDependencies, ): Promise> { @@ -32,7 +32,7 @@ export async function refinanceLendingToLending( const FLASHLOAN_MARGIN = 1.001 const flashloanAmount = position.debtAmount.multiply(FLASHLOAN_MARGIN) - const simulator = Simulator.create(refinanceLendingToLendingStrategy) + const simulator = Simulator.create(refinanceLendingToLendingAnyPairStrategy) const targetTokenConfig = targetPool.collaterals.get({ token: position.collateralAmount.token }) if (!targetTokenConfig) { @@ -130,6 +130,23 @@ export async function refinanceLendingToLending( amount: flashloanAmount, }, })) + .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( + (p) => p.pool.protocol === targetPool.protocol, + ) + if (!targetPosition) { + throw new Error('Target position not found') + } + + return { + name: 'NewPositionEvent', + type: SimulationSteps.NewPositionEvent, + inputs: { + position: targetPosition, + }, + } + }) .run() const targetPosition = Object.values(simulation.positions).find( diff --git a/sdk/simulator-service/src/strategies/refinance/Strategy.ts b/sdk/simulator-service/src/strategies/refinanceAnyPair/Strategy.ts similarity index 84% rename from sdk/simulator-service/src/strategies/refinance/Strategy.ts rename to sdk/simulator-service/src/strategies/refinanceAnyPair/Strategy.ts index aca24441ce..c0887bd188 100644 --- a/sdk/simulator-service/src/strategies/refinance/Strategy.ts +++ b/sdk/simulator-service/src/strategies/refinanceAnyPair/Strategy.ts @@ -1,7 +1,7 @@ import { SimulationSteps } from '@summerfi/sdk-common/simulation' import { makeStrategy } from '../../implementation/utils' -export const refinanceLendingToLendingStrategy = makeStrategy([ +export const refinanceLendingToLendingAnyPairStrategy = makeStrategy([ { step: SimulationSteps.Flashloan, optional: false, @@ -32,4 +32,8 @@ export const refinanceLendingToLendingStrategy = makeStrategy([ step: SimulationSteps.ReturnFunds, optional: true, }, + { + step: SimulationSteps.NewPositionEvent, + optional: false, + }, ]) diff --git a/sdk/simulator-service/src/strategies/refinanceAnyPair/index.ts b/sdk/simulator-service/src/strategies/refinanceAnyPair/index.ts new file mode 100644 index 0000000000..6ea863f32a --- /dev/null +++ b/sdk/simulator-service/src/strategies/refinanceAnyPair/index.ts @@ -0,0 +1,2 @@ +export * from './RefinanceLendingToLendingAnyPair' +export * from './Strategy' diff --git a/sdk/simulator-service/src/strategies/refinanceSamePair/RefinanceLendingToLendingSamePair.ts b/sdk/simulator-service/src/strategies/refinanceSamePair/RefinanceLendingToLendingSamePair.ts new file mode 100644 index 0000000000..a6c40dd887 --- /dev/null +++ b/sdk/simulator-service/src/strategies/refinanceSamePair/RefinanceLendingToLendingSamePair.ts @@ -0,0 +1,120 @@ +import { + FlashloanProvider, + ISimulation, + SimulationSteps, + SimulationType, + TokenTransferTargetType, +} from '@summerfi/sdk-common/simulation' +import { Simulator } from '../../implementation/simulator-engine' +import { Position, TokenAmount } 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 { refinanceLendingToLendingSamePairStrategy } from './Strategy' +import { type IRefinanceDependencies } from '../common/Types' + +export async function refinanceLendingToLendingSamePair( + args: IRefinanceParameters, + dependencies: IRefinanceDependencies, +): Promise> { + // args validation + if (!isLendingPool(args.targetPool)) { + throw new Error('Target pool is not a lending pool') + } + + const position = Position.createFrom(args.position) + const targetPool = await dependencies.protocolManager.getPool(args.targetPool.poolId) + + if (!isLendingPool(targetPool)) { + throw new Error('Target pool is not a lending pool') + } + + const FLASHLOAN_MARGIN = 1.001 + const flashloanAmount = position.debtAmount.multiply(FLASHLOAN_MARGIN) + const simulator = Simulator.create(refinanceLendingToLendingSamePairStrategy) + + const targetTokenConfig = targetPool.collaterals.get({ token: position.collateralAmount.token }) + if (!targetTokenConfig) { + throw new Error('Target token not found in pool') + } + + // TODO: read debt amount from chain (special step: ReadDebtAmount) + // TODO: the swap quote should also include the summer fee, in this case we need to know when we are taking the fee, + // before or after the swap, it influences actual call to oneInch api + const simulation = await simulator + .next(async () => ({ + name: 'Flashloan', + type: SimulationSteps.Flashloan, + inputs: { + amount: flashloanAmount, + provider: FlashloanProvider.Maker, + }, + })) + .next(async () => ({ + name: 'PaybackWithdrawFromSource', + type: SimulationSteps.PaybackWithdraw, + inputs: { + paybackAmount: TokenAmount.createFrom({ + amount: Number.MAX_SAFE_INTEGER.toString(), + token: position.debtAmount.token, + }), + withdrawAmount: position.collateralAmount, + position: position, + }, + })) + .next(async (ctx) => ({ + name: 'DepositBorrowToTarget', + type: SimulationSteps.DepositBorrow, + inputs: { + depositAmount: ctx.getReference(['PaybackWithdrawFromSource', 'withdrawAmount']), + borrowAmount: position.debtAmount, // TODO figure the debt amount + position: newEmptyPositionFromPool( + targetPool, + position.debtAmount.token, + position.collateralAmount.token, + ), + borrowTargetType: TokenTransferTargetType.PositionsManager, + }, + })) + .next(async () => ({ + name: 'RepayFlashloan', + type: SimulationSteps.RepayFlashloan, + inputs: { + amount: flashloanAmount, + }, + })) + .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( + (p) => p.pool.protocol === targetPool.protocol, + ) + if (!targetPosition) { + throw new Error('Target position not found') + } + + return { + name: 'NewPositionEvent', + type: SimulationSteps.NewPositionEvent, + inputs: { + position: targetPosition, + }, + } + }) + .run() + + const targetPosition = Object.values(simulation.positions).find( + (p) => p.pool.protocol === targetPool.protocol, + ) + + if (!targetPosition) { + throw new Error('Target position not found') + } + + return { + simulationType: SimulationType.Refinance, + sourcePosition: position, + targetPosition, + swaps: Object.values(simulation.swaps), + steps: Object.values(simulation.steps), + } as ISimulation +} diff --git a/sdk/simulator-service/src/strategies/refinanceSamePair/Strategy.ts b/sdk/simulator-service/src/strategies/refinanceSamePair/Strategy.ts new file mode 100644 index 0000000000..4b8d6c9896 --- /dev/null +++ b/sdk/simulator-service/src/strategies/refinanceSamePair/Strategy.ts @@ -0,0 +1,25 @@ +import { SimulationSteps } from '@summerfi/sdk-common/simulation' +import { makeStrategy } from '../../implementation/utils' + +export const refinanceLendingToLendingSamePairStrategy = makeStrategy([ + { + step: SimulationSteps.Flashloan, + optional: false, + }, + { + step: SimulationSteps.PaybackWithdraw, + optional: false, + }, + { + step: SimulationSteps.DepositBorrow, + optional: false, + }, + { + step: SimulationSteps.RepayFlashloan, + optional: false, + }, + { + step: SimulationSteps.NewPositionEvent, + optional: false, + }, +]) diff --git a/sdk/simulator-service/src/strategies/refinanceSamePair/index.ts b/sdk/simulator-service/src/strategies/refinanceSamePair/index.ts new file mode 100644 index 0000000000..df1f26236a --- /dev/null +++ b/sdk/simulator-service/src/strategies/refinanceSamePair/index.ts @@ -0,0 +1,2 @@ +export * from './RefinanceLendingToLendingSamePair' +export * from './Strategy' diff --git a/sdk/simulator-service/src/types/Types.ts b/sdk/simulator-service/src/types/Types.ts new file mode 100644 index 0000000000..10334aba37 --- /dev/null +++ b/sdk/simulator-service/src/types/Types.ts @@ -0,0 +1,10 @@ +import { AddressValue, Position, TokenAmount } from '@summerfi/sdk-common/common' +import { steps } from '@summerfi/sdk-common/simulation' +import { SimulatedSwapData } from '@summerfi/sdk-common/swap' + +export type StepName = string + +export type BalancesRecord = Record +export type PositionsRecord = Record +export type StepsRecord = Record +export type SwapsRecord = Record diff --git a/sdk/simulator-service/tests/simulator.test.ts b/sdk/simulator-service/tests/simulator.test.ts index a9a224900a..85cc48d922 100644 --- a/sdk/simulator-service/tests/simulator.test.ts +++ b/sdk/simulator-service/tests/simulator.test.ts @@ -1,6 +1,14 @@ import { Percentage } from '@summerfi/sdk-common/common' -import { ISimulation, SimulationSteps, SimulationType } from '@summerfi/sdk-common/simulation' -import { refinanceLendingToLending } from '../src/strategies' +import { + ISimulation, + SimulationSteps, + SimulationType, + steps, +} from '@summerfi/sdk-common/simulation' +import { + refinanceLendingToLendingAnyPair, + refinanceLendingToLendingSamePair, +} from '../src/strategies' import { otherTestCollateral, otherTestDebt, @@ -9,12 +17,13 @@ import { testTargetLendingPoolRequiredSwaps, } from './mocks/testSourcePosition' import { mockRefinanceContext } from './mocks/contextMock' +import assert from 'assert' describe('Refinance', () => { describe('to the position with the same collateral and debt (no swaps)', () => { let simulation: ISimulation beforeAll(async () => { - simulation = await refinanceLendingToLending( + simulation = await refinanceLendingToLendingSamePair( { position: testSourcePosition, targetPool: testTargetLendingPool, @@ -54,12 +63,21 @@ describe('Refinance', () => { expect(targetPosition.positionId).toBeDefined() }) + + it('should include a new position event step', async () => { + const newPositionStep = simulation.steps.find( + (step) => step.type === SimulationSteps.NewPositionEvent, + ) as steps.NewPositionEvent + + assert(newPositionStep, 'New position event step not found') + expect(newPositionStep.inputs.position).toEqual(simulation.targetPosition) + }) }) describe.skip('to the position with the different collateral and debt (with swaps)', () => { let simulation: ISimulation beforeAll(async () => { - simulation = await refinanceLendingToLending( + simulation = await refinanceLendingToLendingAnyPair( { position: testSourcePosition, targetPool: testTargetLendingPoolRequiredSwaps, diff --git a/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts b/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts index 13441caaed..50f9e1b49b 100644 --- a/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts +++ b/sdk/swap-service/src/implementation/oneinch/OneInchSwapProvider.ts @@ -103,7 +103,7 @@ export class OneInchSwapProvider implements ISwapProvider { if (!(response.status === 200 && response.statusText === 'OK')) { throw new Error( - `Error performing 1inch swap quote request ${swapUrl}: ${await response.body}`, + `Error [${response.statusText}] performing 1inch swap quote request ${swapUrl}: ${JSON.stringify(await response.body)}`, ) } diff --git a/turbo.json b/turbo.json index eaf1f90a64..eaff06d6a7 100644 --- a/turbo.json +++ b/turbo.json @@ -54,11 +54,14 @@ "lint": { "dependsOn": ["prebuild", "build", "^lint"] }, + "format": { + "dependsOn": ["prebuild", "build", "^format"] + }, "check-circular": { "dependsOn": ["prebuild", "build", "^check-circular"] }, "cicheck": { - "dependsOn": ["prebuild", "build", "test", "lint", "check-circular"] + "dependsOn": ["prebuild", "build", "test", "lint", "check-circular", "format"] }, "deploy:staging": { "dependsOn": ["cicheck", "^deploy:staging"]