├── .eslintrc.json ├── .gitignore ├── README.md ├── components ├── common │ ├── Loading.tsx │ └── Notify.tsx ├── layout │ ├── Header.tsx │ └── index.tsx └── raydium │ ├── SwapOperateContainer.tsx │ ├── TokenList.tsx │ ├── TokenSelect.tsx │ └── index.tsx ├── hooks └── useDapp.ts ├── next-env.d.ts ├── next.config.js ├── package-lock.json ├── package.json ├── pages ├── _app.tsx ├── exchange.tsx ├── index.tsx └── my_spl.tsx ├── public ├── bg.jpeg └── image │ └── dappio-logo.png ├── styles ├── color.module.sass ├── common.module.sass ├── globals.css ├── header.module.sass ├── layout.module.sass ├── mySpl.module.sass └── swap.module.sass ├── tsconfig.json ├── types.d.ts └── utils ├── ids.ts ├── layouts.ts ├── liquidity.ts ├── pools.ts ├── safe-math.ts ├── swap.ts ├── tokenList.ts ├── tokens.ts ├── types.d.ts └── web3.ts /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | 36 | # typescript 37 | *.tsbuildinfo 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Getting started 3 | 4 | This boilerplate aim to help solana devloper to start building a frontend dapp quickly. 5 | 6 | The project is bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with Solana web3 wallet. 7 | 8 | ## prerequisites 9 | 10 | Below are some key dependencies of this project 11 | 1. Chakra UI framewark 12 | 2. Solana wallet adaptor (Including adaptor-ui) to make use of sollana wallet 13 | 3. Solana web3 to interact with solana chain programs 14 | 15 | Simply implement all neccessory packages by npm install 16 | ``` 17 | npm install 18 | ``` 19 | 20 | ## Runing demo dapp 21 | 22 | You can run test server on localhost:3000 with the boilerplate basic template by runing " npm run dev" 23 | ``` 24 | npm run dev 25 | ``` 26 | 27 | ## Build UI component on top of boilerplate 28 | 29 | You can make your own react component by 30 | 1. Adding/Editing layout components into ./components/Layout/ such as Header, footer, sider ..etc 31 | 32 | 2. Changing the style of common components by editing Loading.tsx or Notify.tsx under ./components/Common/ 33 | 34 | 35 | ## Default Context provider 36 | 37 | This boilerplate by default contains two built in context providers in ./pages/_app.tsx: 38 | 1. WalletProvier is to take advantage of solana wallet adaptor 39 | 2. ChakraProvider is to equip the project with [Chakra UI components](https://chakra-ui.com/docs/getting-started) 40 | 41 | 42 | # TODO 43 | 44 | 1. Build in Anchor framework 45 | 2. Dynamic adjusting exchange pool data 46 | -------------------------------------------------------------------------------- /components/common/Loading.tsx: -------------------------------------------------------------------------------- 1 | import { Spinner } from "@chakra-ui/react" 2 | import style from "../../styles/common.module.sass"; 3 | 4 | function Loading(props: LoadingProps): JSX.Element { 5 | const {size, msg, thickness, speed, emptyColor, color} = props.data 6 | return <> 7 |
8 |
{msg}
9 | 16 |
17 | 18 | 19 | } 20 | export default Loading -------------------------------------------------------------------------------- /components/common/Notify.tsx: -------------------------------------------------------------------------------- 1 | import { FunctionComponent } from "react"; 2 | import { 3 | Alert, 4 | AlertIcon, 5 | AlertTitle, 6 | AlertDescription 7 | } from "@chakra-ui/react"; 8 | import style from "../../styles/common.module.sass"; 9 | 10 | const Notify: FunctionComponent = props => { 11 | return ( 12 | 13 |
14 | 15 | {props.message.title} 16 |
17 | 18 | {props.message.description} 19 | 20 | {props.message.link ? ( 21 | 25 | Check Explorer 26 | 27 | ) : ( 28 | "" 29 | )} 30 |
31 | ); 32 | }; 33 | 34 | export default Notify; 35 | -------------------------------------------------------------------------------- /components/layout/Header.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | WalletModalProvider, 3 | WalletDisconnectButton, 4 | WalletMultiButton 5 | } from "@solana/wallet-adapter-react-ui"; 6 | import { useWallet} from "@solana/wallet-adapter-react"; 7 | import Link from "next/link"; 8 | import style from "../../styles/header.module.sass" 9 | import Image from "next/image"; 10 | 11 | 12 | export default function Header() { 13 | const wallet = useWallet() 14 | 15 | return <> 16 |
17 | dappio logo 18 | My SPL Tokens 19 | Home 20 | Exchange 21 | 22 | {wallet.connected ? : } 23 | 24 |
25 | 26 | } -------------------------------------------------------------------------------- /components/layout/index.tsx: -------------------------------------------------------------------------------- 1 | import Head from 'next/head' 2 | import Header from "./Header" 3 | import { useWallet } from "@solana/wallet-adapter-react" 4 | import { Connection } from "@solana/web3.js" 5 | import { getSPLTokenData } from "../../utils/web3" 6 | import { useEffect, useState } from "react" 7 | import { DappContext } from "../../hooks/useDapp" 8 | // import { Liquidity, LiquidityPoolKeysV4 } from '@raydium-io/raydium-sdk' 9 | import Loading from '../common/Loading' 10 | import Notify from '../common/Notify' 11 | import style from '../../styles/layout.module.sass' 12 | 13 | function Layout({...props}): JSX.Element { 14 | 15 | const connection = new Connection("https://rpc-mainnet-fork.dappio.xyz", { 16 | wsEndpoint: "wss://rpc-mainnet-fork.dappio.xyz/ws", 17 | commitment: "processed" 18 | }); 19 | // --> // 3rd party Hooks 20 | const wallet = useWallet(); 21 | 22 | // --> // React Hooks 23 | const [splTokenData, setSplTokenData] = useState([]); 24 | // const [poolKeys, setPoolKeys] = useState([]) 25 | const [notify, setNotify] = useState(null); 26 | const [loading, setLoading] = useState(null); 27 | 28 | useEffect(()=>{ // Show notify component for 5s if there is any 29 | if (notify) { 30 | setTimeout(()=>setNotify(null), 5000) 31 | } 32 | }, [notify]) 33 | 34 | // useEffect(()=>{ 35 | // Liquidity.fetchAllPoolKeys(connection).then((pools: LiquidityPoolKeysV4[])=>{ 36 | // setPoolKeys(pools) 37 | // }) 38 | // }, [wallet.connected]) 39 | 40 | useEffect(() => { 41 | if (wallet.connected) { 42 | setLoading({ 43 | msg: "Loading spl tokens" 44 | }) 45 | getSPLTokenData(wallet, connection).then((tokenList: ISplToken[]) => { 46 | if (tokenList) { 47 | setSplTokenData(() => tokenList.filter(t => t !== undefined)); 48 | } 49 | setLoading(null) 50 | }); 51 | } else { 52 | setSplTokenData([]) 53 | } 54 | }, [wallet.connected]); 55 | 56 | return <> 57 | 58 | 59 | {/* fontawesome */} 60 | 61 | Solana DAPP Boilerplate 62 | 63 | 64 |
65 |
66 | {notify && } 67 | {loading && } 68 | 77 |
{props.children}
78 |
79 |
80 | 81 | } 82 | 83 | 84 | export default Layout 85 | -------------------------------------------------------------------------------- /components/raydium/SwapOperateContainer.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from "react"; 2 | import { ArrowUpDownIcon, QuestionOutlineIcon } from "@chakra-ui/icons"; 3 | import { Tooltip } from "@chakra-ui/react"; 4 | import { useWallet } from "@solana/wallet-adapter-react"; 5 | import { 6 | WalletModalProvider, 7 | WalletMultiButton 8 | } from "@solana/wallet-adapter-react-ui"; 9 | import TokenSelect from "./TokenSelect"; 10 | import style from "../../styles/swap.module.sass"; 11 | 12 | const SwapOperateContainer: FC = props => { 13 | let wallet = useWallet(); 14 | const SwapBtn = (swapProps: any) => { 15 | if (wallet.connected) { 16 | if ( 17 | !swapProps.props.fromData.tokenInfo?.symbol || 18 | !swapProps.props.toData.tokenInfo?.symbol 19 | ) { 20 | return ( 21 | 27 | ); 28 | } 29 | if ( 30 | swapProps.props.fromData.tokenInfo?.symbol && 31 | swapProps.props.toData.tokenInfo?.symbol 32 | ) { 33 | if ( 34 | !swapProps.props.fromData.amount || 35 | !swapProps.props.toData.amount 36 | ) { 37 | return ( 38 | 44 | ); 45 | } 46 | } 47 | 48 | return ( 49 | 55 | ); 56 | } else { 57 | return ( 58 |
59 | 60 | 61 | 62 |
63 | ); 64 | } 65 | }; 66 | 67 | const SwapDetailPreview: FC = props => { 68 | return ( 69 |
70 |
71 |
{props.title}
72 | 79 | 84 | 85 |
86 |
{props.value}
87 |
88 | ); 89 | }; 90 | 91 | const SwapDetailPreviewList = (): JSX.Element => { 92 | return ( 93 | <> 94 | ${props.toData.tokenInfo.symbol}`} 98 | /> 99 | 100 | ); 101 | }; 102 | 103 | return ( 104 |
105 |
106 | 114 |
118 | 119 |
120 | 128 |
129 |
130 |
Slippage Tolerance
131 | 138 | 143 | 144 |
145 |
{props.slippageValue}%
146 |
147 | {props.fromData.amount! > 0 && 148 | props.fromData.tokenInfo.symbol && 149 | props.toData.amount! > 0 && 150 | props.toData.tokenInfo.symbol ? ( 151 | 152 | ) : ( 153 | "" 154 | )} 155 | 156 |
157 |
158 | ); 159 | }; 160 | 161 | export default SwapOperateContainer; 162 | -------------------------------------------------------------------------------- /components/raydium/TokenList.tsx: -------------------------------------------------------------------------------- 1 | import { FunctionComponent, useEffect, useRef, useState } from "react"; 2 | import { CloseIcon } from "@chakra-ui/icons"; 3 | import SPLTokenRegistrySource from "../../utils/tokenList"; 4 | import { TOKENS } from "../../utils/tokens"; 5 | import style from "../../styles/swap.module.sass"; 6 | 7 | const TokenList: FunctionComponent = props => { 8 | 9 | const [initialList, setList] = useState([]); 10 | const [searchedList, setSearchList] = useState([]); 11 | const searchRef = useRef(); 12 | 13 | useEffect(() => { // Fetch all tokens data 14 | SPLTokenRegistrySource().then((res) => { 15 | let list: ITokenInfo[] = []; 16 | res.forEach((item: any) => { 17 | let token = {} as ITokenInfo; 18 | if ( 19 | TOKENS[item.symbol] && 20 | !list.find( 21 | (t: ITokenInfo) => t.mintAddress === TOKENS[item.symbol].mintAddress 22 | ) 23 | ) { 24 | token = TOKENS[item.symbol]; 25 | token["logoURI"] = item.logoURI; 26 | list.push(token); 27 | } 28 | }); 29 | setList(() => list); // Put tokens into list 30 | 31 | props.getTokenInfo( // Select SOL as default 32 | list.find((item: ITokenInfo) => item.symbol === "SOL") 33 | ) 34 | }) 35 | }, []); 36 | 37 | useEffect(() => { 38 | setSearchList(() => initialList); 39 | }, [initialList]); 40 | 41 | const setTokenInfo = (item: ITokenInfo) => { 42 | props.getTokenInfo(item); 43 | props.toggleTokenList("From"); 44 | }; 45 | 46 | const listItems = (data: ITokenInfo[]) => { 47 | return data.map((item: ITokenInfo) => { 48 | return ( 49 |
setTokenInfo(item)} 53 | > 54 | 55 |
{item.symbol}
56 |
57 | ); 58 | }); 59 | }; 60 | 61 | const searchToken = (e: any) => { 62 | let key = e.target.value.toUpperCase(); 63 | let newList: ITokenInfo[] = []; 64 | initialList.map((item: ITokenInfo) => { 65 | if (item.symbol.includes(key)) { 66 | newList.push(item); 67 | } 68 | }); 69 | setSearchList(newList); 70 | }; 71 | 72 | let tokeListComponentStyle; 73 | if (!props.showTokenList) { 74 | tokeListComponentStyle = { 75 | display: "none" 76 | }; 77 | } else { 78 | tokeListComponentStyle = { 79 | display: "block" 80 | }; 81 | } 82 | 83 | return ( 84 |
85 |
86 |
87 |
Select a token
88 |
props.toggleTokenList(undefined)}> 89 | 90 |
91 |
92 |
93 | 100 |
101 |
Token name
102 |
103 |
104 |
{listItems(searchedList)}
105 |
View Token List
106 |
107 |
108 | ); 109 | }; 110 | 111 | export default TokenList; 112 | -------------------------------------------------------------------------------- /components/raydium/TokenSelect.tsx: -------------------------------------------------------------------------------- 1 | import { FunctionComponent, useEffect, useState } from "react"; 2 | import { ArrowDownIcon } from "@chakra-ui/icons"; 3 | import { useWallet } from "@solana/wallet-adapter-react"; 4 | import style from "../../styles/swap.module.sass"; 5 | 6 | const TokenSelect: FunctionComponent = props => { 7 | let wallet = useWallet(); 8 | const [tokenBalance, setTokenBalance] = useState(null); 9 | 10 | const updateAmount = (e: any) => { 11 | e.preventDefault(); 12 | 13 | const amountData: IUpdateAmountData = { 14 | amount: e.target.value, 15 | type: props.type 16 | }; 17 | props.updateAmount(amountData); 18 | }; 19 | 20 | const selectToken = () => { 21 | props.toggleTokenList(props.type); 22 | }; 23 | 24 | useEffect(() => { 25 | const updateSelectedTokenBalance = () => { 26 | console.log(props.tokenData.tokenInfo?.mintAddress) 27 | let data: ISplToken | undefined = props.splTokenData.find( 28 | (t: ISplToken) => 29 | t.parsedInfo.mint === props.tokenData.tokenInfo?.mintAddress 30 | ); 31 | console.log(props.splTokenData) 32 | if (data) { 33 | setTokenBalance(data.amount); 34 | } else { 35 | setTokenBalance(0); 36 | } 37 | }; 38 | updateSelectedTokenBalance(); 39 | }, [props.tokenData, props.splTokenData]); 40 | 41 | const DropDownTokenListBtn: FunctionComponent = selectTokenProps => { 42 | if (selectTokenProps.tokenData.tokenInfo?.symbol) { 43 | return ( 44 | <> 45 | logo 50 |
51 | 52 | {selectTokenProps.tokenData.tokenInfo?.symbol} 53 | 54 | 55 |
56 | 57 | ); 58 | } 59 | return ( 60 | <> 61 | Select a token 62 | 63 | 64 | ); 65 | }; 66 | 67 | return ( 68 |
69 |
70 |
71 | {props.type === "To" ? `${props.type} (Estimate)` : props.type} 72 |
73 |
74 | {wallet.connected && tokenBalance 75 | ? `Balance: ${tokenBalance.toFixed(4)}` 76 | : ""} 77 |
78 |
79 |
80 | {props.type !== "From" ? ( 81 |
82 | {props.tokenData.amount ? props.tokenData.amount : "-"} 83 |
84 | ) : ( 85 | 92 | )} 93 | 94 |
95 | 96 |
97 |
98 |
99 | ); 100 | }; 101 | 102 | export default TokenSelect; 103 | -------------------------------------------------------------------------------- /components/raydium/index.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, FunctionComponent } from "react"; 2 | import { useWallet } from "@solana/wallet-adapter-react"; 3 | import { getPoolByTokenMintAddresses } from "../../utils/pools"; 4 | import { swap, getSwapOutAmount, setupPools } from "../../utils/swap"; 5 | import { getSPLTokenData } from "../../utils/web3"; 6 | import useDapp from "../../hooks/useDapp"; 7 | import TokenList from "./TokenList"; 8 | import SwapOperateContainer from "./SwapOperateContainer"; 9 | 10 | const SwapPage: FunctionComponent = () => { 11 | // React Hooks 12 | const [showTokenList, setShowTokenList] = useState(false); 13 | const [showSlippageSetting, setShowSlippageSetting] = useState(false); 14 | const [selectType, setSelectType] = useState<"From" | "To" | undefined>("From"); 15 | const [fromData, setFromData] = useState({} as TokenData); 16 | const [toData, setToData] = useState({} as TokenData); 17 | const [slippageValue, setSlippageValue] = useState(1); 18 | const [splTokenData, setSplTokenData] = useState([]); 19 | const [liquidityPools, setLiquidityPools] = useState(""); 20 | // Other Hooks 21 | let wallet = useWallet(); 22 | let { connection, splTokens, setNotify, setLoading } = useDapp() 23 | 24 | useEffect(()=>{ 25 | splTokens && setSplTokenData(splTokens) 26 | }, [splTokens]) 27 | 28 | useEffect(() => { // Setup Liquidity Pools 29 | setLoading!({ 30 | msg: "Loading Liquidity Pools" 31 | }); 32 | setupPools(connection).then(data => { 33 | setLiquidityPools(data); 34 | setLoading!(null) 35 | }); 36 | return () => { 37 | setLiquidityPools(""); 38 | }; 39 | }, []); 40 | 41 | const updateAmount = (e: IUpdateAmountData) => { 42 | if (e.type === "From") { 43 | setFromData((old: TokenData) => ({ 44 | ...old, 45 | amount: e.amount 46 | })); 47 | 48 | if (!e.amount) { 49 | setToData((old: TokenData) => ({ 50 | ...old, 51 | amount: 0 52 | })); 53 | } 54 | } 55 | }; 56 | 57 | const updateSwapOutAmount = () => { 58 | if ( 59 | fromData.amount! > 0 && 60 | fromData.tokenInfo?.symbol && 61 | toData.tokenInfo?.symbol 62 | ) { 63 | // Get LP info 64 | let poolInfo = getPoolByTokenMintAddresses( 65 | fromData.tokenInfo.mintAddress, 66 | toData.tokenInfo.mintAddress 67 | ); 68 | 69 | if (!poolInfo) { // If get no LP then trigger notification 70 | setNotify!(() => ({ /** @TODO Manual update pool?? how to get the Liquidity pool in util auto update? */ 71 | status: "error", 72 | title: "AMM error", 73 | description: "Current token pair pool not found" 74 | })); 75 | return; 76 | } 77 | 78 | let parsedPoolsData = liquidityPools; 79 | let parsedPoolInfo = parsedPoolsData[poolInfo?.lp.mintAddress]; 80 | 81 | // //@ts-ignore 82 | const { amountOutWithSlippage } = getSwapOutAmount( 83 | parsedPoolInfo, 84 | fromData.tokenInfo.mintAddress, 85 | toData.tokenInfo.mintAddress, 86 | fromData.amount!.toString(), 87 | slippageValue 88 | ); 89 | 90 | setToData((old: TokenData) => ({ 91 | ...old, 92 | amount: parseFloat(amountOutWithSlippage.fixed()) 93 | })); 94 | } 95 | }; 96 | 97 | useEffect(() => { // Update SwapOut Amount when there is change of src or dist coins or slippage 98 | updateSwapOutAmount(); 99 | }, [fromData, toData.tokenInfo?.symbol, slippageValue]); 100 | 101 | const toggleTokenList = (type: "From"|"To" | undefined) => { /**@Param e: selected type */ 102 | setShowTokenList(() => !showTokenList); 103 | setSelectType(type) 104 | }; 105 | 106 | const toggleSlippageSetting = () => { // pop-up slippage selection 107 | setShowSlippageSetting(() => !showSlippageSetting); 108 | }; 109 | 110 | const getSlippageValue = (e: number) => { 111 | if (!e) { 112 | setSlippageValue(() => e); 113 | } else { 114 | setSlippageValue(() => e); 115 | } 116 | }; 117 | 118 | const switchFromAndTo = () => { 119 | const fromToken = fromData.tokenInfo; 120 | const toToken = toData.tokenInfo; 121 | setFromData((old: TokenData) => ({ 122 | ...old, 123 | tokenInfo: toToken, 124 | amount: null 125 | })); 126 | 127 | setToData((old: TokenData) => ({ 128 | ...old, 129 | tokenInfo: fromToken, 130 | amount: null 131 | })); 132 | }; 133 | 134 | const getTokenInfo = (e: ITokenInfo) => { // Set src and dist coin when user select 135 | if (selectType === "From") { // When user selects src token which is the same as current dist coin 136 | if (toData.tokenInfo?.symbol === e?.symbol) { 137 | setToData((old: TokenData) => ({ 138 | ...old, 139 | tokenInfo: { 140 | symbol: "", 141 | mintAddress: "", 142 | logoURI: "" 143 | } 144 | })); 145 | } 146 | 147 | setFromData((old: TokenData) => ({ 148 | ...old, 149 | tokenInfo: e 150 | })); 151 | } else { // Else when user selects dist token which is the same as current src coin 152 | if (fromData.tokenInfo?.symbol === e.symbol) { 153 | setFromData((old: TokenData) => ({ 154 | ...old, 155 | tokenInfo: { 156 | symbol: "", 157 | mintAddress: "", 158 | logoURI: "" 159 | } 160 | })); 161 | } 162 | 163 | setToData((old: TokenData) => ({ 164 | ...old, 165 | tokenInfo: e 166 | })); 167 | } 168 | }; 169 | 170 | const sendSwapTransaction = async () => { 171 | let poolInfo = getPoolByTokenMintAddresses( 172 | fromData.tokenInfo.mintAddress, 173 | toData.tokenInfo.mintAddress 174 | ); 175 | 176 | let fromTokenAccount: ISplToken | undefined | string = splTokenData.find( 177 | (token: ISplToken) => 178 | token.parsedInfo.mint === fromData.tokenInfo.mintAddress 179 | ); 180 | if (fromTokenAccount) { 181 | fromTokenAccount = fromTokenAccount.pubkey; 182 | } else { 183 | fromTokenAccount = ""; 184 | } 185 | 186 | let toTokenAccount: ISplToken | undefined | string = splTokenData.find( 187 | (token: ISplToken) => 188 | token.parsedInfo.mint === toData.tokenInfo.mintAddress 189 | ); 190 | if (toTokenAccount) { 191 | toTokenAccount = toTokenAccount.pubkey; 192 | } else { 193 | toTokenAccount = ""; 194 | } 195 | 196 | let wsol: ISplToken | undefined = splTokenData.find( 197 | (token: ISplToken) => 198 | token.parsedInfo.mint === "So11111111111111111111111111111111111111112" 199 | ); 200 | let wsolMint: string = ""; 201 | if (wsol) { 202 | wsolMint = wsol.parsedInfo.mint; 203 | } 204 | 205 | if (poolInfo === undefined) { 206 | alert("Pool not exist"); 207 | return; 208 | } 209 | 210 | swap( 211 | connection, 212 | wallet, 213 | poolInfo, 214 | fromData.tokenInfo.mintAddress, 215 | toData.tokenInfo.mintAddress, 216 | fromTokenAccount, 217 | toTokenAccount, 218 | fromData.amount!.toString(), 219 | toData.amount!.toString(), 220 | wsolMint 221 | ).then(async res => { 222 | setNotify!(() => ({ 223 | status: "error", 224 | title: "AMM error", 225 | description: "Current token pair pool not found" 226 | })); 227 | 228 | let result = await connection.confirmTransaction(res); 229 | 230 | if (!result.value.err) { 231 | setNotify!({ 232 | status: "success", 233 | title: "Transaction Success", 234 | description: "", 235 | }); 236 | } else { 237 | setNotify!({ 238 | status: "success", 239 | title: "Fail", 240 | description: "Transaction fail, please check below link", 241 | link: `https://explorer.solana.com/address/${res}` 242 | }); 243 | } 244 | 245 | getSPLTokenData(wallet, connection).then((tokenList: ISplToken[]) => { 246 | if (tokenList) { 247 | setSplTokenData(() => 248 | tokenList.filter((t: ISplToken) => t !== undefined) 249 | ); 250 | } 251 | }); 252 | }); 253 | }; 254 | 255 | useEffect(() => { 256 | if (wallet.connected) { 257 | setNotify!({ 258 | status: "success", 259 | title: "Wallet connected", 260 | description: wallet.publicKey?.toBase58() as string 261 | }); 262 | } else { 263 | let description = wallet.publicKey?.toBase58(); 264 | if (!description) { 265 | description = "Please try again"; 266 | } 267 | setNotify!({ 268 | status: "error", 269 | title: "Wallet disconnected", 270 | description: description as string 271 | }); 272 | } 273 | 274 | }, [wallet.connected]); 275 | 276 | return ( 277 |
278 | toggleTokenList(undefined)} 281 | getTokenInfo={getTokenInfo} 282 | /> 283 | 293 | 294 |
295 | ); 296 | }; 297 | 298 | export default SwapPage; 299 | -------------------------------------------------------------------------------- /hooks/useDapp.ts: -------------------------------------------------------------------------------- 1 | import { Connection } from "@solana/web3.js"; 2 | import { useContext, createContext } from "react"; 3 | 4 | const DappContext = createContext({ 5 | splTokens: undefined, 6 | connection: new Connection("https://rpc-mainnet-fork.dappio.xyz", { 7 | wsEndpoint: "wss://rpc-mainnet-fork.dappio.xyz/ws", 8 | commitment: "processed", 9 | }), 10 | setNotify: null, 11 | setLoading: null, 12 | }) 13 | 14 | export default function useDapp() { 15 | return useContext(DappContext) 16 | } 17 | 18 | export {DappContext} 19 | -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const withPlugins = require("next-compose-plugins"); 3 | 4 | /** eslint-disable @typescript-eslint/no-var-requires */ 5 | const withTM = require("next-transpile-modules")([ 6 | "@solana/wallet-adapter-base", 7 | // Uncomment wallets you want to use 8 | // "@solana/wallet-adapter-bitpie", 9 | // "@solana/wallet-adapter-coin98", 10 | // "@solana/wallet-adapter-ledger", 11 | // "@solana/wallet-adapter-mathwallet", 12 | "@solana/wallet-adapter-phantom", 13 | "@solana/wallet-adapter-react", 14 | "@solana/wallet-adapter-solflare", 15 | "@solana/wallet-adapter-sollet", 16 | // "@solana/wallet-adapter-solong", 17 | // "@solana/wallet-adapter-torus", 18 | "@solana/wallet-adapter-wallets", 19 | // "@project-serum/sol-wallet-adapter", 20 | // "@solana/wallet-adapter-ant-design", 21 | ]); 22 | 23 | const plugins = [ 24 | [ 25 | withTM, 26 | { 27 | webpack5: true, 28 | reactStrictMode: true, 29 | }, 30 | ], 31 | ]; 32 | 33 | const nextConfig = { 34 | swcMinify: false, 35 | webpack: (config, { 36 | isServer 37 | }) => { 38 | if (!isServer) { 39 | config.resolve.fallback.fs = false; 40 | } 41 | return config; 42 | }, 43 | }; 44 | 45 | module.exports = withPlugins(plugins, nextConfig); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "project60_solana_dapp", 3 | "private": true, 4 | "scripts": { 5 | "dev": "next dev", 6 | "build": "next build", 7 | "start": "next start", 8 | "lint": "next lint" 9 | }, 10 | "dependencies": { 11 | "@chakra-ui/icons": "^1.1.1", 12 | "@chakra-ui/react": "^1.7.4", 13 | "@emotion/react": "^11", 14 | "@emotion/styled": "^11", 15 | "@jup-ag/react-hook": "^1.0.0-beta.2", 16 | "@project-serum/borsh": "^0.2.3", 17 | "@project-serum/serum": "^0.13.61", 18 | "@solana/spl-token-registry": "^0.2.1733", 19 | "@solana/wallet-adapter-base": "^0.9.2", 20 | "@solana/wallet-adapter-react": "^0.15.2", 21 | "@solana/wallet-adapter-react-ui": "^0.9.4", 22 | "@solana/wallet-adapter-wallets": "^0.14.2", 23 | "@solana/web3.js": "^1.32.0", 24 | "framer-motion": "^5", 25 | "lodash-es": "^4.17.21", 26 | "next": "12.0.8", 27 | "next-compose-plugins": "^2.2.1", 28 | "next-transpile-modules": "^9.0.0", 29 | "react": "17.0.2", 30 | "react-dom": "17.0.2", 31 | "sass": "^1.49.0" 32 | }, 33 | "devDependencies": { 34 | "@types/lodash-es": "^4.17.5", 35 | "@types/node": "17.0.10", 36 | "@types/react": "17.0.38", 37 | "eslint": "8.7.0", 38 | "eslint-config-next": "12.0.8", 39 | "typescript": "4.5.5" 40 | }, 41 | "resolutions": { 42 | "@solana/buffer-layout": "^3.0.0" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import '../styles/globals.css' 2 | import type { AppProps } from 'next/app' 3 | // import { Wallet } from '../components/common/WalletProvider' 4 | import { ChakraProvider } from '@chakra-ui/react' 5 | import Layout from '../components/layout' 6 | 7 | import { ConnectionProvider, WalletProvider } from "@solana/wallet-adapter-react"; 8 | import { WalletAdapterNetwork } from "@solana/wallet-adapter-base"; 9 | import { 10 | LedgerWalletAdapter, 11 | PhantomWalletAdapter, 12 | SlopeWalletAdapter, 13 | SolflareWalletAdapter, 14 | SolletExtensionWalletAdapter, 15 | SolletWalletAdapter, 16 | TorusWalletAdapter 17 | } from "@solana/wallet-adapter-wallets"; 18 | import { useMemo } from 'react' 19 | // import { clusterApiUrl } from "@solana/web3.js"; 20 | 21 | // Default styles that can be overridden by your app 22 | require("@solana/wallet-adapter-react-ui/styles.css"); 23 | 24 | function MyApp({ Component, pageProps }: AppProps) { 25 | // // The network can be set to 'devnet', 'testnet', or 'mainnet-beta'. 26 | const network = WalletAdapterNetwork.Mainnet; 27 | 28 | // // You can also provide a custom RPC endpoint. 29 | const endpoint = "https://rpc-mainnet-fork.dappio.xyz"; 30 | 31 | // @solana/wallet-adapter-wallets includes all the adapters but supports tree shaking and lazy loading -- 32 | // Only the wallets you configure here will be compiled into your application, and only the dependencies 33 | // of wallets that your users connect to will be loaded. 34 | const wallets = useMemo( 35 | () => [ 36 | new PhantomWalletAdapter(), 37 | new SlopeWalletAdapter(), 38 | new SolflareWalletAdapter(), 39 | new TorusWalletAdapter(), 40 | new LedgerWalletAdapter(), 41 | new SolletWalletAdapter({ network }), 42 | new SolletExtensionWalletAdapter({ network }) 43 | ], 44 | [network] 45 | ); 46 | 47 | return 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | } 57 | 58 | export default MyApp 59 | -------------------------------------------------------------------------------- /pages/exchange.tsx: -------------------------------------------------------------------------------- 1 | 2 | import SwapPage from "../components/raydium" 3 | import useDapp from "../hooks/useDapp" 4 | 5 | 6 | export default function ExchangePage() { 7 | const {splTokens} = useDapp() 8 | return <> 9 |
10 | 11 |
12 | 13 | 14 | } -------------------------------------------------------------------------------- /pages/index.tsx: -------------------------------------------------------------------------------- 1 | import type { NextPage } from 'next' 2 | 3 | 4 | 5 | const Home: NextPage = () => { 6 | 7 | return <> 8 | 9 | } 10 | 11 | export default Home 12 | -------------------------------------------------------------------------------- /pages/my_spl.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useMemo, useState } from "react"; 2 | import useDapp from "../hooks/useDapp" 3 | import { TOKENS } from "../utils/tokens"; 4 | import style from "../styles/mySpl.module.sass" 5 | import { useWallet } from "@solana/wallet-adapter-react"; 6 | 7 | 8 | export default function MySplPage() { 9 | 10 | const {splTokens, setNotify} = useDapp() 11 | 12 | const wallet = useWallet() 13 | 14 | const [tokenList, setTokenList] = useState([]); 15 | 16 | useEffect(()=>{ // Show error notify if there !wallet.connected 17 | setTokenList(updateTokenList()) 18 | if (!wallet.connected) { 19 | setNotify!({ 20 | status: "error", 21 | title: "Wallet not connected", 22 | description: "Please login with your wallet", 23 | }) 24 | return 25 | } 26 | setNotify!(null) 27 | }, []) 28 | 29 | function updateTokenList(): SplTokenDisplayData[] { 30 | let tokenList = []; 31 | for (const [_, value] of Object.entries(TOKENS)) { 32 | let spl: ISplToken | undefined = splTokens?.find( 33 | (t: ISplToken) => t.parsedInfo.mint === value.mintAddress 34 | ); 35 | 36 | if (spl) { 37 | let token = {} as SplTokenDisplayData; 38 | token["symbol"] = value.symbol; 39 | token["mint"] = spl?.parsedInfo.mint; 40 | token["pubkey"] = spl?.pubkey; 41 | token["amount"] = spl?.amount; 42 | tokenList.push(token); 43 | } 44 | } 45 | return tokenList 46 | } 47 | 48 | return <> 49 |
50 | {tokenList.map((item ) => { 51 | return ( 52 |
53 |
54 | 55 | {item.symbol} 56 | 57 | - {item.amount} 58 |
59 |
60 |
Mint: {item.mint}
61 |
Pubkey: {item.pubkey}
62 |
63 |
64 | ); 65 | })} 66 |
67 | 68 | } -------------------------------------------------------------------------------- /public/bg.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappioLab/swap-ui-example/9b2b71217ab2be5f92ea07e3a50cca4afd59eaaf/public/bg.jpeg -------------------------------------------------------------------------------- /public/image/dappio-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappioLab/swap-ui-example/9b2b71217ab2be5f92ea07e3a50cca4afd59eaaf/public/image/dappio-logo.png -------------------------------------------------------------------------------- /styles/color.module.sass: -------------------------------------------------------------------------------- 1 | $white: #eee 2 | $main_blue: rgb(19, 27, 51) 3 | $swap_card_bgc: #131a35 4 | $coin_select_block_bgc: #000829 5 | $placeholder_grey: #f1f1f2 6 | $swap_btn_border_color: #5ac4be 7 | $token_list_bgc: #1c274f 8 | $slippage_setting_warning_red: #f5222d 9 | -------------------------------------------------------------------------------- /styles/common.module.sass: -------------------------------------------------------------------------------- 1 | @import './color.module' 2 | .notifyContainer 3 | position: fixed !important 4 | bottom: 3rem 5 | left: 2rem 6 | width: auto !important 7 | background-color: $token_list_bgc !important 8 | border-radius: .5rem 9 | padding: 2rem !important 10 | font-size: 1.4rem 11 | display: flex !important 12 | flex-direction: column !important 13 | align-items: center !important 14 | color: $white 15 | .notifyTitleRow 16 | display: flex 17 | align-items: center 18 | justify-content: center 19 | .notifyDescription 20 | margin-top: 2rem 21 | 22 | .loadingContainer 23 | position: fixed 24 | top: 100px 25 | right: 50px 26 | width: auto 27 | background-color: $token_list_bgc 28 | border-radius: .5rem 29 | padding: 2rem 30 | font-size: 1.4rem 31 | display: flex 32 | flex-direction: column 33 | align-items: center 34 | color: $white -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 6 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 7 | } 8 | 9 | a { 10 | color: inherit; 11 | text-decoration: none; 12 | } 13 | 14 | * { 15 | box-sizing: border-box; 16 | } 17 | 18 | 19 | .wallet-adapter-button { 20 | 21 | } 22 | 23 | .wallet-adapter-button-trigger { 24 | background-color: #fbae21 !important; 25 | color: black !important; 26 | padding: 10px 5px; 27 | border-radius: 5px; 28 | font-weight: bold; 29 | } 30 | 31 | .btn { 32 | margin: 30px 33 | } 34 | 35 | 36 | .wallet-adapter-modal-wrapper { 37 | display: flex; 38 | flex-direction: column; 39 | width: 50%; 40 | margin: auto; 41 | justify-content: center; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /styles/header.module.sass: -------------------------------------------------------------------------------- 1 | @import './color.module' 2 | 3 | .header 4 | padding: 10px 5 | display: flex 6 | color: $white 7 | justify-content: space-around 8 | background-color: black 9 | align-items: center 10 | font-weight: bold 11 | -------------------------------------------------------------------------------- /styles/layout.module.sass: -------------------------------------------------------------------------------- 1 | .layoutContainer 2 | background-image: url("../public/bg.jpeg") 3 | background-repeat: no-repeat 4 | background-size: cover 5 | min-height: 100vh -------------------------------------------------------------------------------- /styles/mySpl.module.sass: -------------------------------------------------------------------------------- 1 | @import './color.module' 2 | .splTokenList 3 | display: flex 4 | flex-direction: column 5 | align-items: center 6 | padding: 50px 7 | .item 8 | border: 1px solid $swap_card_bgc 9 | margin-top: 30px 10 | padding: 20px 11 | border-radius: 5px 12 | opacity: 0.7 13 | background-color: $white 14 | -------------------------------------------------------------------------------- /styles/swap.module.sass: -------------------------------------------------------------------------------- 1 | @import './color.module' 2 | 3 | // .swapPage 4 | // position: relative 5 | // height: calc( 100vh - 7rem ) 6 | // color: $white 7 | // background-color: $main_blue 8 | // .container 9 | // position: absolute 10 | // top: 5rem 11 | // left: 50% 12 | // transform: translateX(-50%) 13 | // .titleContainer 14 | // display: flex 15 | // align-items: center 16 | // justify-content: center 17 | // margin-bottom: 1rem 18 | // .title 19 | // flex: 1 20 | // font-weight: 600 21 | // font-size: 2.4rem 22 | // .iconContainer 23 | // display: flex 24 | // flex: 2 25 | // justify-content: flex-end 26 | // .icon 27 | // cursor: pointer 28 | // padding: .5rem 29 | // border-radius: .5rem 30 | // margin-left: 1rem 31 | // &:hover 32 | // background-color: $coin_select_block_bgc 33 | // .percentageCircle 34 | // width: 3rem 35 | // height: 3rem 36 | // .circleBg 37 | // stroke: $white 38 | // fill: none 39 | // stroke-width: 4 40 | // .popover 41 | // box-shadow: none !important 42 | // outline: none !important 43 | // .selectTokenAddressTitle 44 | // font-size: 1.2rem 45 | // font-weight: 600 46 | // color: $placeholder_grey 47 | // margin: .5rem 0 1rem 0 48 | // .selectTokenAddress 49 | // opacity: .7 50 | // display: flex 51 | // align-items: center 52 | // margin-top: .5rem 53 | // .symbol 54 | // width: 5rem 55 | // flex-shrink: 0 56 | // .address 57 | // background-color: $swap_card_bgc 58 | // padding: .5rem 59 | // border-radius: .5rem 60 | // font-weight: 600 61 | .swapCard 62 | margin: auto 63 | width: 36rem 64 | background: linear-gradient(245.22deg,#da2eef 7.97%,#2b6aff 49.17%,#39d0d8 92.1%) 65 | display: flex 66 | align-items: center 67 | justify-content: center 68 | border-radius: .5rem 69 | padding: .1rem 70 | .cardBody 71 | background-color: $swap_card_bgc 72 | border-radius: .5rem 73 | width: 100% 74 | height: 100% 75 | opacity: .9 76 | padding: 3.2rem 1.8rem 3.2rem 1.8rem 77 | display: flex 78 | flex-direction: column 79 | align-items: center 80 | .switchIcon 81 | margin: 1rem 0 82 | width: 3.2rem 83 | height: 3.2rem 84 | background-color: #000829 85 | border-radius: 50% 86 | display: flex 87 | align-items: center 88 | justify-content: center 89 | .icon 90 | cursor: pointer 91 | .lowSOLWarning 92 | font-size: 1.4rem 93 | color: $white 94 | display: flex 95 | align-items: center 96 | justify-content: center 97 | font-weight: 600 98 | padding-top: 1.5rem 99 | .txt 100 | margin-right: 1rem 101 | .coinSelect 102 | color: $white 103 | background-color: $coin_select_block_bgc 104 | border-radius: .4rem 105 | box-sizing: border-box 106 | padding: 1rem 107 | width: 100% 108 | .noteText 109 | font-size: 1.2rem 110 | color: #85858d 111 | display: flex 112 | justify-content: space-between 113 | .coinAmountRow 114 | display: flex 115 | align-items: center 116 | justify-content: space-between 117 | margin: 2rem 0 1rem 0 118 | .input 119 | background-color: transparent 120 | flex: 6 121 | border: none 122 | font-weight: 600 123 | font-size: 1.6rem 124 | color: $placeholder_grey 125 | white-space: nowrap 126 | overflow: hidden 127 | text-overflow: ellipsis 128 | letter-spacing: .1rem 129 | outline: none 130 | .selectTokenBtn 131 | flex: 4 132 | display: flex 133 | align-items: center 134 | justify-content: center 135 | padding: .5rem 136 | border-radius: .5rem 137 | font-weight: 500 138 | height: 4rem 139 | &:hover 140 | background-color: $token_list_bgc 141 | cursor: pointer 142 | .img 143 | width: 2.4rem 144 | height: 2.4rem 145 | border-radius: 50% 146 | margin-right: 1rem 147 | .coinNameBlock 148 | border: none 149 | font-weight: 600 150 | font-size: 1.4rem 151 | border-radius: .4rem 152 | white-space: nowrap 153 | cursor: pointer 154 | font-family: Bakbak One 155 | letter-spacing: 1px 156 | .coinName 157 | margin-right: .5rem 158 | .slippageRow 159 | color: $white 160 | display: flex 161 | align-items: center 162 | justify-content: space-between 163 | width: 100% 164 | padding: 1rem 1.2rem 0 1.2rem 165 | font-size: 1.2rem 166 | opacity: .75 167 | font-weight: 600 168 | .slippageTooltipBlock 169 | display: flex 170 | align-items: center 171 | .icon 172 | margin-left: 1rem 173 | 174 | .operateBtn 175 | width: 100% 176 | height: 4rem 177 | border: solid .1rem $swap_btn_border_color 178 | color: $white 179 | background-color: transparent 180 | border-radius: .4rem 181 | margin-top: 2rem 182 | font-size: 1.6rem 183 | font-weight: 600 184 | &:hover 185 | transition: .5s 186 | color: $swap_btn_border_color 187 | // .selectWallet 188 | // margin-top: 2.5rem 189 | .disabledBtn 190 | border-color: $placeholder_grey 191 | opacity: .7 192 | cursor: unset 193 | &:hover 194 | color: $placeholder_grey 195 | 196 | .tokeListComponent 197 | transition: .3s 198 | width: 100vw 199 | height: 100vh 200 | background-color: rgba(0,0,0,.5) 201 | color: $white 202 | position: fixed 203 | top: 0 204 | left: 0 205 | z-index: 99 206 | .tokeListContainer 207 | max-width: 45rem 208 | width: calc(100vw - 1.6rem) 209 | height: calc( 100vh - 14rem) 210 | overflow: hidden 211 | background-color: $token_list_bgc 212 | position: absolute 213 | top: 10rem 214 | left: 50% 215 | transform: translateX(-50%) 216 | border-radius: .5rem 217 | .header 218 | height: 6rem 219 | padding: 2.4rem 220 | display: flex 221 | align-items: center 222 | justify-content: space-between 223 | font-size: 1.6rem 224 | font-weight: 600 225 | letter-spacing: 1px 226 | border-bottom: solid .1rem $white 227 | .list 228 | height: calc(100% - 10rem) 229 | overflow: scroll 230 | padding: 0 1.5rem 2rem 1.5rem 231 | .tokenRow 232 | display: flex 233 | align-items: center 234 | padding: .8rem 1.2rem 235 | font-size: 1.2rem 236 | cursor: pointer 237 | &:hover 238 | background-color: $coin_select_block_bgc 239 | opacity: .7 240 | .tokenLogo 241 | width: 2rem 242 | height: 2rem 243 | border-radius: 50% 244 | overflow: hidden 245 | margin-right: 1.2rem 246 | .tokenListSetting 247 | border-top: solid .1rem $white 248 | height: 5.5rem 249 | flex-shrink: 0 250 | display: flex 251 | align-items: center 252 | justify-content: center 253 | font-size: 1.4rem 254 | letter-spacing: 1px 255 | position: absolute 256 | bottom: 0 257 | background-color: $token_list_bgc 258 | width: 100% 259 | .closeIcon 260 | cursor: pointer 261 | .inputBlock 262 | padding: 0.2rem 2.5rem 0 2.5rem 263 | .tokenListTitleRow 264 | font-size: 1.4rem 265 | font-weight: 600 266 | height: 5rem 267 | display: flex 268 | justify-content: space-between 269 | align-items: center 270 | .searchTokenInput 271 | // padding: 0.5rem 272 | border: solid .1rem $swap_btn_border_color 273 | outline: none 274 | width: 100% 275 | background-color: $token_list_bgc 276 | font-size: 1.8rem 277 | border-radius: .5rem 278 | margin-top: 2rem 279 | 280 | // .slippageSettingComponent 281 | // width: 100vw 282 | // height: 100vh 283 | // background-color: rgba(0,0,0,.5) 284 | // position: fixed 285 | // z-index: 999 286 | // top: 0 287 | // left: 0 288 | // .slippageSettingContainer 289 | // width: 50rem 290 | // height: 20rem 291 | // background-color: $token_list_bgc 292 | // top: 50% 293 | // left: 50% 294 | // transform: translate(-50%, -50%) 295 | // position: fixed 296 | // z-index: 9999999 297 | // border-radius: .5rem 298 | // .header 299 | // padding: 0 2rem 300 | // font-size: 1.6rem 301 | // height: 5rem 302 | // display: flex 303 | // align-items: center 304 | // justify-content: space-between 305 | // border-bottom: solid .1rem $white 306 | // font-weight: 500 307 | // .closeIcon 308 | // cursor: pointer 309 | // .settingSelectBlock 310 | // padding: 2.4rem 311 | // .title 312 | // font-weight: 700 313 | // font-size: 1.6rem 314 | // color: $placeholder_grey 315 | // .optionsBlock 316 | // display: flex 317 | // align-items: center 318 | // margin-top: 1rem 319 | // .optionBtn 320 | // display: flex 321 | // align-items: center 322 | // justify-content: center 323 | // width: 100% 324 | // background-color: $swap_card_bgc 325 | // color: $placeholder_grey 326 | // padding: 1rem 1.2rem 327 | // border: 0 328 | // border-radius: 4px 329 | // font-size: 1.4rem 330 | // font-weight: 600 331 | // cursor: pointer 332 | // flex: 1 333 | // margin-right: 1.5rem 334 | // .warning 335 | // margin: 1rem 336 | // color: $slippage_setting_warning_red 337 | // font-size: 1.4rem 338 | // .input 339 | // width: 100% 340 | // background-color: transparent 341 | // outline: none 342 | // text-align: center 343 | // .optionBtn.selectedSlippageRateBtn 344 | // background-color: $swap_btn_border_color 345 | // .inputBtn 346 | // border: solid .1rem $swap_btn_border_color 347 | // .splTokenContainer 348 | // padding: 3rem 2rem 3rem 3rem 349 | // margin-top: 5rem 350 | // border-radius: 0 1rem 1rem 0 351 | // height: 80% 352 | // overflow: scroll 353 | // background-color: $token_list_bgc 354 | // display: inline-block 355 | // .splTokenListTitle 356 | // font-size: 2.2rem 357 | // margin-bottom: 4rem 358 | // font-weight: 600 359 | // .splTokenItem 360 | // margin-top: 1rem 361 | // font-size: 1.5rem 362 | // .loading 363 | // font-size: 2rem 364 | // position: absolute 365 | // left: 50% 366 | // transform: translateX(-50%) 367 | // margin-top: 3rem 368 | 369 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true 17 | }, 18 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 19 | "exclude": ["node_modules"] 20 | } 21 | -------------------------------------------------------------------------------- /types.d.ts: -------------------------------------------------------------------------------- 1 | import { WalletContextState } from "@solana/wallet-adapter-react" 2 | import { Connection } from "@solana/web3.js" 3 | import { AlertStatus } from "@chakra-ui/react"; 4 | import { SetStateAction, Dispatch} from "react" 5 | 6 | declare global { 7 | 8 | // Common Components 9 | interface INotify { 10 | status: AlertStatus; 11 | title: string; 12 | description: string; 13 | link?: string; 14 | } 15 | 16 | type LoadingType = { 17 | msg: string, 18 | size?: "xl" | "xs" | "sm" | "md" | "lg", 19 | thickness?: number, // uint ex: 3 (in pixel) 20 | speed?: number, // floating point ex: 0.65s (in second) 21 | emptyColor?: string, // ex: gray.200 (see chakra doc) 22 | color?: string, // ex: blue.500 (see chakra doc) 23 | } 24 | 25 | // Raydium Components 26 | interface IUpdateAmountData { 27 | type: string; 28 | amount: number; 29 | } 30 | 31 | interface ITokenInfo { 32 | symbol: string; 33 | mintAddress: string; 34 | logoURI: string; 35 | } 36 | interface TokenData { 37 | amount: number | null; 38 | tokenInfo: ITokenInfo; 39 | } 40 | 41 | interface IUpdateAmountData { 42 | type: string; 43 | amount: number; 44 | } 45 | 46 | 47 | // SPL token 48 | 49 | interface SplTokenDisplayData { 50 | symbol: string; 51 | mint: string; 52 | pubkey: string; 53 | amount: number; 54 | } 55 | 56 | interface ISplToken { 57 | pubkey: string; 58 | parsedInfo: any; 59 | amount: number; 60 | } 61 | 62 | // Components props 63 | 64 | type LoadingProps = { 65 | data: LoadingType 66 | } 67 | 68 | interface NotifyProps { 69 | message: INotify; 70 | } 71 | 72 | interface ISplTokenProps { 73 | splTokenData: ISplToken[]; 74 | } 75 | 76 | interface TokenListProps { 77 | showTokenList: boolean; 78 | toggleTokenList: (type: "From" | "To" | undefined) => void; 79 | getTokenInfo: Function; 80 | } 81 | 82 | interface TokenSelectProps { 83 | type: string; 84 | toggleTokenList: Function; 85 | tokenData: TokenData; 86 | updateAmount: Function; 87 | wallet: Object; 88 | splTokenData: ISplToken[]; 89 | } 90 | 91 | interface dropDownTokenListBtnProps { 92 | tokenData: TokenData; 93 | } 94 | 95 | interface SwapOperateContainerProps { 96 | toggleTokenList: Function; 97 | fromData: TokenData; 98 | toData: TokenData; 99 | updateAmount: Function; 100 | switchFromAndTo: (event?: React.MouseEvent) => void; 101 | slippageValue: number; 102 | sendSwapTransaction: (event?: React.MouseEvent) => void; 103 | splTokenData: ISplToken[]; 104 | } 105 | 106 | interface SwapDetailProps { 107 | title: string; 108 | tooltipContent: string; 109 | value: string; 110 | } 111 | 112 | 113 | // Context Types 114 | 115 | type DappContextType = { 116 | splTokens: ISplToken[] | undefined, 117 | connection: Connection, 118 | setNotify: Dispatch>| null, 119 | setLoading: Dispatch>| null 120 | } 121 | } 122 | export {} -------------------------------------------------------------------------------- /utils/ids.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from '@solana/web3.js' 2 | 3 | export const SYSTEM_PROGRAM_ID = new PublicKey('11111111111111111111111111111111') 4 | export const TOKEN_PROGRAM_ID = new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA') 5 | export const MEMO_PROGRAM_ID = new PublicKey('Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo') 6 | export const RENT_PROGRAM_ID = new PublicKey('SysvarRent111111111111111111111111111111111') 7 | export const CLOCK_PROGRAM_ID = new PublicKey('SysvarC1ock11111111111111111111111111111111') 8 | export const ASSOCIATED_TOKEN_PROGRAM_ID = new PublicKey('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL') 9 | 10 | export const SERUM_PROGRAM_ID_V2 = 'EUqojwWA2rd19FZrzeBncJsm38Jm1hEhE3zsmX3bRc2o' 11 | export const SERUM_PROGRAM_ID_V3 = '9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin' 12 | 13 | export const LIQUIDITY_POOL_PROGRAM_ID_V2 = 'RVKd61ztZW9GUwhRbbLoYVRE5Xf1B2tVscKqwZqXgEr' 14 | export const LIQUIDITY_POOL_PROGRAM_ID_V3 = '27haf8L6oxUeXrHrgEgsexjSY5hbVUWEmvv9Nyxg8vQv' 15 | export const LIQUIDITY_POOL_PROGRAM_ID_V4 = '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8' 16 | 17 | export const STABLE_POOL_PROGRAM_ID = '5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h' 18 | 19 | export const ROUTE_SWAP_PROGRAM_ID = '93BgeoLHo5AdNbpqy9bD12dtfxtA5M2fh3rj72bE35Y3' 20 | 21 | export const STAKE_PROGRAM_ID = 'EhhTKczWMGQt46ynNeRX1WfeagwwJd7ufHvCDjRxjo5Q' 22 | export const STAKE_PROGRAM_ID_V4 = 'CBuCnLe26faBpcBP2fktp4rp8abpcAnTWft6ZrP5Q4T' 23 | export const STAKE_PROGRAM_ID_V5 = '9KEPoZmtHUrBbhWN1v1KWLMkkvwY6WLtAVUCPRtRjP4z' 24 | 25 | export const IDO_PROGRAM_ID = '6FJon3QE27qgPVggARueB22hLvoh22VzJpXv4rBEoSLF' 26 | export const IDO_PROGRAM_ID_V2 = 'CC12se5To1CdEuw7fDS27B7Geo5jJyL7t5UK2B44NgiH' 27 | export const IDO_PROGRAM_ID_V3 = '9HzJyW1qZsEiSfMUf6L2jo3CcTKAyBmSyKdwQeYisHrC' 28 | 29 | export const AUTHORITY_AMM = 'amm authority' 30 | export const AMM_ASSOCIATED_SEED = 'amm_associated_seed' 31 | export const TARGET_ASSOCIATED_SEED = 'target_associated_seed' 32 | export const WITHDRAW_ASSOCIATED_SEED = 'withdraw_associated_seed' 33 | export const OPEN_ORDER_ASSOCIATED_SEED = 'open_order_associated_seed' 34 | export const COIN_VAULT_ASSOCIATED_SEED = 'coin_vault_associated_seed' 35 | export const PC_VAULT_ASSOCIATED_SEED = 'pc_vault_associated_seed' 36 | export const LP_MINT_ASSOCIATED_SEED = 'lp_mint_associated_seed' 37 | export const TEMP_LP_TOKEN_ASSOCIATED_SEED = 'temp_lp_token_associated_seed' 38 | -------------------------------------------------------------------------------- /utils/layouts.ts: -------------------------------------------------------------------------------- 1 | import { bool, publicKey, struct, u32, u64, u8 } from '@project-serum/borsh' 2 | 3 | // https://github.com/solana-labs/solana-program-library/blob/master/token/js/client/token.js#L210 4 | export const ACCOUNT_LAYOUT = struct([ 5 | publicKey('mint'), 6 | publicKey('owner'), 7 | u64('amount'), 8 | u32('delegateOption'), 9 | publicKey('delegate'), 10 | u8('state'), 11 | u32('isNativeOption'), 12 | u64('isNative'), 13 | u64('delegatedAmount'), 14 | u32('closeAuthorityOption'), 15 | publicKey('closeAuthority') 16 | ]) 17 | 18 | export const MINT_LAYOUT = struct([ 19 | u32('mintAuthorityOption'), 20 | publicKey('mintAuthority'), 21 | u64('supply'), 22 | u8('decimals'), 23 | bool('initialized'), 24 | u32('freezeAuthorityOption'), 25 | publicKey('freezeAuthority') 26 | ]) 27 | 28 | export function getBigNumber(num: any) { 29 | return num === undefined || num === null ? 0 : parseFloat(num.toString()) 30 | } 31 | -------------------------------------------------------------------------------- /utils/liquidity.ts: -------------------------------------------------------------------------------- 1 | //@ts-ignore 2 | import { struct } from "buffer-layout"; 3 | import { publicKey, u128, u64 } from "@project-serum/borsh"; 4 | import { PublicKey } from "@solana/web3.js"; 5 | import { LP_TOKENS } from "./tokens"; 6 | import { commitment, getMultipleAccounts } from "./web3"; 7 | import { MINT_LAYOUT } from "./layouts"; 8 | 9 | export const AMM_INFO_LAYOUT = struct([ 10 | u64("status"), 11 | u64("nonce"), 12 | u64("orderNum"), 13 | u64("depth"), 14 | u64("coinDecimals"), 15 | u64("pcDecimals"), 16 | u64("state"), 17 | u64("resetFlag"), 18 | u64("fee"), 19 | u64("minSize"), 20 | u64("volMaxCutRatio"), 21 | u64("pnlRatio"), 22 | u64("amountWaveRatio"), 23 | u64("coinLotSize"), 24 | u64("pcLotSize"), 25 | u64("minPriceMultiplier"), 26 | u64("maxPriceMultiplier"), 27 | u64("needTakePnlCoin"), 28 | u64("needTakePnlPc"), 29 | u64("totalPnlX"), 30 | u64("totalPnlY"), 31 | u64("systemDecimalsValue"), 32 | publicKey("poolCoinTokenAccount"), 33 | publicKey("poolPcTokenAccount"), 34 | publicKey("coinMintAddress"), 35 | publicKey("pcMintAddress"), 36 | publicKey("lpMintAddress"), 37 | publicKey("ammOpenOrders"), 38 | publicKey("serumMarket"), 39 | publicKey("serumProgramId"), 40 | publicKey("ammTargetOrders"), 41 | publicKey("ammQuantities"), 42 | publicKey("poolWithdrawQueue"), 43 | publicKey("poolTempLpTokenAccount"), 44 | publicKey("ammOwner"), 45 | publicKey("pnlOwner") 46 | ]); 47 | 48 | export const AMM_INFO_LAYOUT_V3 = struct([ 49 | u64("status"), 50 | u64("nonce"), 51 | u64("orderNum"), 52 | u64("depth"), 53 | u64("coinDecimals"), 54 | u64("pcDecimals"), 55 | u64("state"), 56 | u64("resetFlag"), 57 | u64("fee"), 58 | u64("min_separate"), 59 | u64("minSize"), 60 | u64("volMaxCutRatio"), 61 | u64("pnlRatio"), 62 | u64("amountWaveRatio"), 63 | u64("coinLotSize"), 64 | u64("pcLotSize"), 65 | u64("minPriceMultiplier"), 66 | u64("maxPriceMultiplier"), 67 | u64("needTakePnlCoin"), 68 | u64("needTakePnlPc"), 69 | u64("totalPnlX"), 70 | u64("totalPnlY"), 71 | u64("poolTotalDepositPc"), 72 | u64("poolTotalDepositCoin"), 73 | u64("systemDecimalsValue"), 74 | publicKey("poolCoinTokenAccount"), 75 | publicKey("poolPcTokenAccount"), 76 | publicKey("coinMintAddress"), 77 | publicKey("pcMintAddress"), 78 | publicKey("lpMintAddress"), 79 | publicKey("ammOpenOrders"), 80 | publicKey("serumMarket"), 81 | publicKey("serumProgramId"), 82 | publicKey("ammTargetOrders"), 83 | publicKey("ammQuantities"), 84 | publicKey("poolWithdrawQueue"), 85 | publicKey("poolTempLpTokenAccount"), 86 | publicKey("ammOwner"), 87 | publicKey("pnlOwner"), 88 | publicKey("srmTokenAccount") 89 | ]); 90 | 91 | export const AMM_INFO_LAYOUT_V4 = struct([ 92 | u64("status"), 93 | u64("nonce"), 94 | u64("orderNum"), 95 | u64("depth"), 96 | u64("coinDecimals"), 97 | u64("pcDecimals"), 98 | u64("state"), 99 | u64("resetFlag"), 100 | u64("minSize"), 101 | u64("volMaxCutRatio"), 102 | u64("amountWaveRatio"), 103 | u64("coinLotSize"), 104 | u64("pcLotSize"), 105 | u64("minPriceMultiplier"), 106 | u64("maxPriceMultiplier"), 107 | u64("systemDecimalsValue"), 108 | // Fees 109 | u64("minSeparateNumerator"), 110 | u64("minSeparateDenominator"), 111 | u64("tradeFeeNumerator"), 112 | u64("tradeFeeDenominator"), 113 | u64("pnlNumerator"), 114 | u64("pnlDenominator"), 115 | u64("swapFeeNumerator"), 116 | u64("swapFeeDenominator"), 117 | // OutPutData 118 | u64("needTakePnlCoin"), 119 | u64("needTakePnlPc"), 120 | u64("totalPnlPc"), 121 | u64("totalPnlCoin"), 122 | 123 | u64("poolOpenTime"), 124 | u64("punishPcAmount"), 125 | u64("punishCoinAmount"), 126 | u64("orderbookToInitTime"), 127 | 128 | u128("swapCoinInAmount"), 129 | u128("swapPcOutAmount"), 130 | u64("swapCoin2PcFee"), 131 | u128("swapPcInAmount"), 132 | u128("swapCoinOutAmount"), 133 | u64("swapPc2CoinFee"), 134 | 135 | publicKey("poolCoinTokenAccount"), 136 | publicKey("poolPcTokenAccount"), 137 | publicKey("coinMintAddress"), 138 | publicKey("pcMintAddress"), 139 | publicKey("lpMintAddress"), 140 | publicKey("ammOpenOrders"), 141 | publicKey("serumMarket"), 142 | publicKey("serumProgramId"), 143 | publicKey("ammTargetOrders"), 144 | publicKey("poolWithdrawQueue"), 145 | publicKey("poolTempLpTokenAccount"), 146 | publicKey("ammOwner"), 147 | publicKey("pnlOwner") 148 | ]); 149 | 150 | export const AMM_INFO_LAYOUT_STABLE = struct([ 151 | u64("status"), 152 | publicKey("own_address"), 153 | u64("nonce"), 154 | u64("orderNum"), 155 | u64("depth"), 156 | u64("coinDecimals"), 157 | u64("pcDecimals"), 158 | u64("state"), 159 | u64("resetFlag"), 160 | u64("minSize"), 161 | u64("volMaxCutRatio"), 162 | u64("amountWaveRatio"), 163 | u64("coinLotSize"), 164 | u64("pcLotSize"), 165 | u64("minPriceMultiplier"), 166 | u64("maxPriceMultiplier"), 167 | u64("systemDecimalsValue"), 168 | 169 | u64("ammMaxPrice"), 170 | u64("ammMiddlePrice"), 171 | u64("ammPriceMultiplier"), 172 | 173 | // Fees 174 | u64("minSeparateNumerator"), 175 | u64("minSeparateDenominator"), 176 | u64("tradeFeeNumerator"), 177 | u64("tradeFeeDenominator"), 178 | u64("pnlNumerator"), 179 | u64("pnlDenominator"), 180 | u64("swapFeeNumerator"), 181 | u64("swapFeeDenominator"), 182 | // OutPutData 183 | u64("needTakePnlCoin"), 184 | u64("needTakePnlPc"), 185 | u64("totalPnlPc"), 186 | u64("totalPnlCoin"), 187 | u128("poolTotalDepositPc"), 188 | u128("poolTotalDepositCoin"), 189 | u128("swapCoinInAmount"), 190 | u128("swapPcOutAmount"), 191 | u128("swapPcInAmount"), 192 | u128("swapCoinOutAmount"), 193 | u64("swapPcFee"), 194 | u64("swapCoinFee"), 195 | 196 | publicKey("poolCoinTokenAccount"), 197 | publicKey("poolPcTokenAccount"), 198 | publicKey("coinMintAddress"), 199 | publicKey("pcMintAddress"), 200 | publicKey("lpMintAddress"), 201 | publicKey("ammOpenOrders"), 202 | publicKey("serumMarket"), 203 | publicKey("serumProgramId"), 204 | publicKey("ammTargetOrders"), 205 | publicKey("poolWithdrawQueue"), 206 | publicKey("poolTempLpTokenAccount"), 207 | publicKey("ammOwner"), 208 | publicKey("pnlOwner"), 209 | 210 | u128("currentK"), 211 | u128("padding1"), 212 | publicKey("padding2") 213 | ]); 214 | 215 | export async function getLpMintListDecimals( 216 | conn: any, 217 | mintAddressInfos: string[] 218 | ): Promise<{ [name: string]: number }> { 219 | const reLpInfoDict: { [name: string]: number } = {}; 220 | const mintList = [] as PublicKey[]; 221 | mintAddressInfos.forEach(item => { 222 | let lpInfo = Object.values(LP_TOKENS).find( 223 | itemLpToken => itemLpToken.mintAddress === item 224 | ); 225 | if (!lpInfo) { 226 | mintList.push(new PublicKey(item)); 227 | lpInfo = { 228 | decimals: null 229 | }; 230 | } 231 | reLpInfoDict[item] = lpInfo.decimals; 232 | }); 233 | const mintAll = await getMultipleAccounts(conn, mintList, commitment); 234 | for (let mintIndex = 0; mintIndex < mintAll.length; mintIndex += 1) { 235 | const itemMint = mintAll[mintIndex]; 236 | if (itemMint) { 237 | const mintLayoutData = MINT_LAYOUT.decode( 238 | Buffer.from(itemMint.account.data) 239 | ); 240 | reLpInfoDict[mintList[mintIndex].toString()] = mintLayoutData.decimals; 241 | } 242 | } 243 | const reInfo: { [name: string]: number } = {}; 244 | for (const key of Object.keys(reLpInfoDict)) { 245 | if (reLpInfoDict[key] !== null) { 246 | reInfo[key] = reLpInfoDict[key]; 247 | } 248 | } 249 | return reInfo; 250 | } 251 | -------------------------------------------------------------------------------- /utils/safe-math.ts: -------------------------------------------------------------------------------- 1 | import BigNumber from "bignumber.js"; 2 | 3 | // https://github.com/MikeMcl/bignumber.js 4 | // https://blog.csdn.net/shenxianhui1995/article/details/103985434 5 | export class TokenAmount { 6 | public wei: BigNumber; 7 | 8 | public decimals: number; 9 | public _decimals: BigNumber; 10 | 11 | constructor( 12 | wei: number | string | BigNumber, 13 | decimals: number = 0, 14 | isWei = true 15 | ) { 16 | this.decimals = decimals; 17 | this._decimals = new BigNumber(10).exponentiatedBy(decimals); 18 | 19 | if (isWei) { 20 | this.wei = new BigNumber(wei); 21 | } else { 22 | this.wei = new BigNumber(wei).multipliedBy(this._decimals); 23 | } 24 | } 25 | 26 | toWei() { 27 | return this.wei; 28 | } 29 | 30 | fixed() { 31 | return this.wei.dividedBy(this._decimals).toFixed(this.decimals); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /utils/swap.ts: -------------------------------------------------------------------------------- 1 | import { Buffer } from "buffer"; 2 | import { closeAccount } from "@project-serum/serum/lib/token-instructions"; 3 | import { OpenOrders } from "@project-serum/serum"; 4 | // import { _OPEN_ORDERS_LAYOUT_V2} from '@project-serum/serum/lib/market'; 5 | import { 6 | Connection, 7 | PublicKey, 8 | Transaction, 9 | TransactionInstruction, 10 | AccountInfo, 11 | Keypair 12 | } from "@solana/web3.js"; 13 | // @ts-ignore 14 | import { nu64, struct, u8 } from "buffer-layout"; 15 | 16 | // eslint-disable-next-line 17 | import { TokenAmount } from "./safe-math"; 18 | import { 19 | createAssociatedTokenAccountIfNotExist, 20 | createTokenAccountIfNotExist, 21 | sendTransaction, 22 | getMultipleAccounts, 23 | getFilteredProgramAccountsAmmOrMarketCache, 24 | createAmmAuthority 25 | } from "./web3"; 26 | import { TOKEN_PROGRAM_ID } from "./ids"; 27 | import { getBigNumber, ACCOUNT_LAYOUT, MINT_LAYOUT } from "./layouts"; 28 | 29 | // eslint-disable-next-line 30 | import { 31 | getTokenByMintAddress, 32 | NATIVE_SOL, 33 | TOKENS, 34 | // TokenInfo, 35 | LP_TOKENS 36 | } from "./tokens"; 37 | // import { getAddressForWhat, LIQUIDITY_POOLS, LiquidityPoolInfo } from "./pools"; 38 | import { getAddressForWhat, LIQUIDITY_POOLS} from "./pools"; 39 | import { 40 | AMM_INFO_LAYOUT, 41 | AMM_INFO_LAYOUT_STABLE, 42 | AMM_INFO_LAYOUT_V3, 43 | AMM_INFO_LAYOUT_V4, 44 | getLpMintListDecimals 45 | } from "./liquidity"; 46 | import { LIQUIDITY_POOL_PROGRAM_ID_V4, SERUM_PROGRAM_ID_V3 } from "./ids"; 47 | import { MARKET_STATE_LAYOUT_V2 } from "@project-serum/serum/lib/market"; 48 | 49 | export function swapInstruction( 50 | programId: PublicKey, 51 | // tokenProgramId: PublicKey, 52 | // amm 53 | ammId: PublicKey, 54 | ammAuthority: PublicKey, 55 | ammOpenOrders: PublicKey, 56 | ammTargetOrders: PublicKey, 57 | poolCoinTokenAccount: PublicKey, 58 | poolPcTokenAccount: PublicKey, 59 | // serum 60 | serumProgramId: PublicKey, 61 | serumMarket: PublicKey, 62 | serumBids: PublicKey, 63 | serumAsks: PublicKey, 64 | serumEventQueue: PublicKey, 65 | serumCoinVaultAccount: PublicKey, 66 | serumPcVaultAccount: PublicKey, 67 | serumVaultSigner: PublicKey, 68 | // user 69 | userSourceTokenAccount: PublicKey, 70 | userDestTokenAccount: PublicKey, 71 | userOwner: PublicKey, 72 | 73 | amountIn: number, 74 | minAmountOut: number 75 | ): TransactionInstruction { 76 | const dataLayout = struct([ 77 | u8("instruction"), 78 | nu64("amountIn"), 79 | nu64("minAmountOut") 80 | ]); 81 | 82 | const keys = [ 83 | // spl token 84 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 85 | // amm 86 | { pubkey: ammId, isSigner: false, isWritable: true }, 87 | { pubkey: ammAuthority, isSigner: false, isWritable: false }, 88 | { pubkey: ammOpenOrders, isSigner: false, isWritable: true }, 89 | { pubkey: ammTargetOrders, isSigner: false, isWritable: true }, 90 | { pubkey: poolCoinTokenAccount, isSigner: false, isWritable: true }, 91 | { pubkey: poolPcTokenAccount, isSigner: false, isWritable: true }, 92 | // serum 93 | { pubkey: serumProgramId, isSigner: false, isWritable: false }, 94 | { pubkey: serumMarket, isSigner: false, isWritable: true }, 95 | { pubkey: serumBids, isSigner: false, isWritable: true }, 96 | { pubkey: serumAsks, isSigner: false, isWritable: true }, 97 | { pubkey: serumEventQueue, isSigner: false, isWritable: true }, 98 | { pubkey: serumCoinVaultAccount, isSigner: false, isWritable: true }, 99 | { pubkey: serumPcVaultAccount, isSigner: false, isWritable: true }, 100 | { pubkey: serumVaultSigner, isSigner: false, isWritable: false }, 101 | { pubkey: userSourceTokenAccount, isSigner: false, isWritable: true }, 102 | { pubkey: userDestTokenAccount, isSigner: false, isWritable: true }, 103 | { pubkey: userOwner, isSigner: true, isWritable: false } 104 | ]; 105 | 106 | const data = Buffer.alloc(dataLayout.span); 107 | dataLayout.encode( 108 | { 109 | instruction: 9, 110 | amountIn, 111 | minAmountOut 112 | }, 113 | data 114 | ); 115 | 116 | return new TransactionInstruction({ 117 | keys, 118 | programId, 119 | data 120 | }); 121 | } 122 | 123 | export async function swap( 124 | connection: Connection, 125 | wallet: any, 126 | poolInfo: any, 127 | fromCoinMint: string, 128 | toCoinMint: string, 129 | fromTokenAccount: string, 130 | toTokenAccount: string, 131 | aIn: string, 132 | aOut: string, 133 | wsolAddress: string 134 | ) { 135 | const transaction = new Transaction(); 136 | const signers: Keypair[] = []; 137 | 138 | const owner = wallet.publicKey; 139 | 140 | const from = getTokenByMintAddress(fromCoinMint); 141 | const to = getTokenByMintAddress(toCoinMint); 142 | if (!from || !to) { 143 | throw new Error("Miss token info"); 144 | } 145 | 146 | const amountIn = new TokenAmount(aIn, from.decimals, false); 147 | const amountOut = new TokenAmount(aOut, to.decimals, false); 148 | 149 | if (fromCoinMint === NATIVE_SOL.mintAddress && wsolAddress) { 150 | transaction.add( 151 | closeAccount({ 152 | source: new PublicKey(wsolAddress), 153 | destination: owner, 154 | owner 155 | }) 156 | ); 157 | } 158 | 159 | let fromMint = fromCoinMint; 160 | let toMint = toCoinMint; 161 | 162 | if (fromMint === NATIVE_SOL.mintAddress) { 163 | fromMint = TOKENS.WSOL.mintAddress; 164 | } 165 | if (toMint === NATIVE_SOL.mintAddress) { 166 | toMint = TOKENS.WSOL.mintAddress; 167 | } 168 | 169 | let wrappedSolAccount: PublicKey | null = null; 170 | let wrappedSolAccount2: PublicKey | null = null; 171 | let newFromTokenAccount = PublicKey.default; 172 | let newToTokenAccount = PublicKey.default; 173 | 174 | if (fromCoinMint === NATIVE_SOL.mintAddress) { 175 | wrappedSolAccount = await createTokenAccountIfNotExist( 176 | connection, 177 | wrappedSolAccount, 178 | owner, 179 | TOKENS.WSOL.mintAddress, 180 | getBigNumber(amountIn.wei) + 1e7, 181 | transaction, 182 | signers 183 | ); 184 | } else { 185 | newFromTokenAccount = await createAssociatedTokenAccountIfNotExist( 186 | fromTokenAccount, 187 | owner, 188 | fromMint, 189 | transaction 190 | ); 191 | } 192 | 193 | if (toCoinMint === NATIVE_SOL.mintAddress) { 194 | wrappedSolAccount2 = await createTokenAccountIfNotExist( 195 | connection, 196 | wrappedSolAccount2, 197 | owner, 198 | TOKENS.WSOL.mintAddress, 199 | 1e7, 200 | transaction, 201 | signers 202 | ); 203 | } else { 204 | newToTokenAccount = await createAssociatedTokenAccountIfNotExist( 205 | toTokenAccount, 206 | owner, 207 | toMint, 208 | transaction 209 | ); 210 | } 211 | 212 | transaction.add( 213 | swapInstruction( 214 | new PublicKey(poolInfo.programId), 215 | new PublicKey(poolInfo.ammId), 216 | new PublicKey(poolInfo.ammAuthority), 217 | new PublicKey(poolInfo.ammOpenOrders), 218 | new PublicKey(poolInfo.ammTargetOrders), 219 | new PublicKey(poolInfo.poolCoinTokenAccount), 220 | new PublicKey(poolInfo.poolPcTokenAccount), 221 | new PublicKey(poolInfo.serumProgramId), 222 | new PublicKey(poolInfo.serumMarket), 223 | new PublicKey(poolInfo.serumBids), 224 | new PublicKey(poolInfo.serumAsks), 225 | new PublicKey(poolInfo.serumEventQueue), 226 | new PublicKey(poolInfo.serumCoinVaultAccount), 227 | new PublicKey(poolInfo.serumPcVaultAccount), 228 | new PublicKey(poolInfo.serumVaultSigner), 229 | wrappedSolAccount ?? newFromTokenAccount, 230 | wrappedSolAccount2 ?? newToTokenAccount, 231 | owner, 232 | Math.floor(getBigNumber(amountIn.toWei())), 233 | Math.floor(getBigNumber(amountOut.toWei())) 234 | ) 235 | ); 236 | 237 | if (wrappedSolAccount) { 238 | transaction.add( 239 | closeAccount({ 240 | source: wrappedSolAccount, 241 | destination: owner, 242 | owner 243 | }) 244 | ); 245 | } 246 | if (wrappedSolAccount2) { 247 | transaction.add( 248 | closeAccount({ 249 | source: wrappedSolAccount2, 250 | destination: owner, 251 | owner 252 | }) 253 | ); 254 | } 255 | 256 | return await sendTransaction(connection, wallet, transaction, signers); 257 | } 258 | 259 | export function getSwapOutAmount( 260 | poolInfo: any, 261 | fromCoinMint: string, 262 | toCoinMint: string, 263 | amount: string, 264 | slippage: number 265 | ) { 266 | const { coin, pc, fees } = poolInfo; 267 | const { swapFeeNumerator, swapFeeDenominator } = fees; 268 | 269 | if (fromCoinMint === TOKENS.WSOL.mintAddress) 270 | fromCoinMint = NATIVE_SOL.mintAddress; 271 | if (toCoinMint === TOKENS.WSOL.mintAddress) 272 | toCoinMint = NATIVE_SOL.mintAddress; 273 | 274 | if (fromCoinMint === coin.mintAddress && toCoinMint === pc.mintAddress) { 275 | // coin2pc 276 | const fromAmount = new TokenAmount(amount, coin.decimals, false); 277 | const fromAmountWithFee = fromAmount.wei 278 | .multipliedBy(swapFeeDenominator - swapFeeNumerator) 279 | .dividedBy(swapFeeDenominator); 280 | const denominator = coin.balance.wei.plus(fromAmountWithFee); 281 | const amountOut = pc.balance.wei 282 | .multipliedBy(fromAmountWithFee) 283 | .dividedBy(denominator); 284 | const amountOutWithSlippage = amountOut.dividedBy(1 + slippage / 100); 285 | 286 | const outBalance = pc.balance.wei.minus(amountOut); 287 | const beforePrice = new TokenAmount( 288 | parseFloat(new TokenAmount(pc.balance.wei, pc.decimals).fixed()) / 289 | parseFloat(new TokenAmount(coin.balance.wei, coin.decimals).fixed()), 290 | pc.decimals, 291 | false 292 | ); 293 | const afterPrice = new TokenAmount( 294 | parseFloat(new TokenAmount(outBalance, pc.decimals).fixed()) / 295 | parseFloat(new TokenAmount(denominator, coin.decimals).fixed()), 296 | pc.decimals, 297 | false 298 | ); 299 | const priceImpact = 300 | Math.abs( 301 | (parseFloat(beforePrice.fixed()) - parseFloat(afterPrice.fixed())) / 302 | parseFloat(beforePrice.fixed()) 303 | ) * 100; 304 | 305 | return { 306 | amountIn: fromAmount, 307 | amountOut: new TokenAmount(amountOut, pc.decimals), 308 | amountOutWithSlippage: new TokenAmount( 309 | amountOutWithSlippage, 310 | pc.decimals 311 | ), 312 | priceImpact 313 | }; 314 | } else { 315 | // pc2coin 316 | const fromAmount = new TokenAmount(amount, pc.decimals, false); 317 | const fromAmountWithFee = fromAmount.wei 318 | .multipliedBy(swapFeeDenominator - swapFeeNumerator) 319 | .dividedBy(swapFeeDenominator); 320 | 321 | const denominator = pc.balance.wei.plus(fromAmountWithFee); 322 | const amountOut = coin.balance.wei 323 | .multipliedBy(fromAmountWithFee) 324 | .dividedBy(denominator); 325 | const amountOutWithSlippage = amountOut.dividedBy(1 + slippage / 100); 326 | 327 | const outBalance = coin.balance.wei.minus(amountOut); 328 | 329 | const beforePrice = new TokenAmount( 330 | parseFloat(new TokenAmount(pc.balance.wei, pc.decimals).fixed()) / 331 | parseFloat(new TokenAmount(coin.balance.wei, coin.decimals).fixed()), 332 | pc.decimals, 333 | false 334 | ); 335 | const afterPrice = new TokenAmount( 336 | parseFloat(new TokenAmount(denominator, pc.decimals).fixed()) / 337 | parseFloat(new TokenAmount(outBalance, coin.decimals).fixed()), 338 | pc.decimals, 339 | false 340 | ); 341 | const priceImpact = 342 | Math.abs( 343 | (parseFloat(afterPrice.fixed()) - parseFloat(beforePrice.fixed())) / 344 | parseFloat(beforePrice.fixed()) 345 | ) * 100; 346 | return { 347 | amountIn: fromAmount, 348 | amountOut: new TokenAmount(amountOut, coin.decimals), 349 | amountOutWithSlippage: new TokenAmount( 350 | amountOutWithSlippage, 351 | coin.decimals 352 | ), 353 | priceImpact 354 | }; 355 | } 356 | } 357 | 358 | export async function setupPools(conn: Connection) { 359 | let ammAll: { 360 | publicKey: PublicKey; 361 | accountInfo: AccountInfo; 362 | }[] = []; 363 | let marketAll: { 364 | publicKey: PublicKey; 365 | accountInfo: AccountInfo; 366 | }[] = []; 367 | 368 | await Promise.all([ 369 | await (async () => { 370 | ammAll = await getFilteredProgramAccountsAmmOrMarketCache( 371 | "amm", 372 | conn, 373 | new PublicKey(LIQUIDITY_POOL_PROGRAM_ID_V4), 374 | [ 375 | { 376 | dataSize: AMM_INFO_LAYOUT_V4.span 377 | } 378 | ] 379 | ); 380 | })(), 381 | await (async () => { 382 | marketAll = await getFilteredProgramAccountsAmmOrMarketCache( 383 | "market", 384 | conn, 385 | new PublicKey(SERUM_PROGRAM_ID_V3), 386 | [ 387 | { 388 | dataSize: MARKET_STATE_LAYOUT_V2.span 389 | } 390 | ] 391 | ); 392 | })() 393 | ]); 394 | const marketToLayout: { [name: string]: any } = {}; 395 | marketAll.forEach(item => { 396 | marketToLayout[item.publicKey.toString()] = MARKET_STATE_LAYOUT_V2.decode( 397 | item.accountInfo.data 398 | ); 399 | }); 400 | const lpMintAddressList: string[] = []; 401 | ammAll.forEach(item => { 402 | const ammLayout = AMM_INFO_LAYOUT_V4.decode( 403 | Buffer.from(item.accountInfo.data) 404 | ); 405 | console.log("\n",ammLayout.serumMarket.toString()) // Serum Dex Program v3 406 | console.log(ammLayout.coinMintAddress.toString()) // coin Mint Address 407 | console.log(ammLayout.pcMintAddress.toString()) // Pair Coin Mint Address 408 | console.log(ammLayout.lpMintAddress.toString(), "\n") // LP Coin Mint Address 409 | 410 | if ( 411 | ammLayout.pcMintAddress.toString() === ammLayout.serumMarket.toString() || /** How could the pair coin mint be = serum dex program?? */ 412 | ammLayout.lpMintAddress.toString() === "11111111111111111111111111111111" /** How could the lp coin mint be = system program?? */ 413 | ) { 414 | return; 415 | } 416 | lpMintAddressList.push(ammLayout.lpMintAddress.toString()); 417 | }); 418 | const lpMintListDecimls = await getLpMintListDecimals( 419 | conn, 420 | lpMintAddressList 421 | ); 422 | const tokenMintData: { [mintAddress: string]: TokenInfo } = {}; 423 | for (const itemToken of Object.values(TOKENS)) { 424 | tokenMintData[itemToken.mintAddress] = itemToken; 425 | } 426 | /**@TODO combine with prev ammAll.forEach section */ 427 | for (let indexAmmInfo = 0; indexAmmInfo < ammAll.length; indexAmmInfo += 1) { 428 | const ammInfo = AMM_INFO_LAYOUT_V4.decode( 429 | Buffer.from(ammAll[indexAmmInfo].accountInfo.data) 430 | ); 431 | if ( 432 | !Object.keys(lpMintListDecimls).includes( 433 | ammInfo.lpMintAddress.toString() 434 | ) || 435 | ammInfo.pcMintAddress.toString() === ammInfo.serumMarket.toString() || 436 | ammInfo.lpMintAddress.toString() === "11111111111111111111111111111111" || 437 | !Object.keys(marketToLayout).includes(ammInfo.serumMarket.toString()) 438 | ) { 439 | continue; 440 | } 441 | const fromCoin = 442 | ammInfo.coinMintAddress.toString() === TOKENS.WSOL.mintAddress 443 | ? NATIVE_SOL.mintAddress 444 | : ammInfo.coinMintAddress.toString(); 445 | const toCoin = 446 | ammInfo.pcMintAddress.toString() === TOKENS.WSOL.mintAddress 447 | ? NATIVE_SOL.mintAddress 448 | : ammInfo.pcMintAddress.toString(); 449 | let coin = tokenMintData[fromCoin]; 450 | if (!coin && fromCoin !== NATIVE_SOL.mintAddress) { 451 | TOKENS[`unknow-${ammInfo.coinMintAddress.toString()}`] = { 452 | symbol: "unknown", 453 | name: "unknown", 454 | mintAddress: ammInfo.coinMintAddress.toString(), 455 | decimals: getBigNumber(ammInfo.coinDecimals), 456 | cache: true, 457 | tags: [] 458 | }; 459 | coin = TOKENS[`unknow-${ammInfo.coinMintAddress.toString()}`]; 460 | tokenMintData[ammInfo.coinMintAddress.toString()] = coin; 461 | } else if (fromCoin === NATIVE_SOL.mintAddress) { 462 | coin = NATIVE_SOL; 463 | } 464 | if (!coin.tags.includes("unofficial")) { 465 | coin.tags.push("unofficial"); 466 | } 467 | 468 | let pc = tokenMintData[toCoin]; 469 | if (!pc && toCoin !== NATIVE_SOL.mintAddress) { 470 | TOKENS[`unknow-${ammInfo.pcMintAddress.toString()}`] = { 471 | symbol: "unknown", 472 | name: "unknown", 473 | mintAddress: ammInfo.pcMintAddress.toString(), 474 | decimals: getBigNumber(ammInfo.pcDecimals), 475 | cache: true, 476 | tags: [] 477 | }; 478 | pc = TOKENS[`unknow-${ammInfo.pcMintAddress.toString()}`]; 479 | tokenMintData[ammInfo.pcMintAddress.toString()] = pc; 480 | } else if (toCoin === NATIVE_SOL.mintAddress) { 481 | pc = NATIVE_SOL; 482 | } 483 | if (!pc.tags.includes("unofficial")) { 484 | pc.tags.push("unofficial"); 485 | } 486 | 487 | if (coin.mintAddress === TOKENS.WSOL.mintAddress) { 488 | coin.symbol = "SOL"; 489 | coin.name = "SOL"; 490 | coin.mintAddress = "11111111111111111111111111111111"; 491 | } 492 | if (pc.mintAddress === TOKENS.WSOL.mintAddress) { 493 | pc.symbol = "SOL"; 494 | pc.name = "SOL"; 495 | pc.mintAddress = "11111111111111111111111111111111"; 496 | } 497 | const lp = Object.values(LP_TOKENS).find( 498 | item => item.mintAddress === ammInfo.lpMintAddress 499 | ) ?? { 500 | symbol: `${coin.symbol}-${pc.symbol}`, 501 | name: `${coin.symbol}-${pc.symbol}`, 502 | coin, 503 | pc, 504 | mintAddress: ammInfo.lpMintAddress.toString(), 505 | decimals: lpMintListDecimls[ammInfo.lpMintAddress] 506 | }; 507 | 508 | const { publicKey } = await createAmmAuthority( 509 | new PublicKey(LIQUIDITY_POOL_PROGRAM_ID_V4) 510 | ); 511 | 512 | const market = marketToLayout[ammInfo.serumMarket]; 513 | 514 | const serumVaultSigner = await PublicKey.createProgramAddress( 515 | [ 516 | ammInfo.serumMarket.toBuffer(), 517 | market.vaultSignerNonce.toArrayLike(Buffer, "le", 8) 518 | ], 519 | new PublicKey(SERUM_PROGRAM_ID_V3) 520 | ); 521 | 522 | const itemLiquidity: LiquidityPoolInfo = { 523 | name: `${coin.symbol}-${pc.symbol}`, 524 | coin, 525 | pc, 526 | lp, 527 | version: 4, 528 | programId: LIQUIDITY_POOL_PROGRAM_ID_V4, 529 | ammId: ammAll[indexAmmInfo].publicKey.toString(), 530 | ammAuthority: publicKey.toString(), 531 | ammOpenOrders: ammInfo.ammOpenOrders.toString(), 532 | ammTargetOrders: ammInfo.ammTargetOrders.toString(), 533 | ammQuantities: NATIVE_SOL.mintAddress, 534 | poolCoinTokenAccount: ammInfo.poolCoinTokenAccount.toString(), 535 | poolPcTokenAccount: ammInfo.poolPcTokenAccount.toString(), 536 | poolWithdrawQueue: ammInfo.poolWithdrawQueue.toString(), 537 | poolTempLpTokenAccount: ammInfo.poolTempLpTokenAccount.toString(), 538 | serumProgramId: SERUM_PROGRAM_ID_V3, 539 | serumMarket: ammInfo.serumMarket.toString(), 540 | serumBids: market.bids.toString(), 541 | serumAsks: market.asks.toString(), 542 | serumEventQueue: market.eventQueue.toString(), 543 | serumCoinVaultAccount: market.baseVault.toString(), 544 | serumPcVaultAccount: market.quoteVault.toString(), 545 | serumVaultSigner: serumVaultSigner.toString(), 546 | official: false 547 | }; 548 | if (!LIQUIDITY_POOLS.find(item => item.ammId === itemLiquidity.ammId)) { 549 | LIQUIDITY_POOLS.push(itemLiquidity); 550 | } else { 551 | for ( 552 | let itemIndex = 0; 553 | itemIndex < LIQUIDITY_POOLS.length; 554 | itemIndex += 1 555 | ) { 556 | if ( 557 | LIQUIDITY_POOLS[itemIndex].ammId === itemLiquidity.ammId && 558 | LIQUIDITY_POOLS[itemIndex].name !== itemLiquidity.name && 559 | !LIQUIDITY_POOLS[itemIndex].official 560 | ) { 561 | LIQUIDITY_POOLS[itemIndex] = itemLiquidity; 562 | } 563 | } 564 | } 565 | } 566 | 567 | const liquidityPools = {} as any; 568 | const publicKeys = [] as any; 569 | 570 | LIQUIDITY_POOLS.forEach(pool => { 571 | const { 572 | poolCoinTokenAccount, 573 | poolPcTokenAccount, 574 | ammOpenOrders, 575 | ammId, 576 | coin, 577 | pc, 578 | lp 579 | } = pool; 580 | 581 | publicKeys.push( 582 | new PublicKey(poolCoinTokenAccount), 583 | new PublicKey(poolPcTokenAccount), 584 | new PublicKey(ammOpenOrders), 585 | new PublicKey(ammId), 586 | new PublicKey(lp.mintAddress) 587 | ); 588 | 589 | const poolInfo = JSON.parse(JSON.stringify(pool)); 590 | poolInfo.coin.balance = new TokenAmount(0, coin.decimals); 591 | poolInfo.pc.balance = new TokenAmount(0, pc.decimals); 592 | 593 | liquidityPools[lp.mintAddress] = poolInfo; 594 | }); 595 | 596 | const multipleInfo = await getMultipleAccounts(conn, publicKeys, "confirmed"); 597 | multipleInfo.forEach(info => { 598 | if (info) { 599 | const address = info.publicKey.toBase58(); 600 | const data = Buffer.from(info.account.data); 601 | 602 | const { key, lpMintAddress, version } = getAddressForWhat(address); 603 | 604 | if (key && lpMintAddress) { 605 | const poolInfo = liquidityPools[lpMintAddress]; 606 | 607 | switch (key) { 608 | case "poolCoinTokenAccount": { 609 | const parsed = ACCOUNT_LAYOUT.decode(data); 610 | // quick fix: Number can only safely store up to 53 bits 611 | poolInfo.coin.balance.wei = poolInfo.coin.balance.wei.plus( 612 | getBigNumber(parsed.amount) 613 | ); 614 | 615 | break; 616 | } 617 | case "poolPcTokenAccount": { 618 | const parsed = ACCOUNT_LAYOUT.decode(data); 619 | 620 | poolInfo.pc.balance.wei = poolInfo.pc.balance.wei.plus( 621 | getBigNumber(parsed.amount) 622 | ); 623 | 624 | break; 625 | } 626 | case "ammOpenOrders": { 627 | const OPEN_ORDERS_LAYOUT = OpenOrders.getLayout( 628 | new PublicKey(poolInfo.serumProgramId) 629 | ); 630 | const parsed = OPEN_ORDERS_LAYOUT.decode(data); 631 | 632 | const { baseTokenTotal, quoteTokenTotal } = parsed; 633 | poolInfo.coin.balance.wei = poolInfo.coin.balance.wei.plus( 634 | getBigNumber(baseTokenTotal) 635 | ); 636 | poolInfo.pc.balance.wei = poolInfo.pc.balance.wei.plus( 637 | getBigNumber(quoteTokenTotal) 638 | ); 639 | 640 | break; 641 | } 642 | case "ammId": { 643 | let parsed; 644 | if (version === 2) { 645 | parsed = AMM_INFO_LAYOUT.decode(data); 646 | } else if (version === 3) { 647 | parsed = AMM_INFO_LAYOUT_V3.decode(data); 648 | } else { 649 | if (version === 5) { 650 | parsed = AMM_INFO_LAYOUT_STABLE.decode(data); 651 | poolInfo.currentK = getBigNumber(parsed.currentK); 652 | } else { 653 | parsed = AMM_INFO_LAYOUT_V4.decode(data); 654 | if (getBigNumber(parsed.status) === 7) { 655 | poolInfo.poolOpenTime = getBigNumber(parsed.poolOpenTime); 656 | } 657 | } 658 | 659 | const { swapFeeNumerator, swapFeeDenominator } = parsed; 660 | poolInfo.fees = { 661 | swapFeeNumerator: getBigNumber(swapFeeNumerator), 662 | swapFeeDenominator: getBigNumber(swapFeeDenominator) 663 | }; 664 | } 665 | 666 | const { status, needTakePnlCoin, needTakePnlPc } = parsed; 667 | poolInfo.status = getBigNumber(status); 668 | poolInfo.coin.balance.wei = poolInfo.coin.balance.wei.minus( 669 | getBigNumber(needTakePnlCoin) 670 | ); 671 | poolInfo.pc.balance.wei = poolInfo.pc.balance.wei.minus( 672 | getBigNumber(needTakePnlPc) 673 | ); 674 | 675 | break; 676 | } 677 | // getLpSupply 678 | case "lpMintAddress": { 679 | const parsed = MINT_LAYOUT.decode(data); 680 | 681 | poolInfo.lp.totalSupply = new TokenAmount( 682 | getBigNumber(parsed.supply), 683 | poolInfo.lp.decimals 684 | ); 685 | 686 | break; 687 | } 688 | } 689 | } 690 | } 691 | }); 692 | return liquidityPools; 693 | } 694 | -------------------------------------------------------------------------------- /utils/tokenList.ts: -------------------------------------------------------------------------------- 1 | import { TokenListProvider } from "@solana/spl-token-registry"; 2 | 3 | const SPLTokenRegistrySource = async () => { 4 | let tokens = await new TokenListProvider().resolve() 5 | let tokenList = tokens.filterByClusterSlug("mainnet-beta").getList() 6 | return tokenList.sort((a: any, b: any) => 7 | a.symbol < b.symbol ? -1 : a.symbol > b.symbol ? 1 : 0 8 | ) 9 | }; 10 | 11 | export default SPLTokenRegistrySource; 12 | -------------------------------------------------------------------------------- /utils/tokens.ts: -------------------------------------------------------------------------------- 1 | import { cloneDeep } from 'lodash-es'; 2 | 3 | /** 4 | * Get token use symbol 5 | 6 | * @param {string} symbol 7 | 8 | * @returns {TokenInfo | null} tokenInfo 9 | */ 10 | 11 | export function getTokenBySymbol(symbol: string): TokenInfo | null { 12 | if (symbol === 'SOL') { 13 | return cloneDeep(NATIVE_SOL) 14 | } 15 | 16 | let token = cloneDeep(TOKENS[symbol]) 17 | 18 | if (!token) { 19 | token = null 20 | } 21 | 22 | return token 23 | } 24 | 25 | /** 26 | * Get token use mint addresses 27 | 28 | * @param {string} mintAddress 29 | 30 | * @returns {TokenInfo | null} tokenInfo 31 | */ 32 | export function getTokenByMintAddress(mintAddress: string): TokenInfo | null { 33 | if (mintAddress === NATIVE_SOL.mintAddress) { 34 | return cloneDeep(NATIVE_SOL) 35 | } 36 | const token = Object.values(TOKENS).find((item) => item.mintAddress === mintAddress) 37 | return token ? cloneDeep(token) : null 38 | } 39 | 40 | export function getTokenSymbolByMint(mint: string) { 41 | if (mint === NATIVE_SOL.mintAddress) { 42 | return NATIVE_SOL.symbol 43 | } 44 | 45 | const token = Object.values({ ...TOKENS, ...LP_TOKENS }).find((item) => item.mintAddress === mint) 46 | 47 | if (token) { 48 | return token.symbol 49 | } 50 | return 'UNKNOWN' 51 | } 52 | 53 | export interface Tokens { 54 | [key: string]: any 55 | [index: number]: any 56 | } 57 | 58 | export const TOKENS_TAGS: { [key: string]: { mustShow: boolean; show: boolean; outName: string } } = { 59 | raydium: { mustShow: true, show: true, outName: 'Raydium Default List' }, 60 | userAdd: { mustShow: true, show: true, outName: 'User Added Tokens' }, 61 | solana: { mustShow: false, show: false, outName: 'Solana Token List' }, 62 | unofficial: { mustShow: false, show: false, outName: 'Permissionless Pool Tokens' } 63 | } 64 | 65 | export const NATIVE_SOL: TokenInfo = { 66 | symbol: 'SOL', 67 | name: 'Native Solana', 68 | mintAddress: '11111111111111111111111111111111', 69 | decimals: 9, 70 | tags: ['raydium'] 71 | } 72 | 73 | export const TOKENS: Tokens = { 74 | SOL: { 75 | symbol: 'SOL', 76 | name: 'Native Solana', 77 | mintAddress: '11111111111111111111111111111111', 78 | address: '11111111111111111111111111111111', 79 | decimals: 9, 80 | tags: ['raydium'] 81 | }, 82 | WSOL: { 83 | symbol: 'WSOL', 84 | name: 'Wrapped Solana', 85 | mintAddress: 'So11111111111111111111111111111111111111112', 86 | decimals: 9, 87 | referrer: 'HTcarLHe7WRxBQCWvhVB8AP56pnEtJUV2jDGvcpY3xo5', 88 | tags: ['raydium'] 89 | }, 90 | BTC: { 91 | symbol: 'BTC', 92 | name: 'Wrapped Bitcoin', 93 | mintAddress: '9n4nbM75f5Ui33ZbPYXn59EwSgE8CGsHtAeTH5YFeJ9E', 94 | decimals: 6, 95 | referrer: 'GZpS8cY8Nt8HuqxzJh6PXTdSxc38vFUjBmi7eEUkkQtG', 96 | tags: ['raydium'] 97 | }, 98 | ETH: { 99 | symbol: 'ETH', 100 | name: 'Wrapped Ethereum', 101 | mintAddress: '2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk', 102 | decimals: 6, 103 | referrer: 'CXPTcSxxh4AT38gtv3SPbLS7oZVgXzLbMb83o4ziXjjN', 104 | tags: ['raydium'] 105 | }, 106 | USDT: { 107 | symbol: 'USDT', 108 | name: 'USDT', 109 | mintAddress: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', 110 | decimals: 6, 111 | referrer: '8DwwDNagph8SdwMUdcXS5L9YAyutTyDJmK6cTKrmNFk3', 112 | tags: ['raydium'] 113 | }, 114 | WUSDT: { 115 | symbol: 'WUSDT', 116 | name: 'Wrapped USDT', 117 | mintAddress: 'BQcdHdAQW1hczDbBi9hiegXAR7A98Q9jx3X3iBBBDiq4', 118 | decimals: 6, 119 | referrer: 'CA98hYunCLKgBuD6N8MJSgq1GbW9CXdksLf5mw736tS3', 120 | tags: ['raydium'] 121 | }, 122 | USDC: { 123 | symbol: 'USDC', 124 | name: 'USDC', 125 | mintAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', 126 | decimals: 6, 127 | referrer: '92vdtNjEg6Zth3UU1MgPgTVFjSEzTHx66aCdqWdcRkrg', 128 | tags: ['raydium'] 129 | }, 130 | WUSDC: { 131 | symbol: 'WUSDC', 132 | name: 'Wrapped USDC', 133 | mintAddress: 'BXXkv6z8ykpG1yuvUDPgh732wzVHB69RnB9YgSYh3itW', 134 | decimals: 6, 135 | tags: ['raydium'] 136 | }, 137 | YFI: { 138 | symbol: 'YFI', 139 | name: 'Wrapped YFI', 140 | mintAddress: '3JSf5tPeuscJGtaCp5giEiDhv51gQ4v3zWg8DGgyLfAB', 141 | decimals: 6, 142 | referrer: 'DZjgzKfYzZBBSTo5vytMYvGdNF933DvuX8TftDMrThrb', 143 | tags: ['raydium'] 144 | }, 145 | LINK: { 146 | symbol: 'LINK', 147 | name: 'Wrapped Chainlink', 148 | mintAddress: 'CWE8jPTUYhdCTZYWPTe1o5DFqfdjzWKc9WKz6rSjQUdG', 149 | decimals: 6, 150 | referrer: 'DRSKKsYZaPEFkRgGywo7KWBGZikf71R9aDr8tjtpr41V', 151 | tags: ['raydium'] 152 | }, 153 | XRP: { 154 | symbol: 'XRP', 155 | name: 'Wrapped XRP', 156 | mintAddress: 'Ga2AXHpfAF6mv2ekZwcsJFqu7wB4NV331qNH7fW9Nst8', 157 | decimals: 6, 158 | referrer: '6NeHPXG142tAE2Ej3gHgT2N66i1KH6PFR6PBZw6RyrwH', 159 | tags: ['raydium'] 160 | }, 161 | SUSHI: { 162 | symbol: 'SUSHI', 163 | name: 'Wrapped SUSHI', 164 | mintAddress: 'AR1Mtgh7zAtxuxGd2XPovXPVjcSdY3i4rQYisNadjfKy', 165 | decimals: 6, 166 | referrer: '59QxHeHgb28tDc3gStnrW8FNKC9qWuRmRZHBaAqCerJX', 167 | tags: ['raydium'] 168 | }, 169 | ALEPH: { 170 | symbol: 'ALEPH', 171 | name: 'Wrapped ALEPH', 172 | mintAddress: 'CsZ5LZkDS7h9TDKjrbL7VAwQZ9nsRu8vJLhRYfmGaN8K', 173 | decimals: 6, 174 | referrer: '8FKAKrenJMDd7V6cxnM5BsymHTjqxgodtHbLwZReMnWW', 175 | tags: ['raydium'] 176 | }, 177 | SXP: { 178 | symbol: 'SXP', 179 | name: 'Wrapped SXP', 180 | mintAddress: 'SF3oTvfWzEP3DTwGSvUXRrGTvr75pdZNnBLAH9bzMuX', 181 | decimals: 6, 182 | referrer: '97Vyotr284UM2Fyq9gbfQ3azMYtgf7cjnsf8pN1PFfY9', 183 | tags: ['raydium'] 184 | }, 185 | HGET: { 186 | symbol: 'HGET', 187 | name: 'Wrapped HGET', 188 | mintAddress: 'BtZQfWqDGbk9Wf2rXEiWyQBdBY1etnUUn6zEphvVS7yN', 189 | decimals: 6, 190 | referrer: 'AGY2wy1ANzLM2jJLSkVxPUYAY5iAYXYsLMQkoQsAhucj', 191 | tags: ['raydium'] 192 | }, 193 | CREAM: { 194 | symbol: 'CREAM', 195 | name: 'Wrapped CREAM', 196 | mintAddress: '5Fu5UUgbjpUvdBveb3a1JTNirL8rXtiYeSMWvKjtUNQv', 197 | decimals: 6, 198 | referrer: '7WPzEiozJ69MQe8bfbss1t2unR6bHR4S7FimiUVRgu7P', 199 | tags: ['raydium'] 200 | }, 201 | UNI: { 202 | symbol: 'UNI', 203 | name: 'Wrapped UNI', 204 | mintAddress: 'DEhAasscXF4kEGxFgJ3bq4PpVGp5wyUxMRvn6TzGVHaw', 205 | decimals: 6, 206 | referrer: '4ntxDv95ajBbXfZyGy3UhcQDx8xmH1yJ6eKvuNNH466x', 207 | tags: ['raydium'] 208 | }, 209 | SRM: { 210 | symbol: 'SRM', 211 | name: 'Serum', 212 | mintAddress: 'SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt', 213 | decimals: 6, 214 | referrer: 'HYxa4Ea1dz7ya17Cx18rEGUA1WbCvKjXjFKrnu8CwugH', 215 | tags: ['raydium'] 216 | }, 217 | FTT: { 218 | symbol: 'FTT', 219 | name: 'Wrapped FTT', 220 | mintAddress: 'AGFEad2et2ZJif9jaGpdMixQqvW5i81aBdvKe7PHNfz3', 221 | decimals: 6, 222 | referrer: 'CafpgSh8KGL2GPTjdXfctD3vXngNZDJ3Q92FTfV71Hmt', 223 | tags: ['raydium'] 224 | }, 225 | MSRM: { 226 | symbol: 'MSRM', 227 | name: 'MegaSerum', 228 | mintAddress: 'MSRMcoVyrFxnSgo5uXwone5SKcGhT1KEJMFEkMEWf9L', 229 | decimals: 0, 230 | referrer: 'Ge5q9x8gDUNYqqLA1MdnCzWNJGsbj3M15Yxse2cDbw9z', 231 | tags: ['raydium'] 232 | }, 233 | TOMO: { 234 | symbol: 'TOMO', 235 | name: 'Wrapped TOMO', 236 | mintAddress: 'GXMvfY2jpQctDqZ9RoU3oWPhufKiCcFEfchvYumtX7jd', 237 | decimals: 6, 238 | referrer: '9fexfN3eZomF5gfenG5L9ydbKRQkPhq6x74rb5iLrvXP', 239 | tags: ['raydium'] 240 | }, 241 | KARMA: { 242 | symbol: 'KARMA', 243 | name: 'Wrapped KARMA', 244 | mintAddress: 'EcqExpGNFBve2i1cMJUTR4bPXj4ZoqmDD2rTkeCcaTFX', 245 | decimals: 4, 246 | tags: ['raydium'] 247 | }, 248 | LUA: { 249 | symbol: 'LUA', 250 | name: 'Wrapped LUA', 251 | mintAddress: 'EqWCKXfs3x47uVosDpTRgFniThL9Y8iCztJaapxbEaVX', 252 | decimals: 6, 253 | referrer: 'HuZwNApjVFuFSDgrwZA8GP2JD7WMby4qt6rkWDnaMo7j', 254 | tags: ['raydium'] 255 | }, 256 | MATH: { 257 | symbol: 'MATH', 258 | name: 'Wrapped MATH', 259 | mintAddress: 'GeDS162t9yGJuLEHPWXXGrb1zwkzinCgRwnT8vHYjKza', 260 | decimals: 6, 261 | referrer: 'C9K1M8sJX8WMdsnFT7DuzdiHHunEj79EsLuz4DixQYGm', 262 | tags: ['raydium'] 263 | }, 264 | KEEP: { 265 | symbol: 'KEEP', 266 | name: 'Wrapped KEEP', 267 | mintAddress: 'GUohe4DJUA5FKPWo3joiPgsB7yzer7LpDmt1Vhzy3Zht', 268 | decimals: 6, 269 | tags: ['raydium'] 270 | }, 271 | SWAG: { 272 | symbol: 'SWAG', 273 | name: 'Wrapped SWAG', 274 | mintAddress: '9F9fNTT6qwjsu4X4yWYKZpsbw5qT7o6yR2i57JF2jagy', 275 | decimals: 6, 276 | tags: ['raydium'] 277 | }, 278 | FIDA: { 279 | symbol: 'FIDA', 280 | name: 'Bonfida', 281 | mintAddress: 'EchesyfXePKdLtoiZSL8pBe8Myagyy8ZRqsACNCFGnvp', 282 | decimals: 6, 283 | referrer: 'AeAsG75UmyPDB271c6NHonHxXAPXfkvhcf2xjfJhReS8', 284 | tags: ['raydium'] 285 | }, 286 | KIN: { 287 | symbol: 'KIN', 288 | name: 'KIN', 289 | mintAddress: 'kinXdEcpDQeHPEuQnqmUgtYykqKGVFq6CeVX5iAHJq6', 290 | decimals: 5, 291 | referrer: 'AevFXmApVxN2yk1iemSxXc6Wy7Z1udUEfST11kuYKmr9', 292 | tags: ['raydium'] 293 | }, 294 | MAPS: { 295 | symbol: 'MAPS', 296 | name: 'MAPS', 297 | mintAddress: 'MAPS41MDahZ9QdKXhVa4dWB9RuyfV4XqhyAZ8XcYepb', 298 | decimals: 6, 299 | tags: ['raydium'] 300 | }, 301 | OXY: { 302 | symbol: 'OXY', 303 | name: 'OXY', 304 | mintAddress: 'z3dn17yLaGMKffVogeFHQ9zWVcXgqgf3PQnDsNs2g6M', 305 | decimals: 6, 306 | tags: ['raydium'] 307 | }, 308 | RAY: { 309 | symbol: 'RAY', 310 | name: 'Raydium', 311 | mintAddress: '4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R', 312 | decimals: 6, 313 | referrer: '33XpMmMQRf6tSPpmYyzpwU4uXpZHkFwCZsusD9dMYkjy', 314 | tags: ['raydium'] 315 | }, 316 | xCOPE: { 317 | symbol: 'xCOPE', 318 | name: 'xCOPE', 319 | mintAddress: '3K6rftdAaQYMPunrtNRHgnK2UAtjm2JwyT2oCiTDouYE', 320 | decimals: 0, 321 | referrer: '8DTehuES4tfnd2SrqcjN52XofxWXGjiLZRgM12U9pB6f', 322 | tags: ['raydium'] 323 | }, 324 | COPE: { 325 | symbol: 'COPE', 326 | name: 'COPE', 327 | mintAddress: '8HGyAAB1yoM1ttS7pXjHMa3dukTFGQggnFFH3hJZgzQh', 328 | decimals: 6, 329 | referrer: 'G7UYwWhkmgeL57SUKFF45K663V9TdXZw6Ho6ZLQ7p4p', 330 | tags: ['raydium'] 331 | }, 332 | STEP: { 333 | symbol: 'STEP', 334 | name: 'STEP', 335 | mintAddress: 'StepAscQoEioFxxWGnh2sLBDFp9d8rvKz2Yp39iDpyT', 336 | decimals: 9, 337 | referrer: 'EFQVX1S6dFroDDhJDAnMTX4fCfjt4fJXHdk1eEtJ2uRY', 338 | tags: ['raydium'] 339 | }, 340 | MEDIA: { 341 | symbol: 'MEDIA', 342 | name: 'MEDIA', 343 | mintAddress: 'ETAtLmCmsoiEEKfNrHKJ2kYy3MoABhU6NQvpSfij5tDs', 344 | decimals: 6, 345 | referrer: 'AYnaG3AidNWFzjq9U3BJSsQ9DShE8g7FszriBDtRFvsx', 346 | 347 | details: 348 | 'Media Network is a new protocol that bypasses traditional CDN providers’ centralized approach for a self-governed and open source solution where everyone can participate. Media Network creates a distributed bandwidth market that enables service providers such as media platforms to hire resources from the network and dynamically come and go as the demand for last-mile data delivery shifts. It allows anyone to organically serve content without introducing any trust assumptions or pre-authentication requirements. Participants earn MEDIA rewards for their bandwidth contributions, a fixed supply SPL token minted on Solana’s Blockchain.', 349 | docs: { 350 | website: 'https://media.network/', 351 | whitepaper: 'https://media.network/whitepaper.pdf' 352 | }, 353 | socials: { 354 | Twitter: 'https://twitter.com/Media_FDN', 355 | Telegram: 'https://t.me/Media_FDN', 356 | Medium: 'https://mediafoundation.medium.com/' 357 | }, 358 | tags: ['raydium'] 359 | }, 360 | ROPE: { 361 | symbol: 'ROPE', 362 | name: 'ROPE', 363 | mintAddress: '8PMHT4swUMtBzgHnh5U564N5sjPSiUz2cjEQzFnnP1Fo', 364 | decimals: 9, 365 | referrer: '5sGVVniBSPLTwRHDETShovq7STRH2rJwbvdvvH3NcVTF', 366 | tags: ['raydium'] 367 | }, 368 | MER: { 369 | symbol: 'MER', 370 | name: 'Mercurial', 371 | mintAddress: 'MERt85fc5boKw3BW1eYdxonEuJNvXbiMbs6hvheau5K', 372 | decimals: 6, 373 | referrer: '36F4ryvqaNW2yKQsAry4ZHCZ3j7tz3gtEz7NEwv7pSRu', 374 | 375 | details: 376 | 'Mercurial Finance\nMercurial is building DeFi’s first dynamic vaults for stable assets on Solana, providing the technical tools for users to easily deposit, swap and mint stable assets.\n\nInnovations\nMercurial will be introducing several key new technical innovations, including on-chain algorithms to regulate the flow of assets and dynamic fees that tap on the market and price data to assist LPs in optimizing performance. We will also be developing a unique pricing curve that will be the first to combine high efficiency, multi-token support, and generalizability for all types of token sets.\n\nMaximizing Capital Utlilization\nMercurial vaults will dynamically utilize assets for a wide range of use cases, like low slippage swaps, lending, flash loans, and external third-party decentralized protocols. To increase pegged assets availability on Solana, we will allow the creation of synthetics, like mUSD or mBTC, which can be added to our vaults to improve liquidity for other stables and facilitate interaction with other third-party decentralized protocols.\n\nStarting with a vault for the most common stables, for example, USDC, USDT, wUSDC, and wDAI, we will be facilitating low slippage swaps with dynamic fees. Features will be added as key technical and ecosystem pieces become available on Solana, i.e. inter-program composability, price oracles, etc.\n\nMER\nThe MER token will be used to accrue value for the holder via fees from swaps, commission from yield farms, and as collateral for synthetic stables like mUSD. MER will also be intrinsically linked to the governance and growth of Mercurial, playing a crucial role in regulating the system across governance, insurance, and bootstrapping.', 377 | docs: { 378 | website: 'https://www.mercurial.finance/', 379 | whitepaper: 'https://www.mercurial.finance/Mercurial-Lite-Paper-v1.pdf' 380 | }, 381 | socials: { 382 | Twitter: 'https://twitter.com/MercurialFi', 383 | Telegram: 'https://t.me/MercurialFi', 384 | Medium: 'https://mercurialfi.medium.com/' 385 | }, 386 | tags: ['raydium'] 387 | }, 388 | TULIP: { 389 | symbol: 'TULIP', 390 | name: 'TULIP', 391 | mintAddress: 'TuLipcqtGVXP9XR62wM8WWCm6a9vhLs7T1uoWBk6FDs', 392 | decimals: 6, 393 | referrer: 'Bcw1TvX8jUj6CtY2a7GU2THeYVAudvmT8yzRypVMVsSH', 394 | tags: ['raydium'] 395 | }, 396 | SNY: { 397 | symbol: 'SNY', 398 | name: 'SNY', 399 | mintAddress: '4dmKkXNHdgYsXqBHCuMikNQWwVomZURhYvkkX5c4pQ7y', 400 | decimals: 6, 401 | referrer: 'G7gyaTNn2hgjF67SWs4Ee9PEaFU2xadhtXL8HmkJ2cNL', 402 | 403 | detailLink: 'https://raydium.medium.com/synthetify-launching-on-acceleraytor-3755b4903f88', 404 | details: 405 | 'Synthetify is a decentralized protocol that allows for the creation and exchange of synthetic assets that closely track the price of underlying assets. Synthetify’s synthetics adhere to the SPL token standard, allowing them to be easily integrated with DeFi applications across the Solana ecosystem.\n\nSynthetify leverages Solana to enable a fast, cheap and intuitive trading experience for users of the platform while staying fully decentralized thanks to an infrastructure that relies on smart contracts and blockchain oracles.\n\nThe Synthetify Token (SNY) gives the ability to participate in the protocol through staking. Stakers receive a pro rata share of fees generated by the exchange as well as additional rewards. SNY acts as a collateral token for all synthetic assets created on the platform and each token will have voting power on future governance proposals.', 406 | docs: { 407 | website: 'https://synthetify.io/', 408 | whitepaper: 'https://resources.synthetify.io/synthetify-whitepaper.pdf' 409 | }, 410 | socials: { 411 | Twitter: 'https://twitter.com/synthetify', 412 | Telegram: 'https://t.me/synthetify', 413 | Medium: 'https://synthetify.medium.com/' 414 | }, 415 | tags: ['raydium'] 416 | }, 417 | SLRS: { 418 | symbol: 'SLRS', 419 | name: 'SLRS', 420 | mintAddress: 'SLRSSpSLUTP7okbCUBYStWCo1vUgyt775faPqz8HUMr', 421 | decimals: 6, 422 | referrer: 'AmqeHgTdm6kBzy5ewZFKuMAfbynZmhve1GQxbJzQFLbP', 423 | 424 | detailLink: 'https://raydium.medium.com/solrise-is-launching-on-acceleraytor-c2c980362037', 425 | details: 426 | 'Solrise Finance is a fully decentralized and non-custodial protocol for investment funds on Solana. What this means in practice is that anyone can open a fund, and anyone can invest in it.\n\nSolrise’s platform allows fund managers from all across the globe — weWether they are well-established and looking for a new channel, or ambitious rookies with something to prove — to open a fund, with performance kept completely transparent.\n\nExisting decentralized fund management platforms on Ethereum are suffering from brutally high transaction fees. With Solrise, you can create, enter, and exit funds all for under $0.01.', 427 | docs: { 428 | website: 'https://solrise.finance/', 429 | docs: 'https://docs.solrise.finance/' 430 | }, 431 | socials: { 432 | Twitter: 'https://twitter.com/SolriseFinance', 433 | Telegram: 'https://t.me/solrisefinance', 434 | Medium: 'https://blog.solrise.finance/' 435 | }, 436 | tags: ['raydium'] 437 | }, 438 | WOO: { 439 | symbol: 'WOO', 440 | name: 'Wootrade Network', 441 | mintAddress: 'E5rk3nmgLUuKUiS94gg4bpWwWwyjCMtddsAXkTFLtHEy', 442 | decimals: 6, 443 | referrer: '7UbeAZxpza5zN3QawQ5KsUo88zXvohUncYB9Zk5QCiim', 444 | tags: ['raydium'] 445 | }, 446 | BOP: { 447 | symbol: 'BOP', 448 | name: 'Boring Protocol', 449 | mintAddress: 'BLwTnYKqf7u4qjgZrrsKeNs2EzWkMLqVCu6j8iHyrNA3', 450 | decimals: 8, 451 | referrer: 'FWxBZmNsvNckx8DnaL2NuyMtiQmT1x529WwV4e1UWiGk', 452 | tags: ['raydium'] 453 | }, 454 | SAMO: { 455 | symbol: 'SAMO', 456 | name: 'Samoyed Coin', 457 | mintAddress: '7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU', 458 | decimals: 9, 459 | referrer: 'FnMDNFL9t8EpbADSU3hLWBtx7SuwRBB6NM84U3PzSkUu', 460 | tags: ['raydium'] 461 | }, 462 | renBTC: { 463 | symbol: 'renBTC', 464 | name: 'renBTC', 465 | mintAddress: 'CDJWUqTcYTVAKXAVXoQZFes5JUFc7owSeq7eMQcDSbo5', 466 | decimals: 8, 467 | referrer: '7rr64uygy3o5RKVeNv12JGDUFMXVdr2YHvA3NTxzbZT6', 468 | tags: ['raydium'] 469 | }, 470 | renDOGE: { 471 | symbol: 'renDOGE', 472 | name: 'renDOGE', 473 | mintAddress: 'ArUkYE2XDKzqy77PRRGjo4wREWwqk6RXTfM9NeqzPvjU', 474 | decimals: 8, 475 | referrer: 'J5g7uvJRGnpRyLnRQjFs1MqMkiTVgjxVJCXocu4B4BcZ', 476 | tags: ['raydium'] 477 | }, 478 | LIKE: { 479 | symbol: 'LIKE', 480 | name: 'LIKE', 481 | mintAddress: '3bRTivrVsitbmCTGtqwp7hxXPsybkjn4XLNtPsHqa3zR', 482 | decimals: 9, 483 | referrer: '2rnVeVGfM88XqyNyBzGWEb7JViYKqncFzjWq5h1ujS9A', 484 | 485 | detailLink: 'https://raydium.medium.com/only1-is-launching-on-acceleraytor-41ecb89dcc4e', 486 | details: 487 | 'Only1 is the first NFT-powered social platform built on the Solana blockchain. Mixing social media, an NFT marketplace, a scalable blockchain, and the native token — $LIKE, Only1 offers fans a unique way of connecting with the creators they love.\n\nBy using the Only1 platform, fans will have the ability to invest, access, and earn from the limited edition contents created by the world’s largest influencers/celebrities, all powered by NFTs.', 488 | docs: { 489 | website: 'https://only1.io/', 490 | whitepaper: 'https://only1.io/pitch-deck.pdf' 491 | }, 492 | socials: { 493 | Twitter: 'https://twitter.com/only1nft', 494 | Telegram: 'https://t.me/only1nft', 495 | Medium: 'https://medium.com/@only1nft', 496 | Discord: 'https://discord.gg/sUu7KZwNCB' 497 | }, 498 | tags: ['raydium'] 499 | }, 500 | DXL: { 501 | symbol: 'DXL', 502 | name: 'DXL', 503 | mintAddress: 'GsNzxJfFn6zQdJGeYsupJWzUAm57Ba7335mfhWvFiE9Z', 504 | decimals: 6, 505 | referrer: 'HF7mhT9YgD5CULAFDYQmhnUMi1FnNbKeBFCy9SZDh2XE', 506 | tags: ['raydium'] 507 | }, 508 | mSOL: { 509 | symbol: 'mSOL', 510 | name: 'Marinade staked SOL (mSOL)', 511 | mintAddress: 'mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So', 512 | decimals: 9, 513 | referrer: '7h5bckf8P29RdviNoKjDyH3Ky3uwdrBiPgYuSCD4asV5', 514 | tags: ['raydium'] 515 | }, 516 | PAI: { 517 | symbol: 'PAI', 518 | name: 'PAI (Parrot)', 519 | mintAddress: 'Ea5SjE2Y6yvCeW5dYTn7PYMuW5ikXkvbGdcmSnXeaLjS', 520 | decimals: 6, 521 | referrer: '54X98LAxRR2j1KMBBXkbYyUaAWi1iKW9G1Y4TnTJVY2e', 522 | tags: ['raydium'] 523 | }, 524 | PORT: { 525 | symbol: 'PORT', 526 | name: 'PORT', 527 | mintAddress: 'PoRTjZMPXb9T7dyU7tpLEZRQj7e6ssfAE62j2oQuc6y', 528 | decimals: 6, 529 | referrer: '5Ve8q9fb7R2DhdqGV4o1RVy7xxo4D6ifQfbxGiASdxEH', 530 | tags: ['raydium'] 531 | }, 532 | MNGO: { 533 | symbol: 'MNGO', 534 | name: 'Mango', 535 | mintAddress: 'MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac', 536 | decimals: 6, 537 | referrer: 'CijuvE6qDpxZ5WqdEQEe7mS11fXEKiiHc7RR8wRiGzjY', 538 | tags: ['raydium'] 539 | }, 540 | CRP: { 541 | symbol: 'CRP', 542 | name: 'CRP', 543 | mintAddress: 'DubwWZNWiNGMMeeQHPnMATNj77YZPZSAz2WVR5WjLJqz', 544 | decimals: 9, 545 | referrer: 'FKocyVJptELTbnkUkDRmT7y6hUem2JYrqHoph9uyvQXt', 546 | tags: ['raydium'] 547 | }, 548 | ATLAS: { 549 | symbol: 'ATLAS', 550 | name: 'ATLAS', 551 | mintAddress: 'ATLASXmbPQxBUYbxPsV97usA3fPQYEqzQBUHgiFCUsXx', 552 | decimals: 8, 553 | referrer: '9t9mzbkMtLdazj1D9JycS15Geb1KVtcDt4XyAkpM72Ee', 554 | 555 | detailLink: 'https://raydium.medium.com/star-atlas-is-launching-on-acceleraytor-fa35cfe3291f', 556 | details: 557 | 'POLIS is the primary governance token of Star Atlas.\n\nStar Atlas is a grand strategy game that combines space exploration, territorial conquest, and political domination. In the distant future, players can join one of three galactic factions to directly influence the course of the metaverse and earn real-world income for their contributions.\n\nThe Star Atlas offers a unique gaming experience by combining block chain mechanics with traditional game mechanics. All assets in the metaverse are directly owned by players, and can be traded on the marketplace or exchanged on other cryptocurrency networks.', 558 | docs: { 559 | website: 'https://staratlas.com/', 560 | whitepaper: 'https://staratlas.com/files/star-atlas-white-paper.pdf' 561 | }, 562 | socials: { 563 | Twitter: 'https://twitter.com/staratlas', 564 | Telegram: 'https://t.me/staratlasgame', 565 | Medium: 'https://medium.com/star-atlas', 566 | Discord: 'https://discord.gg/staratlas', 567 | Twitch: 'https://www.twitch.tv/staratlasgame', 568 | Youtube: 'https://www.youtube.com/channel/UCt-y8Npwje5KDG5MSZ0a9Jw/videos' 569 | }, 570 | tags: ['raydium'] 571 | }, 572 | POLIS: { 573 | symbol: 'POLIS', 574 | name: 'POLIS', 575 | mintAddress: 'poLisWXnNRwC6oBu1vHiuKQzFjGL4XDSu4g9qjz9qVk', 576 | decimals: 8, 577 | referrer: 'CQ7HWCeSSp3tAfWzqH7ZEzgnTBr5Tvz1No3Y1xbiWzBm', 578 | 579 | detailLink: 'https://raydium.medium.com/star-atlas-is-launching-on-acceleraytor-fa35cfe3291f', 580 | details: 581 | 'POLIS is the primary governance token of Star Atlas.\n\nStar Atlas is a grand strategy game that combines space exploration, territorial conquest, and political domination. In the distant future, players can join one of three galactic factions to directly influence the course of the metaverse and earn real-world income for their contributions.\n\nThe Star Atlas offers a unique gaming experience by combining block chain mechanics with traditional game mechanics. All assets in the metaverse are directly owned by players, and can be traded on the marketplace or exchanged on other cryptocurrency networks.', 582 | docs: { 583 | website: 'https://staratlas.com/', 584 | whitepaper: 'https://staratlas.com/files/star-atlas-white-paper.pdf' 585 | }, 586 | socials: { 587 | Twitter: 'https://twitter.com/staratlas', 588 | Telegram: 'https://t.me/staratlasgame', 589 | Medium: 'https://medium.com/star-atlas', 590 | Discord: 'https://discord.gg/staratlas', 591 | Twitch: 'https://www.twitch.tv/staratlasgame', 592 | Youtube: 'https://www.youtube.com/channel/UCt-y8Npwje5KDG5MSZ0a9Jw/videos' 593 | }, 594 | tags: ['raydium'] 595 | }, 596 | GRAPE: { 597 | symbol: 'GRAPE', 598 | name: 'GRAPE', 599 | mintAddress: '8upjSpvjcdpuzhfR1zriwg5NXkwDruejqNE9WNbPRtyA', 600 | decimals: 6, 601 | referrer: 'M4nDMB9krXbaNFPVu1DjrBTfqPUHbKEQLZSSDNH2JrL', 602 | 603 | detailLink: 'https://raydium.medium.com/grape-protocol-launching-on-acceleraytor-547f58c12937', 604 | details: 605 | 'The GRAPE “Great Ape” community is a token-based membership community focused on accelerating the growth and adoption of Solana. GRAPE token holders at different tiers are rewarded with exclusive benefits and monthly emissions of GRAPE. You can find more details on the GRAPE membership tiers and benefits here.\n\nThe GRAPE toolset creates a framework for decentralized and tokenized communities to better organize and coordinate their activities, unlocking a whole new world of possibility for these dynamic groups. The GRAPE roadmap includes modules for DAO Management, non-custodial tipping, escrow, and event planning to be deployed in the next 6 months.\n\nGRAPE protocol’s first tool, Grape Access, creates a Dynamic Balance-Based Membership solution by connecting members’ social accounts to cryptographic keys. All Solana tokens are supported by Multi-Coin configurations, which grants users permission and access rights based on SPL tokens, token pairs, and LP tokens in their wallet.', 606 | docs: { 607 | website: 'https://grapes.network/' 608 | // whitepaper: '' // TODO 609 | }, 610 | socials: { 611 | Discord: 'https://discord.com/invite/greatape', 612 | Medium: 'https://medium.com/great-ape', 613 | Twitter: 'https://twitter.com/grapeprotocol', 614 | Twitch: 'https://www.twitch.tv/whalesfriend' 615 | }, 616 | tags: ['raydium'] 617 | }, 618 | GENE: { 619 | symbol: 'GENE', 620 | name: 'Genopets', 621 | mintAddress: 'GENEtH5amGSi8kHAtQoezp1XEXwZJ8vcuePYnXdKrMYz', 622 | decimals: 9, 623 | 624 | detailLink: 'https://raydium.medium.com/genopets-is-launching-on-acceleraytor-a4cba0b9f78b', 625 | details: 626 | 'Genopets is the world’s first Free-to-Play, Move-to-Earn NFT game that makes it fun and rewarding to live an active lifestyle. Build on Solana, Genopets integrates your daily activity in real life with blockchain Play-to-Earn economics so you can turn your real-life actions into expansive gameplay and earn crypto while doing it.', 627 | docs: { 628 | website: 'https://www.genopets.me/' 629 | // whitepaper: '' 630 | }, 631 | socials: { 632 | Discord: 'https://discord.gg/genopets', 633 | Medium: 'https://medium.com/@genopets', 634 | Twitter: 'https://twitter.com/genopets' 635 | }, 636 | tags: ['raydium'] 637 | }, 638 | DFL: { 639 | symbol: 'DFL', 640 | name: 'DeFi Land', 641 | mintAddress: 'DFL1zNkaGPWm1BqAVqRjCZvHmwTFrEaJtbzJWgseoNJh', 642 | decimals: 9, 643 | 644 | detailLink: 'https://raydium.medium.com/defi-land-is-launching-on-acceleraytor-8aa06caecc3c', 645 | details: 646 | 'DeFi Land is a multi-chain agriculture simulation web game created to gamify decentralized finance. The game will have all the features that traditional platforms have, but it will be gathered all in one place. DeFi Land gamifies decentralized finance by turning investment activities into games.', 647 | docs: { 648 | website: 'https://defiland.app/' 649 | // whitepaper: '' 650 | }, 651 | socials: { 652 | Discord: 'https://discord.gg/defiland', 653 | Medium: 'https://defiland.medium.com/', 654 | Twitter: 'https://twitter.com/DeFi_Land', 655 | Telegram: 'https://t.me/defiland_official' 656 | }, 657 | tags: ['raydium'] 658 | }, 659 | CHEEMS: { 660 | symbol: 'CHEEMS', 661 | name: 'CHEEMS', 662 | mintAddress: '3FoUAsGDbvTD6YZ4wVKJgTB76onJUKz7GPEBNiR5b8wc', 663 | decimals: 4, 664 | referrer: '', 665 | tags: ['raydium'] 666 | }, 667 | stSOL: { 668 | symbol: 'stSOL', 669 | name: 'stSOL', 670 | mintAddress: '7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj', 671 | decimals: 9, 672 | referrer: '8Mq4Tugv1fcT4gb1wf5ChdEFmdqNGKxFVCnM9TVe44vD', 673 | tags: ['raydium'] 674 | }, 675 | LARIX: { 676 | symbol: 'LARIX', 677 | name: 'LARIX', 678 | mintAddress: 'Lrxqnh6ZHKbGy3dcrCED43nsoLkM1LTzU2jRfWe8qUC', 679 | decimals: 6, 680 | referrer: 'DReKowvoxxEDdi5jnxBWJLTV73D9oHSt9uNMuSCk9cLk', 681 | tags: ['raydium'] 682 | }, 683 | RIN: { 684 | symbol: 'RIN', 685 | name: 'RIN', 686 | mintAddress: 'E5ndSkaB17Dm7CsD22dvcjfrYSDLCxFcMd6z8ddCk5wp', 687 | decimals: 9, 688 | tags: ['raydium'] 689 | }, 690 | APEX: { 691 | symbol: 'APEX', 692 | name: 'APEX', 693 | mintAddress: '51tMb3zBKDiQhNwGqpgwbavaGH54mk8fXFzxTc1xnasg', 694 | decimals: 9, 695 | tags: ['raydium'] 696 | }, 697 | MNDE: { 698 | symbol: 'MNDE', 699 | name: 'MNDE', 700 | mintAddress: 'MNDEFzGvMt87ueuHvVU9VcTqsAP5b3fTGPsHuuPA5ey', 701 | decimals: 9, 702 | tags: ['raydium'] 703 | }, 704 | LIQ: { 705 | symbol: 'LIQ', 706 | name: 'LIQ', 707 | mintAddress: '4wjPQJ6PrkC4dHhYghwJzGBVP78DkBzA2U3kHoFNBuhj', 708 | decimals: 6, 709 | tags: ['raydium'] 710 | }, 711 | WAG: { 712 | symbol: 'WAG', 713 | name: 'WAG', 714 | mintAddress: '5tN42n9vMi6ubp67Uy4NnmM5DMZYN8aS8GeB3bEDHr6E', 715 | decimals: 9, 716 | tags: ['raydium'] 717 | }, 718 | wLDO: { 719 | symbol: 'wLDO', 720 | name: 'wLDO', 721 | mintAddress: 'HZRCwxP2Vq9PCpPXooayhJ2bxTpo5xfpQrwB1svh332p', 722 | decimals: 8, 723 | tags: ['raydium'] 724 | }, 725 | SLIM: { 726 | symbol: 'SLIM', 727 | name: 'SLIM', 728 | mintAddress: 'xxxxa1sKNGwFtw2kFn8XauW9xq8hBZ5kVtcSesTT9fW', 729 | decimals: 6, 730 | tags: ['raydium'] 731 | }, 732 | PRT: { 733 | symbol: 'PRT', 734 | name: 'PRT', 735 | mintAddress: 'PRT88RkA4Kg5z7pKnezeNH4mafTvtQdfFgpQTGRjz44', 736 | decimals: 6, 737 | tags: ['raydium'] 738 | }, 739 | SBR: { 740 | symbol: 'SBR', 741 | name: 'SBR', 742 | mintAddress: 'Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1', 743 | decimals: 6, 744 | tags: ['raydium'] 745 | }, 746 | FAB: { 747 | symbol: 'FAB', 748 | name: 'FAB', 749 | mintAddress: 'EdAhkbj5nF9sRM7XN7ewuW8C9XEUMs8P7cnoQ57SYE96', 750 | decimals: 9, 751 | tags: ['raydium'] 752 | }, 753 | ABR: { 754 | symbol: 'ABR', 755 | name: 'ABR', 756 | mintAddress: 'a11bdAAuV8iB2fu7X6AxAvDTo1QZ8FXB3kk5eecdasp', 757 | decimals: 9, 758 | tags: ['raydium'] 759 | }, 760 | IVN: { 761 | symbol: 'IVN', 762 | name: 'IVN', 763 | mintAddress: 'iVNcrNE9BRZBC9Aqf753iZiZfbszeAVUoikgT9yvr2a', 764 | decimals: 6, 765 | tags: ['raydium'] 766 | }, 767 | CYS: { 768 | symbol: 'CYS', 769 | name: 'CYS', 770 | mintAddress: 'BRLsMczKuaR5w9vSubF4j8HwEGGprVAyyVgS4EX7DKEg', 771 | decimals: 6, 772 | tags: ['raydium'] 773 | }, 774 | FRKT: { 775 | symbol: 'FRKT', 776 | name: 'FRKT', 777 | mintAddress: 'ErGB9xa24Szxbk1M28u2Tx8rKPqzL6BroNkkzk5rG4zj', 778 | decimals: 8, 779 | tags: ['raydium'] 780 | }, 781 | AURY: { 782 | symbol: 'AURY', 783 | name: 'AURY', 784 | mintAddress: 'AURYydfxJib1ZkTir1Jn1J9ECYUtjb6rKQVmtYaixWPP', 785 | decimals: 9, 786 | tags: ['raydium'] 787 | }, 788 | SYP: { 789 | symbol: 'SYP', 790 | name: 'SYP', 791 | mintAddress: 'FnKE9n6aGjQoNWRBZXy4RW6LZVao7qwBonUbiD7edUmZ', 792 | decimals: 9, 793 | tags: ['raydium'] 794 | }, 795 | WOOF: { 796 | symbol: 'WOOF', 797 | name: 'WOOF', 798 | mintAddress: '9nEqaUcb16sQ3Tn1psbkWqyhPdLmfHWjKGymREjsAgTE', 799 | decimals: 6, 800 | tags: ['raydium'] 801 | }, 802 | ORCA: { 803 | symbol: 'ORCA', 804 | name: 'ORCA', 805 | mintAddress: 'orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE', 806 | decimals: 6, 807 | tags: ['raydium'] 808 | }, 809 | SLND: { 810 | symbol: 'SLND', 811 | name: 'SLND', 812 | mintAddress: 'SLNDpmoWTVADgEdndyvWzroNL7zSi1dF9PC3xHGtPwp', 813 | decimals: 6, 814 | tags: ['raydium'] 815 | }, 816 | weWETH: { 817 | symbol: 'weWETH', 818 | name: 'weWETH', 819 | mintAddress: '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs', 820 | decimals: 8, 821 | tags: ['raydium'] 822 | }, 823 | weUNI: { 824 | symbol: 'weUNI', 825 | name: 'weUNI', 826 | mintAddress: '8FU95xFJhUUkyyCLU13HSzDLs7oC4QZdXQHL6SCeab36', 827 | decimals: 8, 828 | tags: ['raydium'] 829 | }, 830 | weSUSHI: { 831 | symbol: 'weSUSHI', 832 | name: 'weSUSHI', 833 | mintAddress: 'ChVzxWRmrTeSgwd3Ui3UumcN8KX7VK3WaD4KGeSKpypj', 834 | decimals: 8, 835 | tags: ['raydium'] 836 | }, 837 | GOFX: { 838 | symbol: 'GOFX', 839 | name: 'GOFX', 840 | mintAddress: 'GFX1ZjR2P15tmrSwow6FjyDYcEkoFb4p4gJCpLBjaxHD', 841 | decimals: 9, 842 | tags: ['raydium'] 843 | }, 844 | IN: { 845 | symbol: 'IN', 846 | name: 'IN', 847 | mintAddress: 'inL8PMVd6iiW3RCBJnr5AsrRN6nqr4BTrcNuQWQSkvY', 848 | decimals: 9, 849 | tags: ['raydium'] 850 | }, 851 | weDYDX: { 852 | symbol: 'weDYDX', 853 | name: 'weDYDX', 854 | mintAddress: '4Hx6Bj56eGyw8EJrrheM6LBQAvVYRikYCWsALeTrwyRU', 855 | decimals: 8, 856 | tags: ['raydium'] 857 | }, 858 | STARS: { 859 | symbol: 'STARS', 860 | name: 'STARS', 861 | mintAddress: 'HCgybxq5Upy8Mccihrp7EsmwwFqYZtrHrsmsKwtGXLgW', 862 | decimals: 6, 863 | tags: ['raydium'] 864 | }, 865 | weAXS: { 866 | symbol: 'weAXS', 867 | name: 'weAXS', 868 | mintAddress: 'HysWcbHiYY9888pHbaqhwLYZQeZrcQMXKQWRqS7zcPK5', 869 | decimals: 8, 870 | tags: ['raydium'] 871 | }, 872 | weSHIB: { 873 | symbol: 'weSHIB', 874 | name: 'weSHIB', 875 | mintAddress: 'CiKu4eHsVrc1eueVQeHn7qhXTcVu95gSQmBpX4utjL9z', 876 | decimals: 8, 877 | tags: ['raydium'] 878 | }, 879 | OXS: { 880 | symbol: 'OXS', 881 | name: 'OXS', 882 | mintAddress: '4TGxgCSJQx2GQk9oHZ8dC5m3JNXTYZHjXumKAW3vLnNx', 883 | decimals: 9, 884 | tags: ['raydium'] 885 | }, 886 | CWAR: { 887 | symbol: 'CWAR', 888 | name: 'CWAR', 889 | mintAddress: 'HfYFjMKNZygfMC8LsQ8LtpPsPxEJoXJx4M6tqi75Hajo', 890 | decimals: 9, 891 | tags: ['raydium'] 892 | }, 893 | UPS: { 894 | symbol: 'UPS', 895 | name: 'UPS', 896 | mintAddress: 'EwJN2GqUGXXzYmoAciwuABtorHczTA5LqbukKXV1viH7', 897 | decimals: 6, 898 | tags: ['raydium'] 899 | }, 900 | weSAND: { 901 | symbol: 'weSAND', 902 | name: 'weSAND', 903 | mintAddress: '49c7WuCZkQgc3M4qH8WuEUNXfgwupZf1xqWkDQ7gjRGt', 904 | decimals: 8, 905 | tags: ['raydium'] 906 | }, 907 | weMANA: { 908 | symbol: 'weMANA', 909 | name: 'weMANA', 910 | mintAddress: '7dgHoN8wBZCc5wbnQ2C47TDnBMAxG4Q5L3KjP67z8kNi', 911 | decimals: 8, 912 | tags: ['raydium'] 913 | }, 914 | CAVE: { 915 | symbol: 'CAVE', 916 | name: 'CAVE', 917 | mintAddress: '4SZjjNABoqhbd4hnapbvoEPEqT8mnNkfbEoAwALf1V8t', 918 | decimals: 6, 919 | tags: ['raydium'] 920 | }, 921 | JSOL: { 922 | symbol: 'JSOL', 923 | name: 'JSOL', 924 | mintAddress: '7Q2afV64in6N6SeZsAAB81TJzwDoD6zpqmHkzi9Dcavn', 925 | decimals: 9, 926 | tags: ['raydium'] 927 | }, 928 | APT: { 929 | symbol: 'APT', 930 | name: 'APT', 931 | mintAddress: 'APTtJyaRX5yGTsJU522N4VYWg3vCvSb65eam5GrPT5Rt', 932 | decimals: 6, 933 | tags: ['raydium'] 934 | }, 935 | SONAR: { 936 | symbol: 'SONAR', 937 | name: 'SONAR', 938 | mintAddress: 'sonarX4VtVkQemriJeLm6CKeW3GDMyiBnnAEMw1MRAE', 939 | decimals: 9, 940 | tags: ['raydium'] 941 | }, 942 | SHILL: { 943 | symbol: 'SHILL', 944 | name: 'SHILL', 945 | mintAddress: '6cVgJUqo4nmvQpbgrDZwyfd6RwWw5bfnCamS3M9N1fd', 946 | decimals: 6, 947 | tags: ['raydium'] 948 | }, 949 | TTT: { 950 | symbol: 'TTT', 951 | name: 'TabTrader', 952 | mintAddress: 'FNFKRV3V8DtA3gVJN6UshMiLGYA8izxFwkNWmJbFjmRj', 953 | decimals: 6, 954 | 955 | detailLink: 'https://raydium.medium.com/tabtrader-is-launching-on-acceleraytor-bc570b6a9628', 956 | details: 957 | 'TabTrader is a trading terminal that supports 34 exchanges with over 12,000 instruments, a variety of analytical tools, and a convenient interface. It’s a quick-access application allowing you to track your exchange accounts, trade, analyze charts, and get instantly notified on price changes, all within one unified interface. The app has a rating of 4.7 on the Apple App Store (with over 52,000 ratings) and a rating of 4.5 on the Google Play Store (with over 55,000 ratings).', 958 | docs: { 959 | website: 'https://tab-trader.com/' 960 | // whitepaper: '' 961 | }, 962 | socials: { 963 | Twitter: 'https://twitter.com/tabtraderpro', 964 | Telegram: 'https://t.me/tabtrader_en' 965 | }, 966 | tags: ['raydium'] 967 | }, 968 | BOKU: { 969 | symbol: 'BOKU', 970 | name: 'BOKU', 971 | mintAddress: 'CN7qFa5iYkHz99PTctvT4xXUHnxwjQ5MHxCuTJtPN5uS', 972 | decimals: 9, 973 | tags: ['raydium'] 974 | }, 975 | MIMO: { 976 | symbol: 'MIMO', 977 | name: 'MIMO', 978 | mintAddress: '9TE7ebz1dsFo1uQ2T4oYAKSm39Y6fWuHrd6Uk6XaiD16', 979 | decimals: 9, 980 | tags: ['raydium'] 981 | }, 982 | wbWBNB: { 983 | symbol: 'wbWBNB', 984 | name: 'wbWBNB', 985 | mintAddress: '9gP2kCy3wA1ctvYWQk75guqXuHfrEomqydHLtcTCqiLa', 986 | decimals: 8, 987 | tags: ['raydium'] 988 | }, 989 | wePEOPLE: { 990 | symbol: 'wePEOPLE', 991 | name: 'wePEOPLE', 992 | mintAddress: 'CobcsUrt3p91FwvULYKorQejgsm5HoQdv5T8RUZ6PnLA', 993 | decimals: 8, 994 | tags: ['raydium'] 995 | }, 996 | XTAG: { 997 | symbol: 'XTAG', 998 | name: 'XTAG', 999 | mintAddress: '5gs8nf4wojB5EXgDUWNLwXpknzgV2YWDhveAeBZpVLbp', 1000 | decimals: 6, 1001 | tags: ['raydium'] 1002 | }, 1003 | KKO: { 1004 | symbol: 'KKO', 1005 | name: 'KKO', 1006 | mintAddress: 'kiNeKo77w1WBEzFFCXrTDRWGRWGP8yHvKC9rX6dqjQh', 1007 | decimals: 9, 1008 | tags: ['raydium'] 1009 | }, 1010 | VI: { 1011 | symbol: 'VI', 1012 | name: 'VI', 1013 | mintAddress: '7zBWymxbZt7PVHQzfi3i85frc1YRiQc23K7bh3gos8ZC', 1014 | decimals: 9, 1015 | tags: ['raydium'] 1016 | }, 1017 | SOLC: { 1018 | symbol: 'SOLC', 1019 | name: 'SOLC', 1020 | mintAddress: 'Bx1fDtvTN6NvE4kjdPHQXtmGSg582bZx9fGy4DQNMmAT', 1021 | decimals: 9, 1022 | tags: ['raydium'] 1023 | }, 1024 | STR: { 1025 | symbol: 'STR', 1026 | name: 'STR', 1027 | mintAddress: '9zoqdwEBKWEi9G5Ze8BSkdmppxGgVv1Kw4LuigDiNr9m', 1028 | decimals: 9, 1029 | tags: ['raydium'] 1030 | }, 1031 | SPWN: { 1032 | symbol: 'SPWN', 1033 | name: 'SPWN', 1034 | mintAddress: '5U9QqCPhqXAJcEv9uyzFJd5zhN93vuPk1aNNkXnUfPnt', 1035 | decimals: 9, 1036 | tags: ['raydium'] 1037 | }, 1038 | ISOLA: { 1039 | symbol: 'ISOLA', 1040 | name: 'ISOLA', 1041 | mintAddress: '333iHoRM2Awhf9uVZtSyTfU8AekdGrgQePZsKMFPgKmS', 1042 | decimals: 6, 1043 | tags: ['raydium'] 1044 | }, 1045 | RUN: { 1046 | symbol: 'RUN', 1047 | name: 'RUN', 1048 | mintAddress: '6F9XriABHfWhit6zmMUYAQBSy6XK5VF1cHXuW5LDpRtC', 1049 | decimals: 9, 1050 | 1051 | detailLink: 'https://raydium.medium.com/runnode-is-launching-on-acceleraytor-3ff7326864b0', 1052 | details: 1053 | 'RunNode is a bridge from web 2.0 to 3.0 and powers the infrastructure of Solana through its RPC protocol. With a quick onboarding application to get an RPC endpoint in under 30 seconds, any project can launch, build and scale its Solana dApp — now.', 1054 | docs: { 1055 | website: 'https://runnode.com/' 1056 | // whitepaper: '' 1057 | }, 1058 | socials: { 1059 | Twitter: 'https://twitter.com/RunNode', 1060 | Telegram: 'https://t.me/runnode', 1061 | Discord: 'https://discord.gg/V2f74X8Zrt' 1062 | }, 1063 | 1064 | tags: ['raydium'] 1065 | }, 1066 | REAL: { 1067 | symbol: 'REAL', 1068 | name: 'REAL', 1069 | mintAddress: 'AD27ov5fVU2XzwsbvnFvb1JpCBaCB5dRXrczV9CqSVGb', 1070 | decimals: 9, 1071 | 1072 | detailLink: 'https://raydium.medium.com/realy-is-launching-on-acceleraytor-b6d6a63d69d8', 1073 | details: 1074 | 'Realy Metaverse will be the 1st Live-to-Earn metaverse on Solana. Developed via Unreal Engine, Realy is a virtual city with AAA graphics that seamlessly integrates virtual and reality.', 1075 | docs: { 1076 | website: 'https://realy.pro/' 1077 | // whitepaper: '' 1078 | }, 1079 | socials: { 1080 | Twitter: 'https://twitter.com/RealyOfficial', 1081 | Telegram: 'https://t.me/realyofficial', 1082 | Discord: 'https://discord.gg/realy' 1083 | }, 1084 | 1085 | tags: ['raydium'] 1086 | }, 1087 | CRWNY: { 1088 | symbol: 'CRWNY', 1089 | name: 'CRWNY', 1090 | mintAddress: 'CRWNYkqdgvhGGae9CKfNka58j6QQkaD5bLhKXvUYqnc1', 1091 | decimals: 6, 1092 | tags: ['raydium'] 1093 | }, 1094 | BLOCK: { 1095 | symbol: 'BLOCK', 1096 | name: 'BLOCK', 1097 | mintAddress: 'NFTUkR4u7wKxy9QLaX2TGvd9oZSWoMo4jqSJqdMb7Nk', 1098 | decimals: 6, 1099 | tags: ['raydium'] 1100 | }, 1101 | SOLAR: { 1102 | symbol: 'SOLAR', 1103 | name: 'SOLAR', 1104 | mintAddress: '2wmKXX1xsxLfrvjEPrt2UHiqj8Gbzwxvffr9qmNjsw8g', 1105 | decimals: 9, 1106 | tags: ['raydium'] 1107 | }, 1108 | BASIS: { 1109 | symbol: 'BASIS', 1110 | name: 'BASIS', 1111 | mintAddress: 'Basis9oJw9j8cw53oMV7iqsgo6ihi9ALw4QR31rcjUJa', 1112 | decimals: 6, 1113 | tags: ['raydium'] 1114 | }, 1115 | SOLX: { 1116 | symbol: 'SOLX', 1117 | name: 'SOLX', 1118 | mintAddress: 'CH74tuRLTYcxG7qNJCsV9rghfLXJCQJbsu7i52a8F1Gn', 1119 | decimals: 9, 1120 | tags: ['raydium'] 1121 | }, 1122 | CHICKS: { 1123 | symbol: 'CHICKS', 1124 | name: 'CHICKS', 1125 | mintAddress: 'cxxShYRVcepDudXhe7U62QHvw8uBJoKFifmzggGKVC2', 1126 | decimals: 9, 1127 | tags: ['raydium'] 1128 | } 1129 | } 1130 | 1131 | export const LP_TOKENS: Tokens = { 1132 | 'RAY-WUSDT': { 1133 | symbol: 'RAY-WUSDT', 1134 | name: 'RAY-WUSDT V2 LP', 1135 | coin: { ...TOKENS.RAY }, 1136 | pc: { ...TOKENS.WUSDT }, 1137 | 1138 | mintAddress: 'CzPDyvotTcxNqtPne32yUiEVQ6jk42HZi1Y3hUu7qf7f', 1139 | decimals: TOKENS.RAY.decimals 1140 | }, 1141 | 'RAY-SOL': { 1142 | symbol: 'RAY-SOL', 1143 | name: 'RAY-SOL LP', 1144 | coin: { ...TOKENS.RAY }, 1145 | pc: { ...NATIVE_SOL }, 1146 | 1147 | mintAddress: '134Cct3CSdRCbYgq5SkwmHgfwjJ7EM5cG9PzqffWqECx', 1148 | decimals: TOKENS.RAY.decimals 1149 | }, 1150 | 'LINK-WUSDT': { 1151 | symbol: 'LINK-WUSDT', 1152 | name: 'LINK-WUSDT LP', 1153 | coin: { ...TOKENS.LINK }, 1154 | pc: { ...TOKENS.WUSDT }, 1155 | 1156 | mintAddress: 'EVDmwajM5U73PD34bYPugwiA4Eqqbrej4mLXXv15Z5qR', 1157 | decimals: TOKENS.LINK.decimals 1158 | }, 1159 | 'ETH-WUSDT': { 1160 | symbol: 'ETH-WUSDT', 1161 | name: 'ETH-WUSDT LP', 1162 | coin: { ...TOKENS.ETH }, 1163 | pc: { ...TOKENS.WUSDT }, 1164 | 1165 | mintAddress: 'KY4XvwHy7JPzbWYAbk23jQvEb4qWJ8aCqYWREmk1Q7K', 1166 | decimals: TOKENS.ETH.decimals 1167 | }, 1168 | 'RAY-USDC': { 1169 | symbol: 'RAY-USDC', 1170 | name: 'RAY-USDC V2 LP', 1171 | coin: { ...TOKENS.RAY }, 1172 | pc: { ...TOKENS.USDC }, 1173 | 1174 | mintAddress: 'FgmBnsF5Qrnv8X9bomQfEtQTQjNNiBCWRKGpzPnE5BDg', 1175 | decimals: TOKENS.RAY.decimals 1176 | }, 1177 | 'RAY-SRM': { 1178 | symbol: 'RAY-SRM', 1179 | name: 'RAY-SRM V2 LP', 1180 | coin: { ...TOKENS.RAY }, 1181 | pc: { ...TOKENS.SRM }, 1182 | 1183 | mintAddress: '5QXBMXuCL7zfAk39jEVVEvcrz1AvBGgT9wAhLLHLyyUJ', 1184 | decimals: TOKENS.RAY.decimals 1185 | }, 1186 | // v3 1187 | 'RAY-WUSDT-V3': { 1188 | symbol: 'RAY-WUSDT', 1189 | name: 'RAY-WUSDT V3 LP', 1190 | coin: { ...TOKENS.RAY }, 1191 | pc: { ...TOKENS.WUSDT }, 1192 | 1193 | mintAddress: 'FdhKXYjCou2jQfgKWcNY7jb8F2DPLU1teTTTRfLBD2v1', 1194 | decimals: TOKENS.RAY.decimals 1195 | }, 1196 | 'RAY-USDC-V3': { 1197 | symbol: 'RAY-USDC', 1198 | name: 'RAY-USDC V3 LP', 1199 | coin: { ...TOKENS.RAY }, 1200 | pc: { ...TOKENS.USDC }, 1201 | 1202 | mintAddress: 'BZFGfXMrjG2sS7QT2eiCDEevPFnkYYF7kzJpWfYxPbcx', 1203 | decimals: TOKENS.RAY.decimals 1204 | }, 1205 | 'RAY-SRM-V3': { 1206 | symbol: 'RAY-SRM', 1207 | name: 'RAY-SRM V3 LP', 1208 | coin: { ...TOKENS.RAY }, 1209 | pc: { ...TOKENS.SRM }, 1210 | 1211 | mintAddress: 'DSX5E21RE9FB9hM8Nh8xcXQfPK6SzRaJiywemHBSsfup', 1212 | decimals: TOKENS.RAY.decimals 1213 | }, 1214 | 'RAY-SOL-V3': { 1215 | symbol: 'RAY-SOL', 1216 | name: 'RAY-SOL V3 LP', 1217 | coin: { ...TOKENS.RAY }, 1218 | pc: { ...NATIVE_SOL }, 1219 | 1220 | mintAddress: 'F5PPQHGcznZ2FxD9JaxJMXaf7XkaFFJ6zzTBcW8osQjw', 1221 | decimals: TOKENS.RAY.decimals 1222 | }, 1223 | 'RAY-ETH-V3': { 1224 | symbol: 'RAY-ETH', 1225 | name: 'RAY-ETH V3 LP', 1226 | coin: { ...TOKENS.RAY }, 1227 | pc: { ...TOKENS.ETH }, 1228 | 1229 | mintAddress: '8Q6MKy5Yxb9vG1mWzppMtMb2nrhNuCRNUkJTeiE3fuwD', 1230 | decimals: TOKENS.RAY.decimals 1231 | }, 1232 | // v4 1233 | 'FIDA-RAY-V4': { 1234 | symbol: 'FIDA-RAY', 1235 | name: 'FIDA-RAY LP', 1236 | coin: { ...TOKENS.FIDA }, 1237 | pc: { ...TOKENS.RAY }, 1238 | 1239 | mintAddress: 'DsBuznXRTmzvEdb36Dx3aVLVo1XmH7r1PRZUFugLPTFv', 1240 | decimals: TOKENS.FIDA.decimals 1241 | }, 1242 | 'OXY-RAY-V4': { 1243 | symbol: 'OXY-RAY', 1244 | name: 'OXY-RAY LP', 1245 | coin: { ...TOKENS.OXY }, 1246 | pc: { ...TOKENS.RAY }, 1247 | 1248 | mintAddress: 'FwaX9W7iThTZH5MFeasxdLpxTVxRcM7ZHieTCnYog8Yb', 1249 | decimals: TOKENS.OXY.decimals 1250 | }, 1251 | 'MAPS-RAY-V4': { 1252 | symbol: 'MAPS-RAY', 1253 | name: 'MAPS-RAY LP', 1254 | coin: { ...TOKENS.MAPS }, 1255 | pc: { ...TOKENS.RAY }, 1256 | 1257 | mintAddress: 'CcKK8srfVdTSsFGV3VLBb2YDbzF4T4NM2C3UEjC39RLP', 1258 | decimals: TOKENS.MAPS.decimals 1259 | }, 1260 | 'KIN-RAY-V4': { 1261 | symbol: 'KIN-RAY', 1262 | name: 'KIN-RAY LP', 1263 | coin: { ...TOKENS.KIN }, 1264 | pc: { ...TOKENS.RAY }, 1265 | 1266 | mintAddress: 'CHT8sft3h3gpLYbCcZ9o27mT5s3Z6VifBVbUiDvprHPW', 1267 | decimals: 6 1268 | }, 1269 | 'RAY-USDT-V4': { 1270 | symbol: 'RAY-USDT', 1271 | name: 'RAY-USDT LP', 1272 | coin: { ...TOKENS.RAY }, 1273 | pc: { ...TOKENS.USDT }, 1274 | 1275 | mintAddress: 'C3sT1R3nsw4AVdepvLTLKr5Gvszr7jufyBWUCvy4TUvT', 1276 | decimals: TOKENS.RAY.decimals 1277 | }, 1278 | 'SOL-USDC-V4': { 1279 | symbol: 'SOL-USDC', 1280 | name: 'SOL-USDC LP', 1281 | coin: { ...NATIVE_SOL }, 1282 | pc: { ...TOKENS.USDC }, 1283 | 1284 | mintAddress: '8HoQnePLqPj4M7PUDzfw8e3Ymdwgc7NLGnaTUapubyvu', 1285 | decimals: NATIVE_SOL.decimals 1286 | }, 1287 | 'YFI-USDC-V4': { 1288 | symbol: 'YFI-USDC', 1289 | name: 'YFI-USDC LP', 1290 | coin: { ...TOKENS.YFI }, 1291 | pc: { ...TOKENS.USDC }, 1292 | 1293 | mintAddress: '865j7iMmRRycSYUXzJ33ZcvLiX9JHvaLidasCyUyKaRE', 1294 | decimals: TOKENS.YFI.decimals 1295 | }, 1296 | 'SRM-USDC-V4': { 1297 | symbol: 'SRM-USDC', 1298 | name: 'SRM-USDC LP', 1299 | coin: { ...TOKENS.SRM }, 1300 | pc: { ...TOKENS.USDC }, 1301 | 1302 | mintAddress: '9XnZd82j34KxNLgQfz29jGbYdxsYznTWRpvZE3SRE7JG', 1303 | decimals: TOKENS.SRM.decimals 1304 | }, 1305 | 'FTT-USDC-V4': { 1306 | symbol: 'FTT-USDC', 1307 | name: 'FTT-USDC LP', 1308 | coin: { ...TOKENS.FTT }, 1309 | pc: { ...TOKENS.USDC }, 1310 | 1311 | mintAddress: '75dCoKfUHLUuZ4qEh46ovsxfgWhB4icc3SintzWRedT9', 1312 | decimals: TOKENS.FTT.decimals 1313 | }, 1314 | 'BTC-USDC-V4': { 1315 | symbol: 'BTC-USDC', 1316 | name: 'BTC-USDC LP', 1317 | coin: { ...TOKENS.BTC }, 1318 | pc: { ...TOKENS.USDC }, 1319 | 1320 | mintAddress: '2hMdRdVWZqetQsaHG8kQjdZinEMBz75vsoWTCob1ijXu', 1321 | decimals: TOKENS.BTC.decimals 1322 | }, 1323 | 'SUSHI-USDC-V4': { 1324 | symbol: 'SUSHI-USDC', 1325 | name: 'SUSHI-USDC LP', 1326 | coin: { ...TOKENS.SUSHI }, 1327 | pc: { ...TOKENS.USDC }, 1328 | 1329 | mintAddress: '2QVjeR9d2PbSf8em8NE8zWd8RYHjFtucDUdDgdbDD2h2', 1330 | decimals: TOKENS.SUSHI.decimals 1331 | }, 1332 | 'TOMO-USDC-V4': { 1333 | symbol: 'TOMO-USDC', 1334 | name: 'TOMO-USDC LP', 1335 | coin: { ...TOKENS.TOMO }, 1336 | pc: { ...TOKENS.USDC }, 1337 | 1338 | mintAddress: 'CHyUpQFeW456zcr5XEh4RZiibH8Dzocs6Wbgz9aWpXnQ', 1339 | decimals: TOKENS.TOMO.decimals 1340 | }, 1341 | 'LINK-USDC-V4': { 1342 | symbol: 'LINK-USDC', 1343 | name: 'LINK-USDC LP', 1344 | coin: { ...TOKENS.LINK }, 1345 | pc: { ...TOKENS.USDC }, 1346 | 1347 | mintAddress: 'BqjoYjqKrXtfBKXeaWeAT5sYCy7wsAYf3XjgDWsHSBRs', 1348 | decimals: TOKENS.LINK.decimals 1349 | }, 1350 | 'ETH-USDC-V4': { 1351 | symbol: 'ETH-USDC', 1352 | name: 'ETH-USDC LP', 1353 | coin: { ...TOKENS.ETH }, 1354 | pc: { ...TOKENS.USDC }, 1355 | 1356 | mintAddress: '13PoKid6cZop4sj2GfoBeujnGfthUbTERdE5tpLCDLEY', 1357 | decimals: TOKENS.ETH.decimals 1358 | }, 1359 | 'xCOPE-USDC-V4': { 1360 | symbol: 'xCOPE-USDC', 1361 | name: 'xCOPE-USDC LP', 1362 | coin: { ...TOKENS.xCOPE }, 1363 | pc: { ...TOKENS.USDC }, 1364 | 1365 | mintAddress: '2Vyyeuyd15Gp8aH6uKE72c4hxc8TVSLibxDP9vzspQWG', 1366 | decimals: TOKENS.xCOPE.decimals 1367 | }, 1368 | 'SOL-USDT-V4': { 1369 | symbol: 'SOL-USDT', 1370 | name: 'SOL-USDT LP', 1371 | coin: { ...NATIVE_SOL }, 1372 | pc: { ...TOKENS.USDT }, 1373 | 1374 | mintAddress: 'Epm4KfTj4DMrvqn6Bwg2Tr2N8vhQuNbuK8bESFp4k33K', 1375 | decimals: NATIVE_SOL.decimals 1376 | }, 1377 | 'YFI-USDT-V4': { 1378 | symbol: 'YFI-USDT', 1379 | name: 'YFI-USDT LP', 1380 | coin: { ...TOKENS.YFI }, 1381 | pc: { ...TOKENS.USDT }, 1382 | 1383 | mintAddress: 'FA1i7fej1pAbQbnY8NbyYUsTrWcasTyipKreDgy1Mgku', 1384 | decimals: TOKENS.YFI.decimals 1385 | }, 1386 | 'SRM-USDT-V4': { 1387 | symbol: 'SRM-USDT', 1388 | name: 'SRM-USDT LP', 1389 | coin: { ...TOKENS.SRM }, 1390 | pc: { ...TOKENS.USDT }, 1391 | 1392 | mintAddress: 'HYSAu42BFejBS77jZAZdNAWa3iVcbSRJSzp3wtqCbWwv', 1393 | decimals: TOKENS.SRM.decimals 1394 | }, 1395 | 'FTT-USDT-V4': { 1396 | symbol: 'FTT-USDT', 1397 | name: 'FTT-USDT LP', 1398 | coin: { ...TOKENS.FTT }, 1399 | pc: { ...TOKENS.USDT }, 1400 | 1401 | mintAddress: '2cTCiUnect5Lap2sk19xLby7aajNDYseFhC9Pigou11z', 1402 | decimals: TOKENS.FTT.decimals 1403 | }, 1404 | 'BTC-USDT-V4': { 1405 | symbol: 'BTC-USDT', 1406 | name: 'BTC-USDT LP', 1407 | coin: { ...TOKENS.BTC }, 1408 | pc: { ...TOKENS.USDT }, 1409 | 1410 | mintAddress: 'DgGuvR9GSHimopo3Gc7gfkbKamLKrdyzWkq5yqA6LqYS', 1411 | decimals: TOKENS.BTC.decimals 1412 | }, 1413 | 'SUSHI-USDT-V4': { 1414 | symbol: 'SUSHI-USDT', 1415 | name: 'SUSHI-USDT LP', 1416 | coin: { ...TOKENS.SUSHI }, 1417 | pc: { ...TOKENS.USDT }, 1418 | 1419 | mintAddress: 'Ba26poEYDy6P2o95AJUsewXgZ8DM9BCsmnU9hmC9i4Ki', 1420 | decimals: TOKENS.SUSHI.decimals 1421 | }, 1422 | 'TOMO-USDT-V4': { 1423 | symbol: 'TOMO-USDT', 1424 | name: 'TOMO-USDT LP', 1425 | coin: { ...TOKENS.TOMO }, 1426 | pc: { ...TOKENS.USDT }, 1427 | 1428 | mintAddress: 'D3iGro1vn6PWJXo9QAPj3dfta6dKkHHnmiiym2EfsAmi', 1429 | decimals: TOKENS.TOMO.decimals 1430 | }, 1431 | 'LINK-USDT-V4': { 1432 | symbol: 'LINK-USDT', 1433 | name: 'LINK-USDT LP', 1434 | coin: { ...TOKENS.LINK }, 1435 | pc: { ...TOKENS.USDT }, 1436 | 1437 | mintAddress: 'Dr12Sgt9gkY8WU5tRkgZf1TkVWJbvjYuPAhR3aDCwiiX', 1438 | decimals: TOKENS.LINK.decimals 1439 | }, 1440 | 'ETH-USDT-V4': { 1441 | symbol: 'ETH-USDT', 1442 | name: 'ETH-USDT LP', 1443 | coin: { ...TOKENS.ETH }, 1444 | pc: { ...TOKENS.USDT }, 1445 | 1446 | mintAddress: 'nPrB78ETY8661fUgohpuVusNCZnedYCgghzRJzxWnVb', 1447 | decimals: TOKENS.ETH.decimals 1448 | }, 1449 | 'YFI-SRM-V4': { 1450 | symbol: 'YFI-SRM', 1451 | name: 'YFI-SRM LP', 1452 | coin: { ...TOKENS.YFI }, 1453 | pc: { ...TOKENS.SRM }, 1454 | 1455 | mintAddress: 'EGJht91R7dKpCj8wzALkjmNdUUUcQgodqWCYweyKcRcV', 1456 | decimals: TOKENS.YFI.decimals 1457 | }, 1458 | 'FTT-SRM-V4': { 1459 | symbol: 'FTT-SRM', 1460 | name: 'FTT-SRM LP', 1461 | coin: { ...TOKENS.FTT }, 1462 | pc: { ...TOKENS.SRM }, 1463 | 1464 | mintAddress: 'AsDuPg9MgPtt3jfoyctUCUgsvwqAN6RZPftqoeiPDefM', 1465 | decimals: TOKENS.FTT.decimals 1466 | }, 1467 | 'BTC-SRM-V4': { 1468 | symbol: 'BTC-SRM', 1469 | name: 'BTC-SRM LP', 1470 | coin: { ...TOKENS.BTC }, 1471 | pc: { ...TOKENS.SRM }, 1472 | 1473 | mintAddress: 'AGHQxXb3GSzeiLTcLtXMS2D5GGDZxsB2fZYZxSB5weqB', 1474 | decimals: TOKENS.BTC.decimals 1475 | }, 1476 | 'SUSHI-SRM-V4': { 1477 | symbol: 'SUSHI-SRM', 1478 | name: 'SUSHI-SRM LP', 1479 | coin: { ...TOKENS.SUSHI }, 1480 | pc: { ...TOKENS.SRM }, 1481 | 1482 | mintAddress: '3HYhUnUdV67j1vn8fu7ExuVGy5dJozHEyWvqEstDbWwE', 1483 | decimals: TOKENS.SUSHI.decimals 1484 | }, 1485 | 'TOMO-SRM-V4': { 1486 | symbol: 'TOMO-SRM', 1487 | name: 'TOMO-SRM LP', 1488 | coin: { ...TOKENS.TOMO }, 1489 | pc: { ...TOKENS.SRM }, 1490 | 1491 | mintAddress: 'GgH9RnKrQpaMQeqmdbMvs5oo1A24hERQ9wuY2pSkeG7x', 1492 | decimals: TOKENS.TOMO.decimals 1493 | }, 1494 | 'LINK-SRM-V4': { 1495 | symbol: 'LINK-SRM', 1496 | name: 'LINK-SRM LP', 1497 | coin: { ...TOKENS.LINK }, 1498 | pc: { ...TOKENS.SRM }, 1499 | 1500 | mintAddress: 'GXN6yJv12o18skTmJXaeFXZVY1iqR18CHsmCT8VVCmDD', 1501 | decimals: TOKENS.LINK.decimals 1502 | }, 1503 | 'ETH-SRM-V4': { 1504 | symbol: 'ETH-SRM', 1505 | name: 'ETH-SRM LP', 1506 | coin: { ...TOKENS.ETH }, 1507 | pc: { ...TOKENS.SRM }, 1508 | 1509 | mintAddress: '9VoY3VERETuc2FoadMSYYizF26mJinY514ZpEzkHMtwG', 1510 | decimals: TOKENS.ETH.decimals 1511 | }, 1512 | 'SRM-SOL-V4': { 1513 | symbol: 'SRM-SOL', 1514 | name: 'SRM-SOL LP', 1515 | coin: { ...TOKENS.SRM }, 1516 | pc: { ...NATIVE_SOL }, 1517 | 1518 | mintAddress: 'AKJHspCwDhABucCxNLXUSfEzb7Ny62RqFtC9uNjJi4fq', 1519 | decimals: TOKENS.SRM.decimals 1520 | }, 1521 | 'STEP-USDC-V4': { 1522 | symbol: 'STEP-USDC', 1523 | name: 'STEP-USDC LP', 1524 | coin: { ...TOKENS.STEP }, 1525 | pc: { ...TOKENS.USDC }, 1526 | 1527 | mintAddress: '3k8BDobgihmk72jVmXYLE168bxxQUhqqyESW4dQVktqC', 1528 | decimals: TOKENS.STEP.decimals 1529 | }, 1530 | 'MEDIA-USDC-V4': { 1531 | symbol: 'MEDIA-USDC', 1532 | name: 'MEDIA-USDC LP', 1533 | coin: { ...TOKENS.MEDIA }, 1534 | pc: { ...TOKENS.USDC }, 1535 | 1536 | mintAddress: 'A5zanvgtioZGiJMdEyaKN4XQmJsp1p7uVxaq2696REvQ', 1537 | decimals: TOKENS.MEDIA.decimals 1538 | }, 1539 | 'ROPE-USDC-V4': { 1540 | symbol: 'ROPE-USDC', 1541 | name: 'ROPE-USDC LP', 1542 | coin: { ...TOKENS.ROPE }, 1543 | pc: { ...TOKENS.USDC }, 1544 | 1545 | mintAddress: 'Cq4HyW5xia37tKejPF2XfZeXQoPYW6KfbPvxvw5eRoUE', 1546 | decimals: TOKENS.ROPE.decimals 1547 | }, 1548 | 'MER-USDC-V4': { 1549 | symbol: 'MER-USDC', 1550 | name: 'MER-USDC LP', 1551 | coin: { ...TOKENS.MER }, 1552 | pc: { ...TOKENS.USDC }, 1553 | 1554 | mintAddress: '3H9NxvaZoxMZZDZcbBDdWMKbrfNj7PCF5sbRwDr7SdDW', 1555 | decimals: TOKENS.MER.decimals 1556 | }, 1557 | 'COPE-USDC-V4': { 1558 | symbol: 'COPE-USDC', 1559 | name: 'COPE-USDC LP', 1560 | coin: { ...TOKENS.COPE }, 1561 | pc: { ...TOKENS.USDC }, 1562 | 1563 | mintAddress: 'Cz1kUvHw98imKkrqqu95GQB9h1frY8RikxPojMwWKGXf', 1564 | decimals: TOKENS.COPE.decimals 1565 | }, 1566 | 'ALEPH-USDC-V4': { 1567 | symbol: 'ALEPH-USDC', 1568 | name: 'ALEPH-USDC LP', 1569 | coin: { ...TOKENS.ALEPH }, 1570 | pc: { ...TOKENS.USDC }, 1571 | 1572 | mintAddress: 'iUDasAP2nXm5wvTukAHEKSdSXn8vQkRtaiShs9ceGB7', 1573 | decimals: TOKENS.ALEPH.decimals 1574 | }, 1575 | 'TULIP-USDC-V4': { 1576 | symbol: 'TULIP-USDC', 1577 | name: 'TULIP-USDC LP', 1578 | coin: { ...TOKENS.TULIP }, 1579 | pc: { ...TOKENS.USDC }, 1580 | 1581 | mintAddress: '2doeZGLJyACtaG9DCUyqMLtswesfje1hjNA11hMdj6YU', 1582 | decimals: TOKENS.TULIP.decimals 1583 | }, 1584 | 'WOO-USDC-V4': { 1585 | symbol: 'WOO-USDC', 1586 | name: 'WOO-USDC LP', 1587 | coin: { ...TOKENS.WOO }, 1588 | pc: { ...TOKENS.USDC }, 1589 | 1590 | mintAddress: '7cu42ao8Jgrd5A3y3bNQsCxq5poyGZNmTydkGfJYQfzh', 1591 | decimals: TOKENS.WOO.decimals 1592 | }, 1593 | 'SNY-USDC-V4': { 1594 | symbol: 'SNY-USDC', 1595 | name: 'SNY-USDC LP', 1596 | coin: { ...TOKENS.SNY }, 1597 | pc: { ...TOKENS.USDC }, 1598 | 1599 | mintAddress: 'G8qcfeFqxwbCqpxv5LpLWxUCd1PyMB5nWb5e5YyxLMKg', 1600 | decimals: TOKENS.SNY.decimals 1601 | }, 1602 | 'BOP-RAY-V4': { 1603 | symbol: 'BOP-RAY', 1604 | name: 'BOP-RAY LP', 1605 | coin: { ...TOKENS.BOP }, 1606 | pc: { ...TOKENS.RAY }, 1607 | 1608 | mintAddress: '9nQPYJvysyfnXhQ6nkK5V7sZG26hmDgusfdNQijRk5LD', 1609 | decimals: TOKENS.BOP.decimals 1610 | }, 1611 | 'SLRS-USDC-V4': { 1612 | symbol: 'SLRS-USDC', 1613 | name: 'SLRS-USDC LP', 1614 | coin: { ...TOKENS.SLRS }, 1615 | pc: { ...TOKENS.USDC }, 1616 | 1617 | mintAddress: '2Xxbm1hdv5wPeen5ponDSMT3VqhGMTQ7mH9stNXm9shU', 1618 | decimals: TOKENS.SLRS.decimals 1619 | }, 1620 | 'SAMO-RAY-V4': { 1621 | symbol: 'SAMO-RAY', 1622 | name: 'SAMO-RAY LP', 1623 | coin: { ...TOKENS.SAMO }, 1624 | pc: { ...TOKENS.RAY }, 1625 | 1626 | mintAddress: 'HwzkXyX8B45LsaHXwY8su92NoRBS5GQC32HzjQRDqPnr', 1627 | decimals: TOKENS.SAMO.decimals 1628 | }, 1629 | 'renBTC-USDC-V4': { 1630 | symbol: 'renBTC-USDC', 1631 | name: 'renBTC-USDC LP', 1632 | coin: { ...TOKENS.renBTC }, 1633 | pc: { ...TOKENS.USDC }, 1634 | 1635 | mintAddress: 'CTEpsih91ZLo5gunvryLpJ3pzMjmt5jbS6AnSQrzYw7V', 1636 | decimals: TOKENS.renBTC.decimals 1637 | }, 1638 | 'renDOGE-USDC-V4': { 1639 | symbol: 'renDOGE-USDC', 1640 | name: 'renDOGE-USDC LP', 1641 | coin: { ...TOKENS.renDOGE }, 1642 | pc: { ...TOKENS.USDC }, 1643 | 1644 | mintAddress: 'Hb8KnZNKvRxu7pgMRWJgoMSMcepfvNiBFFDDrdf9o3wA', 1645 | decimals: TOKENS.renDOGE.decimals 1646 | }, 1647 | 'RAY-USDC-V4': { 1648 | symbol: 'RAY-USDC', 1649 | name: 'RAY-USDC LP', 1650 | coin: { ...TOKENS.RAY }, 1651 | pc: { ...TOKENS.USDC }, 1652 | 1653 | mintAddress: 'FbC6K13MzHvN42bXrtGaWsvZY9fxrackRSZcBGfjPc7m', 1654 | decimals: TOKENS.RAY.decimals 1655 | }, 1656 | 'RAY-SRM-V4': { 1657 | symbol: 'RAY-SRM', 1658 | name: 'RAY-SRM LP', 1659 | coin: { ...TOKENS.RAY }, 1660 | pc: { ...TOKENS.SRM }, 1661 | 1662 | mintAddress: '7P5Thr9Egi2rvMmEuQkLn8x8e8Qro7u2U7yLD2tU2Hbe', 1663 | decimals: TOKENS.RAY.decimals 1664 | }, 1665 | 'RAY-ETH-V4': { 1666 | symbol: 'RAY-ETH', 1667 | name: 'RAY-ETH LP', 1668 | coin: { ...TOKENS.RAY }, 1669 | pc: { ...TOKENS.ETH }, 1670 | 1671 | mintAddress: 'mjQH33MqZv5aKAbKHi8dG3g3qXeRQqq1GFcXceZkNSr', 1672 | decimals: TOKENS.RAY.decimals 1673 | }, 1674 | 'RAY-SOL-V4': { 1675 | symbol: 'RAY-SOL', 1676 | name: 'RAY-SOL LP', 1677 | coin: { ...TOKENS.RAY }, 1678 | pc: { ...NATIVE_SOL }, 1679 | 1680 | mintAddress: '89ZKE4aoyfLBe2RuV6jM3JGNhaV18Nxh8eNtjRcndBip', 1681 | decimals: TOKENS.RAY.decimals 1682 | }, 1683 | 'DXL-USDC-V4': { 1684 | symbol: 'DXL-USDC', 1685 | name: 'DXL-USDC LP', 1686 | coin: { ...TOKENS.DXL }, 1687 | pc: { ...TOKENS.USDC }, 1688 | 1689 | mintAddress: '4HFaSvfgskipvrzT1exoVKsUZ174JyExEsA8bDfsAdY5', 1690 | decimals: TOKENS.DXL.decimals 1691 | }, 1692 | 'LIKE-USDC-V4': { 1693 | symbol: 'LIKE-USDC', 1694 | name: 'LIKE-USDC LP', 1695 | coin: { ...TOKENS.LIKE }, 1696 | pc: { ...TOKENS.USDC }, 1697 | 1698 | mintAddress: 'cjZmbt8sJgaoyWYUttomAu5LJYU44ZrcKTbzTSEPDVw', 1699 | decimals: TOKENS.LIKE.decimals 1700 | }, 1701 | 'mSOL-USDC-V4': { 1702 | symbol: 'mSOL-USDC', 1703 | name: 'mSOL-USDC LP', 1704 | coin: { ...TOKENS.mSOL }, 1705 | pc: { ...TOKENS.USDC }, 1706 | 1707 | mintAddress: '4xTpJ4p76bAeggXoYywpCCNKfJspbuRzZ79R7pRhbqSf', 1708 | decimals: TOKENS.mSOL.decimals 1709 | }, 1710 | 'mSOL-SOL-V4': { 1711 | symbol: 'mSOL-SOL', 1712 | name: 'mSOL-SOL LP', 1713 | coin: { ...TOKENS.mSOL }, 1714 | pc: { ...NATIVE_SOL }, 1715 | 1716 | mintAddress: '5ijRoAHVgd5T5CNtK5KDRUBZ7Bffb69nktMj5n6ks6m4', 1717 | decimals: TOKENS.mSOL.decimals 1718 | }, 1719 | 'MER-PAI-V4': { 1720 | symbol: 'MER-PAI', 1721 | name: 'MER-PAI LP', 1722 | coin: { ...TOKENS.MER }, 1723 | pc: { ...TOKENS.PAI }, 1724 | 1725 | mintAddress: 'DU5RT2D9EviaSmX6Ta8MZwMm85HwSEqGMRdqUiuCGfmD', 1726 | decimals: TOKENS.MER.decimals 1727 | }, 1728 | 'PORT-USDC-V4': { 1729 | symbol: 'PORT-USDC', 1730 | name: 'PORT-USDC LP', 1731 | coin: { ...TOKENS.PORT }, 1732 | pc: { ...TOKENS.USDC }, 1733 | 1734 | mintAddress: '9tmNtbUCrLS15qC4tEfr5NNeqcqpZ4uiGgi2vS5CLQBS', 1735 | decimals: TOKENS.PORT.decimals 1736 | }, 1737 | 'MNGO-USDC-V4': { 1738 | symbol: 'MNGO-USDC', 1739 | name: 'MNGO-USDC LP', 1740 | coin: { ...TOKENS.MNGO }, 1741 | pc: { ...TOKENS.USDC }, 1742 | 1743 | mintAddress: 'DkiqCQ792n743xjWQVCbBUaVtkdiuvQeYndM53ReWnCC', 1744 | decimals: TOKENS.MNGO.decimals 1745 | }, 1746 | 'ATLAS-USDC-V4': { 1747 | symbol: 'ATLAS-USDC', 1748 | name: 'ATLAS-USDC LP', 1749 | coin: { ...TOKENS.ATLAS }, 1750 | pc: { ...TOKENS.USDC }, 1751 | 1752 | mintAddress: '9shGU9f1EsxAbiR567MYZ78WUiS6ZNCYbHe53WUULQ7n', 1753 | decimals: TOKENS.ATLAS.decimals 1754 | }, 1755 | 'POLIS-USDC-V4': { 1756 | symbol: 'POLIS-USDC', 1757 | name: 'POLIS-USDC LP', 1758 | coin: { ...TOKENS.POLIS }, 1759 | pc: { ...TOKENS.USDC }, 1760 | 1761 | mintAddress: '8MbKSBpyXs8fVneKgt71jfHrn5SWtX8n4wMLpiVfF9So', 1762 | decimals: TOKENS.POLIS.decimals 1763 | }, 1764 | 'ATLAS-RAY-V4': { 1765 | symbol: 'ATLAS-RAY', 1766 | name: 'ATLAS-RAY LP', 1767 | coin: { ...TOKENS.ATLAS }, 1768 | pc: { ...TOKENS.RAY }, 1769 | 1770 | mintAddress: '418MFhkaYQtbn529wmjLLqL6uKxDz7j4eZBaV1cobkyd', 1771 | decimals: TOKENS.ATLAS.decimals 1772 | }, 1773 | 'POLIS-RAY-V4': { 1774 | symbol: 'POLIS-RAY', 1775 | name: 'POLIS-RAY LP', 1776 | coin: { ...TOKENS.POLIS }, 1777 | pc: { ...TOKENS.RAY }, 1778 | 1779 | mintAddress: '9ysGKUH6WqzjQEUT4dxqYCUaFNVK9QFEa24pGzjFq8xg', 1780 | decimals: TOKENS.POLIS.decimals 1781 | }, 1782 | 'ALEPH-RAY-V4': { 1783 | symbol: 'ALEPH-RAY', 1784 | name: 'ALEPH-RAY LP', 1785 | coin: { ...TOKENS.ALEPH }, 1786 | pc: { ...TOKENS.RAY }, 1787 | 1788 | mintAddress: 'n76skjqv4LirhdLok2zJELXNLdRpYDgVJQuQFbamscy', 1789 | decimals: TOKENS.ALEPH.decimals 1790 | }, 1791 | 'TULIP-RAY-V4': { 1792 | symbol: 'TULIP-RAY', 1793 | name: 'TULIP-RAY LP', 1794 | coin: { ...TOKENS.TULIP }, 1795 | pc: { ...TOKENS.RAY }, 1796 | 1797 | mintAddress: '3AZTviji5qduMG2s4FfWGR3SSQmNUCyx8ao6UKCPg3oJ', 1798 | decimals: TOKENS.TULIP.decimals 1799 | }, 1800 | 'SLRS-RAY-V4': { 1801 | symbol: 'SLRS-RAY', 1802 | name: 'SLRS-RAY LP', 1803 | coin: { ...TOKENS.SLRS }, 1804 | pc: { ...TOKENS.RAY }, 1805 | 1806 | mintAddress: '2pk78vsKT3jfJAcN2zbpMUnrR57SZrxHqaZYyFgp92mM', 1807 | decimals: TOKENS.SLRS.decimals 1808 | }, 1809 | 'MER-RAY-V4': { 1810 | symbol: 'MER-RAY', 1811 | name: 'MER-RAY LP', 1812 | coin: { ...TOKENS.MER }, 1813 | pc: { ...TOKENS.RAY }, 1814 | 1815 | mintAddress: '214hxy3AbKoaEKgqcg2aC1cP5R67cGGAyDEg5GDwC7Ub', 1816 | decimals: TOKENS.MER.decimals 1817 | }, 1818 | 'MEDIA-RAY-V4': { 1819 | symbol: 'MEDIA-RAY', 1820 | name: 'MEDIA-RAY LP', 1821 | coin: { ...TOKENS.MEDIA }, 1822 | pc: { ...TOKENS.RAY }, 1823 | 1824 | mintAddress: '9Aseg5A1JD1yCiFFdDaNNxCiJ7XzrpZFmcEmLjXFdPaH', 1825 | decimals: TOKENS.MEDIA.decimals 1826 | }, 1827 | 'SNY-RAY-V4': { 1828 | symbol: 'SNY-RAY', 1829 | name: 'SNY-RAY LP', 1830 | coin: { ...TOKENS.SNY }, 1831 | pc: { ...TOKENS.RAY }, 1832 | 1833 | mintAddress: '2k4quTuuLUxrSEhFH99qcoZzvgvVEc3b5sz3xz3qstfS', 1834 | decimals: TOKENS.SNY.decimals 1835 | }, 1836 | 'LIKE-RAY-V4': { 1837 | symbol: 'LIKE-RAY', 1838 | name: 'LIKE-RAY LP', 1839 | coin: { ...TOKENS.LIKE }, 1840 | pc: { ...TOKENS.RAY }, 1841 | 1842 | mintAddress: '7xqDycbFSCpUpzkYapFeyPJWPwEpV7zdWbYf2MVHTNjv', 1843 | decimals: TOKENS.LIKE.decimals 1844 | }, 1845 | 'COPE-RAY-V4': { 1846 | symbol: 'COPE-RAY', 1847 | name: 'COPE-RAY LP', 1848 | coin: { ...TOKENS.COPE }, 1849 | pc: { ...TOKENS.RAY }, 1850 | 1851 | mintAddress: 'A7GCVHA8NSsbdFscHdoNU41tL1TRKNmCH4K94CgcLK9F', 1852 | decimals: TOKENS.COPE.decimals 1853 | }, 1854 | 'ETH-SOL-V4': { 1855 | symbol: 'ETH-SOL', 1856 | name: 'ETH-SOL LP', 1857 | coin: { ...TOKENS.ETH }, 1858 | pc: { ...NATIVE_SOL }, 1859 | 1860 | mintAddress: 'GKfgC86iJoMjwAtcyiLu6nWnjggqUXsDQihXkP14fDez', 1861 | decimals: TOKENS.ETH.decimals 1862 | }, 1863 | 'stSOL-USDC-V4': { 1864 | symbol: 'stSOL-USDC', 1865 | name: 'stSOL-USDC LP', 1866 | coin: { ...TOKENS.stSOL }, 1867 | pc: { ...TOKENS.USDC }, 1868 | 1869 | mintAddress: 'HDUJMwYZkjUZre63xUeDhdCi8c6LgUDiBqxmP3QC3VPX', 1870 | decimals: TOKENS.stSOL.decimals 1871 | }, 1872 | 'GRAPE-USDC-V4': { 1873 | symbol: 'GRAPE-USDC', 1874 | name: 'GRAPE-USDC LP', 1875 | coin: { ...TOKENS.GRAPE }, 1876 | pc: { ...TOKENS.USDC }, 1877 | 1878 | mintAddress: 'A8ZYmnZ1vwxUa4wpJVUaJgegsuTEz5TKy5CiJXffvmpt', 1879 | decimals: TOKENS.GRAPE.decimals 1880 | }, 1881 | 'LARIX-USDC-V4': { 1882 | symbol: 'LARIX-USDC', 1883 | name: 'LARIX-USDC LP', 1884 | coin: { ...TOKENS.LARIX }, 1885 | pc: { ...TOKENS.USDC }, 1886 | 1887 | mintAddress: '7yieit4YsNsZ9CAK8H5ZEMvvk35kPEHHeXwp6naoWU9V', 1888 | decimals: TOKENS.LARIX.decimals 1889 | }, 1890 | 'RIN-USDC-V4': { 1891 | symbol: 'RIN-USDC', 1892 | name: 'RIN-USDC LP', 1893 | coin: { ...TOKENS.RIN }, 1894 | pc: { ...TOKENS.USDC }, 1895 | 1896 | mintAddress: 'GfCWfrZez7BDmCSEeMERVDVUaaM2TEreyYUgb2cpuS3w', 1897 | decimals: TOKENS.RIN.decimals 1898 | }, 1899 | 'APEX-USDC-V4': { 1900 | symbol: 'APEX-USDC', 1901 | name: 'APEX-USDC LP', 1902 | coin: { ...TOKENS.APEX }, 1903 | pc: { ...TOKENS.USDC }, 1904 | 1905 | mintAddress: '444cVqYyDxJNo6FqiMb9qQWFUd7tYzFRdDuJRFrSAGnU', 1906 | decimals: TOKENS.APEX.decimals 1907 | }, 1908 | 'mSOL-RAY-V4': { 1909 | symbol: 'mSOL-RAY', 1910 | name: 'mSOL-RAY LP', 1911 | coin: { ...TOKENS.mSOL }, 1912 | pc: { ...TOKENS.RAY }, 1913 | 1914 | mintAddress: 'De2EHBAdkgfc72DpShqDGG42cV3iDWh8wvvZdPsiEcqP', 1915 | decimals: TOKENS.mSOL.decimals 1916 | }, 1917 | 'MNDE-mSOL-V4': { 1918 | symbol: 'MNDE-mSOL', 1919 | name: 'MNDE-mSOL LP', 1920 | coin: { ...TOKENS.MNDE }, 1921 | pc: { ...TOKENS.mSOL }, 1922 | 1923 | mintAddress: '4bh8XCzTHSbqbWN8o1Jn4ueBdz1LvJFoEasN6K6CQ8Ny', 1924 | decimals: TOKENS.MNDE.decimals 1925 | }, 1926 | 'LARIX-RAY-V4': { 1927 | symbol: 'LARIX-RAY', 1928 | name: 'LARIX-RAY LP', 1929 | coin: { ...TOKENS.LARIX }, 1930 | pc: { ...TOKENS.RAY }, 1931 | 1932 | mintAddress: 'ZRDfSLgWGeaYSmhdPvFNKQQhDcYdZQaue2N8YDmHX4q', 1933 | decimals: TOKENS.LARIX.decimals 1934 | }, 1935 | 'LIQ-USDC-V4': { 1936 | symbol: 'LIQ-USDC', 1937 | name: 'LIQ-USDC LP', 1938 | coin: { ...TOKENS.LIQ }, 1939 | pc: { ...TOKENS.USDC }, 1940 | 1941 | mintAddress: 'GWpD3eTfhJB5KDCcnE85dBQrjAk2CsrgDF9b52R9CrjV', 1942 | decimals: TOKENS.LIQ.decimals 1943 | }, 1944 | 'WAG-USDC-V4': { 1945 | symbol: 'WAG-USDC', 1946 | name: 'WAG-USDC LP', 1947 | coin: { ...TOKENS.WAG }, 1948 | pc: { ...TOKENS.USDC }, 1949 | 1950 | mintAddress: '4yykyPugitUVRewNPXXCviRvxGfsfsRMoP32z3b6FmUC', 1951 | decimals: TOKENS.WAG.decimals 1952 | }, 1953 | 'ETH-mSOL-V4': { 1954 | symbol: 'ETH-mSOL', 1955 | name: 'ETH-mSOL LP', 1956 | coin: { ...TOKENS.ETH }, 1957 | pc: { ...TOKENS.mSOL }, 1958 | 1959 | mintAddress: 'HYv3grQfi8QbV7nG7EFgNK1aJSrsJ7HynXJKJVPLL2Uh', 1960 | decimals: TOKENS.ETH.decimals 1961 | }, 1962 | 'mSOL-USDT-V4': { 1963 | symbol: 'mSOL-USDT', 1964 | name: 'mSOL-USDT LP', 1965 | coin: { ...TOKENS.mSOL }, 1966 | pc: { ...TOKENS.USDT }, 1967 | 1968 | mintAddress: '69NCmEW9mGpiWLjAcAWHq51k4ionJZmzgRfRT3wQaCCf', 1969 | decimals: TOKENS.mSOL.decimals 1970 | }, 1971 | 'BTC-mSOL-V4': { 1972 | symbol: 'BTC-mSOL', 1973 | name: 'BTC-mSOL LP', 1974 | coin: { ...TOKENS.BTC }, 1975 | pc: { ...TOKENS.mSOL }, 1976 | 1977 | mintAddress: '92bcERNtUmuaJ6mwLSxYHZYSph37jdKxRdoYNxpcYNPp', 1978 | decimals: TOKENS.BTC.decimals 1979 | }, 1980 | 'SLIM-SOL-V4': { 1981 | symbol: 'SLIM-SOL', 1982 | name: 'SLIM-SOL LP', 1983 | coin: { ...TOKENS.SLIM }, 1984 | pc: { ...NATIVE_SOL }, 1985 | 1986 | mintAddress: '9X4EK8E59VAVi6ChnNvvd39m6Yg9RtkBbAPq1mDVJT57', 1987 | decimals: TOKENS.SLIM.decimals 1988 | }, 1989 | 'AURY-USDC-V4': { 1990 | symbol: 'AURY-USDC', 1991 | name: 'AURY-USDC LP', 1992 | coin: { ...TOKENS.AURY }, 1993 | pc: { ...TOKENS.USDC }, 1994 | 1995 | mintAddress: 'Gub5dvTy4nzP82qpmpNkBxmRqjtqRddBTBqHSdNcf2oS', 1996 | decimals: TOKENS.AURY.decimals 1997 | }, 1998 | 'PRT-SOL-V4': { 1999 | symbol: 'PRT-SOL', 2000 | name: 'PRT-SOL LP', 2001 | coin: { ...TOKENS.PRT }, 2002 | pc: { ...NATIVE_SOL }, 2003 | 2004 | mintAddress: 'EcJ8Wgwt1AzSPiDpVr6aaSur8TKAsNTPmmzRACeqT68Z', 2005 | decimals: TOKENS.PRT.decimals 2006 | }, 2007 | 'LIQ-RAY-V4': { 2008 | symbol: 'LIQ-RAY', 2009 | name: 'LIQ-RAY LP', 2010 | coin: { ...TOKENS.LIQ }, 2011 | pc: { ...TOKENS.RAY }, 2012 | 2013 | mintAddress: '49YUsDrThJosHSagCn1F59Uc9NRxbr9thVrZikUnQDXy', 2014 | decimals: TOKENS.LIQ.decimals 2015 | }, 2016 | 'SYP-SOL-V4': { 2017 | symbol: 'SYP-SOL', 2018 | name: 'SYP-SOL LP', 2019 | coin: { ...TOKENS.SYP }, 2020 | pc: { ...NATIVE_SOL }, 2021 | 2022 | mintAddress: 'KHV6dfj2bDntzJ9z1S26cDfqWfUZdJRFmteLR6LxHwW', 2023 | decimals: TOKENS.SYP.decimals 2024 | }, 2025 | 'SYP-RAY-V4': { 2026 | symbol: 'SYP-RAY', 2027 | name: 'SYP-RAY LP', 2028 | coin: { ...TOKENS.SYP }, 2029 | pc: { ...TOKENS.RAY }, 2030 | 2031 | mintAddress: 'FT2KZqxxM8F2h9pZtTF4PyjK88bM4YbuBzd7ZPwQ5wMB', 2032 | decimals: TOKENS.SYP.decimals 2033 | }, 2034 | 'SYP-USDC-V4': { 2035 | symbol: 'SYP-USDC', 2036 | name: 'SYP-USDC LP', 2037 | coin: { ...TOKENS.SYP }, 2038 | pc: { ...TOKENS.USDC }, 2039 | 2040 | mintAddress: '2xJGuLAivAR1WkARRA6zP1v4jaA9jV2Qis8JfMNvrVyZ', 2041 | decimals: TOKENS.SYP.decimals 2042 | }, 2043 | 'FAB-USDC-V4': { 2044 | symbol: 'FAB-USDC', 2045 | name: 'FAB-USDC LP', 2046 | coin: { ...TOKENS.FAB }, 2047 | pc: { ...TOKENS.USDC }, 2048 | 2049 | mintAddress: '5rTCvZq6BcApsC3VV1EEUuTJfaVd8uYhcGjwTy1By6P8', 2050 | decimals: TOKENS.FAB.decimals 2051 | }, 2052 | 'WOOF-RAY-V4': { 2053 | symbol: 'WOOF-RAY', 2054 | name: 'WOOF-RAY LP', 2055 | coin: { ...TOKENS.WOOF }, 2056 | pc: { ...TOKENS.RAY }, 2057 | 2058 | mintAddress: 'H2FAnazDaGFutcmnrwDxhmdncR1Bd7GG4mhPCSUiamDX', 2059 | decimals: TOKENS.WOOF.decimals 2060 | }, 2061 | 'WOOF-USDC-V4': { 2062 | symbol: 'WOOF-USDC', 2063 | name: 'WOOF-USDC LP', 2064 | coin: { ...TOKENS.WOOF }, 2065 | pc: { ...TOKENS.USDC }, 2066 | 2067 | mintAddress: 'EFSu5TMc1ijRevaYCxUkS7uGvbhsymDHEaTK3UVdNE3q', 2068 | decimals: TOKENS.WOOF.decimals 2069 | }, 2070 | 'SLND-USDC-V4': { 2071 | symbol: 'SLND-USDC', 2072 | name: 'SLND-USDC LP', 2073 | coin: { ...TOKENS.SLND }, 2074 | pc: { ...TOKENS.USDC }, 2075 | 2076 | mintAddress: 'EunE9uDh2cGsyJcsGuGKc6wte7kBn8iye2gzC4w2ePHn', 2077 | decimals: TOKENS.SLND.decimals 2078 | }, 2079 | 'FRKT-SOL-V4': { 2080 | symbol: 'FRKT-SOL', 2081 | name: 'FRKT-SOL LP', 2082 | coin: { ...TOKENS.FRKT }, 2083 | pc: { ...NATIVE_SOL }, 2084 | 2085 | mintAddress: 'HYUKXgpjaxMXHttyrFYtv3z2rdhZ1U9QDH8zEc8BooQC', 2086 | decimals: TOKENS.FRKT.decimals 2087 | }, 2088 | 'weWETH-SOL-V4': { 2089 | symbol: 'weWETH-SOL', 2090 | name: 'weWETH-SOL LP', 2091 | coin: { ...TOKENS.weWETH }, 2092 | pc: { ...NATIVE_SOL }, 2093 | 2094 | mintAddress: '3hbozt2Por7bcrGod8N7kEeJNMocFFjCJrQR16TQGBrE', 2095 | decimals: TOKENS.weWETH.decimals 2096 | }, 2097 | 'weWETH-USDC-V4': { 2098 | symbol: 'weWETH-USDC', 2099 | name: 'weWETH-USDC LP', 2100 | coin: { ...TOKENS.weWETH }, 2101 | pc: { ...TOKENS.USDC }, 2102 | 2103 | mintAddress: '3529SBnMCDW3S3xQ52aABbRHo7PcHvpQA4no8J12L5eK', 2104 | decimals: TOKENS.weWETH.decimals 2105 | }, 2106 | 'weUNI-USDC-V4': { 2107 | symbol: 'weUNI-USDC', 2108 | name: 'weUNI-USDC LP', 2109 | coin: { ...TOKENS.weUNI }, 2110 | pc: { ...TOKENS.USDC }, 2111 | 2112 | mintAddress: 'EEC4QnT41py39QaYnzQnoYQEtDUDNa6Se8SBDgfPSN2a', 2113 | decimals: TOKENS.weUNI.decimals 2114 | }, 2115 | 'weSUSHI-USDC-V4': { 2116 | symbol: 'weSUSHI-USDC', 2117 | name: 'weSUSHI-USDC LP', 2118 | coin: { ...TOKENS.weSUSHI }, 2119 | pc: { ...TOKENS.USDC }, 2120 | 2121 | mintAddress: '3wVrtQZsiDNp5yTPyfEzQHPU6iuJoMmpnWg6CTt4V8sR', 2122 | decimals: TOKENS.weSUSHI.decimals 2123 | }, 2124 | 'CYS-USDC-V4': { 2125 | symbol: 'CYS-USDC', 2126 | name: 'CYS-USDC LP', 2127 | coin: { ...TOKENS.CYS }, 2128 | pc: { ...TOKENS.USDC }, 2129 | 2130 | mintAddress: 'GfV3QDzzdVUwCNSdfn6PjhmyJvjw18tn51RingWZYwk3', 2131 | decimals: TOKENS.CYS.decimals 2132 | }, 2133 | 'SAMO-USDC-V4': { 2134 | symbol: 'SAMO-USDC', 2135 | name: 'SAMO-USDC LP', 2136 | coin: { ...TOKENS.SAMO }, 2137 | pc: { ...TOKENS.USDC }, 2138 | 2139 | mintAddress: 'B2PjGEP3vPf1999fUD14pYdxvSDRVBk43hxB2rgthwEY', 2140 | decimals: TOKENS.SAMO.decimals 2141 | }, 2142 | 'ABR-USDC-V4': { 2143 | symbol: 'ABR-USDC', 2144 | name: 'ABR-USDC LP', 2145 | coin: { ...TOKENS.ABR }, 2146 | pc: { ...TOKENS.USDC }, 2147 | 2148 | mintAddress: 'ECHfxkf5zjjZFTX95QfFahNyzG7feyEKcfTdjsdrMSGU', 2149 | decimals: TOKENS.ABR.decimals 2150 | }, 2151 | 'IN-USDC-V4': { 2152 | symbol: 'IN-USDC', 2153 | name: 'IN-USDC LP', 2154 | coin: { ...TOKENS.IN }, 2155 | pc: { ...TOKENS.USDC }, 2156 | 2157 | mintAddress: 'GbmJtVgg9fRmmmjKUYGMZeSt8wZ47cDDXasg5Y3iF4kz', 2158 | decimals: TOKENS.IN.decimals 2159 | }, 2160 | 'weDYDX-USDC-V4': { 2161 | symbol: 'weDYDX-USDC', 2162 | name: 'weDYDX-USDC LP', 2163 | coin: { ...TOKENS.weDYDX }, 2164 | pc: { ...TOKENS.USDC }, 2165 | 2166 | mintAddress: 'BjkkMZnnzmgLqzGErzDbkk15ozv48iVKQuunpeM2Hqnk', 2167 | decimals: TOKENS.weDYDX.decimals 2168 | }, 2169 | 'STARS-USDC-V4': { 2170 | symbol: 'STARS-USDC', 2171 | name: 'STARS-USDC LP', 2172 | coin: { ...TOKENS.STARS }, 2173 | pc: { ...TOKENS.USDC }, 2174 | 2175 | mintAddress: 'FJ68q7NChhETcGVdinMbM2FF1Cy79dpmUi6HC83K55Hv', 2176 | decimals: TOKENS.STARS.decimals 2177 | }, 2178 | 'weAXS-USDC-V4': { 2179 | symbol: 'weAXS-USDC', 2180 | name: 'weAXS-USDC LP', 2181 | coin: { ...TOKENS.weAXS }, 2182 | pc: { ...TOKENS.USDC }, 2183 | 2184 | mintAddress: '6PSoJQ7myQ1BJtbQC6oiWR8HSecQGyoWsPYTZRJo2ci3', 2185 | decimals: TOKENS.weAXS.decimals 2186 | }, 2187 | 'weSHIB-USDC-V4': { 2188 | symbol: 'weSHIB-USDC', 2189 | name: 'weSHIB-USDC LP', 2190 | coin: { ...TOKENS.weSHIB }, 2191 | pc: { ...TOKENS.USDC }, 2192 | 2193 | mintAddress: 'AcjX5pmTMGSgxkdxc3r82r6WMKBvS6eQXXFz5ck5KKUa', 2194 | decimals: TOKENS.weSHIB.decimals 2195 | }, 2196 | 'SBR-USDC-V4': { 2197 | symbol: 'SBR-USDC', 2198 | name: 'SBR-USDC LP', 2199 | coin: { ...TOKENS.SBR }, 2200 | pc: { ...TOKENS.USDC }, 2201 | 2202 | mintAddress: '9FC8xTFRbgTpuZZYAYnZLxgnQ8r7FwfSBM1SWvGwgF7s', 2203 | decimals: TOKENS.SBR.decimals 2204 | }, 2205 | 'OXS-USDC-V4': { 2206 | symbol: 'OXS-USDC', 2207 | name: 'OXS-USDC LP', 2208 | coin: { ...TOKENS.OXS }, 2209 | pc: { ...TOKENS.USDC }, 2210 | 2211 | mintAddress: 'et9pdjWm97rbmsJoN183GkFV5qzTGru79GE1Zhe7NTU', 2212 | decimals: TOKENS.OXS.decimals 2213 | }, 2214 | 'CWAR-USDC-V4': { 2215 | symbol: 'CWAR-USDC', 2216 | name: 'CWAR-USDC LP', 2217 | coin: { ...TOKENS.CWAR }, 2218 | pc: { ...TOKENS.USDC }, 2219 | 2220 | mintAddress: 'HjR23bxn2gtRDB2P1Tm3DLepAPPZgazsWJpLG9wqjnYR', 2221 | decimals: TOKENS.CWAR.decimals 2222 | }, 2223 | 'UPS-USDC-V4': { 2224 | symbol: 'UPS-USDC', 2225 | name: 'UPS-USDC LP', 2226 | coin: { ...TOKENS.UPS }, 2227 | pc: { ...TOKENS.USDC }, 2228 | 2229 | mintAddress: '9hSUZdREEsbaYaKY4FouvXr7xyAqtpdHRDoYCb6Mb28a', 2230 | decimals: TOKENS.UPS.decimals 2231 | }, 2232 | 'weSAND-USDC-V4': { 2233 | symbol: 'weSAND-USDC', 2234 | name: 'weSAND-USDC LP', 2235 | coin: { ...TOKENS.weSAND }, 2236 | pc: { ...TOKENS.USDC }, 2237 | 2238 | mintAddress: '3dADrQa7utyiCsaFeVk9r7oebW1WheowhKo5soBYKBVT', 2239 | decimals: TOKENS.weSAND.decimals 2240 | }, 2241 | 'weMANA-USDC-V4': { 2242 | symbol: 'weMANA-USDC', 2243 | name: 'weMANA-USDC LP', 2244 | coin: { ...TOKENS.weMANA }, 2245 | pc: { ...TOKENS.USDC }, 2246 | 2247 | mintAddress: 'HpUkVAPRJ5zNRuJ1ZwMXEhbMHL3gSuPb2QuSER9YUd3a', 2248 | decimals: TOKENS.weMANA.decimals 2249 | }, 2250 | 'CAVE-USDC-V4': { 2251 | symbol: 'CAVE-USDC', 2252 | name: 'CAVE-USDC LP', 2253 | coin: { ...TOKENS.CAVE }, 2254 | pc: { ...TOKENS.USDC }, 2255 | 2256 | mintAddress: '5Gba1k3fU7Vh7UtAiBmie9vhQNNq1JfEwgn1DPGZ7NKQ', 2257 | decimals: TOKENS.CAVE.decimals 2258 | }, 2259 | 'GENE-USDC-V4': { 2260 | symbol: 'GENE-USDC', 2261 | name: 'GENE-USDC LP', 2262 | coin: { ...TOKENS.GENE }, 2263 | pc: { ...TOKENS.USDC }, 2264 | 2265 | mintAddress: '7GKvfHEXenNiWYbJBKae89mdaMPr5gGMYwZmyC8gBNVG', 2266 | decimals: TOKENS.GENE.decimals 2267 | }, 2268 | 'GENE-RAY-V4': { 2269 | symbol: 'GENE-RAY', 2270 | name: 'GENE-RAY LP', 2271 | coin: { ...TOKENS.GENE }, 2272 | pc: { ...TOKENS.RAY }, 2273 | 2274 | mintAddress: '3HzXnc1qZ8mGqun18Ck3KA616XnZNqF1RWbgYE2nGRMA', 2275 | decimals: TOKENS.GENE.decimals 2276 | }, 2277 | 'APT-USDC-V4': { 2278 | symbol: 'APT-USDC', 2279 | name: 'APT-USDC LP', 2280 | coin: { ...TOKENS.APT }, 2281 | pc: { ...TOKENS.USDC }, 2282 | 2283 | mintAddress: 'Hk8mDAJFq4E9kF3DtNgPFwzbo5kbeiusNFJgWmo3LoQ5', 2284 | decimals: TOKENS.APT.decimals 2285 | }, 2286 | 'GOFX-USDC-V4': { 2287 | symbol: 'GOFX-USDC', 2288 | name: 'GOFX-USDC LP', 2289 | coin: { ...TOKENS.GOFX }, 2290 | pc: { ...TOKENS.USDC }, 2291 | 2292 | mintAddress: '4svqAwrLPGRDCQuuieYTmtLXF75wiahjeK2rEN9tY1YL', 2293 | decimals: TOKENS.GOFX.decimals 2294 | }, 2295 | 'SONAR-USDC-V4': { 2296 | symbol: 'SONAR-USDC', 2297 | name: 'SONAR-USDC LP', 2298 | coin: { ...TOKENS.SONAR }, 2299 | pc: { ...TOKENS.USDC }, 2300 | 2301 | mintAddress: '2tAcfqJ1YYjpGLqwh76kyNt9VaNFDd4fJySfH6SmWfKt', 2302 | decimals: TOKENS.SONAR.decimals 2303 | }, 2304 | 'JSOL-SOL-V4': { 2305 | symbol: 'JSOL-SOL', 2306 | name: 'JSOL-SOL LP', 2307 | coin: { ...TOKENS.JSOL }, 2308 | pc: { ...NATIVE_SOL }, 2309 | 2310 | mintAddress: '61z37rpHsU6d3Fq5sUjJ85K6tXGzkoYKDAG3kPJQNDRo', 2311 | decimals: TOKENS.JSOL.decimals 2312 | }, 2313 | 'JSOL-USDC-V4': { 2314 | symbol: 'JSOL-USDC', 2315 | name: 'JSOL-USDC LP', 2316 | coin: { ...TOKENS.JSOL }, 2317 | pc: { ...TOKENS.USDC }, 2318 | 2319 | mintAddress: '3JZqf2VPNxj1kDZQsfzC7myM6spsGQbGuFv1gVfdYosN', 2320 | decimals: TOKENS.JSOL.decimals 2321 | }, 2322 | 'SHILL-USDC-V4': { 2323 | symbol: 'SHILL-USDC', 2324 | name: 'SHILL-USDC LP', 2325 | coin: { ...TOKENS.SHILL }, 2326 | pc: { ...TOKENS.USDC }, 2327 | 2328 | mintAddress: 'CnUhYBtQEbSBZ76bgxAouVCTCb8rofZzwerVF5z5LREJ', 2329 | decimals: TOKENS.SHILL.decimals 2330 | }, 2331 | 'DFL-USDC-V4': { 2332 | symbol: 'DFL-USDC', 2333 | name: 'DFL-USDC LP', 2334 | coin: { ...TOKENS.DFL }, 2335 | pc: { ...TOKENS.USDC }, 2336 | 2337 | mintAddress: 'Fffijd6UVJdQeLVXhenS8YcsnMUdWJqpbBeH42LFkXgS', 2338 | decimals: TOKENS.DFL.decimals 2339 | }, 2340 | 'BOKU-USDC-V4': { 2341 | symbol: 'BOKU-USDC', 2342 | name: 'BOKU-USDC LP', 2343 | coin: { ...TOKENS.BOKU }, 2344 | pc: { ...TOKENS.USDC }, 2345 | 2346 | mintAddress: '8jjQn5Yagb6Nm2WGAxPW1bcGqrTWpg5adf6QukXEarcP', 2347 | decimals: TOKENS.BOKU.decimals 2348 | }, 2349 | 'MIMO-SOL-V4': { 2350 | symbol: 'MIMO-SOL', 2351 | name: 'MIMO-SOL LP', 2352 | coin: { ...TOKENS.MIMO }, 2353 | pc: { ...NATIVE_SOL }, 2354 | 2355 | mintAddress: 'HUJ1opSk8AiPfDT47r7n4hTiK2EXgrR3Msy7T8q1BywS', 2356 | decimals: TOKENS.MIMO.decimals 2357 | }, 2358 | 'wbWBNB-USDC-V4': { 2359 | symbol: 'wbWBNB-USDC', 2360 | name: 'wbWBNB-USDC LP', 2361 | coin: { ...TOKENS.wbWBNB }, 2362 | pc: { ...TOKENS.USDC }, 2363 | 2364 | mintAddress: 'FEsEfEJJSfiMQcshUgZ5UigfytfGRQ3z5puyF6DXDp9C', 2365 | decimals: TOKENS.wbWBNB.decimals 2366 | }, 2367 | 'wePEOPLE-USDC-V4': { 2368 | symbol: 'wePEOPLE-USDC', 2369 | name: 'wePEOPLE-USDC LP', 2370 | coin: { ...TOKENS.wePEOPLE }, 2371 | pc: { ...TOKENS.USDC }, 2372 | 2373 | mintAddress: '3e5ZCKi4etorpV4pv1fSckP5iJD67xcUkx3RtFCZhbzD', 2374 | decimals: TOKENS.wePEOPLE.decimals 2375 | }, 2376 | 'ISOLA-USDT-V4': { 2377 | symbol: 'ISOLA-USDT', 2378 | name: 'ISOLA-USDT LP', 2379 | coin: { ...TOKENS.ISOLA }, 2380 | pc: { ...TOKENS.USDT }, 2381 | 2382 | mintAddress: 'H8s1wQsZpRK61pyLF3XwyQc6E8vNUnwRDhy3TBDCDENQ', 2383 | decimals: TOKENS.ISOLA.decimals 2384 | }, 2385 | 'SPWN-USDC-V4': { 2386 | symbol: 'SPWN-USDC', 2387 | name: 'SPWN-USDC LP', 2388 | coin: { ...TOKENS.SPWN }, 2389 | pc: { ...TOKENS.USDC }, 2390 | 2391 | mintAddress: 'B5uyCAQcX6nAjZypLgiivbEKabSptgUb8JK9tkaSnqdW', 2392 | decimals: TOKENS.SPWN.decimals 2393 | }, 2394 | 'STR-USDC-V4': { 2395 | symbol: 'STR-USDC', 2396 | name: 'STR-USDC LP', 2397 | coin: { ...TOKENS.STR }, 2398 | pc: { ...TOKENS.USDC }, 2399 | 2400 | mintAddress: '8uDVKmVwNmbXHDB7rNKqtpcT9VAsFHTJ5pPYxjyoBbNg', 2401 | decimals: TOKENS.STR.decimals 2402 | }, 2403 | 'SOLC-USDT-V4': { 2404 | symbol: 'SOLC-USDT', 2405 | name: 'SOLC-USDT LP', 2406 | coin: { ...TOKENS.SOLC }, 2407 | pc: { ...TOKENS.USDT }, 2408 | 2409 | mintAddress: '2g9JzTWycLzK4KEBBHsponAtZRee2ii63bRrJ8tefEyt', 2410 | decimals: TOKENS.SOLC.decimals 2411 | }, 2412 | 'VI-USDC-V4': { 2413 | symbol: 'VI-USDC', 2414 | name: 'VI-USDC LP', 2415 | coin: { ...TOKENS.VI }, 2416 | pc: { ...TOKENS.USDC }, 2417 | 2418 | mintAddress: '3MwHyHCRfVqtH3ABFtdKXdY9dwemr9GGxQFaBkeq6NjY', 2419 | decimals: TOKENS.VI.decimals 2420 | }, 2421 | 'KKO-USDC-V4': { 2422 | symbol: 'KKO-USDC', 2423 | name: 'KKO-USDC LP', 2424 | coin: { ...TOKENS.KKO }, 2425 | pc: { ...TOKENS.USDC }, 2426 | 2427 | mintAddress: '7xr1Doc1NiMWbUg99YVFqQSLfYXNzo6YvacXUsSgBMNW', 2428 | decimals: TOKENS.KKO.decimals 2429 | }, 2430 | 'XTAG-USDC-V4': { 2431 | symbol: 'XTAG-USDC', 2432 | name: 'XTAG-USDC LP', 2433 | coin: { ...TOKENS.XTAG }, 2434 | pc: { ...TOKENS.USDC }, 2435 | 2436 | mintAddress: 'GCEQbLg4ik5YJ4CMcbtuVqEc4sjLdSGy34rFk1CtGjdg', 2437 | decimals: TOKENS.XTAG.decimals 2438 | }, 2439 | 'TTT-USDC-V4': { 2440 | symbol: 'TTT-USDC', 2441 | name: 'TTT-USDC LP', 2442 | coin: { ...TOKENS.TTT }, 2443 | pc: { ...TOKENS.USDC }, 2444 | 2445 | mintAddress: '84fmrerHGohoRf4iLPDQ1KG4CjSjCRksYWGzjWfCRM8a', 2446 | decimals: TOKENS.TTT.decimals 2447 | }, 2448 | 'RUN-USDC-V4': { 2449 | symbol: 'RUN-USDC', 2450 | name: 'RUN-USDC LP', 2451 | coin: { ...TOKENS.RUN }, 2452 | pc: { ...TOKENS.USDC }, 2453 | 2454 | mintAddress: 'CjTLvvKSQdEujcSzeZRYgk4w1DpuXBbMppLHaxZyz11Y', 2455 | decimals: TOKENS.RUN.decimals 2456 | }, 2457 | 'CRWNY-USDC-V4': { 2458 | symbol: 'CRWNY-USDC', 2459 | name: 'CRWNY-USDC LP', 2460 | coin: { ...TOKENS.CRWNY }, 2461 | pc: { ...TOKENS.USDC }, 2462 | 2463 | mintAddress: 'H3D9Gyi4frRLW6bS9vBthDVDJyzyRJ6XhhpP6PJGWaDC', 2464 | decimals: TOKENS.CRWNY.decimals 2465 | }, 2466 | 'CRWNY-RAY-V4': { 2467 | symbol: 'CRWNY-RAY', 2468 | name: 'CRWNY-RAY LP', 2469 | coin: { ...TOKENS.CRWNY }, 2470 | pc: { ...TOKENS.RAY }, 2471 | 2472 | mintAddress: '5Cz9wGStNjiUg81q8t6sJJeckuT2C14CYSfyQbtYirSX', 2473 | decimals: TOKENS.CRWNY.decimals 2474 | }, 2475 | 'BLOCK-USDC-V4': { 2476 | symbol: 'BLOCK-USDC', 2477 | name: 'BLOCK-USDC LP', 2478 | coin: { ...TOKENS.BLOCK }, 2479 | pc: { ...TOKENS.USDC }, 2480 | 2481 | mintAddress: '8i44Y23GkkwDYZ5iSkVEqmrXUfwNmwo9grguTDWKM8wg', 2482 | decimals: TOKENS.BLOCK.decimals 2483 | }, 2484 | 'REAL-USDC-V4': { 2485 | symbol: 'REAL-USDC', 2486 | name: 'REAL-USDC LP', 2487 | coin: { ...TOKENS.REAL }, 2488 | pc: { ...TOKENS.USDC }, 2489 | 2490 | mintAddress: 'EN43tp8xdkcM8RYSJ4msFHMPTJRXKhUteVYBDJLwTvr3', 2491 | decimals: TOKENS.REAL.decimals 2492 | } 2493 | } 2494 | 2495 | function addUserLocalCoinMint() { 2496 | const localMintStr = window.localStorage.user_add_coin_mint 2497 | const localMintList = (localMintStr ?? '').split('---') 2498 | if (localMintList.length % 3 !== 0) { 2499 | window.localStorage.removeItem('user_add_coin_mint') 2500 | } else { 2501 | for (let index = 0; index < Math.floor(localMintList.length / 3); index += 1) { 2502 | const name = localMintList[index * 3 + 0] 2503 | const mintAddress = localMintList[index * 3 + 1] 2504 | const decimals = localMintList[index * 3 + 2] 2505 | if (!Object.values(TOKENS).find((item) => item.mintAddress === mintAddress)) { 2506 | TOKENS[name + mintAddress + 'unofficialUserAdd'] = { 2507 | name, 2508 | symbol: name, 2509 | decimals: parseInt(decimals), 2510 | mintAddress, 2511 | tags: ['userAdd'] 2512 | } 2513 | } else if ( 2514 | !Object.values(TOKENS) 2515 | .find((item) => item.mintAddress === mintAddress) 2516 | .tags.includes('userAdd') 2517 | ) { 2518 | Object.values(TOKENS) 2519 | .find((item) => item.mintAddress === mintAddress) 2520 | .tags.push('userAdd') 2521 | } 2522 | } 2523 | } 2524 | } 2525 | 2526 | // fake 2527 | const BLACK_LIST = ['3pX59cis3ZXnX6ZExPoUQjpvJVspmj4YavtUmpTpkB33'] 2528 | 2529 | function blockBlackList(tokens: { address: string }[]) { 2530 | return tokens.filter((item) => !BLACK_LIST.includes(item.address)) 2531 | } 2532 | 2533 | function addTokensSolana() { 2534 | fetch('https://api.raydium.io/cache/solana-token-list') 2535 | .then(async (response) => { 2536 | addTokensSolanaFunc(blockBlackList((await response.json()).tokens)) 2537 | }) 2538 | .catch(() => { 2539 | fetch('https://raw.githubusercontent.com/solana-labs/token-list/main/src/tokens/solana.tokenlist.json') 2540 | .then(function (response) { 2541 | return response.json() 2542 | }) 2543 | .then(function (myJson) { 2544 | addTokensSolanaFunc(blockBlackList(myJson.tokens)) 2545 | }) 2546 | }) 2547 | } 2548 | 2549 | const notUseSolanaPicMint: string[] = [TOKENS.TTT.mintAddress] 2550 | 2551 | function addTokensSolanaFunc(tokens: any[]) { 2552 | tokens.forEach((itemToken: any) => { 2553 | if (itemToken.tags && itemToken.tags.includes('lp-token')) { 2554 | return 2555 | } 2556 | if (!Object.values(TOKENS).find((item) => item.mintAddress === itemToken.address)) { 2557 | TOKENS[itemToken.symbol + itemToken.address + 'solana'] = { 2558 | symbol: itemToken.symbol, 2559 | name: itemToken.name, 2560 | mintAddress: itemToken.address, 2561 | decimals: itemToken.decimals, 2562 | picUrl: itemToken.logoURI, 2563 | tags: ['solana'] 2564 | } 2565 | } else { 2566 | const token = Object.values(TOKENS).find((item) => item.mintAddress === itemToken.address) 2567 | if (token.symbol !== itemToken.symbol && !token.tags.includes('raydium')) { 2568 | token.symbol = itemToken.symbol 2569 | token.name = itemToken.name 2570 | token.decimals = itemToken.decimals 2571 | token.tags.push('solana') 2572 | } 2573 | const picToken = Object.values(TOKENS).find((item) => item.mintAddress === itemToken.address) 2574 | if (picToken && !notUseSolanaPicMint.includes(itemToken.address)) { 2575 | picToken.picUrl = itemToken.logoURI 2576 | } 2577 | } 2578 | }) 2579 | 2580 | if (window.localStorage.addSolanaCoin) { 2581 | window.localStorage.addSolanaCoin.split('---').forEach((itemMint: string) => { 2582 | if (itemMint === NATIVE_SOL.mintAddress) NATIVE_SOL.tags.push('userAdd') 2583 | else 2584 | Object.keys(TOKENS).forEach((item) => { 2585 | if (TOKENS[item].mintAddress === itemMint) { 2586 | TOKENS[item].tags.push('userAdd') 2587 | } 2588 | }) 2589 | }) 2590 | } 2591 | } 2592 | 2593 | function updateTokenTagsChange() { 2594 | const userSelectSource = window.localStorage.userSelectSource ?? '' 2595 | const userSelectSourceList: string[] = userSelectSource.split('---') 2596 | for (const itemSource of userSelectSourceList) { 2597 | if (TOKENS_TAGS[itemSource] && !TOKENS_TAGS[itemSource].mustShow) { 2598 | TOKENS_TAGS[itemSource].show = true 2599 | } 2600 | } 2601 | } 2602 | 2603 | addUserLocalCoinMint() 2604 | addTokensSolana() 2605 | updateTokenTagsChange() 2606 | -------------------------------------------------------------------------------- /utils/types.d.ts: -------------------------------------------------------------------------------- 1 | 2 | declare global { 3 | 4 | // tokens.ts 5 | interface TokenInfo { 6 | symbol: string 7 | name: string 8 | 9 | mintAddress: string 10 | decimals: number 11 | totalSupply?: TokenAmount 12 | 13 | referrer?: string 14 | 15 | details?: string 16 | docs?: object 17 | socials?: object 18 | 19 | tokenAccountAddress?: string 20 | balance?: TokenAmount 21 | tags: string[] 22 | } 23 | 24 | // pools.ts 25 | 26 | interface LiquidityPoolInfo { 27 | name: string; 28 | coin: TokenInfo; 29 | pc: TokenInfo; 30 | lp: TokenInfo; 31 | 32 | version: number; 33 | programId: string; 34 | 35 | ammId: string; 36 | ammAuthority: string; 37 | ammOpenOrders: string; 38 | ammTargetOrders: string; 39 | ammQuantities: string; 40 | 41 | poolCoinTokenAccount: string; 42 | poolPcTokenAccount: string; 43 | poolWithdrawQueue: string; 44 | poolTempLpTokenAccount: string; 45 | 46 | serumProgramId: string; 47 | serumMarket: string; 48 | serumBids?: string; 49 | serumAsks?: string; 50 | serumEventQueue?: string; 51 | serumCoinVaultAccount: string; 52 | serumPcVaultAccount: string; 53 | serumVaultSigner: string; 54 | 55 | official: boolean; 56 | 57 | status?: number; 58 | currentK?: number; 59 | } 60 | } 61 | export {} -------------------------------------------------------------------------------- /utils/web3.ts: -------------------------------------------------------------------------------- 1 | import { initializeAccount } from "@project-serum/serum/lib/token-instructions"; 2 | import { WalletContextState } from "@solana/wallet-adapter-react"; 3 | 4 | // @ts-ignore without ts ignore, yarn build will failed 5 | import { Token } from "@solana/spl-token"; 6 | import { 7 | Keypair, // Account is deprecated, using Keypair instead 8 | Commitment, 9 | Connection, 10 | PublicKey, 11 | TransactionSignature, 12 | Transaction, 13 | SystemProgram, 14 | AccountInfo, 15 | LAMPORTS_PER_SOL 16 | } from "@solana/web3.js"; 17 | 18 | import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from "./ids"; 19 | import { ACCOUNT_LAYOUT } from "./layouts"; 20 | 21 | export const commitment: Commitment = "confirmed"; 22 | export async function createTokenAccountIfNotExist( // returns Token Account 23 | connection: Connection, 24 | account: string | undefined | null, 25 | owner: PublicKey, 26 | mintAddress: string, 27 | lamports: number | null, 28 | 29 | transaction: Transaction, 30 | signer: Array 31 | ) : Promise { 32 | let publicKey; 33 | 34 | if (account) { 35 | publicKey = new PublicKey(account); 36 | } else { 37 | publicKey = await createProgramAccountIfNotExist( 38 | connection, 39 | account, 40 | owner, 41 | TOKEN_PROGRAM_ID, 42 | lamports, 43 | ACCOUNT_LAYOUT, 44 | transaction, 45 | signer 46 | ); 47 | 48 | transaction.add( 49 | initializeAccount({ 50 | account: publicKey, 51 | mint: new PublicKey(mintAddress), 52 | owner 53 | }) 54 | ); 55 | } 56 | return publicKey; 57 | } 58 | 59 | export async function createAssociatedTokenAccountIfNotExist( 60 | account: string | undefined | null, 61 | owner: PublicKey, 62 | mintAddress: string, 63 | 64 | transaction: Transaction, 65 | atas: string[] = [] 66 | ) { 67 | let publicKey; 68 | if (account) { 69 | publicKey = new PublicKey(account); 70 | } 71 | 72 | const mint = new PublicKey(mintAddress); 73 | // @ts-ignore without ts ignore, yarn build will failed 74 | const ata = await Token.getAssociatedTokenAddress( 75 | ASSOCIATED_TOKEN_PROGRAM_ID, 76 | TOKEN_PROGRAM_ID, 77 | mint, 78 | owner, 79 | true 80 | ); 81 | 82 | if ( 83 | (!publicKey || !ata.equals(publicKey)) && 84 | !atas.includes(ata.toBase58()) 85 | ) { 86 | transaction.add( 87 | Token.createAssociatedTokenAccountInstruction( 88 | ASSOCIATED_TOKEN_PROGRAM_ID, 89 | TOKEN_PROGRAM_ID, 90 | mint, 91 | ata, 92 | owner, 93 | owner 94 | ) 95 | ); 96 | atas.push(ata.toBase58()); 97 | } 98 | 99 | return ata; 100 | } 101 | 102 | export async function sendTransaction( 103 | connection: Connection, 104 | wallet: any, 105 | transaction: Transaction, 106 | signers: Array = [] 107 | ) { 108 | const txid: TransactionSignature = await wallet.sendTransaction( 109 | transaction, 110 | connection, 111 | { 112 | signers, 113 | skipPreflight: true, 114 | preflightCommitment: commitment 115 | } 116 | ); 117 | 118 | return txid; 119 | } 120 | 121 | export async function createProgramAccountIfNotExist( 122 | connection: Connection, 123 | account: string | undefined | null, 124 | owner: PublicKey, 125 | programId: PublicKey, 126 | lamports: number | null, 127 | layout: any, 128 | 129 | transaction: Transaction, 130 | signer: Array 131 | ) { 132 | let publicKey; 133 | 134 | if (account) { 135 | publicKey = new PublicKey(account); 136 | } else { 137 | const newAccount = new Keypair(); 138 | publicKey = newAccount.publicKey; 139 | 140 | transaction.add( 141 | SystemProgram.createAccount({ 142 | fromPubkey: owner, 143 | newAccountPubkey: publicKey, 144 | lamports: 145 | lamports ?? 146 | (await connection.getMinimumBalanceForRentExemption(layout.span)), 147 | space: layout.span, 148 | programId 149 | }) 150 | ); 151 | 152 | signer.push(newAccount); 153 | } 154 | 155 | return publicKey; 156 | } 157 | 158 | export async function findAssociatedTokenAddress( 159 | walletAddress: PublicKey, 160 | tokenMintAddress: PublicKey 161 | ) { 162 | const { publicKey } = await findProgramAddress( 163 | [ 164 | walletAddress.toBuffer(), 165 | TOKEN_PROGRAM_ID.toBuffer(), 166 | tokenMintAddress.toBuffer() 167 | ], 168 | ASSOCIATED_TOKEN_PROGRAM_ID 169 | ); 170 | return publicKey; 171 | } 172 | 173 | export async function findProgramAddress( 174 | seeds: Array, 175 | programId: PublicKey 176 | ) { 177 | const [publicKey, nonce] = await PublicKey.findProgramAddress( 178 | seeds, 179 | programId 180 | ); 181 | return { publicKey, nonce }; 182 | } 183 | 184 | export async function getMultipleAccounts( 185 | connection: Connection, 186 | publicKeys: PublicKey[], 187 | commitment?: Commitment 188 | ): Promise }>> { 189 | const keys: PublicKey[][] = []; 190 | let tempKeys: PublicKey[] = []; 191 | 192 | publicKeys.forEach(k => { 193 | if (tempKeys.length >= 100) { 194 | keys.push(tempKeys); 195 | tempKeys = []; 196 | } 197 | tempKeys.push(k); 198 | }); 199 | if (tempKeys.length > 0) { 200 | keys.push(tempKeys); 201 | } 202 | 203 | const accounts: Array = []; 209 | const resArray: { [key: number]: any } = {}; 210 | 211 | await Promise.all( 212 | keys.map(async (key, index) => { 213 | const res = await connection.getMultipleAccountsInfo(key, commitment); 214 | resArray[index] = res; 215 | }) 216 | ); 217 | 218 | Object.keys(resArray) 219 | .sort((a, b) => parseInt(a) - parseInt(b)) 220 | .forEach(itemIndex => { 221 | const res = resArray[parseInt(itemIndex)]; 222 | for (const account of res) { 223 | accounts.push(account); 224 | } 225 | }); 226 | 227 | return accounts.map((account, idx) => { 228 | if (account === null) { 229 | return null; 230 | } 231 | return { 232 | publicKey: publicKeys[idx], 233 | account 234 | }; 235 | }); 236 | } 237 | 238 | export async function getFilteredProgramAccountsAmmOrMarketCache( 239 | cacheName: String, 240 | connection: Connection, 241 | programId: PublicKey, 242 | filters: any 243 | ): Promise<{ publicKey: PublicKey; accountInfo: AccountInfo }[]> { 244 | try { 245 | if (!cacheName) { 246 | throw new Error("cacheName error"); 247 | } 248 | 249 | const resp = await ( 250 | await fetch("https://api.raydium.io/cache/rpc/" + cacheName) 251 | ).json(); 252 | if (resp.error) { 253 | throw new Error(resp.error.message); 254 | } 255 | // @ts-ignore 256 | return resp.result.map( 257 | // @ts-ignore 258 | ({ pubkey, account: { data, executable, owner, lamports } }) => ({ 259 | publicKey: new PublicKey(pubkey), 260 | accountInfo: { 261 | data: Buffer.from(data[0], "base64"), 262 | executable, 263 | owner: new PublicKey(owner), 264 | lamports 265 | } 266 | }) 267 | ); 268 | } catch (e) { 269 | return getFilteredProgramAccounts(connection, programId, filters); 270 | } 271 | } 272 | 273 | export async function getFilteredProgramAccounts( 274 | connection: Connection, 275 | programId: PublicKey, 276 | filters: any 277 | ): Promise<{ publicKey: PublicKey; accountInfo: AccountInfo }[]> { 278 | // @ts-ignore 279 | const resp = await connection._rpcRequest("getProgramAccounts", [ 280 | programId.toBase58(), 281 | { 282 | commitment: connection.commitment, 283 | filters, 284 | encoding: "base64" 285 | } 286 | ]); 287 | if (resp.error) { 288 | throw new Error(resp.error.message); 289 | } 290 | return resp.result.map( 291 | // @ts-ignore 292 | ({ pubkey, account: { data, executable, owner, lamports } }) => ({ 293 | publicKey: new PublicKey(pubkey), 294 | accountInfo: { 295 | data: Buffer.from(data[0], "base64"), 296 | executable, 297 | owner: new PublicKey(owner), 298 | lamports 299 | } 300 | }) 301 | ); 302 | } 303 | 304 | export async function createAmmAuthority(programId: PublicKey) { 305 | return await findProgramAddress( 306 | [ 307 | new Uint8Array( 308 | Buffer.from("amm authority".replace("\u00A0", " "), "utf-8") 309 | ) 310 | ], 311 | programId 312 | ); 313 | } 314 | // export interface ISplToken { 315 | // pubkey: string; 316 | // parsedInfo: any; 317 | // amount: number; 318 | // } 319 | 320 | export const getSPLTokenData = async ( 321 | wallet: WalletContextState, 322 | connection: Connection 323 | ): Promise => { 324 | if (!wallet.connected) { 325 | return []; 326 | } 327 | const res = await connection.getParsedTokenAccountsByOwner( 328 | wallet.publicKey!, 329 | { 330 | programId: new PublicKey(TOKEN_PROGRAM_ID) 331 | }, 332 | "confirmed" 333 | ); 334 | // Get all SPL tokens owned by connected wallet 335 | let data = await connection.getAccountInfo(wallet.publicKey!); 336 | 337 | let list = res.value.map(item => { 338 | let token = { 339 | pubkey: item.pubkey.toBase58(), 340 | parsedInfo: item.account.data.parsed.info, 341 | amount: 342 | item.account.data.parsed.info.tokenAmount.amount / 343 | 10 ** item.account.data.parsed.info.tokenAmount.decimals 344 | }; 345 | // Filter out empty account 346 | if (item.account.data.parsed.info.tokenAmount.decimals === 0) { 347 | return undefined; 348 | } else { 349 | return token; 350 | } 351 | }); 352 | // Add SOL into list 353 | list.push({ 354 | //@ts-ignore 355 | pubkey: wallet.publicKey?.toBase58(), 356 | parsedInfo: { 357 | mint: data?.owner.toBase58() 358 | }, 359 | //@ts-ignore 360 | amount: data?.lamports / LAMPORTS_PER_SOL 361 | }); 362 | return list as ISplToken[]; 363 | }; 364 | --------------------------------------------------------------------------------