Skip to content
This repository has been archived by the owner on Jan 24, 2024. It is now read-only.

Commit

Permalink
feat(raft): add position presenter (#2728)
Browse files Browse the repository at this point in the history
Co-authored-by: William Poulin <will@zapper.fi>
  • Loading branch information
tonzgao and wpoulin committed Jun 7, 2023
1 parent 606632b commit 5de709f
Show file tree
Hide file tree
Showing 8 changed files with 335 additions and 1 deletion.
14 changes: 14 additions & 0 deletions src/apps/raft/common/raft.position.contract-position-fetcher.ts
Expand Up @@ -46,6 +46,20 @@ export abstract class EthereumRaftContractPositionFetcher extends ContractPositi
];
}

async getDataProps({
contractPosition,
multicall,
}) {
const positionManager = this.raftContractFactory.raftPositionManager({ address: this.positionManagerAddress, network: this.network })
const liquidiationContractAddress = await multicall.wrap(positionManager).splitLiquidationCollateral(this.collateral)
const liquidationContract = this.raftContractFactory.raftLiquiditation({ address: liquidiationContractAddress, network: this.network })

const collateralToken = contractPosition.tokens[0];
const minCRatio = Number(await multicall.wrap(liquidationContract).MCR()) / 10 ** collateralToken.decimals

return { minCRatio };
}

async getLabel(): Promise<string> {
const baseTokens = await this.appToolkit.getBaseTokenPrices(this.network);
const tokenFound = baseTokens.find(p => p.address === this.collateral);
Expand Down
31 changes: 31 additions & 0 deletions src/apps/raft/contracts/abis/raft-liquiditation.json
@@ -0,0 +1,31 @@
[
{
"inputs": [],
"name": "LOW_TOTAL_DEBT",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MCR",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "uint256", "name": "totalCollateral", "type": "uint256" },
{ "internalType": "uint256", "name": "totalDebt", "type": "uint256" },
{ "internalType": "uint256", "name": "price", "type": "uint256" },
{ "internalType": "bool", "name": "isRedistribution", "type": "bool" }
],
"name": "split",
"outputs": [
{ "internalType": "uint256", "name": "collateralToSendToProtocol", "type": "uint256" },
{ "internalType": "uint256", "name": "collateralToSentToLiquidator", "type": "uint256" }
],
"stateMutability": "pure",
"type": "function"
}
]
152 changes: 152 additions & 0 deletions src/apps/raft/contracts/ethers/RaftLiquiditation.ts
@@ -0,0 +1,152 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
import type {
BaseContract,
BigNumber,
BigNumberish,
BytesLike,
CallOverrides,
PopulatedTransaction,
Signer,
utils,
} from 'ethers';
import type { FunctionFragment, Result } from '@ethersproject/abi';
import type { Listener, Provider } from '@ethersproject/providers';
import type { TypedEventFilter, TypedEvent, TypedListener, OnEvent, PromiseOrValue } from './common';

export interface RaftLiquiditationInterface extends utils.Interface {
functions: {
'LOW_TOTAL_DEBT()': FunctionFragment;
'MCR()': FunctionFragment;
'split(uint256,uint256,uint256,bool)': FunctionFragment;
};

getFunction(nameOrSignatureOrTopic: 'LOW_TOTAL_DEBT' | 'MCR' | 'split'): FunctionFragment;

encodeFunctionData(functionFragment: 'LOW_TOTAL_DEBT', values?: undefined): string;
encodeFunctionData(functionFragment: 'MCR', values?: undefined): string;
encodeFunctionData(
functionFragment: 'split',
values: [
PromiseOrValue<BigNumberish>,
PromiseOrValue<BigNumberish>,
PromiseOrValue<BigNumberish>,
PromiseOrValue<boolean>,
],
): string;

decodeFunctionResult(functionFragment: 'LOW_TOTAL_DEBT', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'MCR', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'split', data: BytesLike): Result;

events: {};
}

