74 |
75 |
76 |
77 | {toggleList}
78 |
79 |
80 |
81 | {
84 | setIsModal(true)
85 | }} />
86 |
87 |
88 |
{
90 | setIsModal(false)
91 | }}>
92 |
93 |
94 |
95 |
96 |
97 | {isModal ? "Are you sure you want to submit?" : ""}
98 |
99 |
100 | {
104 | setIsModal(false)
105 | setSubmit()
106 | }} />
107 | {
110 | setIsModal(false)
111 | }} />
112 |
113 |
114 |
115 |
116 | {
117 | isToast && (
118 |
119 | {
120 | isSuccess ?
121 |
:
122 |
123 | }
124 |
125 |
{isSuccess ? "Success" : "Error"}
126 |
127 |
128 | )
129 | }
130 |
131 |
132 | )
133 | }
134 |
--------------------------------------------------------------------------------
/backend/utils/tx.ts:
--------------------------------------------------------------------------------
1 | import { getAssociatedTokenAddressSync, createCloseAccountInstruction } from "@solana/spl-token";
2 | import { Keypair, PublicKey, VersionedTransaction, sendAndConfirmRawTransaction, TransactionMessage, ComputeBudgetProgram, Connection } from "@solana/web3.js";
3 | import { COMMITMENT_LEVEL , QUOTE_AMOUNT, QUOTE_MINT, BUY_SLIPPAGE, SELL_SLIPPAGE} from "../constants";
4 |
5 | export async function swap(percent:number, wallet:Keypair, mint:PublicKey,mode:string, connection:Connection, QUOTE_AMOUNT:number, slippage:number){
6 | if(mode=="buy"){
7 | try{
8 | const quoteResponse = await (
9 | await fetch(
10 | `https://lite-api.jup.ag/swap/v1/quote?inputMint=${QUOTE_MINT}&outputMint=${mint.toString()}&amount=${QUOTE_AMOUNT}&slippageBps=${slippage*100}&restrictIntermediateTokens=true`
11 | )
12 | ).json();
13 | const swapResponse = await (
14 | await fetch('https://lite-api.jup.ag/swap/v1/swap', {
15 | method: 'POST',
16 | headers: {
17 | 'Content-Type': 'application/json',
18 | },
19 | body: JSON.stringify({
20 | quoteResponse,
21 | userPublicKey: wallet.publicKey,
22 | dynamicComputeUnitLimit: true,
23 | dynamicSlippage: true,
24 | prioritizationFeeLamports: {
25 | priorityLevelWithMaxLamports: {
26 | maxLamports: 4000,
27 | priorityLevel: "high"
28 | }
29 | }
30 | })
31 | })
32 | ).json();
33 | const transactionBase64 = swapResponse.swapTransaction
34 | const transactionBytes = new Uint8Array(Buffer.from(transactionBase64, 'base64'));
35 | const transaction = VersionedTransaction.deserialize(transactionBytes);
36 | transaction.sign([wallet]);
37 | await sendAndConfirmRawTransaction(
38 | connection,
39 | Buffer.from(transaction.serialize()),
40 | { skipPreflight: true, maxRetries: 5 }
41 | )
42 | }catch(e){
43 | console.log(e)
44 | }
45 | }else if(mode=="sell"){
46 | const ata = getAssociatedTokenAddressSync(
47 | mint,
48 | wallet.publicKey
49 | );
50 | let amount:number=0;
51 | let cc=0;
52 | while(true){
53 | try{
54 | let balance_response=await connection.getTokenAccountBalance(ata,COMMITMENT_LEVEL)
55 | amount=Number(balance_response.value.amount);
56 | cc++;
57 | if(amount!=0||cc>=150){
58 | break;
59 | }
60 | await new Promise((resolve)=>setTimeout(resolve,100))
61 | }catch(e){
62 | cc++;
63 | if(cc>=150){
64 | break
65 | }
66 | await new Promise((resolve)=>setTimeout(resolve,100))
67 | }
68 | }
69 | if(amount==0) return;
70 | if(percent!=100){
71 | amount=Math.floor(amount*percent/100);
72 | }
73 | try {
74 | const quoteResponse = await (
75 | await fetch(
76 | `https://lite-api.jup.ag/swap/v1/quote?inputMint=${mint}&outputMint=${QUOTE_MINT}&amount=${amount}&slippageBps=${slippage*100}&restrictIntermediateTokens=true`
77 | )
78 | ).json();
79 | const swapResponse = await (
80 | await fetch('https://lite-api.jup.ag/swap/v1/swap', {
81 | method: 'POST',
82 | headers: {
83 | 'Content-Type': 'application/json',
84 | },
85 | body: JSON.stringify({
86 | quoteResponse,
87 | userPublicKey: wallet.publicKey,
88 | dynamicComputeUnitLimit: true,
89 | dynamicSlippage: true,
90 | prioritizationFeeLamports: {
91 | priorityLevelWithMaxLamports: {
92 | maxLamports: 4000,
93 | priorityLevel: "high"
94 | }
95 | }
96 | })
97 | })
98 | ).json();
99 | const transactionBase64 = swapResponse.swapTransaction
100 | const transactionBytes = new Uint8Array(Buffer.from(transactionBase64, 'base64'));
101 | const transaction = VersionedTransaction.deserialize(transactionBytes);
102 | transaction.sign([wallet]);
103 | await sendAndConfirmRawTransaction(
104 | connection,
105 | Buffer.from(transaction.serialize()),
106 | { skipPreflight: true, maxRetries: 5 }
107 | )
108 | if(percent==100){
109 | const latestBlockHash = (await connection.getLatestBlockhash(COMMITMENT_LEVEL)).blockhash;
110 | const message = new TransactionMessage({
111 | payerKey: wallet.publicKey,
112 | recentBlockhash: latestBlockHash,
113 | instructions: [
114 | ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1000 }), // Set a low compute unit price
115 | ComputeBudgetProgram.setComputeUnitLimit({ units: 8000 }),
116 | createCloseAccountInstruction(
117 | ata,
118 | wallet.publicKey,
119 | wallet.publicKey
120 | ),
121 | ],
122 | }).compileToV0Message();
123 | const transaction = new VersionedTransaction(message);
124 | transaction.sign([wallet]);
125 | setTimeout(async()=>{
126 | try{
127 | await connection.sendTransaction(transaction)
128 | }catch(e){}
129 | },30000);
130 | }
131 | } catch (error) {
132 | console.log("Error while closing token account");
133 | }
134 | }
135 | };
--------------------------------------------------------------------------------
/backend/utils/parse_transaction.ts:
--------------------------------------------------------------------------------
1 | import { LAMPORTS_PER_SOL, PublicKey } from "@solana/web3.js";
2 | import bs58 from "bs58";
3 | const PUMP_FUN_PROGRAM = new PublicKey("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P");
4 | const pump_fun_fee_accounts=[
5 | "AVmoTthdrX6tKt4nDjco2D775W2YK3sDhxPcMmzUAmTY",
6 | "9rPYyANsfQZw3DnDmKE3YCQF5E8oD89UXoHn9JFEhJUz",
7 | "FWsW1xNtWscwNmKv6wVsU1iTzRN6wmmk3MjxRP5tT7hz",
8 | "62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV",
9 | "7VtfL8fvgNfhz17qKRMjzQEXgbdpnHHHQRh54R9jP2RJ",
10 | "G5UZAVbAf46s7cKWoyKu8kYTip9DGTpbLZ2qa9Aq69dP",
11 | "CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM",
12 | ]
13 | export function getParsedData(data:any, isLaunch:boolean) {
14 | if(isLaunch==true){
15 | let keys=[""]
16 | data.transaction.transaction.transaction.message.accountKeys.map((account:any, index:number)=>{
17 | keys.push(bs58.encode(account));
18 | })
19 | keys.shift()
20 | const dev=keys[0];
21 | const mint=keys[1];
22 | const [pda] = PublicKey.findProgramAddressSync(
23 | [Buffer.from('bonding-curve'), new PublicKey(mint).toBuffer()],
24 | PUMP_FUN_PROGRAM
25 | );
26 | const bondingcurve_address=pda.toString();
27 | let fee_recipient=pump_fun_fee_accounts[4];
28 | for(const key of keys){
29 | if(pump_fun_fee_accounts.includes(key)){
30 | fee_recipient=key;
31 | break;
32 | }
33 | }
34 | let post_bondingcurve_vsol_balance=0;
35 | let post_bondingcurve_vtoken_balance=0;
36 | let post_trader_sol_balance=0;
37 | let post_trader_token_balance=0;
38 | let solAmount=0;
39 | let tokenAmount=0;
40 | let txType="mint";
41 | data.transaction.transaction.transaction.message.accountKeys.map((account:any, index:number)=>{
42 | if(bs58.encode(account)==bondingcurve_address){
43 | post_bondingcurve_vsol_balance=Number(data.transaction.transaction.meta.postBalances[index])+30*LAMPORTS_PER_SOL;
44 | }
45 | if(bs58.encode(account)==dev){
46 | post_trader_sol_balance=Number(data.transaction.transaction.meta.postBalances[index]);
47 | solAmount=Number(data.transaction.transaction.meta.preBalances[index])-Number(data.transaction.transaction.meta.postBalances[index]);
48 |
49 | }
50 | })
51 | data.transaction.transaction.meta.postTokenBalances.map((post:any)=>{
52 | if(post.owner==bondingcurve_address){
53 | post_bondingcurve_vtoken_balance=Number(post["uiTokenAmount"]["amount"]);
54 | }
55 | if(post.owner==dev){
56 | post_trader_token_balance=Number(post["uiTokenAmount"]["amount"]);
57 | tokenAmount=post_trader_token_balance;
58 | }
59 | })
60 | const price=post_bondingcurve_vsol_balance/post_bondingcurve_vtoken_balance;
61 | const sol_price=post_bondingcurve_vtoken_balance/post_bondingcurve_vsol_balance;
62 | return{
63 | mint,
64 | txType,
65 | dev,
66 | bondingcurve_address,
67 | fee_recipient,
68 | post_bondingcurve_vsol_balance,
69 | post_bondingcurve_vtoken_balance,
70 | post_trader_sol_balance,
71 | post_trader_token_balance,
72 | price,
73 | sol_price,
74 | solAmount,
75 | tokenAmount
76 | };
77 | }else{
78 | let keys=[""]
79 | data.transaction.transaction.transaction.message.accountKeys.map((account:any, index:number)=>{
80 | keys.push(bs58.encode(account));
81 | })
82 | keys.shift()
83 | const dev=keys[0];
84 | let mint="";
85 | const post_datas= data.transaction.transaction.meta.postTokenBalances;
86 | for(const post_data of post_datas){
87 | if(post_data["mint"]!="So11111111111111111111111111111111111111112"){
88 | mint=post_data["mint"];
89 | break;
90 | }
91 | }
92 | const [pda] = PublicKey.findProgramAddressSync(
93 | [Buffer.from('bonding-curve'), new PublicKey(mint).toBuffer()],
94 | PUMP_FUN_PROGRAM
95 | );
96 | const bondingcurve_address=pda.toString();
97 | let fee_recipient=pump_fun_fee_accounts[4];
98 | for(const key of keys){
99 | if(pump_fun_fee_accounts.includes(key)){
100 | fee_recipient=key;
101 | break;
102 | }
103 | }
104 | let txType=""
105 | const logs=data.transaction.transaction.meta.logMessages;
106 | for(const log of logs){
107 | if(log.includes("Buy")){
108 | txType="buy";
109 | break;
110 | }
111 | if(log.includes("Sell")){
112 | txType="sell";
113 | break;
114 | }
115 | }
116 | let post_bondingcurve_vsol_balance=0;
117 | let post_bondingcurve_vtoken_balance=0;
118 | let post_trader_sol_balance=0;
119 | let post_trader_token_balance=0;
120 | let solAmount=0;
121 | let tokenAmount=0;
122 | data.transaction.transaction.transaction.message.accountKeys.map((account:any, index:number)=>{
123 | if(bs58.encode(account)==bondingcurve_address){
124 | post_bondingcurve_vsol_balance=Number(data.transaction.transaction.meta.postBalances[index])+30*LAMPORTS_PER_SOL;
125 | }
126 | if(bs58.encode(account)==dev){
127 | post_trader_sol_balance=Number(data.transaction.transaction.meta.postBalances[index]);
128 | solAmount=Number(data.transaction.transaction.meta.preBalances[index])-Number(data.transaction.transaction.meta.postBalances[index]);
129 |
130 | }
131 | })
132 | data.transaction.transaction.meta.postTokenBalances.map((post:any, index:number)=>{
133 | if(post.owner==bondingcurve_address){
134 | post_bondingcurve_vtoken_balance=Number(post["uiTokenAmount"]["amount"]);
135 | }
136 | if(post.owner==dev){
137 | post_trader_token_balance=Number(post["uiTokenAmount"]["amount"]);
138 | if(data.transaction.transaction.meta.preTokenBalances[index]!=undefined){
139 | tokenAmount=post_trader_token_balance-Number(data.transaction.transaction.meta.preTokenBalances[index]["uiTokenAmount"]["amount"]);
140 | }else{
141 | tokenAmount=post_trader_token_balance
142 | }
143 |
144 | }
145 | })
146 | const price=post_bondingcurve_vsol_balance/post_bondingcurve_vtoken_balance;
147 | const sol_price=post_bondingcurve_vtoken_balance/post_bondingcurve_vsol_balance;
148 | return{
149 | mint,
150 | txType,
151 | dev,
152 | bondingcurve_address,
153 | fee_recipient,
154 | post_bondingcurve_vsol_balance,
155 | post_bondingcurve_vtoken_balance,
156 | post_trader_sol_balance,
157 | post_trader_token_balance,
158 | price,
159 | sol_price,
160 | solAmount,
161 | tokenAmount
162 | };
163 | }
164 | }
165 |
166 |
167 |
--------------------------------------------------------------------------------
/backend/streaming/pump_copy.ts:
--------------------------------------------------------------------------------
1 | import { CommitmentLevel, SubscribeRequest } from "@triton-one/yellowstone-grpc";
2 | import { sendNewTokenAlert , delay, logger, getParsedData} from "../utils";
3 | import bs58 from "bs58"
4 | import Client from "@triton-one/yellowstone-grpc";
5 | import { Connection, Keypair, LAMPORTS_PER_SOL, PublicKey } from "@solana/web3.js";
6 | import { RPC_ENDPOINT, COMMITMENT_LEVEL , COPY_WALLET, MAX_BUY, MAX_HOLDING_TIME, QUOTE_AMOUNT, TAKE_PROFIT, STOP_LOSS, SELL_SLIPPAGE, BUY_SLIPPAGE, PRIVATE_KEY, COMPOUNDING_BUY_AMOUNT_PERCENTAGE, TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID, TIME_BASED_SELL_SIZE} from "../constants";
7 | import TelegramBot from "node-telegram-bot-api";
8 | import { swap } from "../utils";
9 | const solanaConnection = new Connection(RPC_ENDPOINT, COMMITMENT_LEVEL);
10 | let bought_tokens: string[] = [];
11 | let bought_count=0;
12 | let isBought: boolean = false;
13 | let solBalance=0;
14 | const wallet=Keypair.fromSecretKey(bs58.decode(PRIVATE_KEY))
15 | const PUMP_FUN_PROGRAM = new PublicKey("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P");
16 | export async function pump_copy(client: Client) {
17 | setInterval(async ()=>{
18 | solBalance=await solanaConnection.getBalance(wallet.publicKey, "processed");
19 | }, 3000)
20 | const stream = await client.subscribe();
21 | const request: SubscribeRequest = {
22 | "slots": {},
23 | "accounts": {},
24 | "transactions": {
25 | pumpfun: {
26 | "vote": false,
27 | "failed": false,
28 | accountInclude: [],
29 | accountExclude: [],
30 | accountRequired: [COPY_WALLET, PUMP_FUN_PROGRAM.toString()]
31 | }
32 | },
33 | "blocks": {},
34 | "blocksMeta": {},
35 | "accountsDataSlice": [],
36 | "commitment": CommitmentLevel.PROCESSED,
37 | entry: {},
38 | }
39 | await new Promise