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

Commit

Permalink
fix(inverse-firm): Migration to template (#2046)
Browse files Browse the repository at this point in the history
* fix(inverse-firm): Linting

* fix(rpc-url): Updated Ethereum network RPC url enabling fetching data older than 128 blocks

* fix(inverse-firm): Migration to template

* chore(inverse-firm): Add links
  • Loading branch information
wpoulin authored Jan 5, 2023
1 parent e71550c commit 701dc99
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 194 deletions.
7 changes: 0 additions & 7 deletions src/apps/inverse-firm/common/inverse-firm.utils.ts

This file was deleted.

66 changes: 0 additions & 66 deletions src/apps/inverse-firm/ethereum/inverse-firm.balance-fetcher.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,118 +1,109 @@
import { Inject } from '@nestjs/common';
import { BigNumberish } from 'ethers';
import { uniq } from 'lodash';

import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface';
import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator';
import { getLabelFromToken } from '~app-toolkit/helpers/presentation/image.present';
import { DefaultDataProps } from '~position/display.interface';
import { MetaType } from '~position/position.interface';
import { ContractPositionTemplatePositionFetcher } from '~position/template/contract-position.template.position-fetcher';
import {
GetDisplayPropsParams,
GetTokenBalancesParams,
GetTokenDefinitionsParams,
} from '~position/template/contract-position.template.types';

import { InverseFirmContractFactory, SimpleMarket } from '../contracts';

export type InverseFirmLoanContractPositionDefinition = {
address: string;
suppliedTokenAddress: string;
borrowedTokenAddress: string;
};

@PositionTemplate()
export class EthereumInverseFirmLoanContractPositionFetcher extends ContractPositionTemplatePositionFetcher<
SimpleMarket,
DefaultDataProps,
InverseFirmLoanContractPositionDefinition
> {
groupLabel = 'Lending';

import { IAppToolkit, APP_TOOLKIT } from '~app-toolkit/app-toolkit.interface';
import { Register } from '~app-toolkit/decorators';
import { PositionFetcher } from '~position/position-fetcher.interface';
import { ContractPosition, MetaType } from '~position/position.interface';
import { Network } from '~types/network.interface';

import { InverseFirmContractFactory } from '../contracts';
import { INVERSE_FIRM_DEFINITION } from '../inverse-firm.definition';
import _ from 'lodash';
import { ContractType } from '~position/contract.interface';
import { borrowed, supplied } from '~position/position.utils';
import { getMarkets } from '../common/inverse-firm.utils';
import { getImagesFromToken } from '~app-toolkit/helpers/presentation/image.present';

const appId = INVERSE_FIRM_DEFINITION.id;
const dola = INVERSE_FIRM_DEFINITION.dola;
const dbr = INVERSE_FIRM_DEFINITION.dbr;
const groupId = INVERSE_FIRM_DEFINITION.groups.loan.id;
const network = Network.ETHEREUM_MAINNET;

@Register.ContractPositionFetcher({ appId, groupId, network })
export class EthereumInverseFirmLoanContractPositionFetcher implements PositionFetcher<ContractPosition> {
constructor(
@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit,
@Inject(InverseFirmContractFactory) private readonly inverseFirmContractFactory: InverseFirmContractFactory,
) { }
@Inject(APP_TOOLKIT) protected readonly appToolkit: IAppToolkit,
@Inject(InverseFirmContractFactory) private readonly contractFactory: InverseFirmContractFactory,
) {
super(appToolkit);
}

async getMarkets() {
const dbrContract = this.inverseFirmContractFactory.dbr({ address: dbr, network });
return getMarkets(dbrContract);
getContract(address: string): SimpleMarket {
return this.contractFactory.simpleMarket({ network: this.network, address });
}

async getPositions() {
const baseTokens = await this.appToolkit.getBaseTokenPrices(network);
const dolaToken = baseTokens.find(bt => bt.address === dola.toLowerCase())!;
const dolaAsBorrowToken = borrowed(dolaToken);

const markets = await this.getMarkets();

const multicall = this.appToolkit.getMulticall(network);
const dolaContract = this.appToolkit.globalContracts.erc20({ address: dola, network });

const marketsData = await Promise.all(
markets.map(m => {
const contract = this.inverseFirmContractFactory.simpleMarket({ address: m, network });
return Promise.all(
[
multicall.wrap(contract).totalDebt(),
multicall.wrap(contract).collateral(),
multicall.wrap(dolaContract).balanceOf(m),
]
);
})
async getDefinitions(): Promise<InverseFirmLoanContractPositionDefinition[]> {
const multicall = this.appToolkit.getMulticall(this.network);

const dolaBorrowRightContract = this.contractFactory.dbr({
address: '0xad038eb671c44b853887a7e32528fab35dc5d710',
network: this.network,
});

const logs = await dolaBorrowRightContract.queryFilter(dolaBorrowRightContract.filters.AddMarket(), 16155757);
const markets = uniq(logs.map(l => l.args.market.toLowerCase()));

const definitions = await Promise.all(
markets.map(async address => {
const simpleMarketContract = this.contractFactory.simpleMarket({ address, network: this.network });
const collateralTokenAddressRaw = await multicall.wrap(simpleMarketContract).collateral();

return {
address,
suppliedTokenAddress: collateralTokenAddressRaw.toLowerCase(),
borrowedTokenAddress: '0x865377367054516e17014ccded1e7d814edc9ce4', // dola
};
}),
);

const positions: ContractPosition[] = marketsData.map((data, i) => {
const collateralAddress = data[1];
const dolaBalance = data[2];
const liquidity = Number(dolaBalance) / 1e18;
const token = baseTokens.find(bt => bt.address === collateralAddress.toLowerCase())!;
const suppliedToken = supplied(token);

const tokens = [
{
"type": suppliedToken.type,
"network": suppliedToken.network,
"address": suppliedToken.address,
"symbol": suppliedToken.symbol,
"decimals": suppliedToken.decimals,
"price": suppliedToken.price,
metaType: MetaType.SUPPLIED,
},
{
"type": dolaAsBorrowToken.type,
"network": dolaAsBorrowToken.network,
"address": dolaAsBorrowToken.address,
"symbol": dolaAsBorrowToken.symbol,
"decimals": dolaAsBorrowToken.decimals,
"price": dolaAsBorrowToken.price,
metaType: MetaType.BORROWED,
},
];

return {
type: ContractType.POSITION,
address: markets[i],
appId,
groupId,
network,
tokens,
dataProps: {
liquidity,
},
displayProps: {
label: `${suppliedToken.symbol} Market`,
secondaryLabel: {
type: 'dollar',
value: suppliedToken.price,
},
images: getImagesFromToken(suppliedToken),
},
statsItems: [
{
"label": "Total Liquidity",
"value": {
"type": "dollar",
"value": liquidity,
}
},
],
}
})

return _.compact(positions);
return definitions;
}

async getTokenDefinitions({
definition,
}: GetTokenDefinitionsParams<SimpleMarket, InverseFirmLoanContractPositionDefinition>) {
return [
{
metaType: MetaType.SUPPLIED,
address: definition.suppliedTokenAddress,
network: this.network,
},
{
metaType: MetaType.BORROWED,
address: definition.borrowedTokenAddress,
network: this.network,
},
];
}

async getLabel({ contractPosition }: GetDisplayPropsParams<SimpleMarket>): Promise<string> {
return `${getLabelFromToken(contractPosition.tokens[0])} Market`;
}

async getTokenBalancesPerPosition({
address,
contract,
multicall,
}: GetTokenBalancesParams<SimpleMarket>): Promise<BigNumberish[]> {
const personalEscrow = await contract.escrows(address);

const simpleEscrowContract = this.contractFactory.simpleEscrow({
address: personalEscrow.toLowerCase(),
network: this.network,
});
const supplied = await multicall.wrap(simpleEscrowContract).balance();

const borrowed = await contract.debts(address);

return [supplied, borrowed];
}
}
9 changes: 6 additions & 3 deletions src/apps/inverse-firm/inverse-firm.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ export const INVERSE_FIRM_DEFINITION = appDefinition({
description: `FiRM is a Fixed-Rate lending protocol by Inverse Finance which allows borrowing the DOLA stablecoin at a fixed-rate through the utility token named DOLA Borrowing Right (DBR).`,
url: 'https://www.inverse.finance/firm',
tags: [AppTag.YIELD_AGGREGATOR, AppTag.LENDING],
links: {},
dola: '0x865377367054516e17014CcdED1e7d814EDC9ce4',
dbr: '0xAD038Eb671c44b853887A7E32528FaB35dC5D710',
links: {
discord: 'https://discord.com/invite/YpYJC7R5nv',
github: 'https://github.com/InverseFinance',
telegram: 'https://t.me/InverseFinance',
twitter: 'https://twitter.com/InverseFinance',
},

groups: {
loan: {
Expand Down
12 changes: 3 additions & 9 deletions src/apps/inverse-firm/inverse-firm.module.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import { Register } from '~app-toolkit/decorators';
import { AbstractApp } from '~app/app.dynamic-module';

import { InverseFirmContractFactory } from './contracts';
import { EthereumInverseFirmLoanContractPositionFetcher } from './ethereum/inverse-firm.loan.contract-position-fetcher';
import { EthereumInverseFirmBalanceFetcher } from './ethereum/inverse-firm.balance-fetcher';
import { InverseFirmAppDefinition, INVERSE_FIRM_DEFINITION } from './inverse-firm.definition';

@Register.AppModule({
appId: INVERSE_FIRM_DEFINITION.id,
imports: [],
providers: [
InverseFirmAppDefinition,
InverseFirmContractFactory,
EthereumInverseFirmLoanContractPositionFetcher,
EthereumInverseFirmBalanceFetcher,
],
providers: [InverseFirmAppDefinition, InverseFirmContractFactory, EthereumInverseFirmLoanContractPositionFetcher],
})
export class InverseFirmAppModule extends AbstractApp() { }
export class InverseFirmAppModule extends AbstractApp() {}
2 changes: 1 addition & 1 deletion src/network-provider/network-provider.registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const DEFAULT_REGISTRY: Record<Exclude<Network, Network.BITCOIN_MAINNET>,
[Network.AVALANCHE_MAINNET]: 'https://avalanche.public-rpc.com',
[Network.BINANCE_SMART_CHAIN_MAINNET]: 'https://bsc-dataseed.binance.org/',
[Network.CELO_MAINNET]: 'https://forno.celo.org',
[Network.ETHEREUM_MAINNET]: 'https://cloudflare-eth.com',
[Network.ETHEREUM_MAINNET]: 'https://eth-mainnet-public.unifra.io',
[Network.FANTOM_OPERA_MAINNET]: 'https://rpc.ftm.tools/',
[Network.GNOSIS_MAINNET]: 'https://rpc.gnosischain.com/',
[Network.HARMONY_MAINNET]: 'https://harmony.public-rpc.com',
Expand Down

0 comments on commit 701dc99

Please sign in to comment.