Skip to content

Commit

Permalink
feat: add tezos's cdp kolibri
Browse files Browse the repository at this point in the history
iiAku committed Jan 24, 2023
1 parent 5b9d9f1 commit 0b66d1d
Showing 3 changed files with 121 additions and 0 deletions.
24 changes: 24 additions & 0 deletions liquidations/kolibri/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { CONTRACTS, HarbingerClient } from "@hover-labs/kolibri-js";
import { OVEN_DATA_BASE_URL, TEZOS_RPC, getOvens, mapOven } from "./utils";

import { Liq } from "../utils/types";

const harbingerClient = new HarbingerClient(
TEZOS_RPC,
CONTRACTS.MAIN.HARBINGER_NORMALIZER
);

const positions = async (): Promise<Liq[]> => {
const [ovens, { price }] = await Promise.all([
getOvens(OVEN_DATA_BASE_URL),
harbingerClient.getPriceData(),
]);

return Promise.all(ovens.map((oven) => mapOven(oven, price)));
};

module.exports = {
tezos: {
liquidations: positions(),
},
};
96 changes: 96 additions & 0 deletions liquidations/kolibri/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import BigNumber from "bignumber.js";
import { ConversionUtils } from "@hover-labs/kolibri-js";
import { Liq } from "../utils/types";
import axios from "axios";

/*
Credits goes to: https://github.com/Hover-Labs/kolibri-js/blob/master/src/oven-client.ts
As the vast majority of helpers from here were either took, modified or inspired from kolibri-js module
*/

export const TEZOS_RPC = process.env.TEZOS_RPC || "https://rpc.tzkt.io/mainnet";
export const OVEN_DATA_BASE_URL =
"https://kolibri-data.s3.amazonaws.com/mainnet/oven-data.json";

const MUTEZ_DIGITS = 6;
const SHARD_DIGITS = 18;

export const MUTEZ_TO_SHARD = new BigNumber(
Math.pow(10, SHARD_DIGITS - MUTEZ_DIGITS)
);

export const SHARD_PRECISION = new BigNumber(Math.pow(10, SHARD_DIGITS));

export interface KolibriOven {
ovenAddress: string;
ovenOwner: string;
baker: string;
balance: string;
borrowedTokens: string;
stabilityFees: string;
isLiquidated: boolean;
outstandingTokens: string;
}

const liquidatablePrice = (rate: BigNumber, price: BigNumber) => {
const t = 1 - rate.toNumber();
const a = price.dividedBy(Math.pow(10, 6));
return a.minus(a.times(t));
};

export const customGetCollateralUtilization = (
price: BigNumber,
balance: BigNumber,
outstandingTokens: BigNumber
) => {
const priceShard = price.multipliedBy(MUTEZ_TO_SHARD);
const collateralValue = balance
.multipliedBy(MUTEZ_TO_SHARD)
.multipliedBy(priceShard)
.dividedBy(SHARD_PRECISION);

return new BigNumber(
outstandingTokens
.times(Math.pow(10, SHARD_DIGITS))
.dividedBy(collateralValue)
.toFixed(0)
);
};

export const getOvens = async (ovenBaseUrl) => {
const {
data: { allOvenData },
} = await axios.get(ovenBaseUrl);

//remvoving liquidated + empty ovens
return (allOvenData as KolibriOven[]).filter(
(oven) => oven.isLiquidated === false && parseInt(oven.balance, 10) > 0
);
};

export const mapOven = async (
{ balance, ovenAddress, ovenOwner, outstandingTokens }: KolibriOven,
price: BigNumber
) => {
const ovenBalance = new BigNumber(balance);
const collateralUtilization = customGetCollateralUtilization(
price,
ovenBalance,
new BigNumber(outstandingTokens)
);
const rate = collateralUtilization.multipliedBy(2);
const liquidatablePriceValue = liquidatablePrice(rate, price);

return {
owner: ovenOwner,
liqPrice: parseFloat(
ConversionUtils.shardToHumanReadableNumber(liquidatablePriceValue)
),
collateral: `tezos:${ovenAddress}`,
collateralAmount: ovenBalance.toString(),
extra: {
url: `https://tzkt.io/${ovenAddress}/operations/`,
owner: `https://tzkt.io/${ovenOwner}/operations/`,
},
} as Liq;
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
"license": "ISC",
"dependencies": {
"@defillama/sdk": "latest",
"@hover-labs/kolibri-js": "^4.1.3",
"@project-serum/anchor": "^0.25.0",
"@solana/web3.js": "^1.36.0",
"@solendprotocol/solend-sdk": "^0.6.2",

0 comments on commit 0b66d1d

Please sign in to comment.