├── .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 |
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 |
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 |
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 |
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 |
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;
--------------------------------------------------------------------------------