Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions constants/legacyEmps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@ export const legacyEMPs: { [networkId: number]: string[] } = {
"0xe478461458A6846279005c9416256E230376069f",
"0xeb5c6dD4Ba0Bc93cbf9A5fDf8d6B1153a238f1CD", //"Perpetual", yUSD Kovan Oct30
"0x60d6c8E5Ca5D4A2aa1D0D4a4c72944A066008F75",
"0x7D1d0ad876168B0654391b8ADB17D1D157a29C41",
"0xC694Ce83BCf3f7f220BC9B62354CEC6A94446eBD",
"0x15Ff9a9831146642d55079deF442f7D304Ffa027",
],
};
4 changes: 3 additions & 1 deletion constants/syntheticTokenToExchangeMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export const EXCHANGE_LINK_MAP: ExchangeLinkMap = {
// This returns a Balancer exchange URL to swap `tokenAddress` and sell USDC, a well understood currency
};
/*
SUMERO FIX: case BTC added
SUMERO FIX: case BTC, Gold added
*/
// Returns a mapping from synthetic token to the type of exchange on which you can acquire the chosen token
export const getExchangeTypeFromTokenSymbol = (symbol: string | null) => {
Expand All @@ -76,6 +76,8 @@ export const getExchangeTypeFromTokenSymbol = (symbol: string | null) => {
return TOKEN_TO_EXCHANGE_MAP.openeth;
case symbol?.includes("BTC"):
return TOKEN_TO_EXCHANGE_MAP.usdbtc;
case symbol?.includes("Gold"):
return TOKEN_TO_EXCHANGE_MAP.usdbtc;
default:
return null;
}
Expand Down
7 changes: 6 additions & 1 deletion containers/DevMining.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import Connection from "./Connection";

export const defaultTotalRewards = 50000;
const sumeroEMPs = {
empWhitelist: ["0xe478461458A6846279005c9416256E230376069f"],
empWhitelist: [
"0xe478461458A6846279005c9416256E230376069f",
"0x7D1d0ad876168B0654391b8ADB17D1D157a29C41",
"0xC694Ce83BCf3f7f220BC9B62354CEC6A94446eBD",
"0x15Ff9a9831146642d55079deF442f7D304Ffa027",
],
totalReward: 35000,
};

Expand Down
300 changes: 119 additions & 181 deletions containers/EmpSponsors.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createContainer } from "unstated-next";
import { useState, useEffect } from "react";
import { utils } from "ethers";
import { ethers, utils } from "ethers";
const fromWei = utils.formatUnits;

import Connection from "./Connection";
Expand All @@ -14,6 +14,8 @@ import { isPricefeedInvertedFromTokenSymbol } from "../utils/getOffchainPrice";

import { useQuery } from "@apollo/client";
import { EMP_DATA } from "../apollo/uma/queries";
import LiquidationsData from "./LiquidationsData";
import SponsorsData from "./SponsorsData";