export interface RaftLiquiditation extends BaseContract {
connect(signerOrProvider: Signer | Provider | string): this;
attach(addressOrName: string): this;
deployed(): Promise<this>;

interface: RaftLiquiditationInterface;

queryFilter<TEvent extends TypedEvent>(
event: TypedEventFilter<TEvent>,
fromBlockOrBlockhash?: string | number | undefined,
toBlock?: string | number | undefined,
): Promise<Array<TEvent>>;

listeners<TEvent extends TypedEvent>(eventFilter?: TypedEventFilter<TEvent>): Array<TypedListener<TEvent>>;
listeners(eventName?: string): Array<Listener>;
removeAllListeners<TEvent extends TypedEvent>(eventFilter: TypedEventFilter<TEvent>): this;
removeAllListeners(eventName?: string): this;
off: OnEvent<this>;
on: OnEvent<this>;
once: OnEvent<this>;
removeListener: OnEvent<this>;

functions: {
LOW_TOTAL_DEBT(overrides?: CallOverrides): Promise<[BigNumber]>;

MCR(overrides?: CallOverrides): Promise<[BigNumber]>;

split(
totalCollateral: PromiseOrValue<BigNumberish>,
totalDebt: PromiseOrValue<BigNumberish>,
price: PromiseOrValue<BigNumberish>,
isRedistribution: PromiseOrValue<boolean>,
overrides?: CallOverrides,
): Promise<
[BigNumber, BigNumber] & {
collateralToSendToProtocol: BigNumber;
collateralToSentToLiquidator: BigNumber;
}
>;
};

LOW_TOTAL_DEBT(overrides?: CallOverrides): Promise<BigNumber>;

MCR(overrides?: CallOverrides): Promise<BigNumber>;

split(
totalCollateral: PromiseOrValue<BigNumberish>,
totalDebt: PromiseOrValue<BigNumberish>,
price: PromiseOrValue<BigNumberish>,
isRedistribution: PromiseOrValue<boolean>,
overrides?: CallOverrides,
): Promise<
[BigNumber, BigNumber] & {
collateralToSendToProtocol: BigNumber;
collateralToSentToLiquidator: BigNumber;
}
>;

callStatic: {
LOW_TOTAL_DEBT(overrides?: CallOverrides): Promise<BigNumber>;

MCR(overrides?: CallOverrides): Promise<BigNumber>;

split(
totalCollateral: PromiseOrValue<BigNumberish>,
totalDebt: PromiseOrValue<BigNumberish>,
price: PromiseOrValue<BigNumberish>,
isRedistribution: PromiseOrValue<boolean>,
overrides?: CallOverrides,
): Promise<
[BigNumber, BigNumber] & {
collateralToSendToProtocol: BigNumber;
collateralToSentToLiquidator: BigNumber;
}
>;
};

filters: {};

estimateGas: {
LOW_TOTAL_DEBT(overrides?: CallOverrides): Promise<BigNumber>;

MCR(overrides?: CallOverrides): Promise<BigNumber>;

split(
totalCollateral: PromiseOrValue<BigNumberish>,
totalDebt: PromiseOrValue<BigNumberish>,
price: PromiseOrValue<BigNumberish>,
isRedistribution: PromiseOrValue<boolean>,
overrides?: CallOverrides,
): Promise<BigNumber>;
};

populateTransaction: {
LOW_TOTAL_DEBT(overrides?: CallOverrides): Promise<PopulatedTransaction>;

MCR(overrides?: CallOverrides): Promise<PopulatedTransaction>;

split(
totalCollateral: PromiseOrValue<BigNumberish>,
totalDebt: PromiseOrValue<BigNumberish>,
price: PromiseOrValue<BigNumberish>,
isRedistribution: PromiseOrValue<boolean>,
overrides?: CallOverrides,
): Promise<PopulatedTransaction>;
};
}
@@ -0,0 +1,85 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */

import { Contract, Signer, utils } from 'ethers';
import type { Provider } from '@ethersproject/providers';
import type { RaftLiquiditation, RaftLiquiditationInterface } from '../RaftLiquiditation';

const _abi = [
{
inputs: [],
name: 'LOW_TOTAL_DEBT',
outputs: [
{
internalType: 'uint256',
name: '',
type: 'uint256',
},
],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'MCR',
outputs: [
{
internalType: 'uint256',
name: '',
type: 'uint256',
},
],
stateMutability: 'view',
type: 'function',
},
{
inputs: [
{
internalType: 'uint256',
name: 'totalCollateral',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'totalDebt',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'price',
type: 'uint256',
},
{
internalType: 'bool',
name: 'isRedistribution',
type: 'bool',
},
],
name: 'split',
outputs: [
{
internalType: 'uint256',
name: 'collateralToSendToProtocol',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'collateralToSentToLiquidator',
type: 'uint256',
},
],
stateMutability: 'pure',
type: 'function',
},
];

