├── .eslintrc.json ├── public ├── favicon.ico ├── vercel.svg └── next.svg ├── src ├── pages │ ├── _document.tsx │ ├── api │ │ ├── gas.ts │ │ ├── wallet │ │ │ ├── tx-info.ts │ │ │ ├── mint.ts │ │ │ ├── wallets.ts │ │ │ ├── portfolio.ts │ │ │ └── transactions.ts │ │ ├── token-info.ts │ │ ├── honeypot.ts │ │ ├── flashbot.ts │ │ └── cancel.ts │ ├── _app.tsx │ └── index.tsx ├── utils │ ├── wallet.ts │ ├── honeypot.ts │ ├── balance.ts │ ├── transfer.ts │ ├── pending.ts │ ├── buy.ts │ └── sell.ts ├── hooks │ ├── useGasPrice.ts │ ├── useGetTokenInfo.ts │ ├── useGetTxInfo.ts │ ├── usePortfolio.ts │ ├── useGetWallets.ts │ ├── useGetMintWalletInfo.ts │ ├── useGetTransactions.ts │ └── useChangeMintWallet.ts └── components │ ├── Layout │ └── Layout.tsx │ ├── Transactions │ ├── Transactions.tsx │ └── TransactionsCard.tsx │ ├── Button │ └── ShakingButton │ │ └── ShakingButton.tsx │ ├── Portfolio │ ├── Portfolio.tsx │ └── PortfolioCard.tsx │ ├── TokenInfo │ └── TokenInfo.tsx │ ├── Wallet │ ├── Wallet.tsx │ ├── WalletModal.tsx │ └── WalletCard.tsx │ ├── NavBar │ └── NavBar.tsx │ └── Buying │ └── Buying.tsx ├── theme.tsx ├── .gitignore ├── sentry.edge.config.js ├── sentry.client.config.js ├── tsconfig.json ├── .env ├── sentry.server.config.js ├── next.config.js ├── package.json └── README.md /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelshimeles/memecoin-bot/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import { Html, Head, Main, NextScript } from 'next/document' 2 | 3 | export default function Document() { 4 | return ( 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /src/utils/wallet.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "ethers"; 2 | 3 | export const createWallets = () => { 4 | const wallet = ethers.Wallet.createRandom(); 5 | 6 | // console.log("address:", wallet.address); 7 | // console.log("mnemonic:", wallet.mnemonic.phrase); 8 | // console.log("privateKey:", wallet.privateKey); 9 | 10 | return { 11 | address: wallet.address, 12 | private_key: wallet.privateKey, 13 | }; 14 | }; 15 | -------------------------------------------------------------------------------- /src/pages/api/gas.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | export default async function handler( 4 | _req: NextApiRequest, 5 | res: NextApiResponse 6 | ) { 7 | try { 8 | const response = await fetch(`https://api.zerion.io/v1/gas-prices/`); 9 | const data = await response.json(); 10 | return res.status(200).json(data); 11 | } catch (err) { 12 | return res.status(400).json(err); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/utils/honeypot.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | 3 | export const honeypot = async (address: string) => { 4 | try { 5 | const response = await axios.get("https://api.honeypot.is/v2/IsHoneypot", { 6 | params: { 7 | address, 8 | }, 9 | 10 | }); 11 | 12 | console.log("API", response?.data); 13 | 14 | return response?.data; 15 | } catch (err) { 16 | console.log(err); 17 | return err; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /src/pages/api/wallet/tx-info.ts: -------------------------------------------------------------------------------- 1 | import { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | export default async (req: NextApiRequest, res: NextApiResponse) => { 4 | try { 5 | const response = await fetch(`https://protect.flashbots.net/tx/${req.query?.hash}`); 6 | const data = await response.json(); 7 | return res.status(200).json(data); 8 | } catch (err) { 9 | console.error(err); 10 | return res.status(400).json(err); 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /src/pages/api/token-info.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | export default async function handler( 4 | req: NextApiRequest, 5 | res: NextApiResponse 6 | ) { 7 | try { 8 | const response = await fetch( 9 | `https://api.dexscreener.com/latest/dex/tokens/${req.query?.tokenAddress}` 10 | ); 11 | const data = await response.json(); 12 | return res.status(200).json(data); 13 | } catch (err) { 14 | return res.status(400).json(err); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/hooks/useGasPrice.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | 4 | function fetchGasPrice() { 5 | return axios 6 | .get(`${process.env.NEXT_PUBLIC_URL}/api/gas`) 7 | .then((result) => { 8 | return result?.data; 9 | }) 10 | .catch((error) => { 11 | return error; 12 | }); 13 | } 14 | 15 | export const useGasPrice = () => { 16 | return useQuery({ 17 | queryKey: ["gas-price"], 18 | queryFn: () => fetchGasPrice(), 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /theme.tsx: -------------------------------------------------------------------------------- 1 | // 1. Import the extendTheme function 2 | import { extendTheme, theme as base } from "@chakra-ui/react"; 3 | const config = { 4 | initialColorMode: "dark", 5 | useSystemColorMode: true, 6 | }; 7 | 8 | export default extendTheme({ 9 | fonts: { 10 | // heading: `'Oswald', ${base.fonts?.heading}`, 11 | // body: `'Oswald', ${base.fonts?.body}`, 12 | }, 13 | config: { 14 | ...config, 15 | colors: { 16 | black: "#000000", // "#131416", 17 | white: "#FFFFFF", 18 | }, 19 | }, 20 | }); 21 | -------------------------------------------------------------------------------- /.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 | 30 | # vercel 31 | .vercel 32 | 33 | # typescript 34 | *.tsbuildinfo 35 | next-env.d.ts 36 | -------------------------------------------------------------------------------- /src/components/Layout/Layout.tsx: -------------------------------------------------------------------------------- 1 | import { VStack } from "@chakra-ui/react"; 2 | import dynamic from "next/dynamic"; 3 | import React from "react"; 4 | 5 | const NavBar = dynamic(() => import("../NavBar/NavBar"), { ssr: false }); 6 | 7 | interface LayoutProps { 8 | children: any; 9 | } 10 | 11 | const Layout: React.FC = ({ children }) => { 12 | return ( 13 | 14 | 15 | {children} 16 | 17 | ); 18 | }; 19 | 20 | export default Layout; 21 | -------------------------------------------------------------------------------- /src/utils/balance.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "ethers"; 2 | 3 | export const getBalance = (address: string) => { 4 | const network = "homestead"; // use Ethereum mainnet 5 | const apiKey = process.env.NEXT_PUBLIC_ALCHEMY_ID; // replace with your Alchemy API key 6 | const provider = new ethers.providers.AlchemyProvider(network, apiKey); 7 | 8 | return provider.getBalance(address).then((balance) => { 9 | // convert a currency unit from wei to ether 10 | const balanceInEth = ethers.utils.formatEther(balance); 11 | 12 | return balanceInEth; 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /sentry.edge.config.js: -------------------------------------------------------------------------------- 1 | import * as Sentry from "@sentry/nextjs"; 2 | 3 | Sentry.init({ 4 | dsn: "https://dda5bf57e020407da1f927b464541a23@o4505143961649152.ingest.sentry.io/4505143963287552", 5 | 6 | // We recommend adjusting this value in production, or using tracesSampler 7 | // for finer control 8 | tracesSampleRate: 1.0, 9 | 10 | // ... 11 | 12 | // Note: if you want to override the automatic release value, do not set a 13 | // `release` value here - use the environment variable `SENTRY_RELEASE`, so 14 | // that it will also get attached to your source maps 15 | }); -------------------------------------------------------------------------------- /sentry.client.config.js: -------------------------------------------------------------------------------- 1 | import * as Sentry from "@sentry/nextjs"; 2 | 3 | Sentry.init({ 4 | dsn: "https://dda5bf57e020407da1f927b464541a23@o4505143961649152.ingest.sentry.io/4505143963287552", 5 | 6 | // This sets the sample rate to be 10%. You may want this to be 100% while 7 | // in development and sample at a lower rate in production 8 | replaysSessionSampleRate: 0.1, 9 | // If the entire session is not sampled, use the below sample rate to sample 10 | // sessions when an error occurs. 11 | replaysOnErrorSampleRate: 1.0, 12 | tracesSampleRate: 1.0, 13 | 14 | integrations: [new Sentry.Replay()], 15 | }); -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/api/wallet/mint.ts: -------------------------------------------------------------------------------- 1 | import { NextApiRequest, NextApiResponse } from "next"; 2 | import { createServerSupabaseClient } from "@supabase/auth-helpers-nextjs"; 3 | 4 | export default async (req: NextApiRequest, res: NextApiResponse) => { 5 | const supabase = createServerSupabaseClient({ 6 | req, 7 | res, 8 | }); 9 | 10 | let { data: walletInfo, error } = await supabase 11 | .from("wallet") 12 | .select("*") 13 | .eq("username", req.query?.username); 14 | 15 | if (walletInfo) { 16 | return res.status(200).json(walletInfo[0]); 17 | } 18 | 19 | if (error) { 20 | return res.status(400).json(error); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /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 | "paths": { 18 | "@/*": ["./src/*"] 19 | } 20 | }, 21 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 22 | "exclude": ["node_modules"] 23 | } 24 | -------------------------------------------------------------------------------- /src/hooks/useGetTokenInfo.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | 4 | function fetchTokenInfo(tokenAddress: string) { 5 | return axios 6 | .get(`${process.env.NEXT_PUBLIC_URL}/api/token-info`, { 7 | params: { 8 | tokenAddress, 9 | }, 10 | }) 11 | .then((result) => { 12 | return result?.data; 13 | }) 14 | .catch((error) => { 15 | return error; 16 | }); 17 | } 18 | 19 | export const useGetTokenInfo = (tokenAddress: string) => { 20 | return useQuery({ 21 | queryKey: ["token-info", tokenAddress], 22 | queryFn: () => fetchTokenInfo(tokenAddress), 23 | }); 24 | }; 25 | -------------------------------------------------------------------------------- /src/hooks/useGetTxInfo.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | 4 | function fetchTransactions(hash: string) { 5 | return axios 6 | .get(`${process.env.NEXT_PUBLIC_URL}/api/wallet/tx-info`, { 7 | params: { 8 | hash, 9 | }, 10 | }) 11 | .then((result) => { 12 | return result?.data; 13 | }) 14 | .catch((error) => { 15 | return error; 16 | }); 17 | } 18 | 19 | export const useGetTxInfo = (hash?: string) => { 20 | return useQuery({ 21 | queryKey: ["tx-info", hash], 22 | queryFn: () => (hash ? fetchTransactions(hash) : undefined), 23 | enabled: !!hash, 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /src/pages/api/wallet/wallets.ts: -------------------------------------------------------------------------------- 1 | import { NextApiRequest, NextApiResponse } from "next"; 2 | import { createServerSupabaseClient } from "@supabase/auth-helpers-nextjs"; 3 | 4 | export default async (req: NextApiRequest, res: NextApiResponse) => { 5 | const supabase = createServerSupabaseClient({ 6 | req, 7 | res, 8 | }); 9 | 10 | const { data: wallets, error } = await supabase 11 | .from("wallets") 12 | .select() 13 | .eq("username", req.query?.username) 14 | .order("active", { ascending: true }); 15 | 16 | if (wallets) { 17 | return res.status(200).json(wallets); 18 | } 19 | 20 | if (error) { 21 | return res.status(400).json(error); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /src/hooks/usePortfolio.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | 4 | function fetchPortfolio(address: string) { 5 | return axios 6 | .get(`${process.env.NEXT_PUBLIC_URL}/api/wallet/portfolio`, { 7 | params: { 8 | address, 9 | }, 10 | }) 11 | .then((result) => { 12 | return result?.data; 13 | }) 14 | .catch((error) => { 15 | return error; 16 | }); 17 | } 18 | 19 | export const usePortfolio = (address?: string) => { 20 | return useQuery({ 21 | queryKey: ["portfolio", address], 22 | queryFn: () => (address ? fetchPortfolio(address) : undefined), 23 | enabled: !!address, 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /src/hooks/useGetWallets.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | 4 | function fetchGetWallets(username: string) { 5 | return axios 6 | .get(`${process.env.NEXT_PUBLIC_URL}/api/wallet/wallets`, { 7 | params: { 8 | username, 9 | }, 10 | }) 11 | .then((result) => { 12 | return result?.data; 13 | }) 14 | .catch((error) => { 15 | return error; 16 | }); 17 | } 18 | 19 | export const useGetWalletInfo = (username?: string) => { 20 | return useQuery({ 21 | queryKey: ["wallets", username], 22 | queryFn: () => (username ? fetchGetWallets(username) : undefined), 23 | enabled: !!username, 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /src/hooks/useGetMintWalletInfo.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | 4 | function fetchMintWallet(username: string) { 5 | return axios 6 | .get(`${process.env.NEXT_PUBLIC_URL}/api/wallet/mint`, { 7 | params: { 8 | username, 9 | }, 10 | }) 11 | .then((result) => { 12 | return result?.data; 13 | }) 14 | .catch((error) => { 15 | return error; 16 | }); 17 | } 18 | 19 | export const useGetMintWalletInfo = (username?: string) => { 20 | return useQuery({ 21 | queryKey: ["mint-wallet", username], 22 | queryFn: () => (username ? fetchMintWallet(username) : undefined), 23 | enabled: !!username, 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /src/hooks/useGetTransactions.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | 4 | function fetchTransactions(username: string) { 5 | return axios 6 | .get(`${process.env.NEXT_PUBLIC_URL}/api/wallet/transactions`, { 7 | params: { 8 | username, 9 | }, 10 | }) 11 | .then((result) => { 12 | return result?.data; 13 | }) 14 | .catch((error) => { 15 | return error; 16 | }); 17 | } 18 | 19 | export const useGetTransactions = (username?: string) => { 20 | return useQuery({ 21 | queryKey: ["transactions", username], 22 | queryFn: () => (username ? fetchTransactions(username) : undefined), 23 | enabled: !!username, 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /src/pages/api/wallet/portfolio.ts: -------------------------------------------------------------------------------- 1 | import { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | export default async function handler( 4 | req: NextApiRequest, 5 | res: NextApiResponse 6 | ) { 7 | const options = { 8 | method: "GET", 9 | headers: { 10 | accept: "application/json", 11 | authorization: 12 | `Basic ${process.env.NEXT_PUBLIC_ZERION}`, 13 | }, 14 | }; 15 | 16 | try { 17 | const response = await fetch( 18 | `https://api.zerion.io/v1/wallets/${req?.query?.address}/positions/`, 19 | options 20 | ); 21 | const data = await response.json(); 22 | return res.status(200).json(data); 23 | } catch (err) { 24 | return res.status(400).json(err); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/pages/api/wallet/transactions.ts: -------------------------------------------------------------------------------- 1 | import { NextApiRequest, NextApiResponse } from "next"; 2 | import { createServerSupabaseClient } from "@supabase/auth-helpers-nextjs"; 3 | 4 | export default async (req: NextApiRequest, res: NextApiResponse) => { 5 | const supabase = createServerSupabaseClient({ 6 | req, 7 | res, 8 | }); 9 | 10 | let { data: transactions, error } = await supabase 11 | .from("transactions") 12 | .select("*") 13 | .eq("username", req.query?.username) 14 | .order("created_at", { 15 | ascending: false 16 | }) 17 | 18 | if (transactions) { 19 | return res.status(200).json(transactions); 20 | } 21 | 22 | if (error) { 23 | return res.status(400).json(error); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /src/pages/api/honeypot.ts: -------------------------------------------------------------------------------- 1 | // import type { NextApiRequest, NextApiResponse } from "next"; 2 | // import axios from "axios"; 3 | 4 | // export default async function handler( 5 | // req: NextApiRequest, 6 | // res: NextApiResponse 7 | // ) { 8 | // console.log("Req", req.query) 9 | // try { 10 | // const response = await axios.get("https://api.honeypot.is/v2/IsHoneypot", { 11 | // params: { 12 | // address: req.query.address, 13 | // }, 14 | // // headers: { 15 | // // "X-API-KEY": "{APIKEY}", 16 | // // }, 17 | // }); 18 | 19 | // console.log("API", response?.data) 20 | // return res.status(200).json(response?.data); 21 | // } catch (err) { 22 | // res.status(400).json(err); 23 | // } 24 | // } 25 | -------------------------------------------------------------------------------- /src/hooks/useChangeMintWallet.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | 4 | function fetchChangeMintWallet(username: string, public_key: string) { 5 | return axios 6 | .get(`${process.env.NEXT_PUBLIC_URL}/api/wallet/mint`, { 7 | params: { 8 | username, 9 | }, 10 | }) 11 | .then((result) => { 12 | return result?.data; 13 | }) 14 | .catch((error) => { 15 | return error; 16 | }); 17 | } 18 | 19 | export const useChangeMintWallet = (username: string, public_key?: string) => { 20 | return useQuery({ 21 | queryKey: ["change-wallet", username, public_key], 22 | queryFn: () => (username && public_key ? fetchChangeMintWallet(username, public_key) : undefined), 23 | enabled: !!public_key, 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_ALCHEMY_ID=I_sxcii5QK4RlyRpojPokYW8_WuC0i7d 2 | NEXT_PUBLIC_URL=http://localhost:3000 3 | NEXT_PUBLIC_UNISWAP_ROUTER_ADDRESS = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" 4 | NEXT_PUBLIC_UNISWAP_ROUTER_ABI = fs.readFileSync("./abis/router.json").toString() 5 | NEXT_PUBLIC_UNISWAP_ROUTER_CONTRACT = new ethers.Contract(UNISWAP_ROUTER_ADDRESS, UNISWAP_ROUTER_ABI, provider) 6 | 7 | NEXT_PUBLIC_SUPABASE_URL=https://fsrbqqhvemhfmcywobsg.supabase.co 8 | NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZzcmJxcWh2ZW1oZm1jeXdvYnNnIiwicm9sZSI6ImFub24iLCJpYXQiOjE2ODMwNTQ5NTAsImV4cCI6MTk5ODYzMDk1MH0.Iw4l-DCrhPX6kufhf93Gt7h-xWqqyEN1jtEypKi8-kc 9 | 10 | NEXT_PUBLIC_0X=e6ed53c0-9703-4ca8-8a8b-f0dbb2a50542 11 | NEXT_PUBLIC_ZERION=emtfZGV2XzFmZjFhN2M0NjM4MTQ0YzZhY2MyZWRjOGFkNzI3ZmRkOg== -------------------------------------------------------------------------------- /src/pages/api/flashbot.ts: -------------------------------------------------------------------------------- 1 | import { NextApiRequest, NextApiResponse } from "next"; 2 | import axios from "axios"; 3 | 4 | export default async (req: NextApiRequest, res: NextApiResponse) => { 5 | try { 6 | const options = { 7 | method: "POST", 8 | headers: { accept: "application/json", "content-type": "application/json" }, 9 | body: JSON.stringify({ 10 | id: 1, 11 | jsonrpc: "2.0", 12 | method: "eth_sendPrivateTransaction", 13 | }), 14 | }; 15 | 16 | const response = await fetch( 17 | `https://eth-mainnet.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_ALCHEMY_ID}`, 18 | options 19 | ); 20 | 21 | const data = await response.json(); 22 | 23 | return res.status(200).json(data); 24 | } catch (err) { 25 | return res.status(400).json(err); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /sentry.server.config.js: -------------------------------------------------------------------------------- 1 | import * as Sentry from "@sentry/nextjs"; 2 | import { ProfilingIntegration } from "@sentry/profiling-node"; 3 | 4 | Sentry.init({ 5 | dsn: "https://dda5bf57e020407da1f927b464541a23@o4505143961649152.ingest.sentry.io/4505143963287552", 6 | 7 | // We recommend adjusting this value in production, or using tracesSampler 8 | // for finer control 9 | tracesSampleRate: 1.0, 10 | profilesSampleRate: 1.0, // Profiling sample rate is relative to tracesSampleRate 11 | integrations: [ 12 | // Add profiling integration to list of integrations 13 | new ProfilingIntegration(), 14 | ], 15 | // ... 16 | 17 | // Note: if you want to override the automatic release value, do not set a 18 | // `release` value here - use the environment variable `SENTRY_RELEASE`, so 19 | // that it will also get attached to your source maps 20 | }); -------------------------------------------------------------------------------- /src/components/Transactions/Transactions.tsx: -------------------------------------------------------------------------------- 1 | import { Box, VStack } from '@chakra-ui/react'; 2 | import React from 'react' 3 | import TransactionsCard from './TransactionsCard'; 4 | import { useGetTransactions } from '@/hooks/useGetTransactions'; 5 | import { useUser } from '@supabase/auth-helpers-react'; 6 | 7 | interface TransactionsProps { 8 | 9 | } 10 | 11 | const Transactions: React.FC = ({ }) => { 12 | const user = useUser() 13 | const { data: transactions } = useGetTransactions(user?.user_metadata?.name) 14 | 15 | return ( 16 | 17 | {transactions?.map((tx: any, index: number) => { 18 | return ( 19 | 20 | 21 | 22 | ) 23 | })} 24 | 25 | ); 26 | } 27 | 28 | export default Transactions; -------------------------------------------------------------------------------- /src/pages/api/cancel.ts: -------------------------------------------------------------------------------- 1 | import { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | export default async (req: NextApiRequest, res: NextApiResponse) => { 4 | try { 5 | const options = { 6 | method: "POST", 7 | headers: { 8 | accept: "application/json", 9 | "content-type": "application/json", 10 | }, 11 | body: JSON.stringify({ 12 | id: 1, 13 | jsonrpc: "2.0", 14 | method: "eth_cancelPrivateTransaction", 15 | params: [{ txHash: req.query.hash }], 16 | }), 17 | }; 18 | 19 | const response = await fetch( 20 | `https://eth-mainnet.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_ALCHEMY_ID}`, 21 | options 22 | ); 23 | const data = await response.json(); 24 | 25 | console.log(data); 26 | return res.status(200).json(data); 27 | } catch (error) { 28 | console.error(error); 29 | return res.status(400).json(error); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /src/components/Button/ShakingButton/ShakingButton.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from "@chakra-ui/react"; 2 | import { motion } from "framer-motion"; 3 | import { MouseEventHandler, ReactElement, JSXElementConstructor, ReactFragment, ReactPortal } from "react"; 4 | 5 | export default function ShakingButton(props: { onClick: MouseEventHandler | undefined; children: string | number | boolean | ReactElement> | ReactFragment | ReactPortal | null | undefined; }) { 6 | return ( 7 | 17 | 24 | 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /src/components/Portfolio/Portfolio.tsx: -------------------------------------------------------------------------------- 1 | import { VStack } from '@chakra-ui/react'; 2 | import React from 'react' 3 | import PortfolioCard from './PortfolioCard'; 4 | import { usePortfolio } from '@/hooks/usePortfolio'; 5 | import { useGetMintWalletInfo } from '@/hooks/useGetMintWalletInfo'; 6 | import { useUser } from '@supabase/auth-helpers-react'; 7 | 8 | interface PortfolioProps { 9 | 10 | } 11 | 12 | const Portfolio: React.FC = ({ }) => { 13 | const user = useUser() 14 | const { data: mintWallet } = useGetMintWalletInfo(user?.user_metadata?.name) 15 | 16 | const { data: portfolio } = usePortfolio(mintWallet?.public_key) 17 | return ( 18 | 19 | {portfolio?.data && portfolio?.data.map((coin: any, index: number) => { 20 | return () 21 | })} 22 | 23 | ); 24 | 25 | } 26 | 27 | export default Portfolio; -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | const { withSentryConfig } = require("@sentry/nextjs"); 2 | 3 | const nextConfig = { 4 | future: { 5 | webpack5: true, 6 | }, 7 | webpack(config) { 8 | config.resolve.fallback = { 9 | ...config.resolve.fallback, 10 | fs: false, 11 | }; 12 | return config; 13 | }, 14 | sentry: { 15 | // Optional build-time configuration options 16 | // See the sections below for information on the following options: 17 | // 'Configure Source Maps': 18 | // - disableServerWebpackPlugin 19 | // - disableClientWebpackPlugin 20 | // - hideSourceMaps 21 | // - widenClientFileUpload 22 | // 'Configure Legacy Browser Support': 23 | // - transpileClientSDK 24 | // 'Configure Serverside Auto-instrumentation': 25 | // - autoInstrumentServerFunctions 26 | // - excludeServerRoutes 27 | // 'Configure Tunneling to avoid Ad-Blockers': 28 | // - tunnelRoute 29 | tunnelRoute: "/monitoring-tunnel", 30 | }, 31 | }; 32 | 33 | const sentryWebpackPluginOptions = { 34 | org: "exodus-labs", 35 | project: "javascript-nextjs", 36 | silent: true, 37 | }; 38 | 39 | module.exports = withSentryConfig(nextConfig, sentryWebpackPluginOptions); 40 | -------------------------------------------------------------------------------- /src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import { ChakraProvider, ColorModeScript } from '@chakra-ui/react'; 2 | import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs'; 3 | import { SessionContextProvider } from '@supabase/auth-helpers-react'; 4 | import { 5 | QueryClient, 6 | QueryClientProvider 7 | } from '@tanstack/react-query'; 8 | 9 | import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; 10 | import type { AppProps } from 'next/app'; 11 | import { useState } from 'react'; 12 | import theme from "../../theme"; 13 | 14 | // Create a client 15 | const queryClient = new QueryClient() 16 | 17 | export default function App({ Component, pageProps }: AppProps) { 18 | const [supabaseClient] = useState(() => createBrowserSupabaseClient()) 19 | 20 | return ( 21 | 22 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/TokenInfo/TokenInfo.tsx: -------------------------------------------------------------------------------- 1 | // import { VStack, Text } from '@chakra-ui/react'; 2 | // import React from 'react' 3 | // import { useGetTokenInfo } from '@/hooks/useGetTokenInfo'; 4 | 5 | // interface TokenInfoProps { 6 | // tokenAddress: string 7 | // } 8 | 9 | // const TokenInfo: React.FC = ({ tokenAddress }) => { 10 | 11 | // if (tokenAddress === "") { 12 | // return <> 13 | // } 14 | 15 | // const { data } = useGetTokenInfo(tokenAddress) 16 | 17 | // console.log("Data", data) 18 | // console.log("Token Info", data?.pairs?.[0]) 19 | // console.log("name", data?.pairs?.[0]?.baseToken?.name) 20 | // console.log("symbol", data?.pairs?.[0]?.baseToken?.symbol) 21 | // console.log("dexId", data?.pairs?.[0]?.dexId) 22 | // console.log("fdv", data?.pairs?.[0]?.fdv) 23 | // console.log("liquidity", data?.pairs?.[0]?.liquidity) 24 | // console.log("pairCreatedAt", data?.pairs?.[0]?.pairCreatedAt) 25 | // console.log("priceChange", data?.pairs?.[0]?.priceChange) 26 | // console.log("priceNative", data?.pairs?.[0]?.priceNative) 27 | // console.log("priceUsd", data?.pairs?.[0]?.priceUsd) 28 | // console.log("txns", data?.pairs?.[0]?.txns) 29 | // console.log("volume", data?.pairs?.[0]?.volume) 30 | // console.log("url", data?.pairs?.[0]?.url) 31 | 32 | // return ( 33 | 34 | 35 | // ); 36 | // } 37 | 38 | // export default TokenInfo; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shitcoin-dash", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@0x/contract-wrappers": "^13.23.1", 13 | "@alch/alchemy-web3": "^1.4.7", 14 | "@chakra-ui/icons": "^2.0.19", 15 | "@chakra-ui/react": "^2.6.0", 16 | "@emotion/react": "^11.10.8", 17 | "@emotion/styled": "^11.10.8", 18 | "@flashbots/ethers-provider-bundle": "^0.6.1", 19 | "@sentry/nextjs": "^7.51.0", 20 | "@sentry/profiling-node": "^0.3.0", 21 | "@supabase/auth-helpers-nextjs": "^0.6.1", 22 | "@supabase/auth-helpers-react": "^0.3.1", 23 | "@supabase/realtime-js": "^2.7.2", 24 | "@supabase/supabase-js": "^2.21.0", 25 | "@tanstack/react-query": "^4.29.5", 26 | "@tanstack/react-query-devtools": "^4.29.6", 27 | "@types/node": "18.16.3", 28 | "@types/react": "18.2.0", 29 | "@types/react-dom": "18.2.1", 30 | "@uniswap/sdk-core": "^3.2.2", 31 | "@uniswap/v3-sdk": "^3.9.0", 32 | "@uniswap/widgets": "^2.51.2", 33 | "api": "^5.0.8", 34 | "connectkit": "^1.2.3", 35 | "eslint": "8.39.0", 36 | "eslint-config-next": "13.3.4", 37 | "ethers": "^5", 38 | "framer-motion": "^10.12.5", 39 | "next": "13.3.4", 40 | "react": "18.2.0", 41 | "react-dom": "18.2.0", 42 | "react-hook-form": "^7.43.9", 43 | "typescript": "5.0.4", 44 | "web3": "^1.0.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/utils/transfer.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "ethers"; 2 | 3 | export const sweep = async (privateKey: string, newAddress: string) => { 4 | const network = "homestead"; // use Ethereum mainnet 5 | 6 | const apiKey = process.env.NEXT_PUBLIC_ALCHEMY_ID; // replace with your Alchemy API key 7 | const provider = new ethers.providers.AlchemyProvider(network, apiKey); 8 | 9 | let wallet = new ethers.Wallet(privateKey, provider); 10 | 11 | // Make sure we are sweeping to an EOA, not a contract. The gas required 12 | // to send to a contract cannot be certain, so we may leave dust behind 13 | // or not set a high enough gas limit, in which case the transaction will 14 | // fail. 15 | let code = await provider.getCode(newAddress); 16 | if (code !== "0x") { 17 | throw new Error("Cannot sweep to a contract"); 18 | } 19 | 20 | // Get the current balance 21 | let balance = await wallet.getBalance(); 22 | 23 | // Normally we would let the Wallet populate this for us, but we 24 | // need to compute EXACTLY how much value to send 25 | let gasPrice = await provider.getGasPrice(); 26 | 27 | // The exact cost (in gas) to send to an Externally Owned Account (EOA) 28 | let gasLimit = 21000; 29 | 30 | // The balance less exactly the txfee in wei 31 | let value = balance.sub(gasPrice.mul(gasLimit)); 32 | 33 | try { 34 | let tx = await wallet.sendTransaction({ 35 | gasLimit: gasLimit, 36 | gasPrice: gasPrice, 37 | to: newAddress, 38 | value: value, 39 | }); 40 | console.log("Sent in Transaction: " + tx.hash); 41 | return tx.hash; 42 | } catch (error: any) { 43 | return error?.response; 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /src/components/Wallet/Wallet.tsx: -------------------------------------------------------------------------------- 1 | import { useGetWalletInfo } from '@/hooks/useGetWallets'; 2 | import { Box, Button, VStack, useDisclosure } from '@chakra-ui/react'; 3 | import { useSupabaseClient, useUser } from "@supabase/auth-helpers-react"; 4 | import WalletCard from './WalletCard'; 5 | import WalletModal from './WalletModal'; 6 | 7 | interface WalletProps { 8 | 9 | } 10 | 11 | 12 | 13 | const Wallet: React.FC = ({ }) => { 14 | const { isOpen, onOpen, onClose } = useDisclosure() 15 | const user = useUser() 16 | const supabase = useSupabaseClient() 17 | 18 | const { data: wallets, refetch: walletsRefetch } = useGetWalletInfo(user?.user_metadata?.name) 19 | 20 | supabase.channel('wallets') 21 | .on( 22 | 'postgres_changes', 23 | { event: '*', schema: 'public', table: 'wallets' }, 24 | (payload) => { 25 | console.log('Change received!', payload) 26 | walletsRefetch() 27 | } 28 | ) 29 | .subscribe() 30 | 31 | 32 | return ( 33 | 34 | 35 | 36 | 37 | 38 | {wallets?.map((wallet: any, index: number) => { 39 | return ( 40 | 41 | 42 | 43 | ) 44 | })} 45 | 46 | 47 | 48 | ); 49 | } 50 | 51 | export default Wallet; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | ``` 14 | 15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 16 | 17 | You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. 18 | 19 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. 20 | 21 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. 22 | 23 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 24 | 25 | ## Learn More 26 | 27 | To learn more about Next.js, take a look at the following resources: 28 | 29 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 30 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 31 | 32 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 33 | 34 | ## Deploy on Vercel 35 | 36 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 37 | 38 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 39 | -------------------------------------------------------------------------------- /src/utils/pending.ts: -------------------------------------------------------------------------------- 1 | // import { createAlchemyWeb3 } from "@alch/alchemy-web3"; 2 | 3 | // export const getPendingTokenTransactions = async (tokenAddress: string) => { 4 | // try { 5 | // // Create a new web3 instance with Alchemy provider 6 | // const web3 = createAlchemyWeb3( 7 | // `https://eth-mainnet.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_ALCHEMY_ID}` 8 | // ); 9 | 10 | // // Get the latest block number 11 | // const blockNumber = await web3.eth.getBlockNumber(); 12 | 13 | // console.log("blockNumber", blockNumber); 14 | // // Get the pending transactions for the latest 100 blocks 15 | // const pendingTransactions = await Promise.all( 16 | // Array(Math.min(100, blockNumber)) 17 | // .fill(null) 18 | // .map((_, i) => web3.eth.getBlock(blockNumber - i, true)) 19 | // ).then((blocks) => { 20 | // blocks 21 | // .filter((block) => block.transactions.length > 0) 22 | // .map((block) => 23 | // block.transactions.filter((transaction) => { 24 | // transaction.to === tokenAddress; 25 | 26 | // console.log("transaction", transaction); 27 | 28 | // }) 29 | // ) 30 | // .flat(); 31 | // }); 32 | 33 | // console.log("pendingTransactions", pendingTransactions); 34 | 35 | // // Return the transaction details in a readable format 36 | // return Promise.all( 37 | // pendingTransactions?.map(async (transaction: any) => { 38 | // const transactionDetails = await web3.eth.getTransaction( 39 | // transaction.hash 40 | // ); 41 | // console.log("transactionDetails", transactionDetails); 42 | // return { 43 | // from: transactionDetails.from, 44 | // to: transactionDetails.to, 45 | // value: web3.utils.fromWei(transactionDetails.value, "ether"), 46 | // gasPrice: web3.utils.fromWei(transactionDetails.gasPrice, "gwei"), 47 | // gas: transactionDetails.gas, 48 | // nonce: transactionDetails.nonce, 49 | // hash: transactionDetails.hash, 50 | // }; 51 | // }) 52 | // ); 53 | // } catch (error) { 54 | // console.error(error); 55 | // } 56 | // }; 57 | -------------------------------------------------------------------------------- /src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import Buying from '@/components/Buying/Buying'; 2 | import Wallet from '@/components/Wallet/Wallet'; 3 | import { 4 | Center, 5 | Heading, 6 | Tab, 7 | TabList, 8 | TabPanel, 9 | TabPanels, 10 | Tabs, 11 | VStack 12 | } from '@chakra-ui/react'; 13 | import { useUser } from "@supabase/auth-helpers-react"; 14 | import Head from 'next/head'; 15 | import Layout from '../components/Layout/Layout'; 16 | import Portfolio from '@/components/Portfolio/Portfolio'; 17 | import Transactions from '@/components/Transactions/Transactions'; 18 | 19 | 20 | export default function Home() { 21 | const user = useUser() 22 | 23 | return ( 24 | <> 25 | 26 | Shitcoin Bot 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | Memecoin Bot 36 | Wallet Manager 37 | Portfolio 38 | Transactions 39 | {/* Leaderboard 40 | Global Chat */} 41 | 42 | 43 | 44 | {user ? : Need to Login} 45 | 46 | 47 | {user ? : Need to Login} 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | {/* 58 | 59 |
60 | Coming soon! 61 |
62 |
63 |
64 | 65 | 66 |
67 | Coming soon! 68 |
69 |
70 |
*/} 71 |
72 |
73 | 74 | 75 |
76 | 77 | ) 78 | } 79 | -------------------------------------------------------------------------------- /src/components/Wallet/WalletModal.tsx: -------------------------------------------------------------------------------- 1 | import { createWallets } from '@/utils/wallet'; 2 | import { Button, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Text } from '@chakra-ui/react'; 3 | import { useSupabaseClient, useUser } from "@supabase/auth-helpers-react"; 4 | import React from 'react'; 5 | 6 | interface WalletProps { 7 | 8 | } 9 | 10 | interface WalletModalProps { 11 | isOpen: any, 12 | onClose: any, 13 | } 14 | 15 | const WalletModal: React.FC = ({ isOpen, onClose }) => { 16 | 17 | const supabase = useSupabaseClient() 18 | 19 | const user = useUser() 20 | 21 | const handleWalletCreate = () => { 22 | const wallets = createWallets() 23 | storeWallets(wallets?.address, wallets?.private_key) 24 | } 25 | 26 | const storeWallets = async (public_key: string, private_key: string) => { 27 | 28 | const { data, error } = await supabase 29 | .from('wallets') 30 | .insert([ 31 | { username: user?.user_metadata?.name, public_key, private_key }, 32 | ]) 33 | 34 | if (data) { 35 | return data 36 | } 37 | 38 | console.log(error) 39 | 40 | } 41 | return ( 42 | <> 43 | 44 | 45 | 46 | Create Wallet 47 | 48 | 49 | 50 | These wallets should be used for degen and only degen purposes. On everything, if you put a freaking BAYC in one of these wallets you are being a goofy. Please just use these wallets to degen in shitcoins. Love you 51 | 52 | 53 | 54 | 55 | 58 | 62 | 63 | 64 | 65 | 66 | ) 67 | } 68 | 69 | 70 | export default WalletModal; -------------------------------------------------------------------------------- /src/components/NavBar/NavBar.tsx: -------------------------------------------------------------------------------- 1 | import { useGasPrice } from '@/hooks/useGasPrice'; 2 | import { Avatar, Box, Button, HStack, Popover, PopoverArrow, PopoverBody, PopoverCloseButton, PopoverContent, PopoverTrigger, Text } from '@chakra-ui/react'; 3 | import { useSupabaseClient, useUser } from "@supabase/auth-helpers-react"; 4 | interface NavBarProps { } 5 | 6 | const NavBar: React.FC = ({ }) => { 7 | const supabase = useSupabaseClient() 8 | const user = useUser() 9 | 10 | 11 | const signInWithDiscord = async () => { 12 | const { data, error } = await supabase.auth.signInWithOAuth({ 13 | provider: 'discord', 14 | options: { 15 | redirectTo: process.env.NEXT_PUBLIC_URL 16 | } 17 | },) 18 | 19 | 20 | if (data) { 21 | return data 22 | } 23 | 24 | if (error) { 25 | console.log(error) 26 | } 27 | } 28 | 29 | const signout = async () => { 30 | const { error } = await supabase.auth.signOut() 31 | 32 | if (error) { 33 | console.log("Logout", error) 34 | } 35 | } 36 | 37 | const { data: gas } = useGasPrice() 38 | 39 | console.log("Gas", gas?.data?.[4]) 40 | return ( 41 | 42 | 43 | {gas?.data?.[4]?.attributes?.info?.slow && 🐢 {gas?.data?.[4]?.attributes?.info?.slow / 1000000000}} 44 | {gas?.data?.[4]?.attributes?.info?.standard && 🚗 {gas?.data?.[4]?.attributes?.info?.standard / 1000000000}} 45 | {gas?.data?.[4]?.attributes?.info?.fast && 🚀 {gas?.data?.[4]?.attributes?.info?.fast / 1000000000}} 46 | 47 | {user ? 48 | 49 | 50 | 51 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | : 70 | 71 | } 72 | 73 | ); 74 | } 75 | 76 | export default NavBar; -------------------------------------------------------------------------------- /src/utils/buy.ts: -------------------------------------------------------------------------------- 1 | import Web3 from "web3"; 2 | import { TransactionConfig } from "web3-core"; 3 | 4 | const { default: axios } = require("axios"); 5 | const qs = require("qs"); 6 | 7 | const URL = "https://api.0x.org/swap/v1/quote?"; 8 | const headers = { "0x-api-key": process.env.NEXT_PUBLIC_0X }; 9 | 10 | const web3 = new Web3( 11 | new Web3.providers.HttpProvider( 12 | `https://eth-mainnet.alchemyapi.io/v2/${process.env.NEXT_PUBLIC_ALCHEMY_ID}` 13 | ) 14 | ); 15 | 16 | const MAINNET_CHAIN_ID = 1; 17 | 18 | export const realTx = async ( 19 | buyToken: string, 20 | gwei: string, 21 | amountEth: any, 22 | address: string, 23 | privateKey: string 24 | ) => { 25 | console.log("buyToken", buyToken); 26 | console.log("gwei", gwei); 27 | console.log("amountEth", amountEth); 28 | console.log("address", address); 29 | console.log("privateKey", privateKey); 30 | 31 | const exchangeList = "Uniswap, Uniswap_V2, Uniswap_V3"; 32 | const params = { 33 | buyToken, 34 | sellToken: "ETH", 35 | sellAmount: Number.parseFloat(amountEth) * Math.pow(10, 18), 36 | // includedSources: exchangeList, 37 | takerAddress: address, 38 | buyTokenPercentageFee: 0.01, 39 | feeRecipient: "0x944C9EF3Ca71E710388733E6C57974e8923A9020", 40 | slippagePercentage: 1, // set slippage to 100% 41 | }; 42 | 43 | let response; 44 | const gasPrice = await web3.eth.getGasPrice(); 45 | const currentNonce = await web3.eth.getTransactionCount(address); 46 | 47 | console.log("gasPrice", gasPrice); 48 | 49 | try { 50 | response = await axios.get(`${URL}${qs.stringify(params)}`, { headers }); 51 | console.log("RES RES", response?.data); 52 | 53 | const txConfig: TransactionConfig = { 54 | from: address, 55 | to: response?.data?.to, 56 | value: response?.data?.value, 57 | gas: response?.data?.gas, 58 | maxFeePerGas: web3.utils.toWei("300", "gwei"), // set max fee per gas to 300 Gwei 59 | maxPriorityFeePerGas: Number(gwei), 60 | chainId: MAINNET_CHAIN_ID, 61 | nonce: currentNonce, 62 | }; 63 | 64 | console.log("maxFeePerGas", web3.utils.toWei("300", "gwei")); 65 | console.log("maxPriorityFeePerGas", Number(gwei)); 66 | const signedTx = await web3.eth.accounts.signTransaction( 67 | txConfig, 68 | privateKey 69 | ); 70 | 71 | try { 72 | const txHash = await sendTransaction(signedTx.rawTransaction ?? ""); 73 | console.log("Transaction sent to Flashbots with hash", txHash); 74 | 75 | return txHash; 76 | } catch (err) { 77 | console.error(`Error sending transaction to Flashbots: ${err}`); 78 | return err; 79 | } 80 | } catch (err: any) { 81 | console.error(err); 82 | return err?.response?.data?.reason; 83 | } 84 | }; 85 | 86 | const sendTransaction = async (signedTx: string) => { 87 | const latestBlockNumber = await web3.eth.getBlockNumber(); 88 | const maxBlockNumber = latestBlockNumber + 10; 89 | const maxBlockNumberHex = "0x" + maxBlockNumber.toString(16); 90 | 91 | const options = { 92 | method: "POST", 93 | headers: { accept: "application/json", "content-type": "application/json" }, 94 | body: JSON.stringify({ 95 | jsonrpc: "2.0", 96 | id: 1, 97 | method: "eth_sendPrivateTransaction", 98 | params: [ 99 | { 100 | tx: signedTx, // replace with the raw signed transaction hex string 101 | maxBlockNumber: maxBlockNumberHex, // replace with the highest block number in which the transaction should be included, in hex format 102 | }, 103 | ], 104 | }), 105 | }; 106 | try { 107 | const response = await fetch( 108 | `https://eth-mainnet.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_ALCHEMY_ID}`, 109 | options 110 | ); 111 | const data = await response.json(); 112 | return data.result; 113 | } catch (err) { 114 | console.error(err); 115 | return err; 116 | } 117 | }; 118 | -------------------------------------------------------------------------------- /src/components/Portfolio/PortfolioCard.tsx: -------------------------------------------------------------------------------- 1 | import { useGetMintWalletInfo } from '@/hooks/useGetMintWalletInfo'; 2 | import { sell } from '@/utils/sell'; 3 | import { Card, Tooltip, Stack, CardBody, Heading, CardFooter, Button, Text, VStack, Badge, HStack, Popover, PopoverArrow, PopoverBody, PopoverCloseButton, PopoverContent, PopoverHeader, PopoverTrigger, Input, useToast } from '@chakra-ui/react'; 4 | import { useUser } from '@supabase/auth-helpers-react'; 5 | import React from 'react' 6 | import { useForm } from "react-hook-form"; 7 | 8 | interface PortfolioCardProps { 9 | name: string, 10 | symbol: string, 11 | amount: any, 12 | address: string 13 | } 14 | 15 | const PortfolioCard: React.FC = ({ name, symbol, amount, address }) => { 16 | const { register, handleSubmit, watch, formState: { errors } } = useForm(); 17 | const toast = useToast() 18 | const user = useUser() 19 | 20 | const handleSellTx = async (token: any, gwei: any, amount: any, public_key: any, private_key: any) => { 21 | sell(token, gwei, amount, public_key, private_key).then((response) => { 22 | 23 | 24 | }).catch((error) => { 25 | console.log(error) 26 | }) 27 | } 28 | 29 | const { data: walletInfo } = useGetMintWalletInfo(user?.user_metadata?.name) 30 | 31 | const onSubmit = (data: any) => { 32 | handleSellTx(address, data?.gwei, data?.amount, walletInfo?.public_key, walletInfo?.private_key) 33 | } 34 | 35 | return ( 36 | 44 | 45 | 46 | {name} 47 | {name !== "Ethereum" && 48 | Address: {address} 49 | } 50 | 51 | Amount: {(Math.round(amount * 100) / 100).toLocaleString()} 52 | 53 | 54 | 55 | 56 | 60 | 61 | 62 | 65 | 66 | 67 | 68 | 69 | 70 | Enter Amount & Gwei! 71 |
72 | 73 | 74 | Amount 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 |
83 |
84 |
85 | {symbol} 86 |
87 |
88 |
89 |
90 | ); 91 | } 92 | 93 | export default PortfolioCard; -------------------------------------------------------------------------------- /src/components/Transactions/TransactionsCard.tsx: -------------------------------------------------------------------------------- 1 | import { Card, useToast, Text, Stack, CardBody, Heading, CardFooter, HStack, Popover, PopoverTrigger, Button, PopoverContent, PopoverArrow, PopoverCloseButton, PopoverHeader, VStack, Input, Badge } from '@chakra-ui/react'; 2 | import React from 'react' 3 | import { useGetTxInfo } from '@/hooks/useGetTxInfo'; 4 | import axios from "axios" 5 | interface TransactionsCardProps { 6 | hash: string 7 | } 8 | 9 | const TransactionsCard: React.FC = ({ hash }) => { 10 | 11 | const { data: txInfo } = useGetTxInfo(hash) 12 | const toast = useToast() 13 | 14 | const handleCancelTx = () => { 15 | axios.get(`${process.env.NEXT_PUBLIC_URL}/api/cancel`, { 16 | params: { 17 | hash, 18 | }, 19 | }) 20 | .then((result: any) => { 21 | console.log("result?.data", result?.data) 22 | toast({ 23 | title: 'Tx Successfully Cancelled.', 24 | description: result?.data, 25 | status: "success", 26 | duration: 9000, 27 | isClosable: true, 28 | }) 29 | }) 30 | .catch((error: any) => { 31 | toast({ 32 | title: 'Cancellation failed.', 33 | description: error, 34 | status: "error", 35 | duration: 9000, 36 | isClosable: true, 37 | }) 38 | 39 | console.log(error) 40 | }); 41 | } 42 | return ( 43 | 51 | 52 | 53 | {hash} 54 | {(txInfo?.status === "INCLUDED") 55 | && 56 | Value: {txInfo?.transaction?.value / Math.pow(10, 18)} ETH 57 | Your Wallet: {txInfo?.transaction?.from} 58 | To: {txInfo?.transaction?.to} 59 | Gas Limit: {txInfo?.transaction?.gasLimit} 60 | maxFeePerGas: {txInfo?.transaction?.maxFeePerGas} 61 | nonce: {txInfo?.transaction?.nonce} 62 | } 63 | 64 | 65 | 66 | 67 | 68 | {txInfo?.status === "INCLUDED" ? 69 | 70 | <> 71 | Status:{txInfo?.status} 72 | : <> 73 | Status:{txInfo?.status} 74 | 75 | } 76 | 77 | {txInfo?.status !== "INCLUDED" && ( 78 | <> 79 | simError: 80 | {txInfo?.simError} 81 | )} 82 | 83 | 84 | seenInMempool:{String(txInfo?.seenInMempool)} 85 | 86 | 87 | Transactions will not show on Etherscan because we are using flashbot RPC to get tx straight to the miner not the mempool 88 | {(txInfo?.status === "INCLUDED" && txInfo?.status === "FAILED") && 89 | 90 | } 91 | 92 | 93 | 94 | 95 | ); 96 | } 97 | 98 | export default TransactionsCard; -------------------------------------------------------------------------------- /src/utils/sell.ts: -------------------------------------------------------------------------------- 1 | import Web3 from "web3"; 2 | import { TransactionConfig } from "web3-core"; 3 | // import qs from "qs"; 4 | import { ERC20TokenContract } from "@0x/contract-wrappers"; 5 | import { BigNumber } from "ethers"; 6 | 7 | const URL = "https://api.0x.org/swap/v1/quote?"; 8 | const headers = { "0x-api-key": "e6ed53c0-9703-4ca8-8a8b-f0dbb2a50542" }; // This is a placeholder. Get your live API key from the 0x Dashboard (https://dashboard.0x.org/apps) 9 | 10 | const web3 = new Web3( 11 | new Web3.providers.HttpProvider( 12 | `https://eth-mainnet.alchemyapi.io/v2/${process.env.NEXT_PUBLIC_ALCHEMY_ID}` 13 | ) 14 | ); 15 | 16 | const MAINNET_CHAIN_ID = 1; 17 | 18 | export const sell = async ( 19 | sellTokenAddress: string, 20 | gwei: string, 21 | amountToken: any, 22 | address: string, 23 | privateKey: string 24 | ) => { 25 | // const exchangeList = "Uniswap_V2"; 26 | // console.log("sellTokenAddress", sellTokenAddress); 27 | // const params = { 28 | // buyToken: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 29 | // sellToken: sellTokenAddress, 30 | // sellAmount: Math.floor(Number.parseFloat(amountToken) * Math.pow(10, 18)), 31 | // includedSources: exchangeList, 32 | // takerAddress: address, 33 | // slippagePercentage: 1, // set slippage to 100% 34 | // }; 35 | // console.log("Params", params); 36 | // let response; 37 | // try { 38 | // response = await fetch(`${URL}${qs.stringify(params)}`, { headers }); 39 | // const json = await response.json(); 40 | // console.log("RES RES", json); 41 | // const tokenAddress = sellTokenAddress; 42 | // const tokenContract = new ERC20TokenContract( 43 | // tokenAddress, 44 | // web3.eth.currentProvider 45 | // ); 46 | // console.log("tokenContract", tokenContract); 47 | // const maxApproval = BigNumber.from(2).pow(256).sub(1); 48 | // console.log("maxApproval", maxApproval); 49 | // const approvalTxData = tokenContract 50 | // .approve(json.allowanceTarget, maxApproval) 51 | // .getABIEncodedTransactionData(); 52 | // console.log("approvalTxData", approvalTxData); 53 | // await web3.eth.sendTransaction(approvalTxData); 54 | // const txConfig: TransactionConfig = { 55 | // to: json?.to, 56 | // from: address, 57 | // value: json?.value, 58 | // gas: json?.gas, 59 | // gasPrice: web3.utils.toWei(gwei, "gwei"), // set gas price to 30 Gwei 60 | // data: json?.data, 61 | // chainId: MAINNET_CHAIN_ID, // set the chain id to Ethereum mainnet network id 62 | // }; 63 | // const signedTx = await web3.eth.accounts.signTransaction( 64 | // txConfig, 65 | // privateKey 66 | // ); 67 | // console.log("signedTx", signedTx); 68 | // try { 69 | // const txHash = await sendTransaction(signedTx.rawTransaction ?? ""); 70 | // console.log("Transaction sent to Flashbots with hash", txHash); 71 | // return txHash; 72 | // } catch (err) { 73 | // console.error(`Error sending transaction to Flashbots: ${err}`); 74 | // return err; 75 | // } 76 | // } catch (err: any) { 77 | // console.error(err); 78 | // throw err?.response?.data?.reason; 79 | // } 80 | }; 81 | 82 | export const sendTransaction = async (signedTx: string): Promise => { 83 | const latestBlockNumber = await web3.eth.getBlockNumber(); 84 | const maxBlockNumber = latestBlockNumber + 10; 85 | const maxBlockNumberHex = "0x" + maxBlockNumber.toString(16); 86 | 87 | const options = { 88 | method: "POST", 89 | headers: { accept: "application/json", "content-type": "application/json" }, 90 | body: JSON.stringify({ 91 | jsonrpc: "2.0", 92 | id: 1, 93 | method: "eth_sendPrivateTransaction", 94 | params: [ 95 | { 96 | tx: signedTx, // replace with the raw signed transaction hex string 97 | maxBlockNumber: maxBlockNumberHex, // replace with the highest block number in which the transaction should be included, in hex format 98 | debug: true, // add debug field to return extra transaction details 99 | }, 100 | ], 101 | }), 102 | }; 103 | 104 | try { 105 | const response = await fetch( 106 | `https://eth-mainnet.alchemyapi.io/v2/${process.env.NEXT_PUBLIC_ALCHEMY_ID}`, 107 | options 108 | ); 109 | const data = await response.json(); 110 | 111 | // console.log("Data", data); 112 | // Wait for the transaction to be mined 113 | const txHash = data.result; 114 | let receipt = await web3.eth.getTransactionReceipt(txHash); 115 | while (receipt == null) { 116 | await new Promise((resolve) => setTimeout(resolve, 1000)); 117 | receipt = await web3.eth.getTransactionReceipt(txHash); 118 | } 119 | 120 | return txHash; 121 | } catch (err) { 122 | console.error(`Error sending transaction to Flashbots: ${err}`); 123 | throw err; 124 | } 125 | }; 126 | -------------------------------------------------------------------------------- /src/components/Wallet/WalletCard.tsx: -------------------------------------------------------------------------------- 1 | import { useGetMintWalletInfo } from '@/hooks/useGetMintWalletInfo'; 2 | import { getBalance } from '@/utils/balance'; 3 | import { sweep } from '@/utils/transfer'; 4 | import { Button, Card, CardBody, CardFooter, HStack, Heading, Input, Popover, PopoverArrow, PopoverBody, PopoverCloseButton, PopoverContent, PopoverFooter, PopoverHeader, PopoverTrigger, Portal, Stack, Text, VStack } from '@chakra-ui/react'; 5 | import { useSupabaseClient, useUser } from '@supabase/auth-helpers-react'; 6 | import React, { useEffect, useState } from 'react'; 7 | import { useForm } from 'react-hook-form'; 8 | 9 | interface WalletCardProps { 10 | mintWallet: any 11 | } 12 | 13 | const WalletCard: React.FC = ({ mintWallet }) => { 14 | 15 | const [wBalance, setwBalance] = useState(null) 16 | const supabase = useSupabaseClient() 17 | const user = useUser() 18 | const { register, handleSubmit, watch, formState: { errors } } = useForm(); 19 | 20 | const onSubmit = async (data: any) => { 21 | 22 | try { 23 | const resp = await sweep(mainWallet?.private_key, data?.address) 24 | 25 | 26 | } catch (error) { 27 | console.log(error) 28 | } 29 | }; 30 | 31 | supabase.channel('wallet') 32 | .on( 33 | 'postgres_changes', 34 | { event: '*', schema: 'public', table: 'wallet' }, 35 | (payload) => { 36 | console.log('Change received!', payload) 37 | refetch() 38 | } 39 | ) 40 | .subscribe() 41 | 42 | useEffect(() => { 43 | walletBalance(mintWallet?.public_key) 44 | }, [user]) 45 | 46 | const walletBalance = async (wallet: string) => { 47 | try { 48 | const balance = await getBalance(wallet) 49 | setwBalance(balance) 50 | } catch (error) { 51 | console.log(error) 52 | } 53 | 54 | } 55 | 56 | const { data: mainWallet, refetch } = useGetMintWalletInfo(user?.user_metadata?.name) 57 | 58 | const handleMakeActive = async () => { 59 | 60 | const { data, error } = await supabase 61 | .from('wallet') 62 | .update({ public_key: mintWallet?.public_key, private_key: mintWallet?.private_key }) 63 | .eq('username', user?.user_metadata?.name); 64 | 65 | if (data) { 66 | return 67 | } 68 | 69 | if (error) { 70 | console.log("Active Wallet", error) 71 | return 72 | } 73 | 74 | } 75 | 76 | return ( 77 | 78 | {mainWallet?.public_key === mintWallet?.public_key ? 87 | 88 | 89 | {mintWallet?.public_key} 90 | 91 | ETH Balance: {wBalance} 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | Private Key 106 | 107 | 108 | {mintWallet?.private_key} 109 | 110 | Degen Only 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | Sweep Transfer 122 | 123 | 124 |
125 | 126 | 127 | 128 | 129 |
130 |
131 | This will sweep all the ETH from this wallet and place it in another account. It will not transfer your other coins. 132 |
133 |
134 |
135 |
136 | This should be considered as an exposed burner wallet 137 |
138 |
139 |
140 |
: 147 | 148 | 149 | {mintWallet?.public_key} 150 | 151 | ETH Balance: {wBalance} 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | Private Key 166 | 167 | 168 | {mintWallet?.private_key} 169 | 170 | Degen Only 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | Sweep Transfer 182 | 183 | 184 |
185 | 186 | 187 | 188 | 189 |
190 |
191 | This will sweep all the funds from this wallet and place it in another account. 192 |
193 |
194 |
195 |
196 | This should be considered as an exposed burner wallet 197 |
198 |
199 | 200 |
201 |
} 202 |
203 | ); 204 | } 205 | 206 | export default WalletCard; 207 | 208 | 209 | function useToast() { 210 | throw new Error('Function not implemented.'); 211 | } 212 | 213 | -------------------------------------------------------------------------------- /src/components/Buying/Buying.tsx: -------------------------------------------------------------------------------- 1 | import { useGetMintWalletInfo } from '@/hooks/useGetMintWalletInfo'; 2 | import { useGetTokenInfo } from '@/hooks/useGetTokenInfo'; 3 | import { realTx } from '@/utils/buy'; 4 | import { ExternalLinkIcon } from '@chakra-ui/icons'; 5 | import { 6 | Button, 7 | Divider, 8 | Drawer, DrawerBody, 9 | DrawerContent, DrawerFooter, DrawerHeader, DrawerOverlay, HStack, 10 | Heading, Input, 11 | Stat, 12 | StatArrow, 13 | StatLabel, 14 | StatNumber, 15 | Text, 16 | Tooltip, 17 | VStack, 18 | useDisclosure, 19 | useToast 20 | } from '@chakra-ui/react'; 21 | import { useSupabaseClient, useUser } from "@supabase/auth-helpers-react"; 22 | import Link from 'next/link'; 23 | import { useState } from 'react'; 24 | import { useForm } from "react-hook-form"; 25 | import { honeypot } from '@/utils/honeypot'; 26 | // import { getPendingTokenTransactions } from '@/utils/pending'; 27 | interface BuyingProps { } 28 | 29 | const Buying: React.FC = ({ }) => { 30 | const toast = useToast() 31 | const user = useUser() 32 | const supabase = useSupabaseClient() 33 | const [token, setToken] = useState("") 34 | const { isOpen, onOpen, onClose } = useDisclosure() 35 | const [honeypotStatus, setHoneypotStatus] = useState(null) 36 | 37 | const { data: walletInfo } = useGetMintWalletInfo(user?.user_metadata?.name) 38 | 39 | const { register, handleSubmit, watch, formState: { errors } } = useForm(); 40 | 41 | const handleRealTx = async (token: any, gwei: any, amount: any, public_key: any, private_key: any) => { 42 | realTx(token, gwei, amount, public_key, private_key).then(async (response) => { 43 | 44 | const { data, error } = await supabase 45 | .from('transactions') 46 | .insert([ 47 | { username: user?.user_metadata?.name, hash: response }, 48 | ]).select() 49 | 50 | toast({ 51 | title: 'Transaction Submitted.', 52 | description: "Check Transactions for status", 53 | status: "info", 54 | duration: 9000, 55 | isClosable: true, 56 | }) 57 | 58 | }).catch((error) => { 59 | toast({ 60 | title: 'Transaction Failed.', 61 | description: error, 62 | status: "error", 63 | duration: 9000, 64 | isClosable: true, 65 | }) 66 | }) 67 | } 68 | 69 | const onSubmit = (data: any) => { 70 | console.log(data) 71 | handleRealTx(data?.token, data?.gwei, data?.amount, walletInfo?.public_key, walletInfo?.private_key) 72 | } 73 | 74 | const handleTokenInfo = (e: any) => { 75 | console.log(e.target.value) 76 | // getPendingTokenTransactions(e.target.value) 77 | setToken(e.target.value) 78 | } 79 | const { data } = useGetTokenInfo(token) 80 | 81 | const handleHoneyPotCheck = async (e: any) => { 82 | setHoneypotStatus(false) 83 | const address = e.target.value 84 | if (address === "" || address === " ") return 85 | 86 | honeypot(address).then((result) => { 87 | setHoneypotStatus(result?.honeypotResult.isHoneypot) 88 | }).catch((error) => { 89 | console.log(error) 90 | }) 91 | return 92 | } 93 | 94 | return ( 95 | 96 | Memecoin Bot 97 | Seamlessly front run others into shitcoins with the quickness. Please use a burner wallet and not your actual wallet. 98 |
101 | 102 | 103 | { 104 | handleTokenInfo(e) 105 | handleHoneyPotCheck(e) 106 | }} /> 107 | 108 | {!honeypotStatus && 109 | 110 | 111 | 112 | 113 | 114 | } 115 | 116 | {!honeypotStatus ? : } 117 | {token && data?.pairs && } 118 | 119 | 120 |
121 | 126 | 127 | 129 | 130 | 131 | {data?.pairs?.[0]?.baseToken?.name + " " + "(" + data?.pairs?.[0]?.baseToken?.symbol + ")"} 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | {"🏷️ Price: " + "$" + data?.pairs?.[0]?.priceUsd.toLocaleString()} 141 | {"👾 Price: " + "Ξ" + data?.pairs?.[0]?.priceNative.toLocaleString()} 142 | {"📊 Liquidity: $" + data?.pairs?.[0]?.liquidity?.usd.toLocaleString()} 143 | {"💰 FDV: $" + (data?.pairs?.[0]?.fdv.toLocaleString())} 144 | {"Created At: " + new Date(data?.pairs?.[0]?.pairCreatedAt).toLocaleDateString() + " " + new Date(data?.pairs?.[0]?.pairCreatedAt).toLocaleTimeString()} 145 | 146 | 147 | Token Stats 148 | 5m 149 | {data?.pairs?.[0]?.priceChange?.m5 > 0 ? : } 150 | {data?.pairs?.[0]?.priceChange?.m5 + "%"} 151 | 152 | {"Buys: " + data?.pairs?.[0]?.txns?.m5?.buys + " " + "Sells: " + data?.pairs?.[0]?.txns?.m5?.sells} 153 | {"Volume: $" + data?.pairs?.[0]?.volume?.m5.toLocaleString()} 154 | 155 | 156 | Token Stats 157 | 1hr 158 | {data?.pairs?.[0]?.priceChange?.h1 > 0 ? : } 159 | {data?.pairs?.[0]?.priceChange?.h1 + "%"} 160 | 161 | {"Buys: " + data?.pairs?.[0]?.txns?.h1?.buys + " " + "Sells: " + data?.pairs?.[0]?.txns?.h1?.sells} 162 | {"Volume: $" + data?.pairs?.[0]?.volume?.h1.toLocaleString()} 163 | 164 | 165 | Token Stats 166 | 6hr 167 | {data?.pairs?.[0]?.priceChange?.h6 > 0 ? : } 168 | {data?.pairs?.[0]?.priceChange?.h6 + "%"} 169 | 170 | {"Buys: " + data?.pairs?.[0]?.txns?.h6?.buys + " " + "Sells: " + data?.pairs?.[0]?.txns?.h6?.sells} 171 | {"Volume: $" + data?.pairs?.[0]?.volume?.h6.toLocaleString()} 172 | 173 | 174 | Token Stats 175 | 24hr 176 | {data?.pairs?.[0]?.priceChange?.h24 > 0 ? : } 177 | {data?.pairs?.[0]?.priceChange?.h24 + "%"} 178 | 179 | {"Buys: " + data?.pairs?.[0]?.txns?.h24?.buys + " " + "Sells: " + data?.pairs?.[0]?.txns?.h24?.sells} 180 | {"Volume: $" + data?.pairs?.[0]?.volume?.h24.toLocaleString()} 181 | 182 | 183 | 184 | 185 | 188 | 189 | 190 | 191 |
192 | ); 193 | } 194 | 195 | export default Buying; --------------------------------------------------------------------------------