-
Notifications
You must be signed in to change notification settings - Fork 3
/
sniper-jito.ts
166 lines (133 loc) · 5.29 KB
/
sniper-jito.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import dotenv from "dotenv";
import path from "path";
import { Connection, Keypair } from "@solana/web3.js";
import bs58 from "bs58";
import { Currency, CurrencyAmount, LiquidityPoolKeysV4, TokenAmount } from "@raydium-io/raydium-sdk";
import BN, { min } from "bn.js";
import {
checkSolBalance,
getTokenMetadataInfo,
initializeConfigurations,
logErrorToFile,
promptUserConfiguration,
rugCheck,
setupSnipeListMonitoring,
sleep,
storeData,
} from "./utils";
import base58 from "bs58";
import {
BUY_AMOUNT_SOL,
BUY_DELAY,
CHECK_TOKEN_SYMBOL,
ENABLE_RUG_CHECKS,
MAX_SINGLE_OWNER_PERCENTAGE,
MAX_SOL_LP,
MIN_SOL_LP,
MIN_SOL_REQUIRED,
MIN_TOKEN_LP_PERCENTAGE,
TOKEN_SYMBOL_FILTER,
USE_PENDING_SNIPE_LIST,
logger,
rayFee,
sniperWallet,
solanaConnection,
} from "./constants";
import { buyToken, extractMarketAndLpInfoFromLogs, getPoolKeysFromMarketId } from "./swapUtils";
dotenv.config();
/**storage */
const newDataPath = path.join(__dirname, "sniper_data", "bought_tokens.json");
const seenSignatures = new Set<string>();
let pendingSnipeList: string[] = [];
let tokenSymbolToSnipe = TOKEN_SYMBOL_FILTER.toLowerCase();
async function monitorNewTokens(connection: Connection, sniperWallet: Keypair) {
try {
await initializeConfigurations();
setupSnipeListMonitoring(pendingSnipeList, logger);
logger.info(`monitoring new solana tokens...`);
connection.onLogs(
rayFee,
async ({ logs, err, signature }) => {
try {
const websocketRecievedTimestamp = new Date().toISOString();
const websocketReceivedTime = Math.floor(new Date().getTime() / 1000);
if (err) {
return;
}
if (seenSignatures.has(signature)) {
return;
}
logger.info(`found new token signature: ${signature}`);
let signer = "";
let poolKeys: LiquidityPoolKeysV4 & {
poolOpenTime: any;
};
/**You need to use a RPC provider for getparsedtransaction to work properly.
* Check README.md for suggestions.
*/
const parsedTransaction = await connection.getParsedTransaction(signature, {
maxSupportedTransactionVersion: 0,
commitment: "confirmed",
});
if (parsedTransaction && parsedTransaction?.meta.err == null) {
logger.info(`successfully parsed transaction for signature: ${signature}`);
signer = parsedTransaction?.transaction.message.accountKeys[0].pubkey.toString();
const lpInfo = extractMarketAndLpInfoFromLogs(logs);
/**extract pool keys */
poolKeys = await getPoolKeysFromMarketId(lpInfo.marketId, connection);
if (!poolKeys) {
throw new Error(`unable to extract poolkeys for signature: ${signature}`);
}
const initPoolBlockTime = parsedTransaction?.blockTime;
const poolOpenTime = parseInt(poolKeys.poolOpenTime.toString());
logger.info(
`pool open time: ${poolOpenTime}. websocket received time: ${websocketReceivedTime}. open time later than websocket received time?: ${
poolOpenTime > websocketReceivedTime
}`
);
if (!USE_PENDING_SNIPE_LIST) {
if (poolOpenTime > websocketReceivedTime) {
logger.info(
`Open time of pool ${lpInfo.openTime} is later than websocket received time ${websocketReceivedTime} for mint: ${poolKeys.baseMint}. Exiting the function.`
);
return;
}
}
//check if token is in snipe list
if (USE_PENDING_SNIPE_LIST) {
logger.info(`current pending token list: ${pendingSnipeList}`);
if (pendingSnipeList.includes(poolKeys.baseMint.toString())) {
logger.info(`Found token ${poolKeys.baseMint.toString()} in pending snipe list.`);
const currentTime = Math.floor(new Date().getTime() / 1000);
const delayMs = (poolOpenTime - currentTime) * 1000;
//check if pool open time is in the future
if (delayMs > 0) {
logger.info(`Pool open time is in the future for ${poolKeys.baseMint.toString()}. Delaying txn until pool open time for ${delayMs / 1000} seconds.`);
await sleep(delayMs);
logger.info(`Pool open time delay complete for ${poolKeys.baseMint.toString()}. Executing rest of function now...`);
}
} else if (CHECK_TOKEN_SYMBOL) {
const tokenMetadataInfo = await getTokenMetadataInfo(connection, poolKeys.baseMint.toString());
if (tokenMetadataInfo && tokenMetadataInfo.symbol) {
if (tokenMetadataInfo.symbol.toLowerCase() === tokenSymbolToSnipe) {
logger.info(`Found token ${poolKeys.baseMint.toString()} with symbol ${tokenMetadataInfo.symbol} in pending snipe list.`);
} else {
logger.info(`Skipping token ${poolKeys.baseMint.toString()}. Token symbol ${tokenMetadataInfo.symbol} does not match ${tokenSymbolToSnipe}.`);
return;
}
} else {
logger.info(`Skipping token ${poolKeys.baseMint.toString()}. Unable to retrieve the Token symbol info.`);
return;
}
} else {
logger.info(`Skipping token ${poolKeys.baseMint.toString()}. Not in pending snipe list.`);
return;
}
}
}
}
}
}
}
monitorNewTokens();
//discord.gg/solana-scripts