export class RaftLiquiditation__factory {
static readonly abi = _abi;
static createInterface(): RaftLiquiditationInterface {
return new utils.Interface(_abi) as RaftLiquiditationInterface;
}
static connect(address: string, signerOrProvider: Signer | Provider): RaftLiquiditation {
return new Contract(address, _abi, signerOrProvider) as RaftLiquiditation;
}
}
1 change: 1 addition & 0 deletions src/apps/raft/contracts/ethers/factories/index.ts
@@ -1,5 +1,6 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
export { RaftLiquiditation__factory } from './RaftLiquiditation__factory';
export { RaftPositionManager__factory } from './RaftPositionManager__factory';
export { RaftToken__factory } from './RaftToken__factory';
2 changes: 2 additions & 0 deletions src/apps/raft/contracts/ethers/index.ts
@@ -1,8 +1,10 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
export type { RaftLiquiditation } from './RaftLiquiditation';
export type { RaftPositionManager } from './RaftPositionManager';
export type { RaftToken } from './RaftToken';
export * as factories from './factories';
export { RaftLiquiditation__factory } from './factories/RaftLiquiditation__factory';
export { RaftPositionManager__factory } from './factories/RaftPositionManager__factory';
export { RaftToken__factory } from './factories/RaftToken__factory';
6 changes: 5 additions & 1 deletion src/apps/raft/contracts/index.ts
Expand Up @@ -4,7 +4,7 @@ import { IAppToolkit, APP_TOOLKIT } from '~app-toolkit/app-toolkit.interface';
import { ContractFactory } from '~contract/contracts';
import { Network } from '~types/network.interface';

import { RaftPositionManager__factory, RaftToken__factory } from './ethers';
import { RaftLiquiditation__factory, RaftPositionManager__factory, RaftToken__factory } from './ethers';

// eslint-disable-next-line
type ContractOpts = { address: string; network: Network };
Expand All @@ -15,6 +15,9 @@ export class RaftContractFactory extends ContractFactory {
super((network: Network) => appToolkit.getNetworkProvider(network));
}

raftLiquiditation({ address, network }: ContractOpts) {
return RaftLiquiditation__factory.connect(address, this.appToolkit.getNetworkProvider(network));
}
raftPositionManager({ address, network }: ContractOpts) {
return RaftPositionManager__factory.connect(address, this.appToolkit.getNetworkProvider(network));
}
Expand All @@ -23,5 +26,6 @@ export class RaftContractFactory extends ContractFactory {
}
}

export type { RaftLiquiditation } from './ethers';
export type { RaftPositionManager } from './ethers';
export type { RaftToken } from './ethers';
45 changes: 45 additions & 0 deletions src/apps/raft/ethereum/raft.position-presenter.ts
@@ -0,0 +1,45 @@
import { Inject } from '@nestjs/common';

import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface';
import {
buildDollarDisplayItem,
buildPercentageDisplayItem,
} from '~app-toolkit/helpers/presentation/display-item.present';
import { ContractPositionBalance } from '~position/position-balance.interface';
import { MetadataItemWithLabel } from '~balance/balance-fetcher.interface';
import { PositionPresenterTemplate, ReadonlyBalances } from '~position/template/position-presenter.template';

import { RaftContractFactory } from '../contracts';

export const positionManagerAddress = '0x5f59b322eb3e16a0c78846195af1f588b77403fc'

export type RaftPositionPresenterDataProps = {
minCRatio: number;
};

export class EthereumRaftPositionPresenter extends PositionPresenterTemplate<RaftPositionPresenterDataProps> {
constructor(
@Inject(RaftContractFactory) protected readonly contractFactory: RaftContractFactory,
@Inject(APP_TOOLKIT) protected readonly appToolkit: IAppToolkit,
) {
super();
}

override metadataItemsForBalanceGroup(
groupLabel: string,
balances: ReadonlyBalances,
dataProps?: RaftPositionPresenterDataProps,
): MetadataItemWithLabel[] {

const collateral = (balances[0] as ContractPositionBalance)?.tokens[0]
const collateralUSD = collateral?.balanceUSD ?? 0;
const debt = (balances[0] as ContractPositionBalance)?.tokens[1]?.balanceUSD ?? 0;
const cRatio = Math.abs(debt) > 0 ? Math.abs(collateralUSD / debt) : 0;
const liquidationPrice = dataProps?.minCRatio ? (dataProps.minCRatio * debt) / collateral.balance : 0

return [
{ label: 'C-Ratio', ...buildPercentageDisplayItem(cRatio) },
{ label: 'Liquidation Price', ...buildDollarDisplayItem(liquidationPrice) },
];
}
}

0 comments on commit 5de709f

Please sign in to comment.