diff --git a/src/abi/Range.json b/src/abi/Range.json index a65af8112b..24aed3e076 100644 --- a/src/abi/Range.json +++ b/src/abi/Range.json @@ -6,8 +6,8 @@ { "internalType": "contract ERC20", "name": "ohm_", "type": "address" }, { "internalType": "contract ERC20", "name": "reserve_", "type": "address" }, { "internalType": "uint256", "name": "thresholdFactor_", "type": "uint256" }, - { "internalType": "uint256", "name": "cushionSpread_", "type": "uint256" }, - { "internalType": "uint256", "name": "wallSpread_", "type": "uint256" } + { "internalType": "uint256[2]", "name": "lowSpreads_", "type": "uint256[2]" }, + { "internalType": "uint256[2]", "name": "highSpreads_", "type": "uint256[2]" } ], "stateMutability": "nonpayable", "type": "constructor" @@ -56,6 +56,7 @@ { "anonymous": false, "inputs": [ + { "indexed": false, "internalType": "bool", "name": "high_", "type": "bool" }, { "indexed": false, "internalType": "uint256", "name": "cushionSpread_", "type": "uint256" }, { "indexed": false, "internalType": "uint256", "name": "wallSpread_", "type": "uint256" } ], @@ -171,8 +172,8 @@ }, { "inputs": [ - { "internalType": "bool", "name": "wall_", "type": "bool" }, - { "internalType": "bool", "name": "high_", "type": "bool" } + { "internalType": "bool", "name": "high_", "type": "bool" }, + { "internalType": "bool", "name": "wall_", "type": "bool" } ], "name": "price", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], @@ -191,66 +192,62 @@ { "internalType": "uint48", "name": "lastActive", "type": "uint48" }, { "internalType": "uint256", "name": "capacity", "type": "uint256" }, { "internalType": "uint256", "name": "threshold", "type": "uint256" }, - { "internalType": "uint256", "name": "market", "type": "uint256" } - ], - "internalType": "struct RANGEv1.Side", - "name": "low", - "type": "tuple" - }, - { - "components": [ - { "internalType": "bool", "name": "active", "type": "bool" }, - { "internalType": "uint48", "name": "lastActive", "type": "uint48" }, - { "internalType": "uint256", "name": "capacity", "type": "uint256" }, - { "internalType": "uint256", "name": "threshold", "type": "uint256" }, - { "internalType": "uint256", "name": "market", "type": "uint256" } - ], - "internalType": "struct RANGEv1.Side", - "name": "high", - "type": "tuple" - }, - { - "components": [ + { "internalType": "uint256", "name": "market", "type": "uint256" }, { - "components": [{ "internalType": "uint256", "name": "price", "type": "uint256" }], - "internalType": "struct RANGEv1.Line", - "name": "high", + "components": [ + { "internalType": "uint256", "name": "price", "type": "uint256" }, + { "internalType": "uint256", "name": "spread", "type": "uint256" } + ], + "internalType": "struct RANGEv2.Line", + "name": "cushion", "type": "tuple" }, { - "components": [{ "internalType": "uint256", "name": "price", "type": "uint256" }], - "internalType": "struct RANGEv1.Line", - "name": "low", + "components": [ + { "internalType": "uint256", "name": "price", "type": "uint256" }, + { "internalType": "uint256", "name": "spread", "type": "uint256" } + ], + "internalType": "struct RANGEv2.Line", + "name": "wall", "type": "tuple" - }, - { "internalType": "uint256", "name": "spread", "type": "uint256" } + } ], - "internalType": "struct RANGEv1.Band", - "name": "cushion", + "internalType": "struct RANGEv2.Side", + "name": "low", "type": "tuple" }, { "components": [ + { "internalType": "bool", "name": "active", "type": "bool" }, + { "internalType": "uint48", "name": "lastActive", "type": "uint48" }, + { "internalType": "uint256", "name": "capacity", "type": "uint256" }, + { "internalType": "uint256", "name": "threshold", "type": "uint256" }, + { "internalType": "uint256", "name": "market", "type": "uint256" }, { - "components": [{ "internalType": "uint256", "name": "price", "type": "uint256" }], - "internalType": "struct RANGEv1.Line", - "name": "high", + "components": [ + { "internalType": "uint256", "name": "price", "type": "uint256" }, + { "internalType": "uint256", "name": "spread", "type": "uint256" } + ], + "internalType": "struct RANGEv2.Line", + "name": "cushion", "type": "tuple" }, { - "components": [{ "internalType": "uint256", "name": "price", "type": "uint256" }], - "internalType": "struct RANGEv1.Line", - "name": "low", + "components": [ + { "internalType": "uint256", "name": "price", "type": "uint256" }, + { "internalType": "uint256", "name": "spread", "type": "uint256" } + ], + "internalType": "struct RANGEv2.Line", + "name": "wall", "type": "tuple" - }, - { "internalType": "uint256", "name": "spread", "type": "uint256" } + } ], - "internalType": "struct RANGEv1.Band", - "name": "wall", + "internalType": "struct RANGEv2.Side", + "name": "high", "type": "tuple" } ], - "internalType": "struct RANGEv1.Range", + "internalType": "struct RANGEv2.Range", "name": "", "type": "tuple" } @@ -277,6 +274,7 @@ }, { "inputs": [ + { "internalType": "bool", "name": "high_", "type": "bool" }, { "internalType": "uint256", "name": "cushionSpread_", "type": "uint256" }, { "internalType": "uint256", "name": "wallSpread_", "type": "uint256" } ], @@ -293,7 +291,10 @@ "type": "function" }, { - "inputs": [{ "internalType": "bool", "name": "wall_", "type": "bool" }], + "inputs": [ + { "internalType": "bool", "name": "high_", "type": "bool" }, + { "internalType": "bool", "name": "wall_", "type": "bool" } + ], "name": "spread", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", @@ -328,7 +329,7 @@ "type": "function" }, { - "inputs": [{ "internalType": "uint256", "name": "movingAverage_", "type": "uint256" }], + "inputs": [{ "internalType": "uint256", "name": "target_", "type": "uint256" }], "name": "updatePrices", "outputs": [], "stateMutability": "nonpayable", diff --git a/src/constants/addresses.ts b/src/constants/addresses.ts index 346e875f70..a366f571ac 100644 --- a/src/constants/addresses.ts +++ b/src/constants/addresses.ts @@ -143,13 +143,13 @@ export const BALANCER_VAULT_ADDRESSSES = { }; export const RANGE_OPERATOR_ADDRESSES = { - [NetworkId.MAINNET]: "0x0374c001204eF5e7E4F5362A5A2430CB6c219326", - [NetworkId.TESTNET_GOERLI]: "0x255467F1ca090Cd0Ed20014DC957E942d846843b", + [NetworkId.MAINNET]: "0x0AE561226896dA978EaDA0Bec4a7d3CfAE04f506", + [NetworkId.TESTNET_GOERLI]: "0x6620592f9bdffAbadcea644a35946E7b93EaaF56", }; export const RANGE_ADDRESSES = { - [NetworkId.MAINNET]: "0xb212D9584cfc56EFf1117F412Fe0bBdc53673954", - [NetworkId.TESTNET_GOERLI]: "0x446f06f8Df7d5f627B073c6349b948B95c1f9185", + [NetworkId.MAINNET]: "0x399cD3685912bb56aAeD0949119dB6cE5Df60FB5", + [NetworkId.TESTNET_GOERLI]: "0xFF88b47af188d91aC05ff5E843B5F6863472EdD0", }; export const RANGE_PRICE_ADDRESSES = { diff --git a/src/views/Range/RangeChart.tsx b/src/views/Range/RangeChart.tsx index 874db34b1f..bc72883b3f 100644 --- a/src/views/Range/RangeChart.tsx +++ b/src/views/Range/RangeChart.tsx @@ -16,6 +16,7 @@ import { } from "recharts"; import { NameType } from "recharts/types/component/DefaultTooltipContent"; import { formatCurrency, parseBigNumber, trim } from "src/helpers"; +import { RANGEv2 as OlympusRange } from "src/typechain/Range"; import { OperatorMovingAverage, OperatorTargetPrice, PriceHistory } from "src/views/Range/hooks"; const PREFIX = "RangeChart"; @@ -39,7 +40,7 @@ const StyledResponsiveContainer = styled(ResponsiveContainer)(({ theme }) => ({ * Component for Displaying RangeChart */ const RangeChart = (props: { - rangeData: any; + rangeData: OlympusRange.RangeStructOutput; currentPrice: number; bidPrice: number; askPrice: number; @@ -53,10 +54,10 @@ const RangeChart = (props: { const { data: targetPrice } = OperatorTargetPrice(); const { data: movingAverage } = OperatorMovingAverage(); - const formattedWallHigh = trim(parseBigNumber(rangeData.wall.high.price, 18), 2); - const formattedWallLow = trim(parseBigNumber(rangeData.wall.low.price, 18), 2); - const formattedCushionHigh = trim(parseBigNumber(rangeData.cushion.high.price, 18), 2); - const formattedCushionLow = trim(parseBigNumber(rangeData.cushion.low.price, 18), 2); + const formattedWallHigh = trim(parseBigNumber(rangeData.high.wall.price, 18), 2); + const formattedWallLow = trim(parseBigNumber(rangeData.low.wall.price, 18), 2); + const formattedCushionHigh = trim(parseBigNumber(rangeData.high.cushion.price, 18), 2); + const formattedCushionLow = trim(parseBigNumber(rangeData.low.cushion.price, 18), 2); const chartData = priceData.map((item: any) => { return { ...item, @@ -128,19 +129,19 @@ const RangeChart = (props: { <> - Math.min(dataMin, askPrice, bidPrice, parseBigNumber(rangeData.wall.low.price, 18)) * 0.95, + Math.min(dataMin, askPrice, bidPrice, parseBigNumber(rangeData.low.wall.price, 18)) * 0.95, (dataMax: number) => - Math.max(dataMax, askPrice, bidPrice, parseBigNumber(rangeData.wall.low.price, 18)) * 1.05, + Math.max(dataMax, askPrice, bidPrice, parseBigNumber(rangeData.low.wall.price, 18)) * 1.05, ]} padding={{ top: 20, bottom: 20 }} tick={false} diff --git a/src/views/Range/__mocks__/mockRangeCalls.tsx b/src/views/Range/__mocks__/mockRangeCalls.tsx index db0aa79d85..b8a6bb91a4 100644 --- a/src/views/Range/__mocks__/mockRangeCalls.tsx +++ b/src/views/Range/__mocks__/mockRangeCalls.tsx @@ -1,22 +1,21 @@ import { BigNumber } from "ethers"; -import { RANGEv1 as OlympusRange } from "src/typechain/Range"; +import { RANGEv2 as OlympusRange } from "src/typechain/Range"; export const RangeData: OlympusRange.RangeStruct = { - cushion: { - high: { - price: BigNumber.from("22161077252064087762"), - }, - low: { - price: BigNumber.from("18131790478961526351"), - }, - spread: BigNumber.from("1000"), - }, high: { active: true, lastActive: 1656528651, capacity: BigNumber.from("605396958336933"), //9 decimals for OHM market: BigNumber.from("115792089237316195423570985008687907853269984665640564039457584007913129639935"), threshold: BigNumber.from("6054147227010"), + wall: { + price: BigNumber.from("24175720638615368468"), + spread: BigNumber.from(2000), + }, + cushion: { + price: BigNumber.from("22161077252064087762"), + spread: BigNumber.from(1000), + }, }, low: { active: true, @@ -24,11 +23,14 @@ export const RangeData: OlympusRange.RangeStruct = { capacity: BigNumber.from("10000000000000000000000000"), //18 decimals for Reserve market: BigNumber.from("115792089237316195423570985008687907853269984665640564039457584007913129639935"), threshold: BigNumber.from("100000000000000000000000"), - }, - wall: { - low: { price: BigNumber.from("13117147092410245645") }, - high: { price: BigNumber.from("24175720638615368468") }, - spread: BigNumber.from(2000), + wall: { + price: BigNumber.from("13117147092410245645"), + spread: BigNumber.from(2000), + }, + cushion: { + price: BigNumber.from("18131790478961526351"), + spread: BigNumber.from(1000), + }, }, }; diff --git a/src/views/Range/__tests__/Range.test.tsx b/src/views/Range/__tests__/Range.test.tsx index 1fb8b510a4..4d150e474e 100644 --- a/src/views/Range/__tests__/Range.test.tsx +++ b/src/views/Range/__tests__/Range.test.tsx @@ -9,6 +9,7 @@ import { connectWallet, invalidAddress } from "src/testHelpers"; import { fireEvent, render, screen } from "src/testUtils"; import * as IERC20Factory from "src/typechain/factories/IERC20__factory"; import * as RangeFactory from "src/typechain/factories/Range__factory"; +import { RANGEv2 as OlympusRange } from "src/typechain/Range"; import { RangeData } from "src/views/Range/__mocks__/mockRangeCalls"; import { Range } from "src/views/Range/index"; import { beforeEach, describe, expect, it, vi } from "vitest"; @@ -18,7 +19,7 @@ global.ResizeObserver = require("resize-observer-polyfill"); vi.mock("src/hooks/useContractAllowance"); vi.mock("src/views/Range/RangeChart", () => ({ default: (props: { - rangeData: any; + rangeData: OlympusRange.RangeStructOutput; currentPrice: number; bidPrice: number; askPrice: number; diff --git a/src/views/Range/hooks.tsx b/src/views/Range/hooks.tsx index 02e6385f60..2cf51e5271 100644 --- a/src/views/Range/hooks.tsx +++ b/src/views/Range/hooks.tsx @@ -18,7 +18,7 @@ import { queryAssertion } from "src/helpers/react-query/queryAssertion"; import { useOhmPrice } from "src/hooks/usePrices"; import { useTestableNetworks } from "src/hooks/useTestableNetworks"; import { BondFixedTermSDA__factory, BondTeller__factory, IERC20__factory } from "src/typechain"; -import { RANGEv1 as OlympusRange } from "src/typechain/Range"; +import { RANGEv2 as OlympusRange } from "src/typechain/Range"; import { useBondV3 } from "src/views/Bond/hooks/useBondV3"; import { useSigner } from "wagmi"; @@ -147,38 +147,34 @@ export const OperatorReserveSymbol = () => { export const RangeData = () => { const networks = useTestableNetworks(); const contract = RANGE_CONTRACT.getEthersContract(networks.MAINNET); - const { data = { high: sideStruct, low: sideStruct, - wall: band, - cushion: band, } as OlympusRange.RangeStructOutput, isFetched, isLoading, } = useQuery(["getRangeData", networks.MAINNET], async () => { const range = await contract.range(); + return range; }); return { data, isFetched, isLoading }; }; +const line: OlympusRange.LineStruct = { + price: BigNumber.from(0), + spread: BigNumber.from(0), +}; + const sideStruct: OlympusRange.SideStruct = { active: false, lastActive: 0, capacity: BigNumber.from(0), threshold: BigNumber.from(0), market: BigNumber.from(-1), -}; -const line: OlympusRange.LineStruct = { - price: BigNumber.from(0), -}; - -const band: OlympusRange.BandStruct = { - high: line, - low: line, - spread: BigNumber.from(0), + cushion: line, + wall: line, }; export const RangeBondMaxPayout = (id: BigNumber) => { @@ -235,6 +231,7 @@ export const DetermineRangePrice = (bidOrAsk: "bid" | "ask") => { const { data: rangeData } = RangeData(); const { data: upperBondMarket } = useBondV3({ id: rangeData.high.market.toString() }); const { data: lowerBondMarket } = useBondV3({ id: rangeData.low.market.toString(), isInverseBond: true }); + const { data = { price: 0, contract: "swap" }, isFetched, @@ -248,11 +245,11 @@ export const DetermineRangePrice = (bidOrAsk: "bid" | "ask") => { const activeBondMarket = market.gt(-1) && market.lt(ethers.constants.MaxUint256) && liveOnBondAggregator; //>=0 <=MAXUint256 const bondOutsideWall = bidOrAsk === "ask" - ? upperBondMarket?.price.inBaseToken.gt(new DecimalBigNumber(rangeData.wall.high.price, 18)) + ? upperBondMarket?.price.inBaseToken.gt(new DecimalBigNumber(rangeData.high.wall.price, 18)) : lowerBondMarket ? new DecimalBigNumber("1") .div(lowerBondMarket?.price.inBaseToken) - .lt(new DecimalBigNumber(rangeData.wall.low.price, 18)) + .lt(new DecimalBigNumber(rangeData.low.wall.price, 18)) : false; if (sideActive && activeBondMarket && !bondOutsideWall) { return { @@ -274,8 +271,8 @@ export const DetermineRangePrice = (bidOrAsk: "bid" | "ask") => { return { price: bidOrAsk === "ask" - ? parseBigNumber(rangeData.wall.high.price, 18) - : parseBigNumber(rangeData.wall.low.price, 18), + ? parseBigNumber(rangeData.high.wall.price, 18) + : parseBigNumber(rangeData.low.wall.price, 18), contract: "swap" as RangeContracts, }; } @@ -302,13 +299,13 @@ export const DetermineRangeDiscount = (bidOrAsk: "bid" | "ask") => { const bondDiscount = bidOrAskPrice.discount ? bidOrAskPrice.discount : undefined; const sellActive = bidOrAsk === "bid"; const swapWithOperator = sellActive - ? bidOrAskPrice.price < parseBigNumber(rangeData.wall.low.price, 18) - : bidOrAskPrice.price > parseBigNumber(rangeData.wall.high.price, 18); + ? bidOrAskPrice.price < parseBigNumber(rangeData.low.wall.price, 18) + : bidOrAskPrice.price > parseBigNumber(rangeData.high.wall.price, 18); const swapPrice = swapWithOperator ? sellActive - ? parseBigNumber(rangeData.wall.low.price, 18) - : parseBigNumber(rangeData.wall.high.price, 18) + ? parseBigNumber(rangeData.low.wall.price, 18) + : parseBigNumber(rangeData.high.wall.price, 18) : sellActive ? bidOrAskPrice.price : bidOrAskPrice.price; diff --git a/src/views/Range/index.tsx b/src/views/Range/index.tsx index daa51ac583..84fdf15ebe 100644 --- a/src/views/Range/index.tsx +++ b/src/views/Range/index.tsx @@ -77,10 +77,10 @@ export const Range = () => { }, [sellActive]); useEffect(() => { - if (currentPrice < parseBigNumber(rangeData.cushion.low.price, 18)) { + if (currentPrice < parseBigNumber(rangeData.low.cushion.price, 18)) { setSellActive(true); } - }, [rangeData.cushion.low.price, currentPrice]); + }, [rangeData.low.cushion.price, currentPrice]); const maxBalanceString = `${formatNumber(maxCapacity, 2)} ${buyAsset} (${formatNumber( sellActive ? maxCapacity / bidPrice.price : maxCapacity * askPrice.price,