diff --git a/src/views/Bond/hooks/useBondV3.ts b/src/views/Bond/hooks/useBondV3.ts
index 274992003a..a384b937d7 100644
--- a/src/views/Bond/hooks/useBondV3.ts
+++ b/src/views/Bond/hooks/useBondV3.ts
@@ -1,7 +1,8 @@
import { useQuery } from "@tanstack/react-query";
import { BigNumber } from "ethers";
import { NetworkId } from "src/constants";
-import { BOND_AGGREGATOR_CONTRACT, BOND_FIXED_EXPIRY_TELLER } from "src/constants/contracts";
+import { RANGE_OPERATOR_ADDRESSES } from "src/constants/addresses";
+import { BOND_AGGREGATOR_CONTRACT, BOND_FIXED_EXPIRY_TELLER, RANGE_PRICE_CONTRACT } from "src/constants/contracts";
import { OHM_TOKEN } from "src/constants/tokens";
import { getTokenByAddress } from "src/helpers/contracts/getTokenByAddress";
import { DecimalBigNumber } from "src/helpers/DecimalBigNumber/DecimalBigNumber";
@@ -73,7 +74,12 @@ export const fetchBondV3 = async ({ id, isInverseBond, networkId }: UseBondOptio
const quoteTokenPerBaseToken = new DecimalBigNumber(bondMarketPrice.mul(shift), 36);
const bondTeller = BOND_FIXED_EXPIRY_TELLER.getEthersContract(networkId);
const bondToken = await bondTeller.getBondTokenForMarket(id);
- const priceInUsd = quoteTokenPerUsd.mul(quoteTokenPerBaseToken);
+ const rbsBond = market.owner === RANGE_OPERATOR_ADDRESSES[networkId];
+ const rangePriceContract = RANGE_PRICE_CONTRACT.getEthersContract(networkId);
+ const priceInUsd = rbsBond
+ ? new DecimalBigNumber(await rangePriceContract.getCurrentPrice(), 18).mul(quoteTokenPerBaseToken)
+ : quoteTokenPerUsd.mul(quoteTokenPerBaseToken);
+
const discount = baseTokenPerUsd.sub(priceInUsd).div(baseTokenPerUsd);
/**
diff --git a/src/views/Range/__mocks__/mockRangeCalls.tsx b/src/views/Range/__mocks__/mockRangeCalls.tsx
index 1b8f579f44..db0aa79d85 100644
--- a/src/views/Range/__mocks__/mockRangeCalls.tsx
+++ b/src/views/Range/__mocks__/mockRangeCalls.tsx
@@ -26,7 +26,7 @@ export const RangeData: OlympusRange.RangeStruct = {
threshold: BigNumber.from("100000000000000000000000"),
},
wall: {
- low: { price: BigNumber.from("16117147092410245645") },
+ low: { price: BigNumber.from("13117147092410245645") },
high: { price: BigNumber.from("24175720638615368468") },
spread: BigNumber.from(2000),
},
diff --git a/src/views/Range/__tests__/Range.tsx b/src/views/Range/__tests__/Range.tsx
index 7accf33ec9..006c81bb3e 100644
--- a/src/views/Range/__tests__/Range.tsx
+++ b/src/views/Range/__tests__/Range.tsx
@@ -162,32 +162,32 @@ describe("Sell Tab Main Range View", () => {
expect(await screen.findByTestId("max-row")).toHaveTextContent("Max You Can Sell");
});
- it("Should Display Premium instead of Discount", async () => {
+ it("Should Display Discount instead of Premium", async () => {
const { container } = render();
fireEvent.click(container.getElementsByClassName("arrow-wrapper")[0]);
- expect(await screen.findByTestId("premium-discount")).toHaveTextContent("Premium");
+ expect(await screen.findByTestId("premium-discount")).toHaveTextContent("Discount");
});
- it("Should populate DAI Value automatically with 100 when 6.204572026713784 DAI amount is entered", async () => {
+ it("Should populate DAI Value automatically with 81.38628391985866 when 6.204572026713784 DAI amount is entered", async () => {
const { container } = render();
fireEvent.click(container.getElementsByClassName("arrow-wrapper")[0]);
fireEvent.input(await screen.findByTestId("ohm-amount"), { target: { value: "6.204572026713784" } });
- expect(await screen.findByTestId("reserve-amount")).toHaveValue("100");
+ expect(await screen.findByTestId("reserve-amount")).toHaveValue("81.38628391985866");
});
- it("Should populate OHM Value automatically with 6.204572026713784 OHM when 100 DAI is entered", async () => {
+ it("Should populate OHM Value automatically with 7.623608952122014 OHM when 100 DAI is entered", async () => {
const { container } = render();
fireEvent.click(container.getElementsByClassName("arrow-wrapper")[0]);
fireEvent.input(await screen.findByTestId("reserve-amount"), { target: { value: "100" } });
- expect(await screen.findByTestId("ohm-amount")).toHaveValue("6.204572026713784");
+ expect(await screen.findByTestId("ohm-amount")).toHaveValue("7.623608952122014");
});
it("Should change the OHM Value when switching back to the Buy Tab", async () => {
const { container } = render();
fireEvent.click(container.getElementsByClassName("arrow-wrapper")[0]);
fireEvent.input(await screen.findByTestId("ohm-amount"), { target: { value: "6.204572026713784" } });
- expect(await screen.findByTestId("reserve-amount")).toHaveValue("100");
+ expect(await screen.findByTestId("reserve-amount")).toHaveValue("81.38628391985866");
fireEvent.click(container.getElementsByClassName("arrow-wrapper")[0]);
- expect(await screen.findByTestId("ohm-amount")).toHaveValue("4.136381351142522");
+ expect(await screen.findByTestId("ohm-amount")).toHaveValue("3.366447070448939");
});
it("Should display Amount exceeds balance when OHM amount entered exceeds balance", async () => {
@@ -209,10 +209,10 @@ describe("Sell Tab Main Range View", () => {
expect(await screen.findByTestId("ohm-amount")).toHaveValue("10");
});
- it("Should render with Bid price of $16.12 on chart", async () => {
+ it("Should render with Bid price of $13.12 on chart", async () => {
const { container } = render();
fireEvent.click(container.getElementsByClassName("arrow-wrapper")[0]);
- expect(await screen.findByText("Bid: $16.12"));
+ expect(await screen.findByText("Bid: $13.12"));
});
});
diff --git a/src/views/Range/__tests__/RangeBondsUpper.tsx b/src/views/Range/__tests__/RangeBondsUpper.tsx
index 1193528d73..c5a9392304 100644
--- a/src/views/Range/__tests__/RangeBondsUpper.tsx
+++ b/src/views/Range/__tests__/RangeBondsUpper.tsx
@@ -44,7 +44,7 @@ describe("Upper Wall Active Bond Market", () => {
Balance.useBalance = jest.fn().mockReturnValue({ 1: { data: new DecimalBigNumber("10", 9) } });
//@ts-expect-error
rangeData.mockReturnValueOnce({
- range: jest.fn().mockReturnValueOnce({ ...RangeData, high: { ...RangeData.high, market: BigNumber.from("1") } }),
+ range: jest.fn().mockReturnValueOnce({ ...RangeData, high: { ...RangeData.high } }),
reserve: jest.fn().mockReturnValue("address"),
});
//@ts-expect-error
@@ -108,8 +108,9 @@ describe("Upper Wall Active Bond Market", () => {
it("Should have a disclaimer notifying a buy above current market price ($13.20)", async () => {
//@ts-ignore
- RangeHooks.DetermineRangePrice = jest.fn().mockReturnValue({ data: { price: "14.12" } });
- render();
+ RangeHooks.DetermineRangePrice = jest.fn().mockReturnValue({ data: { price: "14.20" } });
+ const { container } = render();
+ fireEvent.click(container.getElementsByClassName("arrow-wrapper")[0]);
fireEvent.input(await screen.findByTestId("reserve-amount"), { target: { value: "6" } });
fireEvent.click(screen.getByTestId("range-submit"));
expect(screen.getByTestId("disclaimer")).toHaveTextContent(
@@ -119,12 +120,9 @@ describe("Upper Wall Active Bond Market", () => {
it("Should successfully complete buy regular bond transaction", async () => {
//@ts-ignore
- RangeHooks.DetermineRangePrice = jest.fn().mockReturnValue({ data: { price: "14.12" } });
- render(
- <>
-
- >,
- );
+ RangeHooks.DetermineRangePrice = jest.fn().mockReturnValue({ data: { price: "14.20" } });
+ const { container } = render();
+ fireEvent.click(container.getElementsByClassName("arrow-wrapper")[0]);
fireEvent.input(await screen.findByTestId("reserve-amount"), { target: { value: "6" } });
fireEvent.click(screen.getByTestId("range-submit"));
fireEvent.click(screen.getByTestId("disclaimer-checkbox"));
diff --git a/src/views/Range/hooks.tsx b/src/views/Range/hooks.tsx
index 54aac02fd2..0415c05e82 100644
--- a/src/views/Range/hooks.tsx
+++ b/src/views/Range/hooks.tsx
@@ -23,7 +23,7 @@ import { assert } from "src/helpers/types/assert";
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 { useNetwork, useSigner } from "wagmi";
+import { useSigner } from "wagmi";
/**Chainlink Price Feed. Retrieves OHMETH and ETH/{RESERVE} feed **/
export const OHMPriceHistory = (assetPair = "OHMv2/ETH") => {
@@ -105,10 +105,10 @@ export const PriceHistory = (reserveToken: string) => {
* Returns the current price of the Operator at the given address
*/
export const OperatorPrice = () => {
- const { chain = { id: 1 } } = useNetwork();
+ const networks = useTestableNetworks();
- const contract = RANGE_PRICE_CONTRACT.getEthersContract(chain.id);
- const { data, isFetched, isLoading } = useQuery(["getOperatorPrice", chain], async () => {
+ const contract = RANGE_PRICE_CONTRACT.getEthersContract(networks.MAINNET);
+ const { data, isFetched, isLoading } = useQuery(["getOperatorPrice", networks.MAINNET], async () => {
return parseBigNumber(await contract.getCurrentPrice(), 18);
});
return { data, isFetched, isLoading };
@@ -118,14 +118,14 @@ export const OperatorPrice = () => {
* Returns the current price of the Operator at the given address
*/
export const OperatorMovingAverage = () => {
- const { chain = { id: 1 } } = useNetwork();
+ const networks = useTestableNetworks();
- const contract = RANGE_PRICE_CONTRACT.getEthersContract(chain.id);
+ const contract = RANGE_PRICE_CONTRACT.getEthersContract(networks.MAINNET);
const {
data = { movingAverage: 0, days: 30 },
isFetched,
isLoading,
- } = useQuery(["getOperatorMovingAverage", chain], async () => {
+ } = useQuery(["getOperatorMovingAverage", networks.MAINNET], async () => {
const movingAverage = parseBigNumber(await contract.getMovingAverage(), 18);
const movingAverageSeconds = await contract.movingAverageDuration();
const days = movingAverageSeconds / 60 / 60 / 24; //seconds to days;
@@ -138,14 +138,14 @@ export const OperatorMovingAverage = () => {
* Returns the reserve contract address on the Operator
*/
export const OperatorReserveSymbol = () => {
- const { chain = { id: 1 } } = useNetwork();
- const contract = RANGE_CONTRACT.getEthersContract(chain.id);
+ const networks = useTestableNetworks();
+ const contract = RANGE_CONTRACT.getEthersContract(networks.MAINNET);
const {
data = { symbol: "", reserveAddress: "" },
isFetched,
isLoading,
- } = useQuery(["getOperatorReserveSymbol", chain], async () => {
- const provider = Providers.getStaticProvider(chain.id);
+ } = useQuery(["getOperatorReserveSymbol", networks.MAINNET], async () => {
+ const provider = Providers.getStaticProvider(networks.MAINNET);
const reserveAddress = await contract.reserve();
const TokenContract = IERC20__factory.connect(reserveAddress, provider);
const symbol = await TokenContract.symbol();
@@ -159,8 +159,8 @@ export const OperatorReserveSymbol = () => {
*/
export const RangeData = () => {
- const { chain = { id: 1 } } = useNetwork();
- const contract = RANGE_CONTRACT.getEthersContract(chain.id);
+ const networks = useTestableNetworks();
+ const contract = RANGE_CONTRACT.getEthersContract(networks.MAINNET);
const {
data = {
@@ -171,7 +171,7 @@ export const RangeData = () => {
} as OlympusRange.RangeStructOutput,
isFetched,
isLoading,
- } = useQuery(["getRangeData", chain.id], async () => {
+ } = useQuery(["getRangeData", networks.MAINNET], async () => {
const range = await contract.range();
return range;
});
@@ -200,24 +200,25 @@ const band: OlympusRange.BandStruct = {
* @param id Bond Market ID
*/
export const RangeBondPrice = (id: BigNumber, side: "low" | "high") => {
- const { chain = { id: 1 } } = useNetwork();
- const contract = BOND_AGGREGATOR_CONTRACT.getEthersContract(chain.id);
+ const networks = useTestableNetworks();
+ const contract = BOND_AGGREGATOR_CONTRACT.getEthersContract(networks.MAINNET);
const { data, isFetched, isLoading } = useQuery(
- ["getRangeBondPrice", id, chain, side],
+ ["getRangeBondPrice", id, networks.MAINNET, side],
async () => {
const bondPrice = await contract.marketPrice(id);
const auctioneerAddress = await contract.getAuctioneer(id);
const auctioneerContract = BondFixedTermSDA__factory.connect(auctioneerAddress, contract.provider);
const market = await auctioneerContract.markets(id);
const inverse =
- market.payoutToken.toLowerCase() !== OHM_ADDRESSES[chain.id as keyof typeof OHM_ADDRESSES].toLowerCase();
+ market.payoutToken.toLowerCase() !==
+ OHM_ADDRESSES[networks.MAINNET as keyof typeof OHM_ADDRESSES].toLowerCase();
const baseToken = inverse
- ? await getTokenByAddress({ address: market.payoutToken, networkId: chain.id })
+ ? await getTokenByAddress({ address: market.payoutToken, networkId: networks.MAINNET })
: OHM_TOKEN;
assert(baseToken, `Unknown base token address: ${market.payoutToken}`);
const quoteToken = inverse
? OHM_TOKEN
- : await getTokenByAddress({ address: market.quoteToken, networkId: chain.id });
+ : await getTokenByAddress({ address: market.quoteToken, networkId: networks.MAINNET });
assert(quoteToken, `Unknown quote token address: ${market.quoteToken}`);
const scale = await contract.marketScale(id);
@@ -237,11 +238,11 @@ export const RangeBondPrice = (id: BigNumber, side: "low" | "high") => {
};
export const RangeBondMaxPayout = (id: BigNumber) => {
- const { chain = { id: 1 } } = useNetwork();
- const aggregatorContract = BOND_AGGREGATOR_CONTRACT.getEthersContract(chain.id);
+ const networks = useTestableNetworks();
+ const aggregatorContract = BOND_AGGREGATOR_CONTRACT.getEthersContract(networks.MAINNET);
const { data, isFetched, isLoading } = useQuery(
- ["getRangeBondMaxPayout", id, chain],
+ ["getRangeBondMaxPayout", id, networks.MAINNET],
async () => {
const auctioneerAddress = await aggregatorContract.getAuctioneer(id);
const contract = BondFixedTermSDA__factory.connect(auctioneerAddress, aggregatorContract.provider);
@@ -256,10 +257,10 @@ export const RangeBondMaxPayout = (id: BigNumber) => {
};
export const BondTellerAddress = (id: BigNumber) => {
- const { chain = { id: 1 } } = useNetwork();
- const contract = BOND_AGGREGATOR_CONTRACT.getEthersContract(chain.id);
+ const networks = useTestableNetworks();
+ const contract = BOND_AGGREGATOR_CONTRACT.getEthersContract(networks.MAINNET);
const { data, isFetched, isLoading } = useQuery(
- ["getRangeBondTeller", id, chain],
+ ["getRangeBondTeller", id, networks.MAINNET],
async () => {
const tellerAddress = await contract.getTeller(id);
return tellerAddress;
@@ -351,7 +352,6 @@ type RangeContracts = "swap" | "bond";
export const RangeSwap = () => {
const networks = useTestableNetworks();
const { data: signer } = useSigner();
- const { chain = { id: 1 } } = useNetwork();
const referrer = DAO_TREASURY_ADDRESSES[networks.MAINNET];
return useMutation<
@@ -369,8 +369,8 @@ export const RangeSwap = () => {
}
>(
async ({ market, tokenAddress, swapType, amount, receiveAmount, sellActive, slippage, recipientAddress }) => {
- const decimals = tokenAddress === OHM_ADDRESSES[chain.id as keyof typeof OHM_ADDRESSES] ? 9 : 18;
- const receiveDecimals = tokenAddress === OHM_ADDRESSES[chain.id as keyof typeof OHM_ADDRESSES] ? 18 : 9; //opposite of send
+ const decimals = tokenAddress === OHM_ADDRESSES[networks.MAINNET as keyof typeof OHM_ADDRESSES] ? 9 : 18;
+ const receiveDecimals = tokenAddress === OHM_ADDRESSES[networks.MAINNET as keyof typeof OHM_ADDRESSES] ? 18 : 9; //opposite of send
if (!signer) throw new Error(t`Please connect a wallet to Range Swap`);
if (!isValidAddress(recipientAddress) || recipientAddress === "") throw new Error(t`Invalid address`);
diff --git a/src/views/Range/index.tsx b/src/views/Range/index.tsx
index ae89d897cf..860336b49a 100644
--- a/src/views/Range/index.tsx
+++ b/src/views/Range/index.tsx
@@ -69,14 +69,21 @@ export const Range = () => {
const buyAsset = sellActive ? reserveSymbol : "OHM";
const sellAsset = sellActive ? "OHM" : reserveSymbol;
+ const { data: bidPrice } = DetermineRangePrice("bid");
+ const { data: askPrice } = DetermineRangePrice("ask");
+
useEffect(() => {
if (reserveAmount && ohmAmount) {
handleChangeReserveAmount(reserveAmount);
}
}, [sellActive]);
- const { data: bidPrice } = DetermineRangePrice("bid");
- const { data: askPrice } = DetermineRangePrice("ask");
+ useEffect(() => {
+ const sellDiscount = (currentPrice - bidPrice.price) / -currentPrice;
+ if (sellDiscount > 0) {
+ setSellActive(true);
+ }
+ }, [bidPrice, currentPrice]);
const maxBalanceString = `${maxCapacity.toFixed(2)} ${buyAsset} (${(sellActive
? maxCapacity / bidPrice.price
@@ -149,22 +156,20 @@ export const Range = () => {
)}