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

Adapt thusd to bob layer #112

Merged
merged 4 commits into from
May 7, 2024
Merged
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
42 changes: 24 additions & 18 deletions packages/contracts/hardhat.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require("@nomiclabs/hardhat-truffle5");
require("@nomiclabs/hardhat-ethers");
require("@nomiclabs/hardhat-etherscan");
require("@nomicfoundation/hardhat-verify");
require("solidity-coverage");
require("hardhat-gas-reporter");

Expand All @@ -22,13 +22,6 @@ const alchemyUrl = () => {
return `https://eth-mainnet.alchemyapi.io/v2/${getSecret('alchemyAPIKey')}`
}

const alchemyUrlRinkeby = () => {
return `https://eth-rinkeby.alchemyapi.io/v2/${getSecret('alchemyAPIKeyRinkeby')}`
}

const alchemyUrlRopsten = () => {
return `https://eth-ropsten.alchemyapi.io/v2/${getSecret('alchemyAPIKeyRopsten')}`
}

module.exports = {
paths: {
Expand All @@ -48,6 +41,9 @@ module.exports = {
}
]
},
sourcify: {
enabled: true
},
networks: {
hardhat: {
accounts: accountsList,
Expand All @@ -65,19 +61,29 @@ module.exports = {
getSecret('ACCOUNT2_PRIVATEKEY', '0x3ec7cedbafd0cb9ec05bf9f7ccfa1e8b42b3e3a02c75addfccbfeb328d1b383b')
]
},
rinkeby: {
url: alchemyUrlRinkeby(),
gas: 10000000, // tx gas limit
accounts: [getSecret('RINKEBY_DEPLOYER_PRIVATEKEY', '0x60ddfe7f579ab6867cbe7a2dc03853dc141d7a4ab6dbefc0dae2d2b1bd4e487f')]
bob_testnet: {
url: "https://testnet.rpc.gobob.xyz/",
chainId: 111,
accounts: [
getSecret('DEPLOYER_PRIVATEKEY', '0x60ddfe7f579ab6867cbe7a2dc03853dc141d7a4ab6dbefc0dae2d2b1bd4e487f'),
getSecret('ACCOUNT2_PRIVATEKEY', '0x3ec7cedbafd0cb9ec05bf9f7ccfa1e8b42b3e3a02c75addfccbfeb328d1b383b')
]
},
ropsten: {
url: alchemyUrlRopsten(),
gas: 120000000, // tx gas limit
accounts: [getSecret('RINKEBY_DEPLOYER_PRIVATEKEY', '0x60ddfe7f579ab6867cbe7a2dc03853dc141d7a4ab6dbefc0dae2d2b1bd4e487f')]
}
},
etherscan: {
apiKey: getSecret("ETHERSCAN_API_KEY")
apiKey: {
bob_testnet: getSecret("ETHERSCAN_API_KEY")
},
customChains: [
{
network: "bob_testnet",
chainId: 111,
urls: {
apiURL: "https://testnet-explorer.gobob.xyz/api?",
browserURL: "https://testnet.rpc.gobob.xyz"
}
},
],
},
mocha: {
timeout: 12000000,
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
},
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-etherscan": "^2.1.2",
"@nomicfoundation/hardhat-verify": "2.0.5",
"@nomiclabs/hardhat-truffle5": "^2.0.0",
"@nomiclabs/hardhat-web3": "^2.0.0",
"@openzeppelin/contracts": "4.9.2",
Expand Down
39 changes: 23 additions & 16 deletions packages/dev-frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const wcV2InitOptions = {
* Strongly recommended to provide atleast one URL as it is required by some wallets (i.e. MetaMask)
* To connect with WalletConnect
*/
dappUrl: 'http://app.thresholdusd.org'
dappUrl: 'https://app.thresholdusd.org'
}

const injected = injectedModule();
Expand All @@ -40,25 +40,38 @@ const wallets = [
walletConnect
]

const publicRpcUrls = {
'0x1': 'https://cloudflare-eth.com/',
'0xaa36a7': 'https://sepolia.eth.aragon.network/',
'0x6f': "wss://testnet.rpc.gobob.xyz",
'0xed88': "wss://rpc.gobob.xyz",
};

const chains = [
{
id: '0x1',
token: 'ETH',
label: 'Ethereum Mainnet',
rpcUrl: getRpcUrl('0x1')
},
{
id: '0x5',
token: 'ETH',
label: 'Goerli',
rpcUrl: getRpcUrl('0x5')
},
{
id: '0xaa36a7',
token: 'ETH',
label: 'Sepolia',
rpcUrl: getRpcUrl('0xaa36a7')
},
{
id: '0x6f',
token: 'ETH',
label: 'BOB Testnet',
rpcUrl: getRpcUrl('0x6f')
},
{
id: '0xed88',
token: 'ETH',
label: 'Ethereum Mainnet',
rpcUrl: getRpcUrl('0xed88')
},
]

const appMetadata = {
Expand Down Expand Up @@ -92,15 +105,9 @@ if (window.ethereum) {
Object.assign(window.ethereum, { autoRefreshOnNetworkChange: false });
}

function getRpcUrl(chainIdHex: '0x1' | '0x5' | '0xaa36a7') {
const publicRpcUrls = {
'0x1': 'https://cloudflare-eth.com/',
'0x5': 'https://goerli.eth.aragon.network/',
'0xaa36a7': 'https://sepolia.eth.aragon.network/'
};

if (process.env.REACT_APP_ALCHEMY_ID) {
return `https://eth-${chainIdHex === '0x1' ? 'mainnet' : chainIdHex === '0x5' ? 'goerli' : 'sepolia'}.g.alchemy.com/v2/${process.env.REACT_APP_ALCHEMY_ID}`;
function getRpcUrl(chainIdHex: keyof typeof publicRpcUrls) {
if (process.env.REACT_APP_ALCHEMY_ID && (chainIdHex === "0x1" || chainIdHex === "0xaa36a7")) {
return `https://eth-${chainIdHex === '0x1' ? 'mainnet' : 'sepolia'}.g.alchemy.com/v2/${process.env.REACT_APP_ALCHEMY_ID}`;
} else {
return publicRpcUrls[chainIdHex];
}
Expand Down
47 changes: 20 additions & 27 deletions packages/dev-frontend/src/components/Dashboard/Chart/LineChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { Line } from 'react-chartjs-2';
import { Decimal } from "@threshold-usd/lib-base";
import { useHover } from "../../../utils/hooks";
import { LoadingChart } from "./LoadingChart";
import { UnsupportedNetworkChart } from "./UnsupportedNetworkChart";

ChartJS.register(
CategoryScale,
Expand Down Expand Up @@ -65,12 +66,18 @@ export const LineChart = (): JSX.Element => {
const [lastTvlDecimal, setLastTvlDecimal] = useState<Decimal>();
const [lastTvlNumber, setLastTvlNumber] = useState<Array<number>>([]);
const [chartLabels, setChartLabels] = useState<Array<TimestampsObject>>();
const [isUnsupportedNetwork, setIsUnsupportedNetwork] = useState<boolean>(false);

useTvl()
.then((result) => {
if (result === null || !isMounted) {
if (result?.isUnsupportedNetwork) {
setIsUnsupportedNetwork(true)
return
}

if (!result?.tvl || !result.timestamps) return

setIsUnsupportedNetwork(false)
setTvl(result.tvl)
setTimestamps(result.timestamps)
setLoadedChart(true);
Expand All @@ -81,33 +88,21 @@ export const LineChart = (): JSX.Element => {
})

useEffect(() => {
if (!isMounted) {
return;
}
const cachedData = localStorage.getItem("chartData");
const cachedLabels = localStorage.getItem("chartLabels");

if (cachedData && cachedLabels) {
setChartData(JSON.parse(cachedData));
setChartLabels(JSON.parse(cachedLabels));
setLastTvlDecimal(JSON.parse(cachedData)[cachedData.length - 1]);
setLoadedChart(true);
}

if (!loadedChart) {
if (!isMounted || !loadedChart) {
return;
}
let memeTvl: Decimal[] = [];

let queriedTvl: Decimal[] = [];

for (const collateralTvl of tvl) {
collateralTvl.tvl.forEach((tvl, index) => {
if (memeTvl[index] === undefined) {
memeTvl[index] = Decimal.from(0);
if (queriedTvl[index] === undefined) {
queriedTvl[index] = Decimal.from(0);
}
memeTvl[index] = tvl.totalCollateral.add(memeTvl[index]);
queriedTvl[index] = tvl.totalCollateral.add(queriedTvl[index]);
});
}
setLastTvlNumber(memeTvl.map(decimal => parseInt(decimal.toString())))
setLastTvlNumber(queriedTvl.map(decimal => parseInt(decimal.toString())))


return () => {
Expand All @@ -119,11 +114,7 @@ export const LineChart = (): JSX.Element => {
if (lastTvlNumber.length > 0 && timestamps.length > 0) {
setChartData(lastTvlNumber);
setChartLabels(timestamps);
localStorage.setItem("chartData", JSON.stringify(lastTvlNumber));
localStorage.setItem("chartLabels", JSON.stringify(timestamps));
}


}, [isMounted, lastTvlNumber, timestamps]);

const labels: Array<{[date: string]: string}> = [];
Expand Down Expand Up @@ -276,9 +267,11 @@ export const LineChart = (): JSX.Element => {
</>}
<Box sx={{ display: "flex", paddingBottom: "1rem", height: "100%", width: "100%", justifyContent: "center", alignItems: "center" }} ref={hoverRef}>
{
!loadedChart
? <LoadingChart />
: <Line options={{ ...options, interaction: { mode: 'index', intersect: false } }} data={data} />
isUnsupportedNetwork
? <UnsupportedNetworkChart />
: !loadedChart
? <LoadingChart />
: <Line options={{ ...options, interaction: { mode: 'index', intersect: false } }} data={data} />
}
</Box>
</Box>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Box, Flex, Text, useColorMode } from "theme-ui";

export const UnsupportedNetworkChart = (): JSX.Element => {
const [colorMode] = useColorMode();

return (
<Box sx={{ position: "relative", width: "100%", height: "20rem" }}>
<Flex
sx={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
zIndex: 2,
pointerEvents: "none",
}}
>
<Text
sx={{
color: colorMode === "dark" ? "white" : "greytext",
textAlign: "center",
}}
>
The TVL chart doesn't support the connected network.
</Text>
</Flex>
<Flex sx={{ width: "100%", transform: "scaleX(-1)", height: "20rem", opacity: 0.4 }}>
<svg width='100%' preserveAspectRatio='xMinYMin slice' viewBox='0 0 766 300'>
<defs>
<linearGradient id='linear-gradient'>
<stop offset='0%' stopColor={colorMode === "dark" ? "#7d00ff" : colorMode === "darkGrey" ? "#e4e5e7b8" : "#e2e9ef"} />
<stop offset='33%' stopColor={colorMode === "dark" ? "#7d00ff" : colorMode === "darkGrey" ? "#e4e5e7b8" : "#e2e9ef"} />
<stop offset='50%' stopColor={colorMode === "dark" ? "#000" : colorMode === "darkGrey" ? "#fff" : "#aebcc9"} />
<stop offset='67%' stopColor={colorMode === "dark" ? "#7d00ff" : colorMode === "darkGrey" ? "#e4e5e7b8" : "#e2e9ef"} />
<stop offset='100%' stopColor={colorMode === "dark" ? "#7d00ff" : colorMode === "darkGrey" ? "#e4e5e7b8" : "#e2e9ef"} />
</linearGradient>
<linearGradient id='area' x1='50%' y1='-104.497044%' x2='50%' y2='85.1203676%'>
<stop offset='0%' stopColor={colorMode === "dark" ? "#7d00ff00" : colorMode === "darkGrey" ? "#f3f3f321" : "#fff"} />
<stop offset='100%' stopColor={colorMode === "dark" ? "#7c00fd8c" : colorMode === "darkGrey" ? "#e4e5e7b8" : "#e8eef5"} />
</linearGradient>
</defs>
<g fill='none' fillRule='evenodd' className='graph-example'>
<path
d='m0 113.767 7.192-6.25c22.34-19.411 56.186-17.038 75.598 5.302a53.587 53.587 0 0 1 5.674 7.869l6.671 11.279c9.695 16.391 30.842 21.82 47.234 12.125a34.482 34.482 0 0 0 9.869-8.774l11.766-15.436c7.005-9.19 20.134-10.96 29.323-3.955a20.922 20.922 0 0 1 5.279 5.913l.267.46c6.449 11.452 20.96 15.508 32.41 9.06a23.796 23.796 0 0 0 5.37-4.13l48.116-49.39c12.445-12.776 32.89-13.043 45.665-.598a32.293 32.293 0 0 1 6.85 9.734l3.073 6.743c5.291 11.604 18.987 16.722 30.59 11.431a23.092 23.092 0 0 0 8.864-7.115l.298-.404c9.31-12.933 27.342-15.87 40.275-6.56a28.854 28.854 0 0 1 6.44 6.396l42.863 58.668c14.744 20.182 43.058 24.59 63.24 9.846a45.256 45.256 0 0 0 11.053-11.583l11.582-17.517c8.396-12.699 25.497-16.187 38.196-7.79a27.565 27.565 0 0 1 8.252 8.512l.282.466c9.637 16.323 30.682 21.742 47.004 12.105a34.321 34.321 0 0 0 6.208-4.689l.6-.585c11.97-11.869 31.295-11.787 43.165.182a30.522 30.522 0 0 1 6.211 9.08l12.08 27.14c6.306 14.167 22.903 20.54 37.071 14.235a28.08 28.08 0 0 0 11.054-8.817l.315-.429V300H0V113.767Z'
fill='url(#area)'
className='graph-area'
/>
<path
d='m0 113.767 7.192-6.25c22.34-19.411 56.186-17.038 75.598 5.302a53.587 53.587 0 0 1 5.674 7.869l6.671 11.279c9.695 16.391 30.842 21.82 47.234 12.125a34.482 34.482 0 0 0 9.869-8.774l11.766-15.436c7.005-9.19 20.134-10.96 29.323-3.955a20.922 20.922 0 0 1 5.546 6.374c6.449 11.451 20.96 15.507 32.41 9.059a23.796 23.796 0 0 0 5.37-4.13l48.116-49.39c12.445-12.776 32.89-13.043 45.665-.598a32.293 32.293 0 0 1 6.85 9.734l3.073 6.743c5.291 11.604 18.987 16.722 30.59 11.431a23.092 23.092 0 0 0 9.162-7.52c9.31-12.932 27.342-15.869 40.275-6.558a28.854 28.854 0 0 1 6.44 6.395l42.863 58.668c14.744 20.182 43.058 24.59 63.24 9.846a45.256 45.256 0 0 0 11.053-11.583l11.582-17.517c8.396-12.699 25.497-16.187 38.196-7.79a27.565 27.565 0 0 1 8.534 8.978c9.637 16.323 30.682 21.742 47.004 12.105a34.321 34.321 0 0 0 6.717-5.183l.091-.09c11.97-11.87 31.295-11.788 43.165.181a30.522 30.522 0 0 1 6.211 9.08l12.08 27.14c6.306 14.167 22.903 20.54 37.071 14.235A28.08 28.08 0 0 0 766 186.29'
strokeWidth='2'
stroke='url(#linear-gradient)'
className='graph-line'
/>
</g>
</svg>
</Flex>
</Box>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { createContext, useContext } from "react";
import { Tvl, TimestampsObject } from "./ChartProvider"

type ChartContextType = {
tvl: Tvl[];
timestamps: Array<TimestampsObject>;
tvl?: Tvl[];
timestamps?: Array<TimestampsObject>;
isUnsupportedNetwork?: boolean;
};

export const ChartContext = createContext<ChartContextType | null>(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,18 +174,20 @@ async function fetchData(API_URL: string, query: string) {

export const ChartProvider = ({ children }: FunctionalPanelProps): JSX.Element => {
const timestamps: Array<TimestampsObject> = createListOfTimestamps();
// Define the state variables for the component using useState hook
const [isTVLDataAvailable, setisTVLDataAvailable] = useState<boolean>(true);
const [tvl, setTvl] = useState<Tvl[]>([]);
const [isMounted, setIsMounted] = useState<boolean>(true);

// Destructure values from useThreshold hook
const { threshold, config, provider } = useThreshold();
const { blocksApiUrl, thresholdUsdApiUrl } = config;
const { blocksApiUrl, thresholdUsdApiUrl, isUnsupportedNetwork } = config;

// Define the getTVLData function for fetching TVL data
const getTVLData = () => {
// Check if the required config properties are present
if (isUnsupportedNetwork) {
console.error(`The network is unsupported in config.json file`);
setisTVLDataAvailable(false);
return;
}

if (!blocksApiUrl || !thresholdUsdApiUrl || !coingeckoIdsBySymbol) {
console.error(`You must add a config.json file into the public source folder.`);
setisTVLDataAvailable(false);
Expand Down Expand Up @@ -223,28 +225,28 @@ export const ChartProvider = ({ children }: FunctionalPanelProps): JSX.Element
});
};

// Use the useEffect hook to fetch TVL data only once when the component mounts
useEffect(() => {
if (!isMounted) {
return;
}
getTVLData();

// Clean up function to set isMounted to false when the component unmounts
return () => {
setIsMounted(false);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isMounted]);

// Return the children wrapped in ChartContext.Provider if TVL data is available
if (isUnsupportedNetwork) return <ChartContext.Provider value={{ isUnsupportedNetwork }}>{children}</ChartContext.Provider>;

if (!isTVLDataAvailable || !timestamps || tvl.length !== threshold.length) {
return <>{children}</>
};

const chartProvider = {
tvl,
timestamps
timestamps,
isUnsupportedNetwork: false,
};

return <ChartContext.Provider value={chartProvider}>{children}</ChartContext.Provider>;
Expand Down
Loading
Loading