Skip to content

Commit

Permalink
Merge pull request #178 from SwaprHQ/develop
Browse files Browse the repository at this point in the history
release: v1.3.0
  • Loading branch information
berteotti authored Jun 7, 2024
2 parents 8b7c85e + 2e21979 commit 0b576ca
Show file tree
Hide file tree
Showing 34 changed files with 363 additions and 100 deletions.
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "stackly-ui",
"repository": "https://github.com/SwaprHQ/stackly-ui",
"version": "1.2.1",
"version": "1.3.0",
"license": "MIT",
"private": true,
"packageManager": "bun@1.0.6",
Expand Down
1 change: 1 addition & 0 deletions packages/app/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ NEXT_PUBLIC_FATHOM_SITE_ID=

RPC_GNOSIS=
RPC_MAINNET=
RPC_ARBITRUM=
1 change: 1 addition & 0 deletions packages/app/components/ConnectButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const CustomConnectButton = ({
const TOKEN_BY_CHAIN: { [chainId: number]: string } = {
[ChainId.ETHEREUM]: WETH[ChainId.ETHEREUM].address,
[ChainId.GNOSIS]: WXDAI.address,
[ChainId.ARBITRUM]: WETH[ChainId.ARBITRUM].address,
};

const { data: balance } = useBalance({
Expand Down
3 changes: 1 addition & 2 deletions packages/app/components/SelectNetwork.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { Listbox, Transition } from "@headlessui/react";

import { Button, Icon } from "@/ui";
import { useNetworkContext, useStackboxFormContext } from "@/contexts";
import { useAccount, useConnect } from "wagmi";

export const SelectNetwork = () => {
const { chains, changeNetwork, chainId, selectedChain } = useNetworkContext();
Expand Down Expand Up @@ -53,7 +52,7 @@ export const SelectNetwork = () => {
<>
<div className="flex items-center space-x-2">
<ChainIcon size={20} id={id} />
<p>{name}</p>
<p className="text-nowrap">{name}</p>
</div>
{selected ? (
<div className="absolute inset-y-0 right-0 flex items-center pr-3 text-amber-600">
Expand Down
45 changes: 44 additions & 1 deletion packages/app/components/strategies/constants.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FREQUENCY_OPTIONS } from "@/models/stack";
import { gnosisTokens, mainnetTokens } from "@/models/token";
import { gnosisTokens, mainnetTokens, arbitrumTokens } from "@/models/token";
import { Strategy } from "@/contexts";
import { ChainId } from "@stackly/sdk";

Expand Down Expand Up @@ -106,4 +106,47 @@ export const STRATEGY_CATEGORIES: { [chainId: number]: ChainStrategies } = {
],
},
},
[ChainId.ARBITRUM]: {
popular: {
label: "Popular Strategies",
strategies: [
{
id: 1,
buyToken: arbitrumTokens.WETH,
daysAmount: 30,
frequency: FREQUENCY_OPTIONS.day,
sellAmountPerTimeframe: 50,
sellToken: arbitrumTokens.USDC,
totalSellAmount: "1500",
},
{
id: 2,
buyToken: arbitrumTokens.ARB,
daysAmount: 7,
frequency: FREQUENCY_OPTIONS.day,
sellAmountPerTimeframe: 20,
sellToken: arbitrumTokens.DAI,
totalSellAmount: "140",
},
{
id: 3,
buyToken: arbitrumTokens.WETH,
daysAmount: 10,
frequency: FREQUENCY_OPTIONS.hour,
sellAmountPerTimeframe: 5,
sellToken: arbitrumTokens.USDC,
totalSellAmount: "1200",
},
{
id: 4,
buyToken: arbitrumTokens.WBTC,
daysAmount: 56,
frequency: FREQUENCY_OPTIONS.week,
sellAmountPerTimeframe: 100,
sellToken: arbitrumTokens.DAI,
totalSellAmount: "800",
},
],
},
},
};
12 changes: 10 additions & 2 deletions packages/app/components/token-picker/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
arbitrumTokens,
gnosisTokens,
mainnetTokens,
TokenFromTokenlist,
Expand All @@ -12,11 +13,18 @@ export const TOKEN_PICKER_COMMON_TOKENS: {
mainnetTokens.USDC,
mainnetTokens.WETH,
mainnetTokens.WBTC,
mainnetTokens.RETH,
mainnetTokens.SWPR,
],
[ChainId.ARBITRUM]: [
arbitrumTokens.USDC,
arbitrumTokens.WETH,
arbitrumTokens.WBTC,
arbitrumTokens.ARB,
arbitrumTokens.SWPR,
],
[ChainId.GNOSIS]: [
gnosisTokens.GNO,
gnosisTokens.SWAPR,
gnosisTokens.SWPR,
gnosisTokens.WETH,
gnosisTokens.WXDAI,
],
Expand Down
4 changes: 3 additions & 1 deletion packages/app/constants/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { ChainId } from "@stackly/sdk";
// RPC endpoints
export const RPC_LIST: { [chainId: number]: string } = {
[ChainId.ETHEREUM]: process.env.RPC_MAINNET ?? "https://eth.meowrpc.com/",
[ChainId.GNOSIS]: process.env.RPC_GNOSIS ?? "https://rpc.gnosis.gateway.fm",
[ChainId.GNOSIS]: process.env.RPC_GNOSIS ?? "https://rpc.gnosis.gateway.fm/",
[ChainId.ARBITRUM]:
process.env.RPC_ARBITRUM ?? "https://arbitrum-one-rpc.publicnode.com/",
};

// App URLs
Expand Down
14 changes: 7 additions & 7 deletions packages/app/contexts/NetworkContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from "react";
import type { Chain } from "viem/chains";
import { ChainId } from "@stackly/sdk";
import { gnosis } from "wagmi/chains";
import { arbitrum } from "wagmi/chains";
import { useAccount, useSwitchChain } from "wagmi";

import { config } from "@/providers/wagmi-config";
Expand All @@ -34,9 +34,9 @@ interface NetworkContextProps {
}

const NetworkContext = createContext<NetworkContextProps>({
chainId: gnosis.id,
chainId: arbitrum.id,
changeNetwork: throwNetworkContextError,
selectedChain: gnosis,
selectedChain: arbitrum,
setChainId: throwNetworkContextError,
});

Expand All @@ -55,8 +55,8 @@ export const NetworkContextProvider = ({
const [searchParamsChainId, setSearchParamsChainId] =
useQueryState("chainId");

const [selectedChain, setSelectedChain] = useState<WagmiChain>(gnosis);
const [selectedChainId, setSelectedChainId] = useState<ChainId>(gnosis.id);
const [selectedChain, setSelectedChain] = useState<WagmiChain>(arbitrum);
const [selectedChainId, setSelectedChainId] = useState<ChainId>(arbitrum.id);

const resetTokensOnSearchParams = useCallback(() => {
setFromTokenSearchParams(null);
Expand Down Expand Up @@ -125,8 +125,8 @@ export const NetworkContextProvider = ({
}
}
// set default chain
setSelectedChain(gnosis);
setSelectedChainId(gnosis.id);
setSelectedChain(arbitrum);
setSelectedChainId(arbitrum.id);

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isConnected, chains, searchParamsChainId, switchChain]);
Expand Down
14 changes: 11 additions & 3 deletions packages/app/contexts/TokenListContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ import {
import { ChainId, MULTICALL_ADDRESS } from "@stackly/sdk";
import { Erc20Abi, MulticallAbi } from "@stackly/sdk/abis";
import { ethers } from "ethers";
import { formatUnits, hexToBigInt } from "viem";
import { formatUnits, hexToBigInt, isAddress } from "viem";
import { useAccount } from "wagmi";

import { RPC_LIST } from "@/constants";
import { TokenFromTokenlist } from "@/models";

import defaultGnosisTokenlist from "public/assets/blockchains/gnosis/tokenlist.json";
import defaultEthereumTokenlist from "public/assets/blockchains/ethereum/tokenlist.json";
import defaultArbitrumTokenList from "public/assets/blockchains/arbitrum/tokenlist.json";

import { useNetworkContext } from "./NetworkContext";

export interface TokenWithBalance extends TokenFromTokenlist {
Expand All @@ -34,6 +36,7 @@ const DEFAULT_TOKEN_LIST_BY_CHAIN: {
} = {
[ChainId.ETHEREUM]: defaultEthereumTokenlist,
[ChainId.GNOSIS]: defaultGnosisTokenlist,
[ChainId.ARBITRUM]: defaultArbitrumTokenList,
};

const TOKEN_LISTS_BY_CHAIN_URL: { [chainId: number]: string[] } = {
Expand All @@ -46,6 +49,10 @@ const TOKEN_LISTS_BY_CHAIN_URL: { [chainId: number]: string[] } = {
"https://tokens.honeyswap.org/",
"https://files.cow.fi/tokens/CowSwap.json",
],
[ChainId.ARBITRUM]: [
"https://raw.githubusercontent.com/cowprotocol/token-lists/main/src/public/ArbitrumOneUniswapTokensList.json",
"https://tokens.coingecko.com/arbitrum-one/all.json",
],
};

const TokenListContext = createContext<{
Expand All @@ -56,7 +63,7 @@ const TokenListContext = createContext<{
getTokenFromList: (tokenAddress: string) => TokenFromTokenlist | null;
}>({
isLoading: true,
tokenList: DEFAULT_TOKEN_LIST_BY_CHAIN[ChainId.ETHEREUM],
tokenList: DEFAULT_TOKEN_LIST_BY_CHAIN[ChainId.ARBITRUM],
getTokenLogoURL: (tokenAddress: string) => "#",
getTokenFromList: (tokenAddress: string) => null,
});
Expand All @@ -67,7 +74,7 @@ export const TokenListProvider = ({ children }: PropsWithChildren) => {
const abortControllerRef = useRef(new AbortController());

const [tokenList, setTokenList] = useState<TokenFromTokenlist[]>(
defaultGnosisTokenlist
DEFAULT_TOKEN_LIST_BY_CHAIN[chainId]
);
const [tokenListWithBalances, setTokenListWithBalances] =
useState<TokenWithBalance[]>();
Expand Down Expand Up @@ -151,6 +158,7 @@ export const TokenListProvider = ({ children }: PropsWithChildren) => {
const tokenUniqueAddressesSet = new Set<string>();
const tokenListNoDuplicates = mergedTokenlist.filter((token) => {
if (
isAddress(token.address) &&
token.chainId === chainId &&
!tokenUniqueAddressesSet.has(token.address.toLowerCase())
) {
Expand Down
18 changes: 12 additions & 6 deletions packages/app/models/cow-order/cow-order.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import { ChainId } from "@stackly/sdk";

export const COW_API_BASE_URL: Readonly<Record<ChainId, string>> = {
[ChainId.ETHEREUM]: `https://api.cow.fi/mainnet/api/v1`,
[ChainId.GNOSIS]: `https://api.cow.fi/xdai/api/v1`,
const COW_API_BASE_URL = "https://api.cow.fi";
const API_VERSION_PATH = "api/v1";

export const COW_API_URL: Readonly<Record<ChainId, string>> = {
[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}`,
};

const COW_EXPLORER_BASE_URL = "https://explorer.cow.fi/";
const COW_EXPLORER_BASE_URL = "https://explorer.cow.fi";
const ORDERS_PATH = "orders";

export const COW_API_EXPLORER_URL: Readonly<Record<ChainId, string>> = {
[ChainId.ETHEREUM]: COW_EXPLORER_BASE_URL + "orders/",
[ChainId.GNOSIS]: COW_EXPLORER_BASE_URL + "gc/orders/",
[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}/`,
};

export const cowExplorerUrl = (chainId: ChainId, uid: string) =>
Expand Down
9 changes: 5 additions & 4 deletions packages/app/models/cow-order/fetcher.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { COW_API_BASE_URL } from "@/models/cow-order/cow-order";
import { COW_API_URL } from "@/models/cow-order/cow-order";
import { ChainId } from "@stackly/sdk";

const buildUrl = (chainId: 1 | 100, address: string) =>
`${COW_API_BASE_URL[chainId]}/account/${address}/orders/?limit=500`;
const buildUrl = (chainId: ChainId, address: string) =>
`${COW_API_URL[chainId]}/account/${address}/orders/?limit=500`;

export async function getCowOrders(chainId: 1 | 100, address: string) {
export async function getCowOrders(chainId: ChainId, address: string) {
try {
const res = await fetch(buildUrl(chainId, address));
if (!res.ok) throw "Failed to fetch cow data";
Expand Down
51 changes: 51 additions & 0 deletions packages/app/models/token/arbitrum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
export const arbitrumTokens = {
ARB: {
address: "0x912CE59144191C1204E64559FE8253a0e49E6548",
name: "Arb Token on Arbitrum chain",
symbol: "ARB",
decimals: 18,
logoURI: "/assets/images/tokens/arb.png",
chainId: 42161,
},

USDC: {
address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
name: "USD Coin",
symbol: "USDC",
decimals: 6,
logoURI: "/assets/images/tokens/usdc.png",
chainId: 42161,
},
WBTC: {
address: "0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f",
name: "Wrapped Bitcoin on Arbitrum Chain",
symbol: "WBTC",
decimals: 8,
logoURI: "/assets/images/tokens/wbtc.png",
chainId: 42161,
},
WETH: {
address: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
name: "Wrapped Ether on Arbitrum chain",
symbol: "WETH",
decimals: 18,
logoURI: "/assets/images/tokens/weth.png",
chainId: 42161,
},
DAI: {
address: "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1",
name: "Dai Stablecoin",
symbol: "DAI",
decimals: 18,
logoURI: "/assets/images/tokens/dai.png",
chainId: 42161,
},
SWPR: {
address: "0xdE903E2712288A1dA82942DDdF2c20529565aC30",
name: "Swapr on Arbitrum chain",
symbol: "SWPR",
decimals: 18,
logoURI: "/assets/images/tokens/swapr.png",
chainId: 42161,
},
};
2 changes: 1 addition & 1 deletion packages/app/models/token/gnosis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const gnosisTokens = {
logoURI: "/assets/images/tokens/gno.png",
chainId: 100,
},
SWAPR: {
SWPR: {
address: "0x532801ED6f82FFfD2DAB70A19fC2d7B2772C4f4b",
name: "Swapr on Gnosis chain",
symbol: "SWPR",
Expand Down
1 change: 1 addition & 0 deletions packages/app/models/token/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./gnosis";
export * from "./arbitrum";
export * from "./mainnet";
export * from "./types";
4 changes: 2 additions & 2 deletions packages/app/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "app",
"version": "0.0.0",
"repository": "https://github.com/ImpeccableHQ/stackly-ui/packages/app",
"version": "1.0.0",
"repository": "https://github.com/SwaprHQ/stackly-ui/",
"license": "MIT",
"private": true,
"scripts": {
Expand Down
16 changes: 4 additions & 12 deletions packages/app/providers/wagmi-config.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@
import { ChainId } from "@stackly/sdk";
import { createConfig, fallback, http } from "wagmi";
import { getDefaultConfig } from "connectkit";
import { gnosis, mainnet } from "wagmi/chains";
import { gnosis, mainnet, arbitrum } from "wagmi/chains";
import { safe } from "wagmi/connectors";

import { RPC_LIST } from "@/constants";

const chainJsonRpc: Record<number, { http: string }> = {
[ChainId.GNOSIS]: {
http: RPC_LIST[ChainId.GNOSIS],
},
[ChainId.ETHEREUM]: {
http: RPC_LIST[ChainId.ETHEREUM],
},
};

const defaultConfig = getDefaultConfig({
chains: [gnosis, mainnet],
chains: [gnosis, mainnet, arbitrum],
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()]),
},
appName: "Stackly",
appDescription: "Stack crypto over time.",
appDescription: "Empower your portfolio with DCA.",
appUrl: "https://stackly.app",
appIcon: "https://stackly.app/favicon.ico",
ssr: true,
Expand Down
Loading

0 comments on commit 0b576ca

Please sign in to comment.