Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui): apply diamond architecture to staking page #804

Merged
merged 22 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b1b2bc2
feat: apply diamond to home page
bojan07 Oct 2, 2023
dd22fa0
fix: added debug option to refreshPrices function
bojan07 Oct 3, 2023
b2bbdca
fix: make code clean in use-prices
bojan07 Oct 3, 2023
510e7a2
Merge branch 'ubiquity:development' into development
bojan07 Oct 3, 2023
8da767d
feat: used protocol-contracts in use-balances and use-named-contracts
bojan07 Oct 3, 2023
b3a3856
feat: applied protocol-contracts to child components of staking page
bojan07 Oct 3, 2023
5e1a071
fix: fixed build error and made code clean in use-balances
bojan07 Oct 3, 2023
f5ac79b
fix: used non-null assertion operator for object null checking
bojan07 Oct 4, 2023
18ee556
fix: added metapool and governancemarket contract to protocol-contrac…
bojan07 Oct 4, 2023
9ad50ee
chore: cleamake use-protocol-contracts clean
bojan07 Oct 4, 2023
1ce1d35
fix: applied new name convention
bojan07 Oct 5, 2023
57bc6e1
fix: object null checking
bojan07 Oct 5, 2023
6972f9c
fix: cleaned refresh balance function
bojan07 Oct 5, 2023
61ee7f7
fix: hardcoded some addresses and fixed prefetch-constants function
bojan07 Oct 6, 2023
eb6e495
fix: checking big number zero value
bojan07 Oct 6, 2023
88c1b46
fix: non-null assertion operator and infinite hook loop
bojan07 Oct 10, 2023
8edb930
Merge branch 'ubiquity:development' into development
bojan07 Oct 10, 2023
9e07817
fix: contract type in allowance functions
bojan07 Oct 10, 2023
de99518
Merge branch 'ubiquity:development' into development
bojan07 Oct 12, 2023
e7dc29f
fix: passed hardcoded addresses as variable
bojan07 Oct 12, 2023
c086a17
fix: updated variable names according to new name convention
bojan07 Oct 12, 2023
cd4ce71
fix: match contract type according to diamond architecture
bojan07 Oct 12, 2023
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
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
import useWeb3, { PossibleProviders } from "../use-web-3";

import Deployed_Contracts from "@ubiquity/contracts/deployments.json";
import NAMED_ACCOUNTS from "../../../config/named-accounts.json";
import { getCurveFactoryContract, getDebtCouponManagerContract, getERC20Contract, getIJarContract, getYieldProxyContract } from "@/components/utils/contracts";

const getDebtCouponManagerAddress = () => {
const contractDeployments: Record<string, any> = Deployed_Contracts;
const record = contractDeployments["1"] ?? {};
const contract = record?.contracts ? record?.contracts["DebtCouponManager"] : undefined;
return contract ? contract.address : undefined;
};
export const DEBT_COUPON_MANAGER_ADDRESS = getDebtCouponManagerAddress();
import { getCurveFactoryContract, getERC20Contract, getIJarContract, getYieldProxyContract } from "@/components/utils/contracts";