// Interfaces for dApp state storage.
interface SponsorPositionState {
Expand Down Expand Up @@ -70,88 +72,24 @@ const useEmpSponsors = () => {
const { latestPrice } = PriceFeed.useContainer();
const { decimals: collDecs } = Collateral.useContainer();
const { symbol: tokenSymbol } = Token.useContainer();
/*
SUMERO FIX: using events data instead of subgraphs for data query
*/
const {
liquidations: liquidationsEventsData,
loading: isGettingLiquidationsData,
} = LiquidationsData.useContainer();

const {
positionsData,
loading: isGettingPositionsData,
} = SponsorsData.useContainer();

const subgraphToQuery = `UMA${network?.chainId.toString()}`;
const { loading, error } = useQuery(EMP_DATA, {
context: { clientName: subgraphToQuery },
pollInterval: 10000,
});
// Data is hardcoded
const data = {
financialContracts: [
{
__typename: "FinancialContract",
id: "0xe478461458a6846279005c9416256e230376069f",
positions: [
{
__typename: "SponsorPosition",
collateral: "1.064204355139777562",
isEnded: false,
tokensOutstanding: "5",
withdrawalRequestPassTimestamp: "0",
withdrawalRequestAmount: "0",
transferPositionRequestPassTimestamp: "0",
sponsor: {
__typename: "Sponsor",
id: "0x53c91f33e4da805d04dce861c536fa1674e7334d",
},
},
{
__typename: "SponsorPosition",
collateral: "10",
isEnded: false,
tokensOutstanding: "33",
withdrawalRequestPassTimestamp: "0",
withdrawalRequestAmount: "0",
transferPositionRequestPassTimestamp: "0",
sponsor: {
__typename: "Sponsor",
id: "0x7eb9d67f9daea510399a1ee978b36e66626058d3",
},
},
{
__typename: "SponsorPosition",
collateral: "41.188539593994385011",
isEnded: false,
tokensOutstanding: "125.91889443999761803",
withdrawalRequestPassTimestamp: "0",
withdrawalRequestAmount: "0",
transferPositionRequestPassTimestamp: "0",
sponsor: {
__typename: "Sponsor",
id: "0xffb607418dbeab7a888e079a34be28a30d8e1de2",
},
},
],
liquidations: [
{
__typename: "Liquidation",
id:
"0xa77ac35aa49536cd0539798eeb2fee1b72f64679-0xfa3aa7ee08399a4ce0b4921c85ab7d645ccac669-0",
sponsor: {
__typename: "Sponsor",
id: "0xa77ac35aa49536cd0539798eeb2fee1b72f64679",
},
liquidationId: "0",
liquidator: "0x428ab2ba90eba0a4be7af34c9ac451ab061ac010",
disputer: null,
tokensLiquidated: "60",
lockedCollateral: "8.4002",
liquidatedCollateral: "8.4002",
status: "PreDispute",
events: [
{
__typename: "LiquidationCreatedEvent",
timestamp: "1613843412",
tx_hash:
"0xcb23eb1c291980bee6218e72971d08d6ea70200802a6c449a9dfe64e92643055",
},
],
},
],
},
],
};

const getCollateralRatio = (
collateral: number,
Expand All @@ -177,127 +115,127 @@ const useEmpSponsors = () => {
latestPrice !== null &&
collateralRequirement !== null &&
collDecs !== null &&
tokenSymbol !== null
tokenSymbol !== null &&
!isGettingLiquidationsData &&
!isGettingPositionsData
) {
if (error) {
console.error(`Apollo client failed to fetch graph data:`, error);
}
if (!loading && data) {
if (!loading) {
// The subgraph query doesn't have data of sumero emp contracts
const empData = data.financialContracts.find(
(contract: any) =>
utils.getAddress(contract.id).toLowerCase() ===
emp.address.toLowerCase()
);
if (empData) {
let newPositions: SponsorMap = {};
let newLiquidations: LiquidationMap = {};

const collReqFromWei = parseFloat(fromWei(collateralRequirement));

empData.positions.forEach((position: PositionQuery) => {
if (position.isEnded) return;

const sponsor = utils.getAddress(position.sponsor.id);
const backingCollateral =
Number(position.collateral) -
Number(position.withdrawalRequestAmount);

const cRatio = getCollateralRatio(
backingCollateral,
Number(position.tokensOutstanding),
latestPrice
);
const liquidationPrice = getLiquidationPrice(
backingCollateral,
Number(position.tokensOutstanding),
collReqFromWei,
isPricefeedInvertedFromTokenSymbol(tokenSymbol)
);
const pendingWithdraw =
position.withdrawalRequestPassTimestamp === "0" ? "No" : "Yes";
// const empData = data.financialContracts.find(
// (contract: any) =>
// utils.getAddress(contract.id).toLowerCase() ===
// emp.address.toLowerCase()
// );
// if (empData) {
let newPositions: SponsorMap = {};
let newLiquidations: LiquidationMap = {};

const collReqFromWei = parseFloat(fromWei(collateralRequirement));

positionsData.forEach((position: PositionQuery) => {
if (position.isEnded) return;

const sponsor = utils.getAddress(position.sponsor.id);
const backingCollateral =
Number(position.collateral) -
Number(position.withdrawalRequestAmount);

const cRatio = getCollateralRatio(
backingCollateral,
Number(position.tokensOutstanding),
latestPrice
);
const liquidationPrice = getLiquidationPrice(
backingCollateral,
Number(position.tokensOutstanding),
collReqFromWei,
isPricefeedInvertedFromTokenSymbol(tokenSymbol)
);
const pendingWithdraw =
position.withdrawalRequestPassTimestamp === "0" ? "No" : "Yes";

const pendingTransfer =
position.transferPositionRequestPassTimestamp === "0"
? "No"
: "Yes";
if (
position.tokensOutstanding !== "0" &&
position.collateral !== "0"
) {
newPositions[sponsor] = {
tokensOutstanding: position.tokensOutstanding,
collateral: position.collateral,
backingCollateral: backingCollateral.toString(),
cRatio: cRatio.toString(),
liquidationPrice: liquidationPrice.toString(),
pendingWithdraw: pendingWithdraw,
pendingTransfer: pendingTransfer,
withdrawalRequestAmount: position.withdrawalRequestAmount,
withdrawalTimestamp: position.withdrawalRequestPassTimestamp,
transferTimestamp: position.transferPositionRequestPassTimestamp,
sponsor,
};
}
});

liquidationsEventsData.forEach((liquidation) => {
const liquidationCreatedEvent = liquidation.events.find(
(e) => e.__typename === "LiquidationCreatedEvent"
);

// There should always be a LiquidationCreatedEvent associated with each liquidation object, but if not then
// we will just ignore this strange edge case.
if (liquidationCreatedEvent) {
const liquidatedCR =
parseFloat(liquidation.tokensLiquidated) > 0
? parseFloat(liquidation.liquidatedCollateral) /
parseFloat(liquidation.tokensLiquidated)
: 0;
const maxDisputablePrice =
parseFloat(liquidation.tokensLiquidated) > 0 && collReqFromWei > 0
? parseFloat(liquidation.liquidatedCollateral) /
(parseFloat(liquidation.tokensLiquidated) * collReqFromWei)
: 0;

const pendingTransfer =
position.transferPositionRequestPassTimestamp === "0"
? "No"
: "Yes";
if (
position.tokensOutstanding !== "0" &&
position.collateral !== "0"
liquidation.tokensLiquidated !== "0" &&
liquidation.lockedCollateral !== "0"
) {
newPositions[sponsor] = {
tokensOutstanding: position.tokensOutstanding,
collateral: position.collateral,
backingCollateral: backingCollateral.toString(),
cRatio: cRatio.toString(),
liquidationPrice: liquidationPrice.toString(),
pendingWithdraw: pendingWithdraw,
pendingTransfer: pendingTransfer,
withdrawalRequestAmount: position.withdrawalRequestAmount,
withdrawalTimestamp: position.withdrawalRequestPassTimestamp,
transferTimestamp:
position.transferPositionRequestPassTimestamp,
sponsor,
// The UMA subgraph uniquely identifies each liquidation with an "id" that concatenates
// the liquidated sponsor's address with the liquidation ID, for example:
// "0x1e17a75616cd74f5846b1b71622aa8e10ea26cc0-0"
const sponsorAddressPlusId = liquidation.id;
newLiquidations[sponsorAddressPlusId] = {
sponsor: utils.getAddress(liquidation.sponsor.id),
liquidator: liquidation.liquidator,
disputer: String(liquidation.disputer),
liquidationId: liquidation.liquidationId,
liquidatedCR: liquidatedCR.toString(),
maxDisputablePrice: maxDisputablePrice.toString(),
tokensLiquidated: liquidation.tokensLiquidated,
lockedCollateral: liquidation.lockedCollateral,
liquidatedCollateral: liquidation.liquidatedCollateral,
status: liquidation.status,
liquidationTimestamp: liquidationCreatedEvent.timestamp,
liquidationReceipt: liquidationCreatedEvent.tx_hash,
};
}
});

empData.liquidations.forEach((liquidation) => {
const liquidationCreatedEvent = liquidation.events.find(
(e) => e.__typename === "LiquidationCreatedEvent"
);

// There should always be a LiquidationCreatedEvent associated with each liquidation object, but if not then
// we will just ignore this strange edge case.
if (liquidationCreatedEvent) {
const liquidatedCR =
parseFloat(liquidation.tokensLiquidated) > 0
? parseFloat(liquidation.liquidatedCollateral) /
parseFloat(liquidation.tokensLiquidated)
: 0;
const maxDisputablePrice =
parseFloat(liquidation.tokensLiquidated) > 0 &&
collReqFromWei > 0
? parseFloat(liquidation.liquidatedCollateral) /
(parseFloat(liquidation.tokensLiquidated) * collReqFromWei)
: 0;

if (
liquidation.tokensLiquidated !== "0" &&
liquidation.lockedCollateral !== "0"
) {
// The UMA subgraph uniquely identifies each liquidation with an "id" that concatenates
// the liquidated sponsor's address with the liquidation ID, for example:
// "0x1e17a75616cd74f5846b1b71622aa8e10ea26cc0-0"
const sponsorAddressPlusId = liquidation.id;
newLiquidations[sponsorAddressPlusId] = {
sponsor: utils.getAddress(liquidation.sponsor.id),
liquidator: liquidation.liquidator,
disputer: String(liquidation.disputer),
liquidationId: liquidation.liquidationId,
liquidatedCR: liquidatedCR.toString(),
maxDisputablePrice: maxDisputablePrice.toString(),
tokensLiquidated: liquidation.tokensLiquidated,
lockedCollateral: liquidation.lockedCollateral,
liquidatedCollateral: liquidation.liquidatedCollateral,
status: liquidation.status,
liquidationTimestamp: liquidationCreatedEvent.timestamp,
liquidationReceipt: liquidationCreatedEvent.tx_hash,
};
}
}
});
setActivePositions(newPositions);
setLiquidations(newLiquidations);
}
}
});
console.log("newLiquidations", newLiquidations);
setActivePositions(newPositions);
setLiquidations(newLiquidations);
}
}
};

// Change state when emp changes or when the graphQL data changes due to polling.
useEffect(() => {
querySponsors();
}, [emp, latestPrice]);
}, [emp, latestPrice, liquidationsEventsData]);

return { activeSponsors: activePositions, liquidations: liquidations };
};
Expand Down
Loading