Skip to content

Commit

Permalink
Add up all external incentive APYs for a specific duration (#916)
Browse files Browse the repository at this point in the history
* Add up all external incentives for a specific duration

* Remove console

* Refactor to accept gaugeId instead

* Fix type issues

* Update comment

* Update comment

* Refactor to stop checking for duration
  • Loading branch information
srph authored Oct 24, 2022
1 parent b9510f3 commit 00415a3
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 42 deletions.
45 changes: 21 additions & 24 deletions packages/stores/src/queries/pool-incentives/incentivized-pools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import {
ObservableQueryEpochProvisions,
ObservableQueryMintParmas,
} from "../mint";
import { ObservableQueryPools, ExternalGauge } from "../pools";
import { ObservableQueryPools } from "../pools";
import { IPriceStore } from "../../price";
import { ObservableQueryDistrInfo } from "./distr-info";
import { ObservableQueryLockableDurations } from "./lockable-durations";
import { ObservableQueryGuage } from "../incentives";
import { IncentivizedPools } from "./types";

export class ObservableQueryIncentivizedPools extends ObservableChainQuery<IncentivizedPools> {
Expand All @@ -27,7 +28,8 @@ export class ObservableQueryIncentivizedPools extends ObservableChainQuery<Incen
protected readonly queryPools: ObservableQueryPools,
protected readonly queryMintParmas: ObservableQueryMintParmas,
protected readonly queryEpochProvision: ObservableQueryEpochProvisions,
protected readonly queryEpochs: ObservableQueryEpochs
protected readonly queryEpochs: ObservableQueryEpochs,
protected readonly queryGauge: ObservableQueryGuage
) {
super(
kvStore,
Expand Down Expand Up @@ -119,51 +121,46 @@ export class ObservableQueryIncentivizedPools extends ObservableChainQuery<Incen
);

/**
* Computes external incentive APY for the given duration
* Computes the external incentive APR for the given gaugeId and denom
*/
readonly computeExternalIncentiveAPYForSpecificDuration = computedFn(
readonly computeExternalIncentiveGaugeAPR = computedFn(
(
poolId: string,
duration: Duration,
gaugeId: string,
denom: string,
priceStore: IPriceStore,
fiatCurrency: FiatCurrency,
allowedGauges: ExternalGauge[]
fiatCurrency: FiatCurrency
): RatePretty => {
if (!allowedGauges.length) {
const observableGauge = this.queryGauge.get(gaugeId);

if (observableGauge.remainingEpoch < 1) {
return new RatePretty(new Dec(0));
}

const externalGauge = allowedGauges.find((externalGauge) => {
return (
duration.asMilliseconds() === externalGauge.duration.asMilliseconds()
);
});
const chainInfo = this.chainGetter.getChain(this.chainId);

const mintCurrency = chainInfo.findCurrency(denom);

if (!externalGauge?.rewardAmount) {
if (!mintCurrency?.coinGeckoId) {
return new RatePretty(new Dec(0));
}

const rewardAmount = observableGauge.getRemainingCoin(mintCurrency);

const pool = this.queryPools.getPool(poolId);

if (!pool) {
return new RatePretty(new Dec(0));
}

const mintDenom = this.queryMintParmas.mintDenom;
const epochIdentifier = this.queryMintParmas.epochIdentifier;

if (!mintDenom || !epochIdentifier) {
if (!epochIdentifier) {
return new RatePretty(new Dec(0));
}

const epoch = this.queryEpochs.getEpoch(epochIdentifier);

const chainInfo = this.chainGetter.getChain(this.chainId);

const mintCurrency = chainInfo.findCurrency(
externalGauge.rewardAmount.currency.coinMinimalDenom
);

if (!mintCurrency?.coinGeckoId || !epoch.duration) {
return new RatePretty(new Dec(0));
}
Expand Down Expand Up @@ -193,11 +190,11 @@ export class ObservableQueryIncentivizedPools extends ObservableChainQuery<Incen
.asMilliseconds() / epoch.duration.asMilliseconds();

const externalIncentivePrice = new Dec(mintPrice.toString()).mul(
externalGauge.rewardAmount.toDec()
rewardAmount.toDec()
);

const yearProvision = new Dec(numEpochPerYear.toString()).quo(
new Dec(externalGauge.remainingEpochs)
new Dec(observableGauge.remainingEpoch)
);

// coins = (X coin's price in USD * remaining incentives in X tokens * (365 / remaining days in gauge))
Expand Down
5 changes: 3 additions & 2 deletions packages/stores/src/queries/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export class OsmosisQueriesImpl {
chainId,
chainGetter
);
this.queryGauge = new ObservableQueryGuage(kvStore, chainId, chainGetter);
this.queryIncentivizedPools = new ObservableQueryIncentivizedPools(
kvStore,
chainId,
Expand All @@ -176,9 +177,9 @@ export class OsmosisQueriesImpl {
this.queryGammPools,
this.queryMintParams,
this.queryEpochProvisions,
this.queryEpochs
this.queryEpochs,
this.queryGauge
);
this.queryGauge = new ObservableQueryGuage(kvStore, chainId, chainGetter);
this.queryPoolsGaugeIds = new ObservableQueryPoolsGaugeIds(
kvStore,
chainId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import { RatePretty } from "@keplr-wallet/unit";
import { Duration } from "dayjs/plugin/duration";
import { ObservableQueryEpochs } from "../epochs";
import { ObservableQueryEpochProvisions, ObservableQueryMintParmas } from "../mint";
import { ObservableQueryPools, ExternalGauge } from "../pools";
import { ObservableQueryPools } from "../pools";
import { IPriceStore } from "../../price";
import { ObservableQueryDistrInfo } from "./distr-info";
import { ObservableQueryLockableDurations } from "./lockable-durations";
import { ObservableQueryGuage } from "../incentives";
import { IncentivizedPools } from "./types";
export declare class ObservableQueryIncentivizedPools extends ObservableChainQuery<IncentivizedPools> {
protected readonly queryLockableDurations: ObservableQueryLockableDurations;
Expand All @@ -17,7 +18,8 @@ export declare class ObservableQueryIncentivizedPools extends ObservableChainQue
protected readonly queryMintParmas: ObservableQueryMintParmas;
protected readonly queryEpochProvision: ObservableQueryEpochProvisions;
protected readonly queryEpochs: ObservableQueryEpochs;
constructor(kvStore: KVStore, chainId: string, chainGetter: ChainGetter, queryLockableDurations: ObservableQueryLockableDurations, queryDistrInfo: ObservableQueryDistrInfo, queryPools: ObservableQueryPools, queryMintParmas: ObservableQueryMintParmas, queryEpochProvision: ObservableQueryEpochProvisions, queryEpochs: ObservableQueryEpochs);
protected readonly queryGauge: ObservableQueryGuage;
constructor(kvStore: KVStore, chainId: string, chainGetter: ChainGetter, queryLockableDurations: ObservableQueryLockableDurations, queryDistrInfo: ObservableQueryDistrInfo, queryPools: ObservableQueryPools, queryMintParmas: ObservableQueryMintParmas, queryEpochProvision: ObservableQueryEpochProvisions, queryEpochs: ObservableQueryEpochs, queryGauge: ObservableQueryGuage);
/** Internally incentivized pools. */
get incentivizedPools(): string[];
/** Is incentivized internally. */
Expand All @@ -29,9 +31,9 @@ export declare class ObservableQueryIncentivizedPools extends ObservableChainQue
*/
readonly computeMostAPY: (poolId: string, priceStore: IPriceStore) => RatePretty;
/**
* Computes external incentive APY for the given duration
* Computes the external incentive APR for the given gaugeId and denom
*/
readonly computeExternalIncentiveAPYForSpecificDuration: (poolId: string, duration: Duration, priceStore: IPriceStore, fiatCurrency: FiatCurrency, allowedGauges: ExternalGauge[]) => RatePretty;
readonly computeExternalIncentiveGaugeAPR: (poolId: string, gaugeId: string, denom: string, priceStore: IPriceStore, fiatCurrency: FiatCurrency) => RatePretty;
/**
* 리워드를 받을 수 있는 풀의 연당 이익률을 반환한다.
* 리워드를 받을 수 없는 풀일 경우 0를 리턴한다.
Expand Down
41 changes: 29 additions & 12 deletions packages/web/pages/pool/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,29 +193,46 @@ const Pool: FunctionComponent = observer(() => {
gaugeDurationMap.set(gauge.duration.asSeconds(), gauge);
});

// Compute combined APR (internal gauge + white-listed external gauge)
const allowedExternalGauges =
pool?.id && ExternalIncentiveGaugeAllowList[pool.id]
? ExternalIncentiveGaugeAllowList[pool.id]
: [];

// Combine the internal incentive APR and sum of external incentive APRs
gaugeDurationMap.forEach((gauge) => {
const baseApy = queryOsmosis.queryIncentivizedPools.computeAPY(
const baseAPR = queryOsmosis.queryIncentivizedPools.computeAPY(
pool?.id ?? "",
gauge.duration,
priceStore,
fiat
);

const externalApy =
queryOsmosis.queryIncentivizedPools.computeExternalIncentiveAPYForSpecificDuration(
pool?.id ?? "",
gauge.duration,
priceStore,
fiat,
allowedGauges
);
const externalAPR = allowedGauges
.filter(
(extGauge) =>
extGauge.duration.asMilliseconds() ===
gauge.duration.asMilliseconds()
)
.reduce((apr, extGauge) => {
const denom =
allowedExternalGauges.find((allowList) => {
return allowList.gaugeId === extGauge.id;
})?.denom ?? "";

const totalApr = baseApy.add(externalApy);
return apr.add(
queryOsmosis.queryIncentivizedPools.computeExternalIncentiveGaugeAPR(
pool?.id ?? "",
extGauge.id,
denom,
priceStore,
fiat
)
);
}, new RatePretty(new Dec(0)));

gaugeDurationMap.set(gauge.duration.asSeconds(), {
...gauge,
apr: totalApr,
apr: baseAPR.add(externalAPR),
});
});

Expand Down

2 comments on commit 00415a3

@vercel
Copy link

@vercel vercel bot commented on 00415a3 Oct 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 00415a3 Oct 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.