export type NamedContracts = ReturnType<typeof connectedContracts> | null;
export function connectedContracts(provider: NonNullable<PossibleProviders>) {
Expand All @@ -20,7 +11,6 @@ export function connectedContracts(provider: NonNullable<PossibleProviders>) {
usdc: getERC20Contract(NAMED_ACCOUNTS.USDC, provider),
dai: getERC20Contract(NAMED_ACCOUNTS.DAI, provider),
usdt: getERC20Contract(NAMED_ACCOUNTS.USDT, provider),
debtCouponManager: getDebtCouponManagerContract(DEBT_COUPON_MANAGER_ADDRESS, provider),
jarUsdc: getIJarContract(NAMED_ACCOUNTS.jarUSDCAddr, provider),
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import UbiquityPoolFacetArtifact from "@ubiquity/contracts/out/UbiquityPoolFacet
* Contracts on hold (i.e. obsolete) until we find a better utility for them:
* - https://github.com/ubiquity/ubiquity-dollar/tree/development/packages/contracts/src/ubiquistick
*/
export type ProtocolContracts = ReturnType<typeof useProtocolContracts> | null;
const useProtocolContracts = () => {
// get current web3 provider
const { provider } = useWeb3();
Expand Down
38 changes: 25 additions & 13 deletions packages/dapp/components/lib/hooks/use-balances.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { erc1155BalanceOf } from "@/lib/utils";
import { BigNumber, Contract } from "ethers";
import { BigNumber } from "ethers";
import { createContext, useContext, useEffect, useState } from "react";
import useManagerManaged from "./contracts/use-manager-managed";
import useNamedContracts from "./contracts/use-named-contracts";
import useWalletAddress from "./use-wallet-address";
import { ChildrenShim } from "./children-shim-d";
import useProtocolContracts from "@/components/lib/hooks/contracts/use-protocol-contracts";
import { getERC20Contract, getIMetaPoolContract } from "@/components/utils/contracts";
import useWeb3 from "@/components/lib/hooks/use-web-3";

export interface Balances {
uad: BigNumber;
Expand All @@ -26,24 +28,34 @@ export const BalancesContext = createContext<[Balances | null, RefreshBalances]>
export const BalancesContextProvider: React.FC<ChildrenShim> = ({ children }) => {
const [balances, setBalances] = useState<Balances | null>(null);
const [walletAddress] = useWalletAddress();
const managedContracts = useManagerManaged();
const namedContracts = useNamedContracts();
const protocolContracts = useProtocolContracts();
const { provider } = useWeb3();

async function refreshBalances() {
if (walletAddress && managedContracts && namedContracts) {
if (!walletAddress || !namedContracts || !protocolContracts || !provider) {
return;
}

if(protocolContracts.managerFacet && protocolContracts.dollarToken && protocolContracts.creditToken && protocolContracts.governanceToken && protocolContracts.creditNft && protocolContracts.stakingShare) {
bojan07 marked this conversation as resolved.
Show resolved Hide resolved
const _3crvToken = await protocolContracts.managerFacet.curve3PoolTokenAddress();
const dollar3poolMarket = await protocolContracts.managerFacet.stableSwapMetaPoolAddress();
const _3crvTokenContract = getERC20Contract(_3crvToken, provider);
const dollarMetapool = getIMetaPoolContract(dollar3poolMarket, provider);

const [uad, _3crv, uad3crv, ucr, ubq, ucrNft, stakingShares, usdc, dai, usdt] = await Promise.all([
bojan07 marked this conversation as resolved.
Show resolved Hide resolved
managedContracts.dollarToken.balanceOf(walletAddress),
managedContracts._3crvToken.balanceOf(walletAddress),
managedContracts.dollarMetapool.balanceOf(walletAddress),
managedContracts.creditToken.balanceOf(walletAddress),
managedContracts.governanceToken.balanceOf(walletAddress),
erc1155BalanceOf(walletAddress, managedContracts.creditNft),
erc1155BalanceOf(walletAddress, managedContracts.stakingToken),
protocolContracts.dollarToken.balanceOf(walletAddress),
_3crvTokenContract.balanceOf(walletAddress),
dollarMetapool.balanceOf(walletAddress),
protocolContracts.creditToken.balanceOf(walletAddress),
protocolContracts.governanceToken.balanceOf(walletAddress),
erc1155BalanceOf(walletAddress, protocolContracts.creditNft),
erc1155BalanceOf(walletAddress, protocolContracts.stakingShare),
namedContracts.usdc.balanceOf(walletAddress),
namedContracts.dai.balanceOf(walletAddress),
namedContracts.usdt.balanceOf(walletAddress),
]);

setBalances({
uad,
_3crv,
Expand All @@ -61,7 +73,7 @@ export const BalancesContextProvider: React.FC<ChildrenShim> = ({ children }) =>

useEffect(() => {
refreshBalances();
}, [walletAddress, managedContracts]);
}, [walletAddress, protocolContracts]);

return <BalancesContext.Provider value={[balances, refreshBalances]}>{children}</BalancesContext.Provider>;
};
Expand Down
15 changes: 5 additions & 10 deletions packages/dapp/components/lib/with-loaded-context.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { ethers } from "ethers";
import useDeployedContracts, { DeployedContracts } from "./hooks/contracts/use-deployed-contracts";
import { ManagedContracts } from "./hooks/contracts/use-manager-managed";
import useProtocolContracts, { ProtocolContracts } from "./hooks/contracts/use-protocol-contracts";
import useNamedContracts, { NamedContracts } from "./hooks/contracts/use-named-contracts";
import useWeb3, { PossibleProviders } from "./hooks/use-web-3";

import useManagerManaged from "@/components/lib/hooks/contracts/use-manager-managed";
export type LoadedContext = {
managedContracts: NonNullable<ManagedContracts>;
deployedContracts: NonNullable<DeployedContracts>;
protocolContracts: NonNullable<ProtocolContracts>;
namedContracts: NonNullable<NamedContracts>;
web3Provider: NonNullable<PossibleProviders>;
walletAddress: string;
Expand All @@ -17,19 +14,17 @@ export type LoadedContext = {
export default function withLoadedContext<T>(El: (params: LoadedContext & T) => JSX.Element, ElNull?: () => JSX.Element) {
return (otherParams: T) => {
const { walletAddress, signer, provider } = useWeb3();
const managedContracts = useManagerManaged();
const deployedContracts = useDeployedContracts();
const namedContracts = useNamedContracts();
const protocolContracts = useProtocolContracts();

if (provider && walletAddress && signer && managedContracts && deployedContracts && namedContracts) {
if (provider && walletAddress && signer && protocolContracts && namedContracts) {
return (
<El
web3Provider={provider}
walletAddress={walletAddress}
signer={signer}
namedContracts={namedContracts}
managedContracts={managedContracts}
deployedContracts={deployedContracts}
protocolContracts={protocolContracts}
{...otherParams}
/>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/dapp/components/redeem/debt-coupon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const uDEBT = "uDEBT";
const uAR = "uAR";

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const DebtCouponContainer = ({ managedContracts, deployedContracts, web3Provider, walletAddress, signer }: LoadedContext) => {
export const DebtCouponContainer = ({ protocolContracts, web3Provider, walletAddress, signer }: LoadedContext) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [balances, refreshBalances] = useBalances();
const [, doTransaction] = useTransactionLogger();
Expand Down
22 changes: 16 additions & 6 deletions packages/dapp/components/staking/bonding-shares-explorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { memo, useCallback, useState } from "react";
import { formatEther } from "@/lib/format";
import { performTransaction, useAsyncInit } from "@/lib/utils";
import withLoadedContext, { LoadedContext } from "@/lib/with-loaded-context";
import { getIMetaPoolContract } from "@/components/utils/contracts";

import DepositShare from "./deposit-share";
import useBalances from "../lib/hooks/use-balances";
Expand Down Expand Up @@ -44,22 +45,28 @@ type Actions = {
const USD_TO_LP = 0.7460387929;
const LP_TO_USD = 1 / USD_TO_LP;

export const BondingSharesExplorerContainer = ({ managedContracts, web3Provider, walletAddress, signer }: LoadedContext) => {
export const BondingSharesExplorerContainer = ({ protocolContracts, web3Provider, walletAddress, signer }: LoadedContext) => {
if (!protocolContracts.chefFacet || !protocolContracts.stakingFacet || !protocolContracts.stakingShare || !protocolContracts.managerFacet) {
return <></>;
}
const [model, setModel] = useState<Model | null>(null);
const [, doTransaction] = useTransactionLogger();
const [, refreshBalances] = useBalances();
// cspell: disable-next-line
const { staking: bonding, masterChef, stakingToken: bondingToken, dollarMetapool: metaPool } = managedContracts;
const { stakingFacet: bonding, chefFacet, stakingShare: bondingToken, managerFacet } = protocolContracts;

useAsyncInit(fetchSharesInformation);
async function fetchSharesInformation(processedShareId?: ShareData["id"]) {
console.time("BondingShareExplorerContainer contract loading");
const currentBlock = await web3Provider.getBlockNumber();
// cspell: disable-next-line
const blockCountInAWeek = +(await bonding.blockCountInAWeek()).toString();
const totalShares = await masterChef.totalShares();
const totalShares = await chefFacet.totalShares();
// cspell: disable-next-line
const bondingShareIds = await bondingToken.holderTokens(walletAddress);

const dollar3poolMarket = await managerFacet.stableSwapMetaPoolAddress();
const metaPool = getIMetaPoolContract(dollar3poolMarket, web3Provider);
const walletLpBalance = await metaPool.balanceOf(walletAddress);

const shares: ShareData[] = [];
Expand All @@ -69,10 +76,10 @@ export const BondingSharesExplorerContainer = ({ managedContracts, web3Provider,
// cspell: disable-next-line
const [ugov, bond, bondingShareInfo, tokenBalance] = await Promise.all([
// cspell: disable-next-line
masterChef.pendingGovernance(id),
chefFacet.pendingGovernance(id),
// cspell: disable-next-line
bondingToken.getStake(id),
masterChef.getStakingShareInfo(id),
chefFacet.getStakingShareInfo(id),
// cspell: disable-next-line
bondingToken.balanceOf(walletAddress, id),
]);
Expand Down Expand Up @@ -149,7 +156,7 @@ export const BondingSharesExplorerContainer = ({ managedContracts, web3Provider,
setModel((prevModel) => (prevModel ? { ...prevModel, processing: [...prevModel.processing, id] } : null));
doTransaction("Claiming Ubiquity Governance tokens...", async () => {
try {
await performTransaction(masterChef.connect(signer).getRewards(BigNumber.from(id)));
await performTransaction(chefFacet.connect(signer).getRewards(BigNumber.from(id)));
} catch (error) {
console.log(`Claiming Ubiquity Governance token rewards from ${id} failed:`, error);
// throws exception to update the transaction log
Expand All @@ -168,6 +175,9 @@ export const BondingSharesExplorerContainer = ({ managedContracts, web3Provider,
if (!model || model.processing.length) return;
console.log(`Staking ${amount} for ${weeks} weeks`);
doTransaction("Staking...", async () => {});

const dollar3poolMarket = await managerFacet.stableSwapMetaPoolAddress();
const metaPool = getIMetaPoolContract(dollar3poolMarket, web3Provider);
// cspell: disable-next-line
const allowance = await metaPool.allowance(walletAddress, bonding.address);
console.log("allowance", ethers.utils.formatEther(allowance));
Expand Down
35 changes: 24 additions & 11 deletions packages/dapp/components/staking/deposit-share.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { BigNumber, ethers } from "ethers";
import { useEffect, useState } from "react";

import { ManagedContracts } from "@/lib/hooks/contracts/use-manager-managed";
import { ProtocolContracts } from "@/components/lib/hooks/contracts/use-protocol-contracts";
import { getSushiSwapPoolContract, getUniswapV2PairContract } from "@/components/utils/contracts";
import { constrainNumber } from "@/lib/utils";
import withLoadedContext, { LoadedContext } from "@/lib/with-loaded-context";
import Button from "../ui/button";
import PositiveNumberInput from "../ui/positive-number-input";
import useWeb3 from "@/lib/hooks/use-web-3";

const toEtherNum = (n: BigNumber) => +n.toString() / 1e18;
const toNum = (n: BigNumber) => +n.toString();
Expand All @@ -15,32 +17,43 @@ const MAX_WEEKS = 208;

// cspell: disable-next-line
type PrefetchedConstants = { totalShares: number; usdPerWeek: number; bondingDiscountMultiplier: BigNumber };
async function prefetchConstants(contracts: NonNullable<ManagedContracts>): Promise<PrefetchedConstants> {
const reserves = await contracts.governanceMarket.getReserves();
async function prefetchConstants(contracts: NonNullable<ProtocolContracts>): Promise<PrefetchedConstants> {
const { provider } = useWeb3();

if (!contracts.managerFacet || !contracts.chefFacet || !contracts.stakingFacet || !provider) {
return { totalShares: 0, usdPerWeek: 0, bondingDiscountMultiplier: new BigNumber(0, "0x") };
}
const sushiSwapPool = await contracts.managerFacet.sushiSwapPoolAddress();
const sushiSwapPoolContract = getSushiSwapPoolContract(sushiSwapPool, provider);
const governanceMarket = getUniswapV2PairContract(await sushiSwapPoolContract.pair(), provider);
const reserves = await governanceMarket.getReserves();

const ubqPrice = +reserves[0].toString() / +reserves[1].toString();
const ubqPerBlock = await contracts.masterChef.governancePerBlock();
const ubqMultiplier = await contracts.masterChef.governanceMultiplier();
const ubqPerBlock = await contracts.chefFacet.governancePerBlock();
const ubqMultiplier = await contracts.chefFacet.governanceMultiplier();
const actualUbqPerBlock = toEtherNum(ubqPerBlock.mul(ubqMultiplier).div(`${1e18}`));
const blockCountInAWeek = toNum(await contracts.staking.blockCountInAWeek());
const blockCountInAWeek = toNum(await contracts.stakingFacet.blockCountInAWeek());
const ubqPerWeek = actualUbqPerBlock * blockCountInAWeek;
const totalShares = toEtherNum(await contracts.masterChef.totalShares());
const totalShares = toEtherNum(await contracts.chefFacet.totalShares());
const usdPerWeek = ubqPerWeek * ubqPrice;
// cspell: disable-next-line
const bondingDiscountMultiplier = await contracts.staking.stakingDiscountMultiplier();
const bondingDiscountMultiplier = await contracts.stakingFacet.stakingDiscountMultiplier();
// cspell: disable-next-line
return { totalShares, usdPerWeek, bondingDiscountMultiplier };
}

async function calculateApyForWeeks(contracts: NonNullable<ManagedContracts>, prefetch: PrefetchedConstants, weeksNum: number): Promise<number> {
async function calculateApyForWeeks(contracts: NonNullable<ProtocolContracts>, prefetch: PrefetchedConstants, weeksNum: number): Promise<number> {
if (!contracts.stakingFormulasFacet) {
return 0;
}
// cspell: disable-next-line
const { totalShares, usdPerWeek, bondingDiscountMultiplier } = prefetch;
const DAYS_IN_A_YEAR = 365.2422;
const usdAsLp = 0.7460387929; // TODO: Get this number from the Curve contract
const bigNumberOneUsdAsLp = ethers.utils.parseEther(usdAsLp.toString());
const weeks = BigNumber.from(weeksNum.toString());
// cspell: disable-next-line
const shares = toEtherNum(await contracts.ubiquityFormulas.durationMultiply(bigNumberOneUsdAsLp, weeks, bondingDiscountMultiplier));
const shares = toEtherNum(await contracts.stakingFormulasFacet.durationMultiply(bigNumberOneUsdAsLp, weeks, bondingDiscountMultiplier));
const rewardsPerWeek = (shares / totalShares) * usdPerWeek;
const yearlyYield = (rewardsPerWeek / 7) * DAYS_IN_A_YEAR * 100;
return Math.round(yearlyYield * 100) / 100;
Expand All @@ -52,7 +65,7 @@ type DepositShareProps = {
maxLp: BigNumber;
} & LoadedContext;

const DepositShare = ({ onStake, disabled, maxLp, managedContracts: contracts }: DepositShareProps) => {
const DepositShare = ({ onStake, disabled, maxLp, protocolContracts: contracts }: DepositShareProps) => {
const [amount, setAmount] = useState("");
const [weeks, setWeeks] = useState("");
const [currentApy, setCurrentApy] = useState<number | null>(null);
Expand Down
Loading