diff --git a/bun.lockb b/bun.lockb index ba366dbc..c439c9e9 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/packages/app/.env.example b/packages/app/.env.example index b1a71694..d308d920 100644 --- a/packages/app/.env.example +++ b/packages/app/.env.example @@ -5,5 +5,7 @@ NEXT_PUBLIC_FATHOM_SITE_ID= RPC_GNOSIS= RPC_MAINNET= RPC_ARBITRUM= +RPC_BASE= + NEXT_STACKLY_SUBGRAPH_API_KEY= \ No newline at end of file diff --git a/packages/app/app/opengraph-image.png b/packages/app/app/opengraph-image.png index bf7a1cd5..c42ae7ab 100644 Binary files a/packages/app/app/opengraph-image.png and b/packages/app/app/opengraph-image.png differ diff --git a/packages/app/app/twitter-image.png b/packages/app/app/twitter-image.png index bf7a1cd5..c42ae7ab 100644 Binary files a/packages/app/app/twitter-image.png and b/packages/app/app/twitter-image.png differ diff --git a/packages/app/components/Avatar.tsx b/packages/app/components/Avatar.tsx new file mode 100644 index 00000000..55c13ac1 --- /dev/null +++ b/packages/app/components/Avatar.tsx @@ -0,0 +1,55 @@ +"use client"; + +import { twMerge } from "tailwind-merge"; +import Image from "next/image"; +import { Address, http } from "viem"; +import { mainnet } from "viem/chains"; +import { createConfig, fallback, useEnsAvatar } from "wagmi"; +import { RPC_LIST } from "@/constants"; + +interface AvatarProps { + address: Address; + className?: string; + size?: number; + ensName?: string; +} + +const mainnetConfigForENS = createConfig({ + chains: [mainnet], + transports: { + [mainnet.id]: fallback([http(RPC_LIST[mainnet.id]), http()]), + }, +}); + +export const Avatar = ({ + address, + ensName, + className, + size = 24, +}: AvatarProps) => { + const { data: ensAvatar } = useEnsAvatar({ + name: ensName ?? undefined, + chainId: mainnet.id, + config: mainnetConfigForENS, + }); + + const GRADIENT_BASED_ON_ADDRESS_URL = "https://avatars.jakerunzer.com"; + const ENS_METADATA_AVATAR_URL = "https://metadata.ens.domains/mainnet/avatar"; + + const avatarGradientUrl = `${GRADIENT_BASED_ON_ADDRESS_URL}/${address}`; + const avatarEnsUrl = `${ENS_METADATA_AVATAR_URL}/${ensName}`; + const avatarUrl = ensName && ensAvatar ? avatarEnsUrl : avatarGradientUrl; + + return ( + + ); +}; diff --git a/packages/app/components/ConnectButton.tsx b/packages/app/components/ConnectButton.tsx index 5c29ddae..769edc10 100644 --- a/packages/app/components/ConnectButton.tsx +++ b/packages/app/components/ConnectButton.tsx @@ -2,12 +2,13 @@ import { ChainId, WETH, WXDAI } from "@stackly/sdk"; import { ConnectKitButton } from "connectkit"; -import Image from "next/image"; -import { useBalance, useEnsAvatar } from "wagmi"; +import { useBalance } from "wagmi"; +import { formatUnits } from "viem"; import { BodyText, Button, SizeProps } from "@/ui"; import { useAutoConnect } from "@/hooks"; import { useNetworkContext } from "@/contexts"; +import { Avatar } from "@/components/Avatar"; const CustomConnectButton = ({ address, @@ -21,15 +22,12 @@ const CustomConnectButton = ({ size: SizeProps; }) => { const { chainId } = useNetworkContext(); - const { data: avatar } = useEnsAvatar({ - name: ensName, - chainId: ChainId.ETHEREUM, - }); const TOKEN_BY_CHAIN: { [chainId: number]: string } = { [ChainId.ETHEREUM]: WETH[ChainId.ETHEREUM].address, [ChainId.GNOSIS]: WXDAI.address, [ChainId.ARBITRUM]: WETH[ChainId.ARBITRUM].address, + [ChainId.BASE]: WETH[ChainId.BASE].address, }; const { data: balance } = useBalance({ @@ -44,11 +42,11 @@ const CustomConnectButton = ({ )}`; const formattedBalance = (balanceData: NonNullable) => - balanceData.formatted === "0" + balanceData.value === BigInt(0) ? `0 ${balanceData.symbol}` - : `${balanceData.formatted.substring( + : `${formatUnits(balanceData.value, balanceData.decimals).substring( 0, - balanceData.formatted.length - balanceData.decimals + 3 + 5 )} ${balanceData.symbol}`; return ( @@ -56,7 +54,7 @@ const CustomConnectButton = ({ {balance && ( {formattedBalance(balance)} @@ -67,20 +65,18 @@ const CustomConnectButton = ({ iconRight="caret-down" onClick={onClick} width="full" - className="flex border-none shadow-sm rounded-xl hover:bg-surface-25 focus:bg-white focus:ring-0 active:ring-0" + className="flex rounded-xl border-none shadow-sm hover:bg-surface-25 focus:bg-white focus:ring-0 active:ring-0" > - {avatar && ( - - )} + - {truncatedAddress(2)} - {truncatedAddress(4)} + {ensName ? ( + <>{ensName}> + ) : ( + <> + {truncatedAddress(2)} + {truncatedAddress(4)} + > + )} diff --git a/packages/app/components/SelectNetwork.tsx b/packages/app/components/SelectNetwork.tsx index 47776c63..63800f39 100644 --- a/packages/app/components/SelectNetwork.tsx +++ b/packages/app/components/SelectNetwork.tsx @@ -3,17 +3,31 @@ import { Fragment } from "react"; import { ChainIcon } from "connectkit"; import { Listbox, Transition } from "@headlessui/react"; -import { usePathname } from "next/navigation"; import { Button, Icon } from "@/ui"; -import { useNetworkContext, useStackboxFormContext } from "@/contexts"; -import { PATHNAMES } from "@/constants"; +import { useNetworkContext } from "@/contexts"; +import Image from "next/image"; +import { ChainId } from "@stackly/sdk"; + +const CustomChainIcon = ({ id, size }: { id: number; size: number }) => { + if (id === ChainId.BASE) { + return ( + + ); + } + + // Fall back to ConnectKit's ChainIcon for other networks + return ; +}; export const SelectNetwork = () => { const { chains, changeNetwork, chainId, selectedChain } = useNetworkContext(); - const { resetFormValues } = useStackboxFormContext(); - const pathname = usePathname(); - return ( { iconRight="caret-down" size="sm" variant="tertiary" - className="flex h-10 border-none shadow-sm rounded-xl focus:bg-white focus:ring-0 active:ring-0" + className="flex h-10 rounded-xl border-none shadow-sm focus:bg-white focus:ring-0 active:ring-0" > - + {selectedChain?.name} @@ -42,22 +56,22 @@ export const SelectNetwork = () => { leaveFrom="opacity-100" leaveTo="opacity-0" > - + {chains?.map(({ id, name }) => ( {({ selected }) => { return ( <> - + {name} {selected ? ( - + + - + > = { [ChainId.ETHEREUM]: `${COW_API_BASE_URL}/mainnet/${API_VERSION_PATH}`, [ChainId.GNOSIS]: `${COW_API_BASE_URL}/xdai/${API_VERSION_PATH}`, [ChainId.ARBITRUM]: `${COW_API_BASE_URL}/arbitrum_one/${API_VERSION_PATH}`, + [ChainId.BASE]: `${COW_API_BASE_URL}/base/${API_VERSION_PATH}`, }; const COW_EXPLORER_BASE_URL = "https://explorer.cow.fi"; @@ -16,6 +17,7 @@ export const COW_API_EXPLORER_URL: Readonly> = { [ChainId.ETHEREUM]: `${COW_EXPLORER_BASE_URL}/${ORDERS_PATH}/`, [ChainId.GNOSIS]: `${COW_EXPLORER_BASE_URL}/gc/${ORDERS_PATH}/`, [ChainId.ARBITRUM]: `${COW_EXPLORER_BASE_URL}/arb1/${ORDERS_PATH}/`, + [ChainId.BASE]: `${COW_EXPLORER_BASE_URL}/base/${ORDERS_PATH}/`, }; export const cowExplorerUrl = (chainId: ChainId, uid: string) => diff --git a/packages/app/models/token/base.ts b/packages/app/models/token/base.ts new file mode 100644 index 00000000..7e95d3c6 --- /dev/null +++ b/packages/app/models/token/base.ts @@ -0,0 +1,26 @@ +export const baseTokens = { + USDC: { + address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + name: "USD Coin", + symbol: "USDC", + decimals: 6, + logoURI: "/assets/images/tokens/usdc.png", + chainId: 8453, + }, + WETH: { + address: "0x4200000000000000000000000000000000000006", + name: "Wrapped Ether on Base", + symbol: "WETH", + decimals: 18, + logoURI: "/assets/images/tokens/weth.png", + chainId: 8453, + }, + CBBTC: { + address: "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf", + name: "Coinbase Wrapped BTC", + symbol: "cbBTC", + decimals: 8, + logoURI: "/assets/images/tokens/cbbtc.png", + chainId: 8453, + }, +}; diff --git a/packages/app/models/token/index.ts b/packages/app/models/token/index.ts index d1c603a7..c9405331 100644 --- a/packages/app/models/token/index.ts +++ b/packages/app/models/token/index.ts @@ -1,4 +1,5 @@ export * from "./gnosis"; export * from "./arbitrum"; export * from "./mainnet"; +export * from "./base"; export * from "./types"; diff --git a/packages/app/package.json b/packages/app/package.json index 0e4f7591..162cbbc7 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -31,8 +31,8 @@ "react-dom": "^18.2.0", "react-popper": "^2.3.0", "tailwind-merge": "^1.12.0", - "viem": "2.x", - "wagmi": "2.x" + "viem": "2.21.55", + "wagmi": "2.14.1" }, "devDependencies": { "@svgr/webpack": "^8.0.1", diff --git a/packages/app/providers/wagmi-config.ts b/packages/app/providers/wagmi-config.ts index 9f03dd63..18520622 100644 --- a/packages/app/providers/wagmi-config.ts +++ b/packages/app/providers/wagmi-config.ts @@ -1,19 +1,20 @@ import { ChainId } from "@stackly/sdk"; import { createConfig, fallback, http } from "wagmi"; import { getDefaultConfig } from "connectkit"; -import { gnosis, mainnet, arbitrum } from "wagmi/chains"; +import { gnosis, mainnet, arbitrum, base } from "wagmi/chains"; import { safe } from "wagmi/connectors"; import { RPC_LIST } from "@/constants"; const defaultConfig = getDefaultConfig({ - chains: [gnosis, mainnet, arbitrum], + chains: [gnosis, mainnet, arbitrum, base], walletConnectProjectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID || "", transports: { [mainnet.id]: fallback([http(RPC_LIST[ChainId.ETHEREUM]), http()]), [gnosis.id]: fallback([http(RPC_LIST[ChainId.GNOSIS]), http()]), [arbitrum.id]: fallback([http(RPC_LIST[ChainId.ARBITRUM]), http()]), + [base.id]: fallback([http(RPC_LIST[ChainId.BASE]), http()]), }, appName: "Stackly", appDescription: "Empower your portfolio with DCA.", diff --git a/packages/app/public/assets/blockchains/base/tokenlist.json b/packages/app/public/assets/blockchains/base/tokenlist.json new file mode 100644 index 00000000..b06c2ed6 --- /dev/null +++ b/packages/app/public/assets/blockchains/base/tokenlist.json @@ -0,0 +1,74 @@ +[ + { + "address": "0x4200000000000000000000000000000000000006", + "name": "Wrapped Ether", + "symbol": "WETH", + "decimals": 18, + "logoURI": "/assets/images/tokens/weth.png", + "chainId": 8453 + }, + { + "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "name": "USD Coin", + "symbol": "USDC", + "decimals": 6, + "logoURI": "/assets/images/tokens/usdc.png", + "chainId": 8453 + }, + { + "address": "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf", + "name": "Coinbase Wrapped BTC", + "symbol": "cbBTC", + "decimals": 8, + "logoURI": "/assets/images/tokens/cbbtc.png", + "chainId": 8453 + }, + { + "address": "0x0b3e328455c4059EEb9e3f84b5543F74E24e7E1b", + "name": "Virtual Protocol", + "symbol": "VIRTUAL", + "decimals": 18, + "logoURI": "/assets/images/tokens/virtual.png", + "chainId": 8453 + }, + { + "address": "0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed", + "name": "Degen", + "symbol": "DEGEN", + "decimals": 18, + "logoURI": "/assets/images/tokens/degen.png", + "chainId": 8453 + }, + { + "address": "0x0578d8A44db98B23BF096A382e016e29a5Ce0ffe", + "name": "Higher", + "symbol": "HIGHER", + "decimals": 18, + "logoURI": "/assets/images/tokens/higher.png", + "chainId": 8453 + }, + { + "address": "0xAC1Bd2486aAf3B5C0fc3Fd868558b082a531B2B4", + "name": "Toshi", + "symbol": "TOSHI", + "decimals": 18, + "logoURI": "/assets/images/tokens/toshi.png", + "chainId": 8453 + }, + { + "address": "0x9a33406165f562E16C3abD82fd1185482E01b49a", + "name": "Talent Protocol Token", + "symbol": "TALENT", + "decimals": 18, + "logoURI": "/assets/images/tokens/talent.png", + "chainId": 8453 + }, + { + "address": "0x4F9Fd6Be4a90f2620860d680c0d4d5Fb53d1A825", + "name": "aixbt by Virtuals", + "symbol": "AIXBT", + "decimals": 18, + "logoURI": "/assets/images/tokens/aixbt.png", + "chainId": 8453 + } +] diff --git a/packages/app/public/assets/images/base-logo.svg b/packages/app/public/assets/images/base-logo.svg new file mode 100644 index 00000000..8785a65c --- /dev/null +++ b/packages/app/public/assets/images/base-logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/app/public/assets/images/tokens/aixbt.png b/packages/app/public/assets/images/tokens/aixbt.png new file mode 100644 index 00000000..8aaedd34 Binary files /dev/null and b/packages/app/public/assets/images/tokens/aixbt.png differ diff --git a/packages/app/public/assets/images/tokens/cbbtc.png b/packages/app/public/assets/images/tokens/cbbtc.png new file mode 100644 index 00000000..70111217 Binary files /dev/null and b/packages/app/public/assets/images/tokens/cbbtc.png differ diff --git a/packages/app/public/assets/images/tokens/degen.png b/packages/app/public/assets/images/tokens/degen.png new file mode 100644 index 00000000..531889dc Binary files /dev/null and b/packages/app/public/assets/images/tokens/degen.png differ diff --git a/packages/app/public/assets/images/tokens/higher.png b/packages/app/public/assets/images/tokens/higher.png new file mode 100644 index 00000000..428f6e1c Binary files /dev/null and b/packages/app/public/assets/images/tokens/higher.png differ diff --git a/packages/app/public/assets/images/tokens/index.tsx b/packages/app/public/assets/images/tokens/index.tsx index f6821b78..d7b93b67 100644 --- a/packages/app/public/assets/images/tokens/index.tsx +++ b/packages/app/public/assets/images/tokens/index.tsx @@ -15,6 +15,12 @@ import WethTokenImg from "./weth.png"; import WxdaiTokenImg from "./wxdai.png"; import XdaiTokenImg from "./xdai.png"; import ArbTokenImg from "./arb.png"; +import CbBtcTokenImg from "./cbbtc.png"; +import VirtualTokenImg from "./virtual.png"; +import DegenTokenImg from "./degen.png"; +import ToshiTokenImg from "./toshi.png"; +import HigherTokenImg from "./higher.png"; +import TalentTokenImg from "./talent.png"; export { OneInchTokenImg, @@ -32,4 +38,10 @@ export { WxdaiTokenImg, XdaiTokenImg, ArbTokenImg, + CbBtcTokenImg, + VirtualTokenImg, + TalentTokenImg, + HigherTokenImg, + ToshiTokenImg, + DegenTokenImg, }; diff --git a/packages/app/public/assets/images/tokens/talent.png b/packages/app/public/assets/images/tokens/talent.png new file mode 100644 index 00000000..08ae1708 Binary files /dev/null and b/packages/app/public/assets/images/tokens/talent.png differ diff --git a/packages/app/public/assets/images/tokens/toshi.png b/packages/app/public/assets/images/tokens/toshi.png new file mode 100644 index 00000000..37a4a6de Binary files /dev/null and b/packages/app/public/assets/images/tokens/toshi.png differ diff --git a/packages/app/public/assets/images/tokens/virtual.png b/packages/app/public/assets/images/tokens/virtual.png new file mode 100644 index 00000000..1d525444 Binary files /dev/null and b/packages/app/public/assets/images/tokens/virtual.png differ diff --git a/packages/app/utils/constants.ts b/packages/app/utils/constants.ts index 67cc569c..34b7d87a 100644 --- a/packages/app/utils/constants.ts +++ b/packages/app/utils/constants.ts @@ -3,6 +3,7 @@ import { gnosisTokens, mainnetTokens, TokenFromTokenlist, + baseTokens, } from "@/models/token"; import { ChainId } from "@stackly/sdk"; @@ -24,4 +25,8 @@ export const DEFAULT_TOKENS_BY_CHAIN: { [chainId: number]: DefaultTokens } = { from: gnosisTokens.WXDAI, to: gnosisTokens.WETH, }, + [ChainId.BASE]: { + from: baseTokens.USDC, + to: baseTokens.WETH, + }, }; diff --git a/packages/app/utils/transaction.ts b/packages/app/utils/transaction.ts index a8814b8f..d83f2cbd 100644 --- a/packages/app/utils/transaction.ts +++ b/packages/app/utils/transaction.ts @@ -4,6 +4,7 @@ const EXPLORER_URL_BY_CHAIN = { [ChainId.ETHEREUM]: "https://etherscan.io", [ChainId.GNOSIS]: "https://gnosisscan.io", [ChainId.ARBITRUM]: "https://arbiscan.io", + [ChainId.BASE]: "https://basescan.org", }; export const getExplorerLink = ( diff --git a/packages/landing/components/sections/FAQ/constants.ts b/packages/landing/components/sections/FAQ/constants.ts index c0c5ee9f..07133f96 100644 --- a/packages/landing/components/sections/FAQ/constants.ts +++ b/packages/landing/components/sections/FAQ/constants.ts @@ -70,7 +70,7 @@ export const FAQ_QUESTIONS_AND_ANSWERS: FaqQa[] = [ { question: "Which networks is Stackly available?", answers: [ - `Currently Stackly supports Arbitrum, Gnosis and Ethereum mainnet networks.`, + `Currently Stackly supports Arbitrum, Base, Gnosis and Ethereum mainnet networks.`, ], trackEventName: EVENTS.SECTIONS.FAQ.NETWORKS_AVAILABLE, }, diff --git a/packages/landing/components/sections/HeroBanner/HeroBanner.tsx b/packages/landing/components/sections/HeroBanner/HeroBanner.tsx index 1b10136a..900dbd2a 100644 --- a/packages/landing/components/sections/HeroBanner/HeroBanner.tsx +++ b/packages/landing/components/sections/HeroBanner/HeroBanner.tsx @@ -15,39 +15,45 @@ import { import { EVENTS } from "@/analytics"; import { STACKLY_APP_URL } from "@/constants"; +export const SUPPORTED_NETWORKS = [ + { + name: "Ethereum", + image: "/assets/images/ethereum-logo.svg", + }, + { + name: "Gnosis", + image: "/assets/images/gnosis-logo.svg", + }, + { + name: "Arbitrum", + image: "/assets/images/arbitrum-logo.svg", + }, + { + name: "Base", + image: "/assets/images/base-logo.svg", + }, +]; + export const HeroBanner = () => { return ( - + Live on: - - - + {SUPPORTED_NETWORKS.map((network) => ( + + ))} - + Empower your portfolio Say goodbye to market timing and hello to effortless recurrent swaps. @@ -65,15 +71,15 @@ export const HeroBanner = () => { > Start stacking now - + + + + \ No newline at end of file diff --git a/packages/landing/public/assets/images/ethereum-avatar.svg b/packages/landing/public/assets/images/ethereum-logo.svg similarity index 100% rename from packages/landing/public/assets/images/ethereum-avatar.svg rename to packages/landing/public/assets/images/ethereum-logo.svg diff --git a/packages/landing/public/assets/images/gnosis-avatar.svg b/packages/landing/public/assets/images/gnosis-logo.svg similarity index 100% rename from packages/landing/public/assets/images/gnosis-avatar.svg rename to packages/landing/public/assets/images/gnosis-logo.svg diff --git a/packages/sdk/src/constants.ts b/packages/sdk/src/constants.ts index f630e44b..0bb23689 100644 --- a/packages/sdk/src/constants.ts +++ b/packages/sdk/src/constants.ts @@ -2,6 +2,7 @@ export enum ChainId { ETHEREUM = 1, GNOSIS = 100, ARBITRUM = 42161, + BASE = 8453, } /** diff --git a/packages/sdk/src/entities/defaultTokens.ts b/packages/sdk/src/entities/defaultTokens.ts index d1795877..e3f426e8 100644 --- a/packages/sdk/src/entities/defaultTokens.ts +++ b/packages/sdk/src/entities/defaultTokens.ts @@ -21,6 +21,12 @@ export const USDC: Readonly> = { 6, "USDC" ), + [ChainId.BASE]: new Token( + ChainId.BASE, + "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + 6, + "USDC" + ), }; export const SETH2 = new Token( @@ -59,9 +65,16 @@ export const WETH: Readonly> = { "WETH", "Wrapped Ether" ), + [ChainId.BASE]: new Token( + ChainId.BASE, + "0x4200000000000000000000000000000000000006", + 18, + "WETH", + "Wrapped Ether" + ), }; -export const SWPR: Readonly> = { +export const SWPR: Record, Token> = { [ChainId.ETHEREUM]: new Token( ChainId.ETHEREUM, "0x6cacdb97e3fc8136805a9e7c342d866ab77d0957", @@ -108,7 +121,7 @@ export const DAI: Readonly> = ), }; -export const GNO: Record = { +export const GNO: Record, Token> = { [ChainId.ETHEREUM]: new Token( ChainId.ETHEREUM, "0x6810e776880c02933d47db1b9fc05908e5386b96", @@ -129,7 +142,7 @@ export const GNO: Record = { ), }; -export const WBTC: Record = { +export const WBTC: Record, Token> = { [ChainId.ETHEREUM]: new Token( ChainId.ETHEREUM, "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599", @@ -150,7 +163,7 @@ export const WBTC: Record = { ), }; -export const DPI: Record = { +export const DPI: Record, Token> = { [ChainId.ETHEREUM]: new Token( ChainId.ETHEREUM, "0x1494ca1f11d487c2bbe4543e90080aeba4ba3c2b", diff --git a/packages/sdk/src/vaults/constants.ts b/packages/sdk/src/vaults/constants.ts index b3c10d70..2c8e1c57 100644 --- a/packages/sdk/src/vaults/constants.ts +++ b/packages/sdk/src/vaults/constants.ts @@ -10,6 +10,9 @@ export const GNOSIS_ORDER_FACTORY_ADDRESS = export const ARBITRUM_ORDER_FACTORY_ADDRESS = "0xf4cd605e5fef8618ac450e84b7e912c870927922"; +export const BASE_ORDER_FACTORY_ADDRESS = + "0xf4cd605e5fef8618ac450e84b7e912c870927922"; + const validateVaultInfo = ( chainId: ChainId, map: Record | Readonly>, @@ -30,6 +33,7 @@ export const ORDER_FACTORY_ADDRESS_LIST: Record = { [ChainId.ETHEREUM]: MAINNET_ORDER_FACTORY_ADDRESS, [ChainId.GNOSIS]: GNOSIS_ORDER_FACTORY_ADDRESS, [ChainId.ARBITRUM]: ARBITRUM_ORDER_FACTORY_ADDRESS, + [ChainId.BASE]: BASE_ORDER_FACTORY_ADDRESS, }; /** @@ -39,6 +43,7 @@ export const DCAORDER_SINGLETON_ADDRESS_LIST: Record = { [ChainId.ETHEREUM]: "0xc97ecbdba20c672c61e27bd657d4dfbd2328f6fa", [ChainId.GNOSIS]: "0xFc41E4DCBab781092a32E8487cFB7444F9e0e403", [ChainId.ARBITRUM]: "0x810f9f1384421b6d185f46253e36f3a558e57369", + [ChainId.BASE]: "0x810f9f1384421b6d185f46253e36f3a558e57369", }; /** @@ -54,6 +59,7 @@ export const COW_SETTLEMENT_ADDRESS_LIST: Record = { [ChainId.ETHEREUM]: COW_SETTLEMENT_ADDRESS, [ChainId.GNOSIS]: COW_SETTLEMENT_ADDRESS, [ChainId.ARBITRUM]: COW_SETTLEMENT_ADDRESS, + [ChainId.BASE]: COW_SETTLEMENT_ADDRESS, }; const API_BASE_URL = "https://gateway-arbitrum.network.thegraph.com/api"; @@ -72,10 +78,15 @@ const ARBITRUM_SUBGRAPH_ENDPOINT_URL = process.env.ARBITRUM_SUBGRAPH_API_URL ?? `${API_BASE_URL}/${SUBGRAPH_API_KEY}/subgraphs/id/FNmemHB6tUh7eHmJnBFKYFf27U5GUAzXnatry4ZbrF7f`; +const BASE_SUBGRAPH_ENDPOINT_URL = + process.env.BASE_SUBGRAPH_API_URL ?? + `${API_BASE_URL}/${SUBGRAPH_API_KEY}/subgraphs/id/7WUXPez9b9DMfJriVPS3yttxA6xLRwq73duq15jXaVi7`; + export const SUBGRAPH_ENDPOINT_LIST: Readonly> = { [ChainId.ETHEREUM]: ETHEREUM_SUBGRAPH_ENDPOINT_URL, [ChainId.GNOSIS]: GNOSIS_SUBGRAPH_ENDPOINT_URL, [ChainId.ARBITRUM]: ARBITRUM_SUBGRAPH_ENDPOINT_URL, + [ChainId.BASE]: BASE_SUBGRAPH_ENDPOINT_URL, }; /** diff --git a/packages/sdk/src/vaults/factory.ts b/packages/sdk/src/vaults/factory.ts index 7a5ee7ab..01af3c28 100644 --- a/packages/sdk/src/vaults/factory.ts +++ b/packages/sdk/src/vaults/factory.ts @@ -142,7 +142,8 @@ export async function createDCAOrderWithNonce( const chainNotSupported = chainId !== ChainId.ETHEREUM && chainId !== ChainId.GNOSIS && - chainId != ChainId.ARBITRUM; + chainId != ChainId.ARBITRUM && + chainId != ChainId.BASE; if (chainNotSupported) { throw new Error(`Chain id ${chainId} is not supported`); diff --git a/packages/subgraph/bin/build-subgraph.ts b/packages/subgraph/bin/build-subgraph.ts index c71ad877..ce5a162a 100644 --- a/packages/subgraph/bin/build-subgraph.ts +++ b/packages/subgraph/bin/build-subgraph.ts @@ -7,7 +7,7 @@ import { config } from "./config"; * @see https://thegraph.com/docs/en/developing/supported-networks/ * for supported chain names */ -const SUPPORTED_NETWORKS = ["mainnet", "gnosis", "arbitrum-one"]; +const SUPPORTED_NETWORKS = ["mainnet", "gnosis", "arbitrum-one", "base"]; async function main() { // get network from command line diff --git a/packages/subgraph/bin/config.ts b/packages/subgraph/bin/config.ts index 8c317e04..bbdc6a72 100644 --- a/packages/subgraph/bin/config.ts +++ b/packages/subgraph/bin/config.ts @@ -25,4 +25,10 @@ export const config: Record< startBlock: 218655333, }, }, + base: { + orderFactory: { + address: "0xf4cd605e5fef8618ac450e84b7e912c870927922", + startBlock: 23650573, + }, + }, }; diff --git a/packages/subgraph/package.json b/packages/subgraph/package.json index 7100d167..29f12786 100644 --- a/packages/subgraph/package.json +++ b/packages/subgraph/package.json @@ -8,12 +8,15 @@ "build:gnosis": "bun run prepare:gnosis && graph build", "build:mainnet": "bun run prepare:mainnet && graph build", "build:arbitrum-one": "bun run prepare:arbitrum-one && graph build", + "build:base": "bun run prepare:base && graph build", "prepare:gnosis": "ts-node bin/build-subgraph.ts gnosis && bun run codegen", "prepare:mainnet": "ts-node bin/build-subgraph.ts mainnet && bun run codegen", "prepare:arbitrum-one": "ts-node bin/build-subgraph.ts arbitrum-one && bun run codegen", + "prepare:base": "ts-node bin/build-subgraph.ts base && bun run codegen", "deploy:mainnet": "bun run prepare:mainnet && graph deploy --studio stackly-mainnet", "deploy:gnosis": "bun run prepare:gnosis && graph deploy --studio stackly-gnosis", "deploy:arbitrum-one": "bun run prepare:arbitrum-one && graph deploy --studio stackly-arbitrum-one", + "deploy:base": "bun run prepare:base && graph deploy --studio stackly-base", "create-local": "graph create --node http://localhost:8020/ swaprhq/stackly", "remove-local": "graph remove --node http://localhost:8020/ swaprhq/stackly", "deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 swaprhq/stackly",
{name}
Live on: