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

Commit

Permalink
feat(exactly): Serialize definition (#2878)
Browse files Browse the repository at this point in the history
  • Loading branch information
immasandwich committed Aug 6, 2023
1 parent f7f873c commit 9d7a2bd
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 10 deletions.
9 changes: 8 additions & 1 deletion src/apps/exactly/common/exactly.definitions-resolver.ts
Expand Up @@ -4,6 +4,7 @@ import { type BigNumber, constants } from 'ethers';
import type { IMulticallWrapper } from '~multicall/multicall.interface';
import type { DefaultAppTokenDefinition } from '~position/template/app-token.template.types';
import { Network } from '~types/network.interface';
import { serializeEthersResult } from '~utils/serialize-ethers';

import { type Previewer, Previewer__factory } from '../contracts/ethers';

Expand Down Expand Up @@ -35,7 +36,13 @@ export class ExactlyDefinitionsResolver {
multicall.contract.interface.decodeFunctionResult('getCurrentBlockTimestamp', ts)[0] as BigNumber
).toNumber();
return (previewer.decodeFunctionResult('exactly', exactly)[0] as Previewer.MarketAccountStructOutput[]).map(
m => ({ address: m.market.toLowerCase(), blockNumber, timestamp, ...m } as ExactlyMarketDefinition),
m =>
({
address: m.market.toLowerCase(),
blockNumber,
timestamp,
...serializeEthersResult(m),
} as ExactlyMarketDefinition),
);
}

Expand Down
6 changes: 4 additions & 2 deletions src/apps/exactly/common/exactly.deposit.token-fetcher.ts
@@ -1,4 +1,4 @@
import { type BigNumber, constants } from 'ethers';
import { BigNumber, constants } from 'ethers';

import type { GetDataPropsParams, GetTokenPropsParams } from '~position/template/app-token.template.types';

Expand Down Expand Up @@ -35,7 +35,9 @@ export abstract class ExactlyDepositFetcher extends ExactlyTokenFetcher {
const [prevTotalAssets] = market.interface.decodeFunctionResult('totalAssets', totalAssetsData) as [BigNumber];
const [prevTimestamp] = multicall.interface.decodeFunctionResult('getCurrentBlockTimestamp', tsData) as [BigNumber];

const shareValue = totalFloatingDepositAssets.mul(constants.WeiPerEther).div(totalFloatingDepositShares);
const shareValue = BigNumber.from(totalFloatingDepositAssets)
.mul(constants.WeiPerEther)
.div(totalFloatingDepositShares);
const prevShareValue = prevTotalAssets.mul(constants.WeiPerEther).div(prevTotalSupply);
const proportion = shareValue.mul(constants.WeiPerEther).div(prevShareValue);
return (Number(proportion) / 1e16 - 100) * (31_536_000 / (timestamp - prevTimestamp.toNumber()));
Expand Down
4 changes: 2 additions & 2 deletions src/apps/exactly/common/exactly.fixed-borrow.token-fetcher.ts
@@ -1,4 +1,4 @@
import { constants } from 'ethers';
import { BigNumber, constants } from 'ethers';

import type { IMulticallWrapper } from '~multicall/multicall.interface';
import type { AppTokenPosition } from '~position/position.interface';
Expand All @@ -19,7 +19,7 @@ export abstract class ExactlyFixedBorrowFetcher extends ExactlyFixedPositionFetc

getBestRate({ definition }: GetDataPropsParams<Market, ExactlyFixedMarketProps, ExactlyMarketDefinition>) {
return definition.fixedPools.reduce(
(best, { maturity, minBorrowRate: rate }) => (rate.lt(best.rate) ? { maturity, rate } : best),
(best, { maturity, minBorrowRate: rate }) => (BigNumber.from(rate).lt(best.rate) ? { maturity, rate } : best),
{ maturity: constants.Zero, rate: constants.MaxUint256 },
);
}
Expand Down
@@ -1,4 +1,4 @@
import { constants } from 'ethers';
import { BigNumber, constants } from 'ethers';

import type { IMulticallWrapper } from '~multicall/multicall.interface';
import type { AppTokenPosition } from '~position/position.interface';
Expand All @@ -18,7 +18,7 @@ export abstract class ExactlyFixedDepositFetcher extends ExactlyFixedPositionFet

getBestRate({ definition }: GetDataPropsParams<Market, ExactlyFixedMarketProps, ExactlyMarketDefinition>) {
return definition.fixedPools.reduce(
(best, { maturity, depositRate: rate }) => (rate.gt(best.rate) ? { maturity, rate } : best),
(best, { maturity, depositRate: rate }) => (BigNumber.from(rate).gt(best.rate) ? { maturity, rate } : best),
{ maturity: constants.Zero, rate: constants.Zero },
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/apps/exactly/common/exactly.fixed-position-fetcher.ts
Expand Up @@ -39,7 +39,7 @@ export abstract class ExactlyFixedPositionFetcher<

getApy(params: GetDataPropsParams<Market, ExactlyMarketProps, ExactlyMarketDefinition>) {
const { maturity, rate } = this.getBestRate(params);
const timeLeft = maturity.toNumber() - Math.round(Date.now() / 1_000);
const timeLeft = Number(maturity) - Math.round(Date.now() / 1_000);
return Promise.resolve(
((1 + ((Number(rate) / 1e18) * timeLeft) / 31_536_000) ** (31_536_000 / timeLeft) - 1) * 100,
);
Expand Down
4 changes: 2 additions & 2 deletions src/apps/exactly/common/exactly.token-fetcher.ts
@@ -1,5 +1,5 @@
import { Inject } from '@nestjs/common';
import { constants, type BigNumber } from 'ethers';
import { BigNumber, constants } from 'ethers';

import { APP_TOOLKIT, type IAppToolkit } from '~app-toolkit/app-toolkit.interface';
import { getLabelFromToken } from '~app-toolkit/helpers/presentation/image.present';
Expand Down Expand Up @@ -73,7 +73,7 @@ export abstract class ExactlyTokenFetcher<
async getPricePerShare(params: GetPricePerShareParams<Market, V, ExactlyMarketDefinition>) {
const [supply, totalAssets] = await Promise.all([this.getSupply(params), this.getTotalAssets(params)]);
if (!BigInt(String(supply))) return [1];
return [Number(totalAssets.mul(constants.WeiPerEther).div(supply)) / 1e18];
return [Number(BigNumber.from(totalAssets).mul(constants.WeiPerEther).div(supply)) / 1e18];
}

async getApy(params: GetDataPropsParams<Market, V, ExactlyMarketDefinition>) {
Expand Down
19 changes: 19 additions & 0 deletions src/utils/serialize-ethers.ts
@@ -0,0 +1,19 @@
import { isBigNumberish } from '@ethersproject/bignumber/lib/bignumber';
import _ from 'lodash';

const isPureArray = (obj: any): obj is any[] => {
const props = Object.getOwnPropertyNames(obj);
return _.isArray(obj) && props.every(key => key === 'length' || _.isInteger(_.toNumber(key)));
};

export const serializeEthersResult = (obj: Record<string, any>) => {
if (isPureArray(obj)) {
return obj.map(innerObj => serializeEthersResult(innerObj));
} else if (_.isObject(obj) && !isBigNumberish(obj)) {
return _.mapValues(obj, val => serializeEthersResult(val));
} else if (_.isString(obj) || _.isBoolean(obj) || _.isNumber(obj)) {
return obj;
} else {
return _.toString(obj);
}
};

0 comments on commit 9d7a2bd

Please sign in to comment.