diff --git a/package.json b/package.json index f7e01d566a..83b3378217 100644 --- a/package.json +++ b/package.json @@ -42,12 +42,18 @@ "sdk:prettier": "yarn prettier projects/sdk -w", "sdk:publish": "yarn workspace @beanstalk/sdk publish", "sdk:version": "yarn workspace @beanstalk/sdk version", + "dex-ui:dev": "yarn workspace dex-ui dev", + "dex-ui:build": "yarn workspace dex-ui build", + "dex-ui:generate": "yarn workspace dex-ui generate", "ui:generate": "yarn workspace ui generate", + "ui:dev": "yarn workspace ui dev", "ui:start": "yarn workspace ui start", "ui:build": "yarn workspace ui build", "ui:test": "yarn workspace ui test", "test:browser": "yarn workspace tests test:browser", "ex": "yarn workspace @beanstalk/examples x", + "anvil-arbitrum": "yarn cli:anvil-arbitrum", + "anvil-eth-mainnet": "yarn cli:anvil-eth-mainnet", "anvil": "anvil --fork-url https://eth-mainnet.g.alchemy.com/v2/5ubn94zT7v7DnB5bNW1VOnoIbX5-AG2N --chain-id 1337", "anvil4tests": "anvil --fork-url https://eth-mainnet.g.alchemy.com/v2/Kk7ktCQL5wz4v4AG8bR2Gun8TAASQ-qi --chain-id 1337 --fork-block-number 18629000" }, diff --git a/projects/cli/.env.example b/projects/cli/.env.example new file mode 100644 index 0000000000..a900f24edb --- /dev/null +++ b/projects/cli/.env.example @@ -0,0 +1,5 @@ +# DEV API key +DEV_ALCHEMY_API_KEY="" + +# Test API key +DEV_TEST_ALCHEMY_API_KEY="" diff --git a/projects/cli/.gitignore b/projects/cli/.gitignore index dd87e2d73f..7f8efdeace 100644 --- a/projects/cli/.gitignore +++ b/projects/cli/.gitignore @@ -1,2 +1,4 @@ node_modules build + +.env \ No newline at end of file diff --git a/projects/cli/anvil.sh b/projects/cli/anvil.sh new file mode 100644 index 0000000000..da688875af --- /dev/null +++ b/projects/cli/anvil.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +source .env + +# Set variables based on arguments +keyType="$1" +chainIdType="$2" + +# Set chain IDs +mainnet_local_chain_id=1338 + +arbitrum_local_chain_id=1337 + +# Determine which API key to use +if [ "$keyType" = "test" ]; then + apiKey="$DEV_TEST_ALCHEMY_API_KEY" +else + apiKey="$DEV_ALCHEMY_API_KEY" +fi + +# Determine which chain ID to use. Defaults to arbitrum local host +if [ "$chainIdType" = "eth-mainnet" ]; then + chainId=$mainnet_local_chain_id + prefix="eth" + port=9545 +else + chainId=$arbitrum_local_chain_id + prefix="arb" + port=8545 +fi + +# Check if required variables are set +if [ -z "$prefix" ] || [ -z "$apiKey" ] || [ -z "$chainId" ]; then + echo "Error: Missing required variables. Please set keyType and chainIdType." + exit 1 +fi + +anvil \ + --fork-url "https://$prefix-mainnet.g.alchemy.com/v2/$apiKey" \ + --chain-id "$chainId" \ + --port "$port" \ + "${@:3}" + +# Check if Anvil exited with an error +if [ $? -ne 0 ]; then + echo "Error: Anvil exited with a non-zero status." + exit 1 +fi \ No newline at end of file diff --git a/projects/cli/package.json b/projects/cli/package.json index aeeac121f1..f06eaa79e5 100644 --- a/projects/cli/package.json +++ b/projects/cli/package.json @@ -1,6 +1,6 @@ { "name": "@beanstalk/cli", - "version": "0.0.10", + "version": "0.0.20", "description": "Beanstalk protocol development cli tool", "license": "MIT", "repository": { @@ -16,7 +16,11 @@ "scripts": { "cli:publish": "yarn cli:build && yarn npm publish --access public", "cli:build": "rimraf build && tsc && chmod u+x build/cli.js", - "g:bean": "yarn ts-node-esm src/cli.ts" + "g:bean": "yarn ts-node-esm src/cli.ts", + "cli:anvil-eth-mainnet": "bash anvil.sh dev eth-mainnet", + "cli:anvil-arbitrum": "bash anvil.sh dev arbitrum-mainnet", + "cli:anvil4tests-mainnet": "bash anvil.sh test eth-mainnet --fork-block-number 18629000", + "cli:anvil4tests-arbitrum": "bash anvil.sh test arbitrum-mainnet --fork-block-number 18629000" }, "devDependencies": { "@types/command-line-args": "^5.2.3", diff --git a/projects/cli/src/commands/balance.ts b/projects/cli/src/commands/balance.ts index 5f1b665f54..5f258255db 100644 --- a/projects/cli/src/commands/balance.ts +++ b/projects/cli/src/commands/balance.ts @@ -14,16 +14,21 @@ export const balance = async (sdk, { account, symbol }) => { [ "ETH", "WETH", + "WSTETH", + "WEETH", + "WBTC", "BEAN", - "USDT", - "USDC", "DAI", - "CRV3", - "UNRIPE_BEAN", - "UNRIPE_BEAN_wstETH", - "BEAN_CRV3_LP", - "BEAN_ETH_WELL_LP", - "ROOT" + "USDC", + "USDT", + "urBEAN", + "urBEANWSTETH", + "BEANWETH", + "BEANWEETH", + "BEANWEETH", + "BEANWBTC", + "BEANUSDC", + "BEANUSDT" ].map((s) => getBal(sdk, s, account)) ); res.push(...bals); @@ -32,7 +37,17 @@ export const balance = async (sdk, { account, symbol }) => { }; async function getBal(sdk, symbol: string, account: string) { - const token = sdk.tokens[symbol]; + let token = sdk.tokens[symbol]; + if (!token) { + if (symbol === "urBEAN") token = sdk.tokens.UNRIPE_BEAN; + if (symbol === "urBEANWSTETH") token = sdk.tokens.UNRIPE_BEAN_WSTETH; + if (symbol === "BEANWETH") token = sdk.tokens.BEAN_ETH_WELL_LP; + if (symbol === "BEANWEETH") token = sdk.tokens.BEAN_WEETH_WELL_LP; + if (symbol === "BEANWSTETH") token = sdk.tokens.BEAN_WSTETH_WELL_LP; + if (symbol === "BEANWBTC") token = sdk.tokens.BEAN_WBTC_WELL_LP; + if (symbol === "BEANUSDC") token = sdk.tokens.BEAN_USDC_WELL_LP; + if (symbol === "BEANUSDT") token = sdk.tokens.BEAN_USDT_WELL_LP; + } if (!token) throw new Error(`No token found: ${symbol}`); try { diff --git a/projects/cli/src/commands/setbalance.ts b/projects/cli/src/commands/setbalance.ts index f75d0346e4..a4a38a5554 100644 --- a/projects/cli/src/commands/setbalance.ts +++ b/projects/cli/src/commands/setbalance.ts @@ -14,16 +14,21 @@ export const setbalance = async (sdk, chain, { account, symbol, amount }) => { const symbols = [ "ETH", "WETH", + "WSTETH", + "WEETH", + "WBTC", "BEAN", - "USDT", - "USDC", "DAI", - "CRV3", - "BEAN3CRV", - "BEANWETH", + "USDC", + "USDT", "urBEAN", - "urBEANwstETH", - "ROOT" + "urBEANWSTETH", + "BEANWETH", + "BEANWSTETH", + "BEANWEETH", + "BEANWBTC", + "BEANUSDC", + "BEANUSDT" ]; if (!symbols.includes(symbol)) { console.log( @@ -33,10 +38,16 @@ export const setbalance = async (sdk, chain, { account, symbol, amount }) => { process.exit(-1); } let t = sdk.tokens[symbol] as Token; - if (symbol === "urBEAN") t = sdk.tokens.UNRIPE_BEAN; - if (symbol === "urBEANwstETH") t = sdk.tokens.UNRIPE_BEAN_WSTETH; - if (symbol === "BEAN3CRV") t = sdk.tokens.BEAN_CRV3_LP; - if (symbol === "BEANWETH") t = sdk.tokens.BEAN_ETH_WELL_LP; + if (!t) { + if (symbol === "urBEAN") t = sdk.tokens.UNRIPE_BEAN; + if (symbol === "urBEANWSTETH") t = sdk.tokens.UNRIPE_BEAN_WSTETH; + if (symbol === "BEANWETH") t = sdk.tokens.BEAN_ETH_WELL_LP; + if (symbol === "BEANWEETH") t = sdk.tokens.BEAN_WEETH_WELL_LP; + if (symbol === "BEANWSTETH") t = sdk.tokens.BEAN_WSTETH_WELL_LP; + if (symbol === "BEANWBTC") t = sdk.tokens.BEAN_WBTC_WELL_LP; + if (symbol === "BEANUSDC") t = sdk.tokens.BEAN_USDC_WELL_LP; + if (symbol === "BEANUSDT") t = sdk.tokens.BEAN_USDT_WELL_LP; + } if (typeof chain[`set${symbol}Balance`] !== "function") throw new Error(`${symbol} is not a valid token or the method ${chalk.bold.whiteBright("")}`); diff --git a/projects/cli/src/commands/setprice.ts b/projects/cli/src/commands/setprice.ts index 6b9caacd52..66c9254d47 100644 --- a/projects/cli/src/commands/setprice.ts +++ b/projects/cli/src/commands/setprice.ts @@ -14,18 +14,18 @@ export const setPrice = async (sdk: BeanstalkSDK, chain: TestUtils.BlockchainUti console.log(beanInput, crv3Input); const newBeanAmount = (beanInput ? beanInput : 20) * 1_000_000; - const newCrv3Amount = (crv3Input ? crv3Input : beanInput ? beanInput : 20) * 1_000_000; + // const newCrv3Amount = (crv3Input ? crv3Input : beanInput ? beanInput : 20) * 1_000_000; - const newBean = sdk.tokens.BEAN.amount(newBeanAmount); - const newCrv3 = sdk.tokens.CRV3.amount(newCrv3Amount); + // const newBean = sdk.tokens.BEAN.amount(newBeanAmount); + // const newCrv3 = sdk.tokens.CRV3.amount(newCrv3Amount); ////// Set the new balance - console.log(`New Balances: ${newBean.toHuman()} ${newCrv3.toHuman()}`); + // console.log(`New Balances: ${newBean.toHuman()} ${newCrv3.toHuman()}`); // update the array tracking balances - await setBalance(sdk, POOL_ADDRESS, BALANCE_SLOT, newBean, newCrv3); + // await setBalance(sdk, POOL_ADDRESS, BALANCE_SLOT, newBean, newCrv3); // actually give the pool the ERC20's - await chain.setBEANBalance(POOL_ADDRESS, newBean); - await chain.setCRV3Balance(POOL_ADDRESS, newCrv3); + // await chain.setBEANBalance(POOL_ADDRESS, newBean); + // await chain.setCRV3Balance(POOL_ADDRESS, newCrv3); // Curve also keeps track of the previous balance, so we just copy the existing current to old. await setBalance(sdk, POOL_ADDRESS, PREV_BALANCE_SLOT, currentBean, currentCrv3); diff --git a/projects/dex-ui/.env.local.example b/projects/dex-ui/.env.local.example index c15b585eca..cdc5eaf7a9 100644 --- a/projects/dex-ui/.env.local.example +++ b/projects/dex-ui/.env.local.example @@ -1,5 +1,7 @@ -VITE_AQUIFER_ADDRESS=local/fork deployed address +VITE_AQUIFER_ADDRESS_ETH="deployed address here" +VITE_AQUIFER_ADDRESS_ARBITRUM="deployed address here" VITE_ALCHEMY_API_KEY="your key here" +VITE_THEGRAPH_API_KEY="your key here" +VITE_WALLET_CONNECT_PROJECT_ID="project key here" VITE_WELLS_ORIGIN_BLOCK=17138465 -VITE_LOAD_HISTORY_FROM_GRAPH=0 -VITE_WALLET_CONNECT_PROJECT_ID="project key here" \ No newline at end of file +VITE_LOAD_HISTORY_FROM_GRAPH=0 \ No newline at end of file diff --git a/projects/dex-ui/.env.production b/projects/dex-ui/.env.production index 0df3966e5a..0803ee8379 100644 --- a/projects/dex-ui/.env.production +++ b/projects/dex-ui/.env.production @@ -1,5 +1,10 @@ // DO NOT ACTUALLY SAVE THINGS HERE // ONLY USE THIS FILE TO TRACK WHAT ENV VARS NEED TO // BE ADDED TO NETLIFY CONFIG +VITE_AQUIFER_ADDRESS_ETH="" +VITE_AQUIFER_ADDRESS_ARBITRUM="" VITE_ALCHEMY_API_KEY="" -VITE_WALLET_CONNECT_PROJECT_ID="" \ No newline at end of file +VITE_THEGRAPH_API_KEY="" +VITE_WALLET_CONNECT_PROJECT_ID="" +VITE_WELLS_ORIGIN_BLOCK="" +VITE_LOAD_HISTORY_FROM_GRAPH="" \ No newline at end of file diff --git a/projects/dex-ui/.eslintrc b/projects/dex-ui/.eslintrc index 5e526b6a46..f2fa3d80af 100644 --- a/projects/dex-ui/.eslintrc +++ b/projects/dex-ui/.eslintrc @@ -2,12 +2,21 @@ "settings": { "react": { "version": "detect" + }, + "import/resolver": { + "typescript": {}, + "node": { + "paths": ["src"], + "extensions": [".js", ".jsx", ".ts", ".tsx"] + } } }, "extends": [ "plugin:react/recommended", "plugin:jsx-a11y/recommended", // "plugin:@typescript-eslint/recommended", + // "plugin:import/errors", + // "plugin:import/warnings", "plugin:import/typescript" ], "parser": "@typescript-eslint/parser", @@ -18,13 +27,7 @@ "ecmaVersion": "latest", "sourceType": "module" }, - "plugins": [ - "react", - "react-hooks", - "@typescript-eslint", - "import", - "jsx-a11y" - ], + "plugins": ["react", "react-hooks", "@typescript-eslint", "import", "jsx-a11y"], "rules": { "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-non-null-assertion": "off", @@ -39,6 +42,41 @@ "react-hooks/rules-of-hooks": "error", "react-hooks/exhaustive-deps": "warn", "react/prop-types": 0, - "react/display-name": 0 + "react/display-name": 0, + "import/order": [ + "warn", + { + "groups": [ + "builtin", + "external", + "internal", + ["parent", "sibling", "index"], + "object", + "type" + ], + "pathGroups": [ + { + "pattern": "react", + "group": "external", + "position": "before" + }, + { + "pattern": "@beanstalk/sdk*", + "group": "external", + "position": "after" + }, + { + "pattern": "src/**", + "group": "internal" + } + ], + "pathGroupsExcludedImportTypes": ["react", "@beanstalk/sdk*"], + "alphabetize": { + "order": "asc", + "caseInsensitive": true + }, + "newlines-between": "always" + } + ] } -} \ No newline at end of file +} diff --git a/projects/dex-ui/codegen.ts b/projects/dex-ui/codegen.ts index 07d4686e04..526d09bdca 100644 --- a/projects/dex-ui/codegen.ts +++ b/projects/dex-ui/codegen.ts @@ -5,7 +5,8 @@ const config: CodegenConfig = { schema: [ "graphql.schema.json", // beanstalk subgraph - "https://graph.node.bean.money/subgraphs/name/beanstalk" + "https://graph.bean.money/beanstalk", + "https://graph.bean.money/beanstalk_eth" ], documents: "src/**/*.graphql", ignoreNoDocuments: true, diff --git a/projects/dex-ui/package.json b/projects/dex-ui/package.json index a01c41b755..f63f669919 100644 --- a/projects/dex-ui/package.json +++ b/projects/dex-ui/package.json @@ -30,6 +30,7 @@ "connectkit": "1.7.2", "ethers": "^5.7.2", "graphql-request": "5.2.0", + "jotai": "2.9.3", "lightweight-charts": "4.1.3", "prettier": "3.2.5", "react": "^18.2.0", diff --git a/projects/dex-ui/src/assets/images/tokens/ARB.svg b/projects/dex-ui/src/assets/images/tokens/ARB.svg new file mode 100644 index 0000000000..d6b9a7527d --- /dev/null +++ b/projects/dex-ui/src/assets/images/tokens/ARB.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/projects/dex-ui/src/assets/images/tokens/WBTC.svg b/projects/dex-ui/src/assets/images/tokens/WBTC.svg new file mode 100644 index 0000000000..2940e9c232 --- /dev/null +++ b/projects/dex-ui/src/assets/images/tokens/WBTC.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/projects/dex-ui/src/assets/images/tokens/index.tsx b/projects/dex-ui/src/assets/images/tokens/index.tsx index 59963997b8..840c4c8c34 100644 --- a/projects/dex-ui/src/assets/images/tokens/index.tsx +++ b/projects/dex-ui/src/assets/images/tokens/index.tsx @@ -1,12 +1,16 @@ -const glob = import.meta.glob("src/assets/images/tokens/*.svg", { - eager: true, - as: "url" - // import: "default" -}); +const glob = import.meta.glob( + ["src/assets/images/tokens/*.svg", "src/assets/images/tokens/*.png"], + { + eager: true, + as: "url" + } +); export const images: Record = {}; for (const key of Object.keys(glob)) { - let symbol = key.replace("/src/assets/images/tokens/", "").replace(".svg", ""); + const parts = key.split("/"); + const filename = parts[parts.length - 1]; + const symbol = filename.replace(/\.(svg|png)$/, ""); images[symbol] = glob[key]; } diff --git a/projects/dex-ui/src/assets/images/tokens/weETH.png b/projects/dex-ui/src/assets/images/tokens/weETH.png new file mode 100644 index 0000000000..e0ba7d239a Binary files /dev/null and b/projects/dex-ui/src/assets/images/tokens/weETH.png differ diff --git a/projects/dex-ui/src/components/App/App.tsx b/projects/dex-ui/src/components/App/App.tsx index cacac60c7c..52e798e3d9 100644 --- a/projects/dex-ui/src/components/App/App.tsx +++ b/projects/dex-ui/src/components/App/App.tsx @@ -1,16 +1,18 @@ import React from "react"; + import { Route, Routes } from "react-router-dom"; + +import { Frame } from "src/components/Frame/Frame"; import { NotFound } from "src/pages/404"; -import { Home } from "src/pages/Home"; +import { Build } from "src/pages/Build"; +import { Create } from "src/pages/Create"; import { Dev } from "src/pages/Dev"; +import { Home } from "src/pages/Home"; +import { Liquidity } from "src/pages/Liquidity"; +import { Swap } from "src/pages/Swap"; import { Well } from "src/pages/Well"; import { Wells } from "src/pages/Wells"; -import { Frame } from "src/components/Frame/Frame"; -import { Build } from "src/pages/Build"; -import { Swap } from "src/pages/Swap"; import { Settings } from "src/settings"; -import { Liquidity } from "src/pages/Liquidity"; -import { Create } from "src/pages/Create"; export const App = ({}) => { const isNotProd = !Settings.PRODUCTION; @@ -27,6 +29,7 @@ export const App = ({}) => { } /> {isNotProd && } />} } /> + {false && <>} ); diff --git a/projects/dex-ui/src/components/App/OnLoad.tsx b/projects/dex-ui/src/components/App/OnLoad.tsx index 963a730e45..a15f182327 100644 --- a/projects/dex-ui/src/components/App/OnLoad.tsx +++ b/projects/dex-ui/src/components/App/OnLoad.tsx @@ -1,7 +1,9 @@ import React, { useEffect } from "react"; + +import { useAccount } from "wagmi"; + import { useAllTokensBalance } from "src/tokens/useAllTokenBalance"; import { FC } from "src/types"; -import { useAccount } from "wagmi"; export const OnLoad: FC<{}> = ({ children }) => { const { address, chain } = useAccount(); @@ -13,20 +15,20 @@ export const OnLoad: FC<{}> = ({ children }) => { refetch(); }, [address, chain?.id, refetch]); - // useEffect(() => { - // const unwatch = watchAccount(config, { - // onChange(account, prevAccount) { - // // if (account.chain?.id !== chain?.id) { - // // console.log("CHECK ME"); - // // } - // // if (prevAccount.address !== account.address) { - // // console.log(`CHANGED! - from(${prevAccount.address}) to => ${account.address}`); - // // } - // } - // }); - - // return () => unwatch(); - // }); - return <>{children}; }; + +// useEffect(() => { +// const unwatch = watchAccount(config, { +// onChange(account, prevAccount) { +// // if (account.chain?.id !== chain?.id) { +// // console.log("CHECK ME"); +// // } +// // if (prevAccount.address !== account.address) { +// // console.log(`CHANGED! - from(${prevAccount.address}) to => ${account.address}`); +// // } +// } +// }); + +// return () => unwatch(); +// }); diff --git a/projects/dex-ui/src/components/App/Wrapper.tsx b/projects/dex-ui/src/components/App/Wrapper.tsx index ef4c809edf..0d5148f122 100644 --- a/projects/dex-ui/src/components/App/Wrapper.tsx +++ b/projects/dex-ui/src/components/App/Wrapper.tsx @@ -1,16 +1,18 @@ import React from "react"; -import { HashRouter } from "react-router-dom"; -import { FC } from "src/types"; -import { ConnectKitProvider } from "connectkit"; -import { WagmiProvider } from "wagmi"; + import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; +import { ConnectKitProvider } from "connectkit"; +import { HashRouter } from "react-router-dom"; +import { WagmiProvider } from "wagmi"; + +import JotaiProvider from "src/state"; +import { FC } from "src/types"; import { Avatar } from "src/utils/wagmi/Avatar"; -import { TokenProvider } from "src/tokens/TokenProvider"; -import { OnLoad } from "./OnLoad"; -import { SdkProvider } from "src/utils/sdk/SdkProvider"; import { config } from "src/utils/wagmi/config"; +import { OnLoad } from "./OnLoad"; + export const Wrapper: FC<{}> = ({ children }) => { const queryClient = new QueryClient(); return ( @@ -31,11 +33,9 @@ export const Wrapper: FC<{}> = ({ children }) => { }} > - - - {children} - - + + {children} + diff --git a/projects/dex-ui/src/components/BottomDrawer.tsx b/projects/dex-ui/src/components/BottomDrawer.tsx index 09d4629fcf..9257a81661 100644 --- a/projects/dex-ui/src/components/BottomDrawer.tsx +++ b/projects/dex-ui/src/components/BottomDrawer.tsx @@ -1,10 +1,13 @@ import React from "react"; -import { FC } from "src/types"; + import styled from "styled-components"; -import { BodyXS } from "./Typography"; + import x from "src/assets/images/x.svg"; -import { ImageButton } from "./ImageButton"; import { size } from "src/breakpoints"; +import { FC } from "src/types"; + +import { ImageButton } from "./ImageButton"; +import { BodyXS } from "./Typography"; interface Composition { Header: typeof Header; @@ -26,7 +29,12 @@ type Props = { toggleDrawer?: (isDrawerOpen: boolean) => void; }; -export const BottomDrawer: FC & Composition = ({ children, showDrawer, headerText, toggleDrawer }) => { +export const BottomDrawer: FC & Composition = ({ + children, + showDrawer, + headerText, + toggleDrawer +}) => { return ( <> diff --git a/projects/dex-ui/src/components/Button.tsx b/projects/dex-ui/src/components/Button.tsx index 2a1df8b064..f2b6737050 100644 --- a/projects/dex-ui/src/components/Button.tsx +++ b/projects/dex-ui/src/components/Button.tsx @@ -1,4 +1,7 @@ import React, { ButtonHTMLAttributes, CSSProperties, forwardRef } from "react"; + +import styled from "styled-components"; + import { CommonCssProps, CommonCssStyles, @@ -7,7 +10,7 @@ import { makeCssStyle } from "src/utils/ui/styled"; import { theme } from "src/utils/ui/theme"; -import styled from "styled-components"; + import { Spinner } from "./Spinner"; export type ButtonVariant = "outlined" | "contained"; // | "text" (Add Text Variant later) diff --git a/projects/dex-ui/src/components/Checkbox.tsx b/projects/dex-ui/src/components/Checkbox.tsx index 22b82c7cdf..9447c2309b 100644 --- a/projects/dex-ui/src/components/Checkbox.tsx +++ b/projects/dex-ui/src/components/Checkbox.tsx @@ -1,8 +1,11 @@ -import { FC } from "src/types"; import React from "react"; + import styled from "styled-components"; -import { BodyXS } from "./Typography"; + import { size } from "src/breakpoints"; +import { FC } from "src/types"; + +import { BodyXS } from "./Typography"; type Props = { label?: string; @@ -12,12 +15,23 @@ type Props = { onClick?: () => void; }; -export const Checkbox: FC = ({ label, checked = false, mode, checkboxColor = "black", onClick = () => {} }) => { +export const Checkbox: FC = ({ + label, + checked = false, + mode, + checkboxColor = "black", + onClick = () => {} +}) => { return ( - + {checked && ( ` - border: 1px solid ${(props) => (props.checkboxColor && props.checked ? props.checkboxColor : "#000")}; + border: 1px solid + ${(props) => (props.checkboxColor && props.checked ? props.checkboxColor : "#000")}; width: 16px; height: 16px; position: ${(props) => (props.mode === "checkOnly" ? "relative" : "absolute")}; diff --git a/projects/dex-ui/src/components/Create/ComponentLibraryTable.tsx b/projects/dex-ui/src/components/Create/ComponentLibraryTable.tsx index a442972848..87123e69f2 100644 --- a/projects/dex-ui/src/components/Create/ComponentLibraryTable.tsx +++ b/projects/dex-ui/src/components/Create/ComponentLibraryTable.tsx @@ -1,10 +1,12 @@ import React from "react"; + +import { Link } from "react-router-dom"; import styled from "styled-components"; import { Table, Td, THead, ResponsiveTr, Th, TBody, Row } from "src/components//Table"; -import { Link } from "react-router-dom"; -import { theme } from "src/utils/ui/theme"; import { Text } from "src/components/Typography"; +import { theme } from "src/utils/ui/theme"; + import { useWhitelistedWellComponents } from "./useWhitelistedWellComponents"; export const ComponentLibraryTable = () => { diff --git a/projects/dex-ui/src/components/Create/CreateWellProvider.tsx b/projects/dex-ui/src/components/Create/CreateWellProvider.tsx index bc9b2a8a44..f41c68e746 100644 --- a/projects/dex-ui/src/components/Create/CreateWellProvider.tsx +++ b/projects/dex-ui/src/components/Create/CreateWellProvider.tsx @@ -1,14 +1,19 @@ import React, { createContext, useCallback, useMemo, useState } from "react"; -import { ERC20Token, TokenValue } from "@beanstalk/sdk-core"; + import { DeepRequired } from "react-hook-form"; -import useSdk from "src/utils/sdk/useSdk"; -import { Log } from "src/utils/logger"; -import { Pump, WellFunction } from "@beanstalk/sdk-wells"; import { useAccount } from "wagmi"; -import { usePumps } from "src/wells/pump/usePumps"; + +import { ERC20Token, TokenValue } from "@beanstalk/sdk-core"; +import { Pump, WellFunction } from "@beanstalk/sdk-wells"; + +import { clearWellsCache } from "src/state/providers/WellsProvider"; +import { Log } from "src/utils/logger"; +import { queryKeys } from "src/utils/query/queryKeys"; +import { useFetchChainScopedQueryData } from "src/utils/query/useChainScopedQuery"; +import useSdk from "src/utils/sdk/useSdk"; +import { useAquifer } from "src/wells/aquifer/aquifer"; import BoreWellUtils from "src/wells/boreWell"; -import { clearWellsCache } from "src/wells/useWells"; -import { useQueryClient } from "@tanstack/react-query"; +import { usePumps } from "src/wells/pump/usePumps"; /** * Architecture notes: @Space-Bean @@ -123,7 +128,8 @@ export const CreateWellProvider = ({ children }: { children: React.ReactNode }) const { address: walletAddress } = useAccount(); const sdk = useSdk(); const pumps = usePumps(); - const queryClient = useQueryClient(); + const aquifer = useAquifer(); + const fetchScopedQueryData = useFetchChainScopedQueryData(); /// ----- Local State ----- const [deploying, setDeploying] = useState(false); @@ -242,6 +248,7 @@ export const CreateWellProvider = ({ children }: { children: React.ReactNode }) const { wellAddress } = await BoreWellUtils.boreWell( sdk, + aquifer, walletAddress, wellImplementation, wellFunction, @@ -255,7 +262,7 @@ export const CreateWellProvider = ({ children }: { children: React.ReactNode }) ); clearWellsCache(); - queryClient.fetchQuery({ queryKey: ["wells", sdk] }); + fetchScopedQueryData(queryKeys.wells(sdk)); Log.module("wellDeployer").debug("Well deployed at address: ", wellAddress || ""); setDeploying(false); @@ -268,7 +275,6 @@ export const CreateWellProvider = ({ children }: { children: React.ReactNode }) }, [ pumpAddress, - queryClient, walletAddress, wellImplementation, wellFunction, @@ -277,7 +283,9 @@ export const CreateWellProvider = ({ children }: { children: React.ReactNode }) wellTokens.token2, wellDetails.name, wellDetails.symbol, - sdk + sdk, + aquifer, + fetchScopedQueryData ] ); diff --git a/projects/dex-ui/src/components/Create/CreateWellStep1.tsx b/projects/dex-ui/src/components/Create/CreateWellStep1.tsx index a7b83dea74..9a600a5692 100644 --- a/projects/dex-ui/src/components/Create/CreateWellStep1.tsx +++ b/projects/dex-ui/src/components/Create/CreateWellStep1.tsx @@ -1,13 +1,15 @@ import React from "react"; + +import { FormProvider, useForm } from "react-hook-form"; +import styled from "styled-components"; + import { Flex } from "src/components/Layout"; import { Text } from "src/components/Typography"; +import { theme } from "src/utils/ui/theme"; -import { FormProvider, useForm } from "react-hook-form"; import { CreateWellStepProps, useCreateWell } from "./CreateWellProvider"; import { ComponentInputWithCustom } from "./shared/ComponentInputWithCustom"; import { CreateWellButtonRow } from "./shared/CreateWellButtonRow"; -import styled from "styled-components"; -import { theme } from "src/utils/ui/theme"; import { StyledForm } from "../Form"; type FormValues = CreateWellStepProps["step1"]; diff --git a/projects/dex-ui/src/components/Create/CreateWellStep2.tsx b/projects/dex-ui/src/components/Create/CreateWellStep2.tsx index 8a1aa9ca53..998f0da273 100644 --- a/projects/dex-ui/src/components/Create/CreateWellStep2.tsx +++ b/projects/dex-ui/src/components/Create/CreateWellStep2.tsx @@ -1,24 +1,28 @@ import React, { useEffect, useMemo, useState } from "react"; -import styled from "styled-components"; + import { FormProvider, useForm, useFormContext, useWatch } from "react-hook-form"; -import { getIsValidEthereumAddress } from "src/utils/addresses"; -import { theme } from "src/utils/ui/theme"; -import { Divider, Flex, FlexCard } from "src/components/Layout"; -import { Text } from "src/components/Typography"; -import { CreateWellButtonRow } from "./shared/CreateWellButtonRow"; +import styled from "styled-components"; + +import { ERC20Token } from "@beanstalk/sdk"; + +import { images } from "src/assets/images/tokens"; +import { Dropdown } from "src/components/Dropdown"; import { StyledForm, TextInputField } from "src/components/Form"; import { XIcon } from "src/components/Icons"; -import { CreateWellStepProps, useCreateWell } from "./CreateWellProvider"; -import { CreateWellFormProgress } from "./shared/CreateWellFormProgress"; -import { ComponentInputWithCustom } from "./shared/ComponentInputWithCustom"; +import { Divider, Flex, FlexCard } from "src/components/Layout"; +import { Text } from "src/components/Typography"; import { useERC20TokenWithAddress } from "src/tokens/useERC20Token"; -import { ERC20Token } from "@beanstalk/sdk"; +import { getIsValidEthereumAddress } from "src/utils/addresses"; import useSdk from "src/utils/sdk/useSdk"; +import { theme } from "src/utils/ui/theme"; +import { useBoolean } from "src/utils/ui/useBoolean"; import BoreWellUtils from "src/wells/boreWell"; import { useValidateWellFunction } from "src/wells/wellFunction/useValidateWellFunction"; -import { useBoolean } from "src/utils/ui/useBoolean"; -import { Dropdown } from "src/components/Dropdown"; -import { images } from "src/assets/images/tokens"; + +import { CreateWellStepProps, useCreateWell } from "./CreateWellProvider"; +import { ComponentInputWithCustom } from "./shared/ComponentInputWithCustom"; +import { CreateWellButtonRow } from "./shared/CreateWellButtonRow"; +import { CreateWellFormProgress } from "./shared/CreateWellFormProgress"; const additionalOptions = [ { diff --git a/projects/dex-ui/src/components/Create/CreateWellStep3.tsx b/projects/dex-ui/src/components/Create/CreateWellStep3.tsx index c39b09969b..dc3cb06eda 100644 --- a/projects/dex-ui/src/components/Create/CreateWellStep3.tsx +++ b/projects/dex-ui/src/components/Create/CreateWellStep3.tsx @@ -1,32 +1,48 @@ import React from "react"; + +import { FormProvider, useForm } from "react-hook-form"; +import styled from "styled-components"; + import { Divider, Flex } from "src/components/Layout"; import { Text } from "src/components/Typography"; +import useSdk from "src/utils/sdk/useSdk"; import { theme } from "src/utils/ui/theme"; -import styled from "styled-components"; +import { useWells } from "src/wells/useWells"; + import { CreateWellStepProps, useCreateWell } from "./CreateWellProvider"; -import { FormProvider, useForm } from "react-hook-form"; +import { CreateWellButtonRow } from "./shared/CreateWellButtonRow"; import { CreateWellFormProgress } from "./shared/CreateWellFormProgress"; import { StyledForm, TextInputField } from "../Form"; -import { useWells } from "src/wells/useWells"; -import { CreateWellButtonRow } from "./shared/CreateWellButtonRow"; export type WellDetailsFormValues = CreateWellStepProps["step3"]; // If the user goes back to step 2 changes the well function & returns to this step, // the default values will not be updated. -// TODO: priofity sm. const useWellDetailsDefaultValues = () => { - const { wellTokens, wellFunction } = useCreateWell(); + const { wellImplementation, wellTokens, wellFunction } = useCreateWell(); + const sdk = useSdk(); + + const wellDotSolL2 = sdk.wells.addresses.WELL_DOT_SOL.ARBITRUM_MAINNET; const wellName = wellFunction?.name; const wellSymbol = wellFunction?.symbol; const token1 = wellTokens?.token1?.symbol; const token2 = wellTokens?.token2?.symbol; - const defaultName = - wellName && token1 && token2 ? `${token1}:${token2} ${wellName} Well` : undefined; + const upgradeable = wellImplementation?.toLowerCase() === wellDotSolL2.toLowerCase(); + const upgradeableNameFragment = upgradeable ? " Upgradeable " : ""; + const upgradeableSymbolFragment = upgradeable ? "U-" : ""; - const defaultSymbol = wellSymbol && token1 && token2 && `${token1}${token2}${wellSymbol}w`; + const defaultName = + wellName && token1 && token2 + ? `${token1}:${token2} ${wellName}${upgradeableNameFragment}Well` + : undefined; + + const defaultSymbol = + wellSymbol && + token1 && + token2 && + `${upgradeableSymbolFragment}${token1}${token2}${wellSymbol}w`; return { name: defaultName, diff --git a/projects/dex-ui/src/components/Create/CreateWellStep4.tsx b/projects/dex-ui/src/components/Create/CreateWellStep4.tsx index 90bc2568f7..ce5731108e 100644 --- a/projects/dex-ui/src/components/Create/CreateWellStep4.tsx +++ b/projects/dex-ui/src/components/Create/CreateWellStep4.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from "react"; -import styled from "styled-components"; + import { Control, Controller, @@ -8,30 +8,31 @@ import { useFormContext, useWatch } from "react-hook-form"; -import { theme } from "src/utils/ui/theme"; +import { useNavigate } from "react-router-dom"; +import styled from "styled-components"; +import { useAccount } from "wagmi"; + +import { ERC20Token, TokenValue } from "@beanstalk/sdk"; import { StyledForm, SwitchField, TextInputField } from "src/components/Form"; import { Box, Divider, Flex, FlexCard } from "src/components/Layout"; import { SelectCard } from "src/components/Selectable"; +import { TokenInput } from "src/components/Swap/TokenInput"; import { Text } from "src/components/Typography"; +import { useTokenAllowance } from "src/tokens/useTokenAllowance"; +import { queryKeys } from "src/utils/query/queryKeys"; +import { useInvalidateQueries } from "src/utils/query/useInvalidateQueries"; +import useSdk from "src/utils/sdk/useSdk"; +import { theme } from "src/utils/ui/theme"; +import { useBoolean } from "src/utils/ui/useBoolean"; import { CreateWellContext, CreateWellStepProps, useCreateWell } from "./CreateWellProvider"; -import { WellComponentInfo, useWhitelistedWellComponents } from "./useWhitelistedWellComponents"; - -import { ERC20Token, TokenValue } from "@beanstalk/sdk"; -import { TokenInput } from "src/components/Swap/TokenInput"; import { CreateWellButtonRow } from "./shared/CreateWellButtonRow"; -import { useTokenAllowance } from "src/tokens/useTokenAllowance"; -import useSdk from "src/utils/sdk/useSdk"; +import { WellComponentInfo, useWhitelistedWellComponents } from "./useWhitelistedWellComponents"; import { ButtonPrimary } from "../Button"; import { ensureAllowance } from "../Liquidity/allowance"; -import { useAccount } from "wagmi"; -import { useQueryClient } from "@tanstack/react-query"; -import { queryKeys } from "src/utils/query/queryKeys"; -import { useBoolean } from "src/utils/ui/useBoolean"; -import { ProgressCircle } from "../ProgressCircle"; -import { useNavigate } from "react-router-dom"; import { Modal } from "../Modal"; +import { ProgressCircle } from "../ProgressCircle"; type FormValues = CreateWellStepProps["step4"] & { usingSalt: boolean; @@ -73,11 +74,15 @@ const FormContent = ({ } }); - const [seeding, _amt1, _amt2] = methods.watch(['seedingLiquidity', 'token1Amount', 'token2Amount']); + const [seeding, _amt1, _amt2] = methods.watch([ + "seedingLiquidity", + "token1Amount", + "token2Amount" + ]); const amt1 = Number(_amt1 || 0); const amt2 = Number(_amt2 || 0); - const bothAmountsNeeded = seeding ? (amt1 > 0 && amt2 <= 0) || (amt1 <= 0 && amt2 > 0) : false; + const bothAmountsNeeded = seeding ? (amt1 > 0 && amt2 <= 0) || (amt1 <= 0 && amt2 > 0) : false; const handleSave = (formValues?: FormValues) => { const values = formValues || methods.getValues(); @@ -280,7 +285,8 @@ const AllowanceButtons = ({ }) => { const { address } = useAccount(); const sdk = useSdk(); - const queryClient = useQueryClient(); + + const invalidateQueries = useInvalidateQueries(); const { data: token1Allowance } = useTokenAllowance(token1, sdk.contracts.beanstalk.address); const { data: token2Allowance } = useTokenAllowance(token2, sdk.contracts.beanstalk.address); @@ -294,9 +300,7 @@ const AllowanceButtons = ({ const approveToken = async (token: ERC20Token, amount: TokenValue) => { if (!address) return; await ensureAllowance(address, sdk.contracts.beanstalk.address, token, amount); - queryClient.invalidateQueries({ - queryKey: queryKeys.tokenAllowance(token.address, sdk.contracts.beanstalk.address) - }); + invalidateQueries(queryKeys.tokenAllowance(token.address, sdk.contracts.beanstalk.address)); }; useEffect(() => { diff --git a/projects/dex-ui/src/components/Create/shared/ComponentAccordionCard.tsx b/projects/dex-ui/src/components/Create/shared/ComponentAccordionCard.tsx index d8f4432b52..9f948bad6d 100644 --- a/projects/dex-ui/src/components/Create/shared/ComponentAccordionCard.tsx +++ b/projects/dex-ui/src/components/Create/shared/ComponentAccordionCard.tsx @@ -1,12 +1,15 @@ import React from "react"; -import styled from "styled-components"; + import { Link } from "react-router-dom"; -import { theme } from "src/utils/ui/theme"; +import styled from "styled-components"; + +import { ChainExplorerIcon, Github } from "src/components/Icons"; import { Box, Flex } from "src/components/Layout"; +import { AccordionSelectCard } from "src/components/Selectable"; import { Text } from "src/components/Typography"; +import { theme } from "src/utils/ui/theme"; + import { WellComponentInfo } from "../useWhitelistedWellComponents"; -import { AccordionSelectCard } from "../../Selectable"; -import { Etherscan, Github } from "../../Icons"; export type WellComponentAccordionCardProps = { selected: boolean; @@ -94,9 +97,9 @@ export const WellComponentAccordionCard = ({ - {links.etherscan && ( - - + {links.explorer && ( + + )} {links.github && ( diff --git a/projects/dex-ui/src/components/Create/shared/ComponentInputWithCustom.tsx b/projects/dex-ui/src/components/Create/shared/ComponentInputWithCustom.tsx index 2f132349e4..9cb90a9498 100644 --- a/projects/dex-ui/src/components/Create/shared/ComponentInputWithCustom.tsx +++ b/projects/dex-ui/src/components/Create/shared/ComponentInputWithCustom.tsx @@ -1,16 +1,19 @@ import React, { useCallback } from "react"; + import { FieldValues, Path, PathValue, useFormContext, useWatch } from "react-hook-form"; -import { useWhitelistedWellComponents } from "../useWhitelistedWellComponents"; -import { useBoolean } from "src/utils/ui/useBoolean"; -import { TextInputField } from "../../Form"; +import styled from "styled-components"; + import { Flex } from "src/components/Layout"; import { ToggleSwitch } from "src/components/ToggleSwitch"; -import { WellComponentAccordionCard } from "./ComponentAccordionCard"; import { Text } from "src/components/Typography"; +import { getIsValidEthereumAddress } from "src/utils/addresses"; import { theme } from "src/utils/ui/theme"; -import styled from "styled-components"; +import { useBoolean } from "src/utils/ui/useBoolean"; + +import { WellComponentAccordionCard } from "./ComponentAccordionCard"; +import { TextInputField } from "../../Form"; import { CircleFilledCheckIcon, CircleEmptyIcon } from "../../Icons"; -import { getIsValidEthereumAddress } from "src/utils/addresses"; +import { useWhitelistedWellComponents } from "../useWhitelistedWellComponents"; type AdditionalOptionProps = { value: string; diff --git a/projects/dex-ui/src/components/Create/shared/CreateWellButtonRow.tsx b/projects/dex-ui/src/components/Create/shared/CreateWellButtonRow.tsx index e6c769bfcd..f3d56468cd 100644 --- a/projects/dex-ui/src/components/Create/shared/CreateWellButtonRow.tsx +++ b/projects/dex-ui/src/components/Create/shared/CreateWellButtonRow.tsx @@ -1,13 +1,16 @@ import React, { useMemo } from "react"; + import { useFormContext, useWatch } from "react-hook-form"; import { useNavigate } from "react-router-dom"; -import { theme } from "src/utils/ui/theme"; import styled from "styled-components"; + +import { ActionWalletButtonWrapper } from "src/components/Wallet"; +import { theme } from "src/utils/ui/theme"; + import { ButtonPrimary } from "../../Button"; import { LeftArrow, RightArrow } from "../../Icons"; import { Flex } from "../../Layout"; import { useCreateWell } from "../CreateWellProvider"; -import { ActionWalletButtonWrapper } from "src/components/Wallet"; const ButtonLabels = [ { @@ -72,7 +75,7 @@ export const CreateWellButtonRow = ({ const goNextEnabled = noErrors && hasRequiredValues; const goBackLabel = ButtonLabels[step].back || "Back"; - const nextLabel = disabled && disabledMessage || ButtonLabels[step].next || "Next"; + const nextLabel = (disabled && disabledMessage) || ButtonLabels[step].next || "Next"; return ( diff --git a/projects/dex-ui/src/components/Create/shared/CreateWellFormProgress.tsx b/projects/dex-ui/src/components/Create/shared/CreateWellFormProgress.tsx index 27ceddd0b2..42b22c42f7 100644 --- a/projects/dex-ui/src/components/Create/shared/CreateWellFormProgress.tsx +++ b/projects/dex-ui/src/components/Create/shared/CreateWellFormProgress.tsx @@ -1,11 +1,14 @@ import React, { useMemo } from "react"; + import { useFormContext, useWatch } from "react-hook-form"; -import { theme } from "src/utils/ui/theme"; -import { CheckIcon, CircleEmptyIcon } from "src/components/Icons"; -import { Flex } from "src/components/Layout"; import { Link } from "react-router-dom"; import styled from "styled-components"; + +import { CheckIcon, CircleEmptyIcon } from "src/components/Icons"; +import { Flex } from "src/components/Layout"; import { Text } from "src/components/Typography"; +import { theme } from "src/utils/ui/theme"; + import { FunctionTokenPumpFormValues } from "../CreateWellStep2"; import { WellDetailsFormValues } from "../CreateWellStep3"; diff --git a/projects/dex-ui/src/components/Create/useWhitelistedWellComponents.ts b/projects/dex-ui/src/components/Create/useWhitelistedWellComponents.ts index b2c1eb6df8..89b832f3b0 100644 --- a/projects/dex-ui/src/components/Create/useWhitelistedWellComponents.ts +++ b/projects/dex-ui/src/components/Create/useWhitelistedWellComponents.ts @@ -1,21 +1,20 @@ import { useMemo } from "react"; + +import { ChainId, ChainResolver } from "@beanstalk/sdk-core"; + import BeanstalkFarmsLogo from "src/assets/images/beanstalk-farms.png"; -import HalbornLogo from "src/assets/images/halborn-logo.png"; -import { - WELL_DOT_SOL_ADDRESS, - toAddressMap, - MULTI_FLOW_PUMP_V_1PT1_ADDRESS, - CONSTANT_PRODUCT_2_V2_ADDRESS -} from "src/utils/addresses"; import BrendanTwitterPFP from "src/assets/images/brendan-twitter-pfp.png"; -import CyrfinLogo from "src/assets/images/cyrfin-logo.svg"; -import Code4renaLogo from "src/assets/images/code4rena-logo.png"; import ClockIcon from "src/assets/images/clock-icon.svg"; -import { useWells } from "src/wells/useWells"; +import Code4renaLogo from "src/assets/images/code4rena-logo.png"; +import CyrfinLogo from "src/assets/images/cyrfin-logo.svg"; +import HalbornLogo from "src/assets/images/halborn-logo.png"; +import { AddressMap } from "src/types"; +import { toAddressMap } from "src/utils/addresses"; +import useSdk from "src/utils/sdk/useSdk"; +import { usePumps } from "src/wells/pump/usePumps"; import { useWellImplementations } from "src/wells/useWellImplementations"; +import { useWells } from "src/wells/useWells"; import { useWellFunctions } from "src/wells/wellFunction/useWellFunctions"; -import { usePumps } from "src/wells/pump/usePumps"; -import { AddressMap } from "src/types"; export enum WellComponentType { WellImplementation = "WellImplementation", @@ -51,7 +50,9 @@ export type WellComponentInfo = { }; info: ComponentInfo[]; links: { - etherscan?: string; + explorer?: string; + // arbiscan?: string; + // etherscan?: string; github?: string; learnMore?: string; }; @@ -82,7 +83,7 @@ const basinAuditInfo = [ ]; const WellDotSol: WellComponentInfo = { - address: WELL_DOT_SOL_ADDRESS, + address: "", component: { name: "Well.sol", summary: "A standard Well implementation that prioritizes flexibility and composability.", @@ -103,14 +104,13 @@ const WellDotSol: WellComponentInfo = { { label: "Audited by", value: basinAuditInfo } ], links: { - etherscan: `https://etherscan.io/address/${WELL_DOT_SOL_ADDRESS}`, github: "https://github.com/BeanstalkFarms/Basin/blob/master/src/Well.sol", learnMore: "https://github.com/BeanstalkFarms/Basin/blob/master/src/Well.sol" } }; const MultiFlowPump: WellComponentInfo = { - address: MULTI_FLOW_PUMP_V_1PT1_ADDRESS, + address: "", component: { name: "Multi Flow", fullName: "Multi Flow Pump V1.1", @@ -136,14 +136,13 @@ const MultiFlowPump: WellComponentInfo = { { label: "Audited by", value: basinAuditInfo } ], links: { - etherscan: `https://etherscan.io/address/${MULTI_FLOW_PUMP_V_1PT1_ADDRESS}`, github: "https://github.com/BeanstalkFarms/Basin/blob/master/src/pumps/MultiFlowPump.sol", learnMore: "https://github.com/BeanstalkFarms/Basin/blob/master/src/pumps/MultiFlowPump.sol" } }; const ConstantProduct2: WellComponentInfo = { - address: CONSTANT_PRODUCT_2_V2_ADDRESS, + address: "", component: { name: "Constant Product 2", summary: "A standard x*y = k token pricing function for two tokens.", @@ -162,7 +161,6 @@ const ConstantProduct2: WellComponentInfo = { { label: "Audited by", value: basinAuditInfo } ], links: { - etherscan: `https://etherscan.io/address/${CONSTANT_PRODUCT_2_V2_ADDRESS}`, github: "https://github.com/BeanstalkFarms/Basin/blob/master/src/functions/ConstantProduct2.sol", learnMore: @@ -176,16 +174,21 @@ type WellComponentMap = { wellFunctions: T; }; -const ComponentWhiteList: WellComponentMap> = { - wellImplementations: { - [WellDotSol.address]: WellDotSol - }, - pumps: { - [MultiFlowPump.address]: MultiFlowPump - }, - wellFunctions: { - [ConstantProduct2.address]: ConstantProduct2 - } +const getComponentWithUpdateLinks = ( + wellComponent: WellComponentInfo, + chainId: ChainId, + address: string +) => { + const explorer = `https://${ChainResolver.isL2Chain(chainId) ? "arbiscan" : "etherscan"}.io/address/${address}`; + + return { + ...wellComponent, + address, + links: { + ...wellComponent.links, + explorer + } + }; }; export const useWhitelistedWellComponents = () => { @@ -193,10 +196,42 @@ export const useWhitelistedWellComponents = () => { const { data: implementations } = useWellImplementations(); const wellFunctions = useWellFunctions(); const pumps = usePumps(); + const sdk = useSdk(); + + const whitelist = useMemo(() => { + // set Addresses + const wellDotSol = getComponentWithUpdateLinks( + WellDotSol, + sdk.chainId, + sdk.wells.addresses.WELL_DOT_SOL.get(sdk.chainId) + ); + const multiFlow = getComponentWithUpdateLinks( + MultiFlowPump, + sdk.chainId, + sdk.wells.addresses.MULTI_FLOW_PUMP_V1_1.get(sdk.chainId) + ); + const cp2 = getComponentWithUpdateLinks( + ConstantProduct2, + sdk.chainId, + sdk.wells.addresses.CONSTANT_PRODUCT_2_V2.get(sdk.chainId) + ); + + return { + wellImplementations: { + [wellDotSol.address]: wellDotSol + }, + pumps: { + [multiFlow.address]: multiFlow + }, + wellFunctions: { + [cp2.address]: cp2 + } + }; + }, [sdk]); return useMemo(() => { // make deep copy of ComponentWhiteList - const map = JSON.parse(JSON.stringify(ComponentWhiteList)) as WellComponentMap< + const map = JSON.parse(JSON.stringify(whitelist)) as WellComponentMap< AddressMap >; @@ -237,5 +272,5 @@ export const useWhitelistedWellComponents = () => { components, lookup: map }; - }, [implementations, pumps, wellFunctions, wells]); + }, [whitelist, implementations, pumps, wellFunctions, wells]); }; diff --git a/projects/dex-ui/src/components/Dropdown.tsx b/projects/dex-ui/src/components/Dropdown.tsx index 3482e18224..0ac1dadb08 100644 --- a/projects/dex-ui/src/components/Dropdown.tsx +++ b/projects/dex-ui/src/components/Dropdown.tsx @@ -1,10 +1,13 @@ import React from "react"; + import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; import styled from "styled-components"; + import { theme } from "src/utils/ui/theme"; -import { Flex } from "./Layout"; import useElementDimensions from "src/utils/ui/useDimensions"; +import { Flex } from "./Layout"; + export type DropdownProps = { open: boolean; trigger: React.ReactNode; diff --git a/projects/dex-ui/src/components/Error.tsx b/projects/dex-ui/src/components/Error.tsx index cc1305d2a7..9be1483db3 100644 --- a/projects/dex-ui/src/components/Error.tsx +++ b/projects/dex-ui/src/components/Error.tsx @@ -1,28 +1,24 @@ import React from "react"; + +import styled from "styled-components"; + import { Footer } from "src/components/Frame/Footer"; import { Frame } from "src/components/Frame/Frame"; -import styled from "styled-components"; type ErrorProps = { message: string; errorOnly?: boolean; -} +}; export const Error = ({ message, errorOnly }: ErrorProps) => { return ( <> {!errorOnly && } - - - Oops! - - - {"Something went wrong :("} - - - {message} - - + + Oops! + {"Something went wrong :("} + {message} + {!errorOnly &&