Compare commits

...

2 Commits

Author SHA1 Message Date
afef9e468c Merge 4fcf5165d5 into 04e5ca7d27 2024-09-16 11:43:21 +08:00
4fcf5165d5 tsc & prettier 2024-04-30 10:54:57 -03:00
56 changed files with 2860 additions and 791 deletions

View File

@ -1,5 +1,6 @@
{
"singleQuote": true,
"singleQuote": false,
"trailingComma": "all",
"printWidth": 120
"printWidth": 120,
"useTabs": true
}

340
bot.js Normal file
View File

@ -0,0 +1,340 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Bot = void 0;
const web3_js_1 = require("@solana/web3.js");
const spl_token_1 = require("@solana/spl-token");
const raydium_sdk_1 = require("@raydium-io/raydium-sdk");
const cache_1 = require("./cache");
const filters_1 = require("./filters");
const helpers_1 = require("./helpers");
const async_mutex_1 = require("async-mutex");
const bn_js_1 = __importDefault(require("bn.js"));
const warp_transaction_executor_1 = require("./transactions/warp-transaction-executor");
const jito_rpc_transaction_executor_1 = require("./transactions/jito-rpc-transaction-executor");
class Bot {
constructor(connection, marketStorage, poolStorage, txExecutor, config) {
this.connection = connection;
this.marketStorage = marketStorage;
this.poolStorage = poolStorage;
this.txExecutor = txExecutor;
this.config = config;
this.sellExecutionCount = 0;
this.stopLoss = new Map();
this.isWarp = false;
this.isJito = false;
this.isWarp = txExecutor instanceof warp_transaction_executor_1.WarpTransactionExecutor;
this.isJito = txExecutor instanceof jito_rpc_transaction_executor_1.JitoTransactionExecutor;
this.semaphore = new async_mutex_1.Semaphore(config.maxTokensAtTheTime);
if (this.config.useSnipeList) {
this.snipeListCache = new cache_1.SnipeListCache();
this.snipeListCache.init();
}
}
validate() {
return __awaiter(this, void 0, void 0, function* () {
try {
yield (0, spl_token_1.getAccount)(this.connection, this.config.quoteAta, this.connection.commitment);
}
catch (error) {
helpers_1.logger.error(`${this.config.quoteToken.symbol} token account not found in wallet: ${this.config.wallet.publicKey.toString()}`);
return false;
}
return true;
});
}
buy(accountId, poolState) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
helpers_1.logger.trace({ mint: poolState.baseMint }, `Processing new pool...`);
if (this.config.useSnipeList && !((_a = this.snipeListCache) === null || _a === void 0 ? void 0 : _a.isInList(poolState.baseMint.toString()))) {
helpers_1.logger.debug({ mint: poolState.baseMint.toString() }, `Skipping buy because token is not in a snipe list`);
return;
}
if (this.config.autoBuyDelay > 0) {
helpers_1.logger.debug({ mint: poolState.baseMint }, `Waiting for ${this.config.autoBuyDelay} ms before buy`);
yield (0, helpers_1.sleep)(this.config.autoBuyDelay);
}
const numberOfActionsBeingProcessed = this.config.maxTokensAtTheTime - this.semaphore.getValue() + this.sellExecutionCount;
if (this.semaphore.isLocked() || numberOfActionsBeingProcessed >= this.config.maxTokensAtTheTime) {
helpers_1.logger.debug({ mint: poolState.baseMint.toString() }, `Skipping buy because max tokens to process at the same time is ${this.config.maxTokensAtTheTime} and currently ${numberOfActionsBeingProcessed} tokens is being processed`);
return;
}
yield this.semaphore.acquire();
try {
const [market, mintAta] = yield Promise.all([
this.marketStorage.get(poolState.marketId.toString()),
(0, spl_token_1.getAssociatedTokenAddress)(poolState.baseMint, this.config.wallet.publicKey),
]);
const poolKeys = (0, helpers_1.createPoolKeys)(accountId, poolState, market);
if (!this.config.useSnipeList) {
const match = yield this.filterMatch(poolKeys);
if (!match) {
helpers_1.logger.trace({ mint: poolKeys.baseMint.toString() }, `Skipping buy because pool doesn't match filters`);
return;
}
}
for (let i = 0; i < this.config.maxBuyRetries; i++) {
try {
helpers_1.logger.info({ mint: poolState.baseMint.toString() }, `Send buy transaction attempt: ${i + 1}/${this.config.maxBuyRetries}`);
const tokenOut = new raydium_sdk_1.Token(spl_token_1.TOKEN_PROGRAM_ID, poolKeys.baseMint, poolKeys.baseDecimals);
const result = yield this.swap(poolKeys, this.config.quoteAta, mintAta, this.config.quoteToken, tokenOut, this.config.quoteAmount, this.config.buySlippage, this.config.wallet, 'buy');
if (result.confirmed) {
helpers_1.logger.info({
mint: poolState.baseMint.toString(),
signature: result.signature,
url: `https://solscan.io/tx/${result.signature}?cluster=${helpers_1.NETWORK}`,
}, `Confirmed buy tx`);
break;
}
helpers_1.logger.info({
mint: poolState.baseMint.toString(),
signature: result.signature,
error: result.error,
}, `Error confirming buy tx`);
}
catch (error) {
helpers_1.logger.debug({ mint: poolState.baseMint.toString(), error }, `Error confirming buy transaction`);
}
}
}
catch (error) {
helpers_1.logger.error({ mint: poolState.baseMint.toString(), error }, `Failed to buy token`);
}
finally {
this.semaphore.release();
}
});
}
sell(accountId, rawAccount) {
return __awaiter(this, void 0, void 0, function* () {
this.sellExecutionCount++;
try {
helpers_1.logger.trace({ mint: rawAccount.mint }, `Processing new token...`);
const poolData = yield this.poolStorage.get(rawAccount.mint.toString());
if (!poolData) {
helpers_1.logger.trace({ mint: rawAccount.mint.toString() }, `Token pool data is not found, can't sell`);
return;
}
const tokenIn = new raydium_sdk_1.Token(spl_token_1.TOKEN_PROGRAM_ID, poolData.state.baseMint, poolData.state.baseDecimal.toNumber());
const tokenAmountIn = new raydium_sdk_1.TokenAmount(tokenIn, rawAccount.amount, true);
if (tokenAmountIn.isZero()) {
helpers_1.logger.info({ mint: rawAccount.mint.toString() }, `Empty balance, can't sell`);
return;
}
if (this.config.autoSellDelay > 0) {
helpers_1.logger.debug({ mint: rawAccount.mint }, `Waiting for ${this.config.autoSellDelay} ms before sell`);
yield (0, helpers_1.sleep)(this.config.autoSellDelay);
}
const market = yield this.marketStorage.get(poolData.state.marketId.toString());
const poolKeys = (0, helpers_1.createPoolKeys)(new web3_js_1.PublicKey(poolData.id), poolData.state, market);
for (let i = 0; i < this.config.maxSellRetries; i++) {
try {
const shouldSell = yield this.waitForSellSignal(tokenAmountIn, poolKeys);
if (!shouldSell) {
return;
}
helpers_1.logger.info({ mint: rawAccount.mint }, `Send sell transaction attempt: ${i + 1}/${this.config.maxSellRetries}`);
const result = yield this.swap(poolKeys, accountId, this.config.quoteAta, tokenIn, this.config.quoteToken, tokenAmountIn, this.config.sellSlippage, this.config.wallet, 'sell');
if (result.confirmed) {
helpers_1.logger.info({
dex: `https://dexscreener.com/solana/${rawAccount.mint.toString()}?maker=${this.config.wallet.publicKey}`,
mint: rawAccount.mint.toString(),
signature: result.signature,
url: `https://solscan.io/tx/${result.signature}?cluster=${helpers_1.NETWORK}`,
}, `Confirmed sell tx`);
break;
}
helpers_1.logger.info({
mint: rawAccount.mint.toString(),
signature: result.signature,
error: result.error,
}, `Error confirming sell tx`);
}
catch (error) {
helpers_1.logger.debug({ mint: rawAccount.mint.toString(), error }, `Error confirming sell transaction`);
}
}
}
catch (error) {
helpers_1.logger.error({ mint: rawAccount.mint.toString(), error }, `Failed to sell token`);
}
finally {
this.sellExecutionCount--;
}
});
}
// noinspection JSUnusedLocalSymbols
swap(poolKeys, ataIn, ataOut, tokenIn, tokenOut, amountIn, slippage, wallet, direction) {
return __awaiter(this, void 0, void 0, function* () {
const slippagePercent = new raydium_sdk_1.Percent(slippage, 100);
const poolInfo = yield raydium_sdk_1.Liquidity.fetchInfo({
connection: this.connection,
poolKeys,
});
const computedAmountOut = raydium_sdk_1.Liquidity.computeAmountOut({
poolKeys,
poolInfo,
amountIn,
currencyOut: tokenOut,
slippage: slippagePercent,
});
const latestBlockhash = yield this.connection.getLatestBlockhash();
const { innerTransaction } = raydium_sdk_1.Liquidity.makeSwapFixedInInstruction({
poolKeys: poolKeys,
userKeys: {
tokenAccountIn: ataIn,
tokenAccountOut: ataOut,
owner: wallet.publicKey,
},
amountIn: amountIn.raw,
minAmountOut: computedAmountOut.minAmountOut.raw,
}, poolKeys.version);
const messageV0 = new web3_js_1.TransactionMessage({
payerKey: wallet.publicKey,
recentBlockhash: latestBlockhash.blockhash,
instructions: [
...(this.isWarp || this.isJito
? []
: [
web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: this.config.unitPrice }),
web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: this.config.unitLimit }),
]),
...(direction === 'buy'
? [
(0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, ataOut, wallet.publicKey, tokenOut.mint),
]
: []),
...innerTransaction.instructions,
...(direction === 'sell' ? [(0, spl_token_1.createCloseAccountInstruction)(ataIn, wallet.publicKey, wallet.publicKey)] : []),
],
}).compileToV0Message();
const transaction = new web3_js_1.VersionedTransaction(messageV0);
transaction.sign([wallet, ...innerTransaction.signers]);
return this.txExecutor.executeAndConfirm(transaction, wallet, latestBlockhash);
});
}
filterMatch(poolKeys) {
return __awaiter(this, void 0, void 0, function* () {
if (this.config.filterCheckInterval === 0 || this.config.filterCheckDuration === 0) {
return true;
}
const filters = new filters_1.PoolFilters(this.connection, {
quoteToken: this.config.quoteToken,
minPoolSize: this.config.minPoolSize,
maxPoolSize: this.config.maxPoolSize,
});
const timesToCheck = this.config.filterCheckDuration / this.config.filterCheckInterval;
let timesChecked = 0;
let matchCount = 0;
do {
try {
const shouldBuy = yield filters.execute(poolKeys);
if (shouldBuy) {
matchCount++;
if (this.config.consecutiveMatchCount <= matchCount) {
helpers_1.logger.debug({ mint: poolKeys.baseMint.toString() }, `Filter match ${matchCount}/${this.config.consecutiveMatchCount}`);
return true;
}
}
else {
matchCount = 0;
}
yield (0, helpers_1.sleep)(this.config.filterCheckInterval);
}
finally {
timesChecked++;
}
} while (timesChecked < timesToCheck);
return false;
});
}
waitForSellSignal(amountIn, poolKeys) {
return __awaiter(this, void 0, void 0, function* () {
if (this.config.priceCheckDuration === 0 || this.config.priceCheckInterval === 0) {
return true;
}
const timesToCheck = this.config.priceCheckDuration / this.config.priceCheckInterval;
const profitFraction = this.config.quoteAmount.mul(this.config.takeProfit).numerator.div(new bn_js_1.default(100));
const profitAmount = new raydium_sdk_1.TokenAmount(this.config.quoteToken, profitFraction, true);
const takeProfit = this.config.quoteAmount.add(profitAmount);
let stopLoss;
if (!this.stopLoss.get(poolKeys.baseMint.toString())) {
const lossFraction = this.config.quoteAmount.mul(this.config.stopLoss).numerator.div(new bn_js_1.default(100));
const lossAmount = new raydium_sdk_1.TokenAmount(this.config.quoteToken, lossFraction, true);
stopLoss = this.config.quoteAmount.subtract(lossAmount);
this.stopLoss.set(poolKeys.baseMint.toString(), stopLoss);
}
else {
stopLoss = this.stopLoss.get(poolKeys.baseMint.toString());
}
const slippage = new raydium_sdk_1.Percent(this.config.sellSlippage, 100);
let timesChecked = 0;
do {
try {
const poolInfo = yield raydium_sdk_1.Liquidity.fetchInfo({
connection: this.connection,
poolKeys,
});
const amountOut = raydium_sdk_1.Liquidity.computeAmountOut({
poolKeys,
poolInfo,
amountIn: amountIn,
currencyOut: this.config.quoteToken,
slippage,
}).amountOut;
if (this.config.trailingStopLoss) {
const trailingLossFraction = amountOut.mul(this.config.stopLoss).numerator.div(new bn_js_1.default(100));
const trailingLossAmount = new raydium_sdk_1.TokenAmount(this.config.quoteToken, trailingLossFraction, true);
const trailingStopLoss = amountOut.subtract(trailingLossAmount);
if (trailingStopLoss.gt(stopLoss)) {
helpers_1.logger.trace({ mint: poolKeys.baseMint.toString() }, `Updating trailing stop loss from ${stopLoss.toFixed()} to ${trailingStopLoss.toFixed()}`);
this.stopLoss.set(poolKeys.baseMint.toString(), trailingStopLoss);
stopLoss = trailingStopLoss;
}
}
if (this.config.skipSellingIfLostMoreThan > 0) {
const stopSellingFraction = this.config.quoteAmount
.mul(this.config.skipSellingIfLostMoreThan)
.numerator.div(new bn_js_1.default(100));
const stopSellingAmount = new raydium_sdk_1.TokenAmount(this.config.quoteToken, stopSellingFraction, true);
if (amountOut.lt(stopSellingAmount)) {
helpers_1.logger.debug({ mint: poolKeys.baseMint.toString() }, `Token dropped more than ${this.config.skipSellingIfLostMoreThan}%, sell stopped. Initial: ${this.config.quoteAmount.toFixed()} | Current: ${amountOut.toFixed()}`);
this.stopLoss.delete(poolKeys.baseMint.toString());
return false;
}
}
helpers_1.logger.debug({ mint: poolKeys.baseMint.toString() }, `Take profit: ${takeProfit.toFixed()} | Stop loss: ${stopLoss.toFixed()} | Current: ${amountOut.toFixed()}`);
if (amountOut.lt(stopLoss)) {
this.stopLoss.delete(poolKeys.baseMint.toString());
break;
}
if (amountOut.gt(takeProfit)) {
this.stopLoss.delete(poolKeys.baseMint.toString());
break;
}
yield (0, helpers_1.sleep)(this.config.priceCheckInterval);
}
catch (e) {
helpers_1.logger.trace({ mint: poolKeys.baseMint.toString(), e }, `Failed to check token price`);
}
finally {
timesChecked++;
}
} while (timesChecked < timesToCheck);
return true;
});
}
}
exports.Bot = Bot;

19
cache/index.js vendored Normal file
View File

@ -0,0 +1,19 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./market.cache"), exports);
__exportStar(require("./pool.cache"), exports);
__exportStar(require("./snipe-list.cache"), exports);

6
cache/index.ts vendored
View File

@ -1,3 +1,3 @@
export * from './market.cache';
export * from './pool.cache';
export * from './snipe-list.cache';
export * from "./market.cache";
export * from "./pool.cache";
export * from "./snipe-list.cache";

68
cache/market.cache.js vendored Normal file
View File

@ -0,0 +1,68 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MarketCache = void 0;
const web3_js_1 = require("@solana/web3.js");
const helpers_1 = require("../helpers");
const raydium_sdk_1 = require("@raydium-io/raydium-sdk");
class MarketCache {
constructor(connection) {
this.connection = connection;
this.keys = new Map();
}
init(config) {
return __awaiter(this, void 0, void 0, function* () {
helpers_1.logger.debug({}, `Fetching all existing ${config.quoteToken.symbol} markets...`);
const accounts = yield this.connection.getProgramAccounts(raydium_sdk_1.MAINNET_PROGRAM_ID.OPENBOOK_MARKET, {
commitment: this.connection.commitment,
dataSlice: {
offset: raydium_sdk_1.MARKET_STATE_LAYOUT_V3.offsetOf("eventQueue"),
length: helpers_1.MINIMAL_MARKET_STATE_LAYOUT_V3.span,
},
filters: [
{ dataSize: raydium_sdk_1.MARKET_STATE_LAYOUT_V3.span },
{
memcmp: {
offset: raydium_sdk_1.MARKET_STATE_LAYOUT_V3.offsetOf("quoteMint"),
bytes: config.quoteToken.mint.toBase58(),
},
},
],
});
for (const account of accounts) {
const market = helpers_1.MINIMAL_MARKET_STATE_LAYOUT_V3.decode(account.account.data);
this.keys.set(account.pubkey.toString(), market);
}
helpers_1.logger.debug({}, `Cached ${this.keys.size} markets`);
});
}
save(marketId, keys) {
if (!this.keys.has(marketId)) {
helpers_1.logger.trace({}, `Caching new market: ${marketId}`);
this.keys.set(marketId, keys);
}
}
get(marketId) {
return __awaiter(this, void 0, void 0, function* () {
if (this.keys.has(marketId)) {
return this.keys.get(marketId);
}
helpers_1.logger.trace({}, `Fetching new market keys for ${marketId}`);
const market = yield this.fetch(marketId);
this.keys.set(marketId, market);
return market;
});
}
fetch(marketId) {
return (0, helpers_1.getMinimalMarketV3)(this.connection, new web3_js_1.PublicKey(marketId), this.connection.commitment);
}
}
exports.MarketCache = MarketCache;

94
cache/market.cache.ts vendored
View File

@ -1,58 +1,58 @@
import { Connection, PublicKey } from '@solana/web3.js';
import { getMinimalMarketV3, logger, MINIMAL_MARKET_STATE_LAYOUT_V3, MinimalMarketLayoutV3 } from '../helpers';
import { MAINNET_PROGRAM_ID, MARKET_STATE_LAYOUT_V3, Token } from '@raydium-io/raydium-sdk';
import { Connection, PublicKey } from "@solana/web3.js";
import { getMinimalMarketV3, logger, MINIMAL_MARKET_STATE_LAYOUT_V3, MinimalMarketLayoutV3 } from "../helpers";
import { MAINNET_PROGRAM_ID, MARKET_STATE_LAYOUT_V3, Token } from "@raydium-io/raydium-sdk";
export class MarketCache {
private readonly keys: Map<string, MinimalMarketLayoutV3> = new Map<string, MinimalMarketLayoutV3>();
constructor(private readonly connection: Connection) {}
private readonly keys: Map<string, MinimalMarketLayoutV3> = new Map<string, MinimalMarketLayoutV3>();
constructor(private readonly connection: Connection) {}
async init(config: { quoteToken: Token }) {
logger.debug({}, `Fetching all existing ${config.quoteToken.symbol} markets...`);
async init(config: { quoteToken: Token }) {
logger.debug({}, `Fetching all existing ${config.quoteToken.symbol} markets...`);
const accounts = await this.connection.getProgramAccounts(MAINNET_PROGRAM_ID.OPENBOOK_MARKET, {
commitment: this.connection.commitment,
dataSlice: {
offset: MARKET_STATE_LAYOUT_V3.offsetOf('eventQueue'),
length: MINIMAL_MARKET_STATE_LAYOUT_V3.span,
},
filters: [
{ dataSize: MARKET_STATE_LAYOUT_V3.span },
{
memcmp: {
offset: MARKET_STATE_LAYOUT_V3.offsetOf('quoteMint'),
bytes: config.quoteToken.mint.toBase58(),
},
},
],
});
const accounts = await this.connection.getProgramAccounts(MAINNET_PROGRAM_ID.OPENBOOK_MARKET, {
commitment: this.connection.commitment,
dataSlice: {
offset: MARKET_STATE_LAYOUT_V3.offsetOf("eventQueue"),
length: MINIMAL_MARKET_STATE_LAYOUT_V3.span,
},
filters: [
{ dataSize: MARKET_STATE_LAYOUT_V3.span },
{
memcmp: {
offset: MARKET_STATE_LAYOUT_V3.offsetOf("quoteMint"),
bytes: config.quoteToken.mint.toBase58(),
},
},
],
});
for (const account of accounts) {
const market = MINIMAL_MARKET_STATE_LAYOUT_V3.decode(account.account.data);
this.keys.set(account.pubkey.toString(), market);
}
for (const account of accounts) {
const market = MINIMAL_MARKET_STATE_LAYOUT_V3.decode(account.account.data);
this.keys.set(account.pubkey.toString(), market);
}
logger.debug({}, `Cached ${this.keys.size} markets`);
}
logger.debug({}, `Cached ${this.keys.size} markets`);
}
public save(marketId: string, keys: MinimalMarketLayoutV3) {
if (!this.keys.has(marketId)) {
logger.trace({}, `Caching new market: ${marketId}`);
this.keys.set(marketId, keys);
}
}
public save(marketId: string, keys: MinimalMarketLayoutV3) {
if (!this.keys.has(marketId)) {
logger.trace({}, `Caching new market: ${marketId}`);
this.keys.set(marketId, keys);
}
}
public async get(marketId: string): Promise<MinimalMarketLayoutV3> {
if (this.keys.has(marketId)) {
return this.keys.get(marketId)!;
}
public async get(marketId: string): Promise<MinimalMarketLayoutV3> {
if (this.keys.has(marketId)) {
return this.keys.get(marketId)!;
}
logger.trace({}, `Fetching new market keys for ${marketId}`);
const market = await this.fetch(marketId);
this.keys.set(marketId, market);
return market;
}
logger.trace({}, `Fetching new market keys for ${marketId}`);
const market = await this.fetch(marketId);
this.keys.set(marketId, market);
return market;
}
private fetch(marketId: string): Promise<MinimalMarketLayoutV3> {
return getMinimalMarketV3(this.connection, new PublicKey(marketId), this.connection.commitment);
}
private fetch(marketId: string): Promise<MinimalMarketLayoutV3> {
return getMinimalMarketV3(this.connection, new PublicKey(marketId), this.connection.commitment);
}
}

12
cache/optimize.js vendored Normal file

File diff suppressed because one or more lines are too long

30
cache/pool.cache.js vendored Normal file
View File

@ -0,0 +1,30 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PoolCache = void 0;
const helpers_1 = require("../helpers");
class PoolCache {
constructor() {
this.keys = new Map();
}
save(id, state) {
if (!this.keys.has(state.baseMint.toString())) {
helpers_1.logger.trace(`Caching new pool for mint: ${state.baseMint.toString()}`);
this.keys.set(state.baseMint.toString(), { id, state });
}
}
get(mint) {
return __awaiter(this, void 0, void 0, function* () {
return this.keys.get(mint);
});
}
}
exports.PoolCache = PoolCache;

30
cache/pool.cache.ts vendored
View File

@ -1,20 +1,20 @@
import { LiquidityStateV4 } from '@raydium-io/raydium-sdk';
import { logger } from '../helpers';
import { LiquidityStateV4 } from "@raydium-io/raydium-sdk";
import { logger } from "../helpers";
export class PoolCache {
private readonly keys: Map<string, { id: string; state: LiquidityStateV4 }> = new Map<
string,
{ id: string; state: LiquidityStateV4 }
>();
private readonly keys: Map<string, { id: string; state: LiquidityStateV4 }> = new Map<
string,
{ id: string; state: LiquidityStateV4 }
>();
public save(id: string, state: LiquidityStateV4) {
if (!this.keys.has(state.baseMint.toString())) {
logger.trace(`Caching new pool for mint: ${state.baseMint.toString()}`);
this.keys.set(state.baseMint.toString(), { id, state });
}
}
public save(id: string, state: LiquidityStateV4) {
if (!this.keys.has(state.baseMint.toString())) {
logger.trace(`Caching new pool for mint: ${state.baseMint.toString()}`);
this.keys.set(state.baseMint.toString(), { id, state });
}
}
public async get(mint: string): Promise<{ id: string; state: LiquidityStateV4 }> {
return this.keys.get(mint)!;
}
public async get(mint: string): Promise<{ id: string; state: LiquidityStateV4 }> {
return this.keys.get(mint)!;
}
}

35
cache/snipe-list.cache.js vendored Normal file
View File

@ -0,0 +1,35 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SnipeListCache = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const helpers_1 = require("../helpers");
class SnipeListCache {
constructor() {
this.snipeList = [];
this.fileLocation = path_1.default.join(__dirname, "../snipe-list.txt");
setInterval(() => this.loadSnipeList(), helpers_1.SNIPE_LIST_REFRESH_INTERVAL);
}
init() {
this.loadSnipeList();
}
isInList(mint) {
return this.snipeList.includes(mint);
}
loadSnipeList() {
helpers_1.logger.trace(`Refreshing snipe list...`);
const count = this.snipeList.length;
const data = fs_1.default.readFileSync(this.fileLocation, "utf-8");
this.snipeList = data
.split("\n")
.map((a) => a.trim())
.filter((a) => a);
if (this.snipeList.length != count) {
helpers_1.logger.info(`Loaded snipe list: ${this.snipeList.length}`);
}
}
}
exports.SnipeListCache = SnipeListCache;

View File

@ -1,35 +1,35 @@
import fs from 'fs';
import path from 'path';
import { logger, SNIPE_LIST_REFRESH_INTERVAL } from '../helpers';
import fs from "fs";
import path from "path";
import { logger, SNIPE_LIST_REFRESH_INTERVAL } from "../helpers";
export class SnipeListCache {
private snipeList: string[] = [];
private fileLocation = path.join(__dirname, '../snipe-list.txt');
private snipeList: string[] = [];
private fileLocation = path.join(__dirname, "../snipe-list.txt");
constructor() {
setInterval(() => this.loadSnipeList(), SNIPE_LIST_REFRESH_INTERVAL);
}
constructor() {
setInterval(() => this.loadSnipeList(), SNIPE_LIST_REFRESH_INTERVAL);
}
public init() {
this.loadSnipeList();
}
public init() {
this.loadSnipeList();
}
public isInList(mint: string) {
return this.snipeList.includes(mint);
}
public isInList(mint: string) {
return this.snipeList.includes(mint);
}
private loadSnipeList() {
logger.trace(`Refreshing snipe list...`);
private loadSnipeList() {
logger.trace(`Refreshing snipe list...`);
const count = this.snipeList.length;
const data = fs.readFileSync(this.fileLocation, 'utf-8');
this.snipeList = data
.split('\n')
.map((a) => a.trim())
.filter((a) => a);
const count = this.snipeList.length;
const data = fs.readFileSync(this.fileLocation, "utf-8");
this.snipeList = data
.split("\n")
.map((a) => a.trim())
.filter((a) => a);
if (this.snipeList.length != count) {
logger.info(`Loaded snipe list: ${this.snipeList.length}`);
}
}
if (this.snipeList.length != count) {
logger.info(`Loaded snipe list: ${this.snipeList.length}`);
}
}
}

43
filters/burn.filter.js Normal file
View File

@ -0,0 +1,43 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BurnFilter = void 0;
const helpers_1 = require("../helpers");
class BurnFilter {
constructor(connection) {
this.connection = connection;
this.cachedResult = undefined;
}
execute(poolKeys) {
return __awaiter(this, void 0, void 0, function* () {
if (this.cachedResult) {
return this.cachedResult;
}
try {
const amount = yield this.connection.getTokenSupply(poolKeys.lpMint, this.connection.commitment);
const burned = amount.value.uiAmount === 0;
const result = { ok: burned, message: burned ? undefined : "Burned -> Creator didn't burn LP" };
if (result.ok) {
this.cachedResult = result;
}
return result;
}
catch (e) {
if (e.code == -32602) {
return { ok: true };
}
helpers_1.logger.error({ mint: poolKeys.baseMint }, `Failed to check if LP is burned`);
}
return { ok: false, message: "Failed to check if LP is burned" };
});
}
}
exports.BurnFilter = BurnFilter;

View File

@ -1,36 +1,36 @@
import { Filter, FilterResult } from './pool-filters';
import { Connection } from '@solana/web3.js';
import { LiquidityPoolKeysV4 } from '@raydium-io/raydium-sdk';
import { logger } from '../helpers';
import { Filter, FilterResult } from "./pool-filters";
import { Connection } from "@solana/web3.js";
import { LiquidityPoolKeysV4 } from "@raydium-io/raydium-sdk";
import { logger } from "../helpers";
export class BurnFilter implements Filter {
private cachedResult: FilterResult | undefined = undefined;
private cachedResult: FilterResult | undefined = undefined;
constructor(private readonly connection: Connection) {}
constructor(private readonly connection: Connection) {}
async execute(poolKeys: LiquidityPoolKeysV4): Promise<FilterResult> {
if (this.cachedResult) {
return this.cachedResult;
}
async execute(poolKeys: LiquidityPoolKeysV4): Promise<FilterResult> {
if (this.cachedResult) {
return this.cachedResult;
}
try {
const amount = await this.connection.getTokenSupply(poolKeys.lpMint, this.connection.commitment);
const burned = amount.value.uiAmount === 0;
const result = { ok: burned, message: burned ? undefined : "Burned -> Creator didn't burn LP" };
try {
const amount = await this.connection.getTokenSupply(poolKeys.lpMint, this.connection.commitment);
const burned = amount.value.uiAmount === 0;
const result = { ok: burned, message: burned ? undefined : "Burned -> Creator didn't burn LP" };
if (result.ok) {
this.cachedResult = result;
}
if (result.ok) {
this.cachedResult = result;
}
return result;
} catch (e: any) {
if (e.code == -32602) {
return { ok: true };
}
return result;
} catch (e: any) {
if (e.code == -32602) {
return { ok: true };
}
logger.error({ mint: poolKeys.baseMint }, `Failed to check if LP is burned`);
}
logger.error({ mint: poolKeys.baseMint }, `Failed to check if LP is burned`);
}
return { ok: false, message: 'Failed to check if LP is burned' };
}
return { ok: false, message: "Failed to check if LP is burned" };
}
}

21
filters/index.js Normal file
View File

@ -0,0 +1,21 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./burn.filter"), exports);
__exportStar(require("./mutable.filter"), exports);
__exportStar(require("./pool-filters"), exports);
__exportStar(require("./pool-size.filter"), exports);
__exportStar(require("./renounced.filter"), exports);

View File

@ -1,5 +1,5 @@
export * from './burn.filter';
export * from './mutable.filter';
export * from './pool-filters';
export * from './pool-size.filter';
export * from './renounced.filter';
export * from "./burn.filter";
export * from "./mutable.filter";
export * from "./pool-filters";
export * from "./pool-size.filter";
export * from "./renounced.filter";

76
filters/mutable.filter.js Normal file
View File

@ -0,0 +1,76 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MutableFilter = void 0;
const raydium_sdk_1 = require("@raydium-io/raydium-sdk");
const helpers_1 = require("../helpers");
class MutableFilter {
constructor(connection, metadataSerializer, checkMutable, checkSocials) {
this.connection = connection;
this.metadataSerializer = metadataSerializer;
this.checkMutable = checkMutable;
this.checkSocials = checkSocials;
this.errorMessage = [];
this.cachedResult = undefined;
if (this.checkMutable) {
this.errorMessage.push("mutable");
}
if (this.checkSocials) {
this.errorMessage.push("socials");
}
}
execute(poolKeys) {
return __awaiter(this, void 0, void 0, function* () {
if (this.cachedResult) {
return this.cachedResult;
}
try {
const metadataPDA = (0, raydium_sdk_1.getPdaMetadataKey)(poolKeys.baseMint);
const metadataAccount = yield this.connection.getAccountInfo(metadataPDA.publicKey, this.connection.commitment);
if (!(metadataAccount === null || metadataAccount === void 0 ? void 0 : metadataAccount.data)) {
return { ok: false, message: "Mutable -> Failed to fetch account data" };
}
const deserialize = this.metadataSerializer.deserialize(metadataAccount.data);
const mutable = !this.checkMutable || deserialize[0].isMutable;
const hasSocials = !this.checkSocials || (yield this.hasSocials(deserialize[0]));
const ok = !mutable && hasSocials;
const message = [];
if (mutable) {
message.push("metadata can be changed");
}
if (!hasSocials) {
message.push("has no socials");
}
const result = { ok: ok, message: ok ? undefined : `MutableSocials -> Token ${message.join(" and ")}` };
if (!mutable) {
this.cachedResult = result;
}
return result;
}
catch (e) {
helpers_1.logger.error({ mint: poolKeys.baseMint }, `MutableSocials -> Failed to check ${this.errorMessage.join(" and ")}`);
}
return {
ok: false,
message: `MutableSocials -> Failed to check ${this.errorMessage.join(" and ")}`,
};
});
}
hasSocials(metadata) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const response = yield fetch(metadata.uri);
const data = yield response.json();
return Object.values((_a = data === null || data === void 0 ? void 0 : data.extensions) !== null && _a !== void 0 ? _a : {}).filter((value) => value).length > 0;
});
}
}
exports.MutableFilter = MutableFilter;

View File

@ -1,77 +1,77 @@
import { Filter, FilterResult } from './pool-filters';
import { Connection } from '@solana/web3.js';
import { LiquidityPoolKeysV4 } from '@raydium-io/raydium-sdk';
import { getPdaMetadataKey } from '@raydium-io/raydium-sdk';
import { MetadataAccountData, MetadataAccountDataArgs } from '@metaplex-foundation/mpl-token-metadata';
import { Serializer } from '@metaplex-foundation/umi/serializers';
import { logger } from '../helpers';
import { Filter, FilterResult } from "./pool-filters";
import { Connection } from "@solana/web3.js";
import { LiquidityPoolKeysV4 } from "@raydium-io/raydium-sdk";
import { getPdaMetadataKey } from "@raydium-io/raydium-sdk";
import { MetadataAccountData, MetadataAccountDataArgs } from "@metaplex-foundation/mpl-token-metadata";
import { Serializer } from "@metaplex-foundation/umi/serializers";
import { logger } from "../helpers";
export class MutableFilter implements Filter {
private readonly errorMessage: string[] = [];
private cachedResult: FilterResult | undefined = undefined;
private readonly errorMessage: string[] = [];
private cachedResult: FilterResult | undefined = undefined;
constructor(
private readonly connection: Connection,
private readonly metadataSerializer: Serializer<MetadataAccountDataArgs, MetadataAccountData>,
private readonly checkMutable: boolean,
private readonly checkSocials: boolean,
) {
if (this.checkMutable) {
this.errorMessage.push('mutable');
}
constructor(
private readonly connection: Connection,
private readonly metadataSerializer: Serializer<MetadataAccountDataArgs, MetadataAccountData>,
private readonly checkMutable: boolean,
private readonly checkSocials: boolean,
) {
if (this.checkMutable) {
this.errorMessage.push("mutable");
}
if (this.checkSocials) {
this.errorMessage.push('socials');
}
}
if (this.checkSocials) {
this.errorMessage.push("socials");
}
}
async execute(poolKeys: LiquidityPoolKeysV4): Promise<FilterResult> {
if (this.cachedResult) {
return this.cachedResult;
}
async execute(poolKeys: LiquidityPoolKeysV4): Promise<FilterResult> {
if (this.cachedResult) {
return this.cachedResult;
}
try {
const metadataPDA = getPdaMetadataKey(poolKeys.baseMint);
const metadataAccount = await this.connection.getAccountInfo(metadataPDA.publicKey, this.connection.commitment);
try {
const metadataPDA = getPdaMetadataKey(poolKeys.baseMint);
const metadataAccount = await this.connection.getAccountInfo(metadataPDA.publicKey, this.connection.commitment);
if (!metadataAccount?.data) {
return { ok: false, message: 'Mutable -> Failed to fetch account data' };
}
if (!metadataAccount?.data) {
return { ok: false, message: "Mutable -> Failed to fetch account data" };
}
const deserialize = this.metadataSerializer.deserialize(metadataAccount.data);
const mutable = !this.checkMutable || deserialize[0].isMutable;
const hasSocials = !this.checkSocials || (await this.hasSocials(deserialize[0]));
const ok = !mutable && hasSocials;
const message: string[] = [];
const deserialize = this.metadataSerializer.deserialize(metadataAccount.data);
const mutable = !this.checkMutable || deserialize[0].isMutable;
const hasSocials = !this.checkSocials || (await this.hasSocials(deserialize[0]));
const ok = !mutable && hasSocials;
const message: string[] = [];
if (mutable) {
message.push('metadata can be changed');
}
if (mutable) {
message.push("metadata can be changed");
}
if (!hasSocials) {
message.push('has no socials');
}
if (!hasSocials) {
message.push("has no socials");
}
const result = { ok: ok, message: ok ? undefined : `MutableSocials -> Token ${message.join(' and ')}` };
const result = { ok: ok, message: ok ? undefined : `MutableSocials -> Token ${message.join(" and ")}` };
if (!mutable) {
this.cachedResult = result;
}
if (!mutable) {
this.cachedResult = result;
}
return result;
} catch (e) {
logger.error({ mint: poolKeys.baseMint }, `MutableSocials -> Failed to check ${this.errorMessage.join(' and ')}`);
}
return result;
} catch (e) {
logger.error({ mint: poolKeys.baseMint }, `MutableSocials -> Failed to check ${this.errorMessage.join(" and ")}`);
}
return {
ok: false,
message: `MutableSocials -> Failed to check ${this.errorMessage.join(' and ')}`,
};
}
return {
ok: false,
message: `MutableSocials -> Failed to check ${this.errorMessage.join(" and ")}`,
};
}
private async hasSocials(metadata: MetadataAccountData) {
const response = await fetch(metadata.uri);
const data = await response.json();
return Object.values(data?.extensions ?? {}).filter((value: any) => value).length > 0;
}
private async hasSocials(metadata: MetadataAccountData) {
const response = await fetch(metadata.uri);
const data = await response.json();
return Object.values(data?.extensions ?? {}).filter((value: any) => value).length > 0;
}
}

54
filters/pool-filters.js Normal file
View File

@ -0,0 +1,54 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PoolFilters = void 0;
const mpl_token_metadata_1 = require("@metaplex-foundation/mpl-token-metadata");
const burn_filter_1 = require("./burn.filter");
const mutable_filter_1 = require("./mutable.filter");
const renounced_filter_1 = require("./renounced.filter");
const pool_size_filter_1 = require("./pool-size.filter");
const helpers_1 = require("../helpers");
class PoolFilters {
constructor(connection, args) {
this.connection = connection;
this.args = args;
this.filters = [];
if (helpers_1.CHECK_IF_BURNED) {
this.filters.push(new burn_filter_1.BurnFilter(connection));
}
if (helpers_1.CHECK_IF_MINT_IS_RENOUNCED || helpers_1.CHECK_IF_FREEZABLE) {
this.filters.push(new renounced_filter_1.RenouncedFreezeFilter(connection, helpers_1.CHECK_IF_MINT_IS_RENOUNCED, helpers_1.CHECK_IF_FREEZABLE));
}
if (helpers_1.CHECK_IF_MUTABLE || helpers_1.CHECK_IF_SOCIALS) {
this.filters.push(new mutable_filter_1.MutableFilter(connection, (0, mpl_token_metadata_1.getMetadataAccountDataSerializer)(), helpers_1.CHECK_IF_MUTABLE, helpers_1.CHECK_IF_SOCIALS));
}
if (!args.minPoolSize.isZero() || !args.maxPoolSize.isZero()) {
this.filters.push(new pool_size_filter_1.PoolSizeFilter(connection, args.quoteToken, args.minPoolSize, args.maxPoolSize));
}
}
execute(poolKeys) {
return __awaiter(this, void 0, void 0, function* () {
if (this.filters.length === 0) {
return true;
}
const result = yield Promise.all(this.filters.map((f) => f.execute(poolKeys)));
const pass = result.every((r) => r.ok);
if (pass) {
return true;
}
for (const filterResult of result.filter((r) => !r.ok)) {
helpers_1.logger.trace(filterResult.message);
}
return false;
});
}
}
exports.PoolFilters = PoolFilters;

View File

@ -1,67 +1,76 @@
import { Connection } from '@solana/web3.js';
import { LiquidityPoolKeysV4, Token, TokenAmount } from '@raydium-io/raydium-sdk';
import { getMetadataAccountDataSerializer } from '@metaplex-foundation/mpl-token-metadata';
import { BurnFilter } from './burn.filter';
import { MutableFilter } from './mutable.filter';
import { RenouncedFreezeFilter } from './renounced.filter';
import { PoolSizeFilter } from './pool-size.filter';
import { CHECK_IF_BURNED, CHECK_IF_FREEZABLE, CHECK_IF_MINT_IS_RENOUNCED, CHECK_IF_MUTABLE, CHECK_IF_SOCIALS, logger } from '../helpers';
import { Connection } from "@solana/web3.js";
import { LiquidityPoolKeysV4, Token, TokenAmount } from "@raydium-io/raydium-sdk";
import { getMetadataAccountDataSerializer } from "@metaplex-foundation/mpl-token-metadata";
import { BurnFilter } from "./burn.filter";
import { MutableFilter } from "./mutable.filter";
import { RenouncedFreezeFilter } from "./renounced.filter";
import { PoolSizeFilter } from "./pool-size.filter";
import {
CHECK_IF_BURNED,
CHECK_IF_FREEZABLE,
CHECK_IF_MINT_IS_RENOUNCED,
CHECK_IF_MUTABLE,
CHECK_IF_SOCIALS,
logger,
} from "../helpers";
export interface Filter {
execute(poolKeysV4: LiquidityPoolKeysV4): Promise<FilterResult>;
execute(poolKeysV4: LiquidityPoolKeysV4): Promise<FilterResult>;
}
export interface FilterResult {
ok: boolean;
message?: string;
ok: boolean;
message?: string;
}
export interface PoolFilterArgs {
minPoolSize: TokenAmount;
maxPoolSize: TokenAmount;
quoteToken: Token;
minPoolSize: TokenAmount;
maxPoolSize: TokenAmount;
quoteToken: Token;
}
export class PoolFilters {
private readonly filters: Filter[] = [];
private readonly filters: Filter[] = [];
constructor(
readonly connection: Connection,
readonly args: PoolFilterArgs,
) {
if (CHECK_IF_BURNED) {
this.filters.push(new BurnFilter(connection));
}
constructor(
readonly connection: Connection,
readonly args: PoolFilterArgs,
) {
if (CHECK_IF_BURNED) {
this.filters.push(new BurnFilter(connection));
}
if (CHECK_IF_MINT_IS_RENOUNCED || CHECK_IF_FREEZABLE) {
this.filters.push(new RenouncedFreezeFilter(connection, CHECK_IF_MINT_IS_RENOUNCED, CHECK_IF_FREEZABLE));
}
if (CHECK_IF_MINT_IS_RENOUNCED || CHECK_IF_FREEZABLE) {
this.filters.push(new RenouncedFreezeFilter(connection, CHECK_IF_MINT_IS_RENOUNCED, CHECK_IF_FREEZABLE));
}
if (CHECK_IF_MUTABLE || CHECK_IF_SOCIALS) {
this.filters.push(new MutableFilter(connection, getMetadataAccountDataSerializer(), CHECK_IF_MUTABLE, CHECK_IF_SOCIALS));
}
if (CHECK_IF_MUTABLE || CHECK_IF_SOCIALS) {
this.filters.push(
new MutableFilter(connection, getMetadataAccountDataSerializer(), CHECK_IF_MUTABLE, CHECK_IF_SOCIALS),
);
}
if (!args.minPoolSize.isZero() || !args.maxPoolSize.isZero()) {
this.filters.push(new PoolSizeFilter(connection, args.quoteToken, args.minPoolSize, args.maxPoolSize));
}
}
if (!args.minPoolSize.isZero() || !args.maxPoolSize.isZero()) {
this.filters.push(new PoolSizeFilter(connection, args.quoteToken, args.minPoolSize, args.maxPoolSize));
}
}
public async execute(poolKeys: LiquidityPoolKeysV4): Promise<boolean> {
if (this.filters.length === 0) {
return true;
}
public async execute(poolKeys: LiquidityPoolKeysV4): Promise<boolean> {
if (this.filters.length === 0) {
return true;
}
const result = await Promise.all(this.filters.map((f) => f.execute(poolKeys)));
const pass = result.every((r) => r.ok);
const result = await Promise.all(this.filters.map((f) => f.execute(poolKeys)));
const pass = result.every((r) => r.ok);
if (pass) {
return true;
}
if (pass) {
return true;
}
for (const filterResult of result.filter((r) => !r.ok)) {
logger.trace(filterResult.message);
}
for (const filterResult of result.filter((r) => !r.ok)) {
logger.trace(filterResult.message);
}
return false;
}
return false;
}
}

View File

@ -0,0 +1,50 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PoolSizeFilter = void 0;
const raydium_sdk_1 = require("@raydium-io/raydium-sdk");
const helpers_1 = require("../helpers");
class PoolSizeFilter {
constructor(connection, quoteToken, minPoolSize, maxPoolSize) {
this.connection = connection;
this.quoteToken = quoteToken;
this.minPoolSize = minPoolSize;
this.maxPoolSize = maxPoolSize;
}
execute(poolKeys) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
try {
const response = yield this.connection.getTokenAccountBalance(poolKeys.quoteVault, this.connection.commitment);
const poolSize = new raydium_sdk_1.TokenAmount(this.quoteToken, response.value.amount, true);
let inRange = true;
if (!((_a = this.maxPoolSize) === null || _a === void 0 ? void 0 : _a.isZero())) {
inRange = poolSize.raw.lte(this.maxPoolSize.raw);
if (!inRange) {
return { ok: false, message: `PoolSize -> Pool size ${poolSize.toFixed()} > ${this.maxPoolSize.toFixed()}` };
}
}
if (!((_b = this.minPoolSize) === null || _b === void 0 ? void 0 : _b.isZero())) {
inRange = poolSize.raw.gte(this.minPoolSize.raw);
if (!inRange) {
return { ok: false, message: `PoolSize -> Pool size ${poolSize.toFixed()} < ${this.minPoolSize.toFixed()}` };
}
}
return { ok: inRange };
}
catch (error) {
helpers_1.logger.error({ mint: poolKeys.baseMint }, `Failed to check pool size`);
}
return { ok: false, message: "PoolSize -> Failed to check pool size" };
});
}
}
exports.PoolSizeFilter = PoolSizeFilter;

View File

@ -1,43 +1,43 @@
import { Filter, FilterResult } from './pool-filters';
import { LiquidityPoolKeysV4, Token, TokenAmount } from '@raydium-io/raydium-sdk';
import { Connection } from '@solana/web3.js';
import { logger } from '../helpers';
import { Filter, FilterResult } from "./pool-filters";
import { LiquidityPoolKeysV4, Token, TokenAmount } from "@raydium-io/raydium-sdk";
import { Connection } from "@solana/web3.js";
import { logger } from "../helpers";
export class PoolSizeFilter implements Filter {
constructor(
private readonly connection: Connection,
private readonly quoteToken: Token,
private readonly minPoolSize: TokenAmount,
private readonly maxPoolSize: TokenAmount,
) {}
constructor(
private readonly connection: Connection,
private readonly quoteToken: Token,
private readonly minPoolSize: TokenAmount,
private readonly maxPoolSize: TokenAmount,
) {}
async execute(poolKeys: LiquidityPoolKeysV4): Promise<FilterResult> {
try {
const response = await this.connection.getTokenAccountBalance(poolKeys.quoteVault, this.connection.commitment);
const poolSize = new TokenAmount(this.quoteToken, response.value.amount, true);
let inRange = true;
async execute(poolKeys: LiquidityPoolKeysV4): Promise<FilterResult> {
try {
const response = await this.connection.getTokenAccountBalance(poolKeys.quoteVault, this.connection.commitment);
const poolSize = new TokenAmount(this.quoteToken, response.value.amount, true);
let inRange = true;
if (!this.maxPoolSize?.isZero()) {
inRange = poolSize.raw.lte(this.maxPoolSize.raw);
if (!this.maxPoolSize?.isZero()) {
inRange = poolSize.raw.lte(this.maxPoolSize.raw);
if (!inRange) {
return { ok: false, message: `PoolSize -> Pool size ${poolSize.toFixed()} > ${this.maxPoolSize.toFixed()}` };
}
}
if (!inRange) {
return { ok: false, message: `PoolSize -> Pool size ${poolSize.toFixed()} > ${this.maxPoolSize.toFixed()}` };
}
}
if (!this.minPoolSize?.isZero()) {
inRange = poolSize.raw.gte(this.minPoolSize.raw);
if (!this.minPoolSize?.isZero()) {
inRange = poolSize.raw.gte(this.minPoolSize.raw);
if (!inRange) {
return { ok: false, message: `PoolSize -> Pool size ${poolSize.toFixed()} < ${this.minPoolSize.toFixed()}` };
}
}
if (!inRange) {
return { ok: false, message: `PoolSize -> Pool size ${poolSize.toFixed()} < ${this.minPoolSize.toFixed()}` };
}
}
return { ok: inRange };
} catch (error) {
logger.error({ mint: poolKeys.baseMint }, `Failed to check pool size`);
}
return { ok: inRange };
} catch (error) {
logger.error({ mint: poolKeys.baseMint }, `Failed to check pool size`);
}
return { ok: false, message: 'PoolSize -> Failed to check pool size' };
}
return { ok: false, message: "PoolSize -> Failed to check pool size" };
}
}

View File

@ -0,0 +1,69 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RenouncedFreezeFilter = void 0;
const spl_token_1 = require("@solana/spl-token");
const helpers_1 = require("../helpers");
class RenouncedFreezeFilter {
constructor(connection, checkRenounced, checkFreezable) {
this.connection = connection;
this.checkRenounced = checkRenounced;
this.checkFreezable = checkFreezable;
this.errorMessage = [];
this.cachedResult = undefined;
if (this.checkRenounced) {
this.errorMessage.push("mint");
}
if (this.checkFreezable) {
this.errorMessage.push("freeze");
}
}
execute(poolKeys) {
return __awaiter(this, void 0, void 0, function* () {
if (this.cachedResult) {
return this.cachedResult;
}
try {
const accountInfo = yield this.connection.getAccountInfo(poolKeys.baseMint, this.connection.commitment);
if (!(accountInfo === null || accountInfo === void 0 ? void 0 : accountInfo.data)) {
return { ok: false, message: "RenouncedFreeze -> Failed to fetch account data" };
}
const deserialize = spl_token_1.MintLayout.decode(accountInfo.data);
const renounced = !this.checkRenounced || deserialize.mintAuthorityOption === 0;
const freezable = !this.checkFreezable || deserialize.freezeAuthorityOption !== 0;
const ok = renounced && !freezable;
const message = [];
if (!renounced) {
message.push("mint");
}
if (freezable) {
message.push("freeze");
}
const result = {
ok: ok,
message: ok ? undefined : `RenouncedFreeze -> Creator can ${message.join(" and ")} tokens`,
};
if (result.ok) {
this.cachedResult = result;
}
return result;
}
catch (e) {
helpers_1.logger.error({ mint: poolKeys.baseMint }, `RenouncedFreeze -> Failed to check if creator can ${this.errorMessage.join(" and ")} tokens`);
}
return {
ok: false,
message: `RenouncedFreeze -> Failed to check if creator can ${this.errorMessage.join(" and ")} tokens`,
};
});
}
}
exports.RenouncedFreezeFilter = RenouncedFreezeFilter;

View File

@ -1,72 +1,72 @@
import { Filter, FilterResult } from './pool-filters';
import { MintLayout } from '@solana/spl-token';
import { Connection } from '@solana/web3.js';
import { LiquidityPoolKeysV4 } from '@raydium-io/raydium-sdk';
import { logger } from '../helpers';
import { Filter, FilterResult } from "./pool-filters";
import { MintLayout } from "@solana/spl-token";
import { Connection } from "@solana/web3.js";
import { LiquidityPoolKeysV4 } from "@raydium-io/raydium-sdk";
import { logger } from "../helpers";
export class RenouncedFreezeFilter implements Filter {
private readonly errorMessage: string[] = [];
private cachedResult: FilterResult | undefined = undefined;
private readonly errorMessage: string[] = [];
private cachedResult: FilterResult | undefined = undefined;
constructor(
private readonly connection: Connection,
private readonly checkRenounced: boolean,
private readonly checkFreezable: boolean,
) {
if (this.checkRenounced) {
this.errorMessage.push('mint');
}
constructor(
private readonly connection: Connection,
private readonly checkRenounced: boolean,
private readonly checkFreezable: boolean,
) {
if (this.checkRenounced) {
this.errorMessage.push("mint");
}
if (this.checkFreezable) {
this.errorMessage.push('freeze');
}
}
if (this.checkFreezable) {
this.errorMessage.push("freeze");
}
}
async execute(poolKeys: LiquidityPoolKeysV4): Promise<FilterResult> {
if (this.cachedResult) {
return this.cachedResult;
}
async execute(poolKeys: LiquidityPoolKeysV4): Promise<FilterResult> {
if (this.cachedResult) {
return this.cachedResult;
}
try {
const accountInfo = await this.connection.getAccountInfo(poolKeys.baseMint, this.connection.commitment);
if (!accountInfo?.data) {
return { ok: false, message: 'RenouncedFreeze -> Failed to fetch account data' };
}
try {
const accountInfo = await this.connection.getAccountInfo(poolKeys.baseMint, this.connection.commitment);
if (!accountInfo?.data) {
return { ok: false, message: "RenouncedFreeze -> Failed to fetch account data" };
}
const deserialize = MintLayout.decode(accountInfo.data);
const renounced = !this.checkRenounced || deserialize.mintAuthorityOption === 0;
const freezable = !this.checkFreezable || deserialize.freezeAuthorityOption !== 0;
const ok = renounced && !freezable;
const message: string[] = [];
const deserialize = MintLayout.decode(accountInfo.data);
const renounced = !this.checkRenounced || deserialize.mintAuthorityOption === 0;
const freezable = !this.checkFreezable || deserialize.freezeAuthorityOption !== 0;
const ok = renounced && !freezable;
const message: string[] = [];
if (!renounced) {
message.push('mint');
}
if (!renounced) {
message.push("mint");
}
if (freezable) {
message.push('freeze');
}
if (freezable) {
message.push("freeze");
}
const result = {
ok: ok,
message: ok ? undefined : `RenouncedFreeze -> Creator can ${message.join(' and ')} tokens`,
};
const result = {
ok: ok,
message: ok ? undefined : `RenouncedFreeze -> Creator can ${message.join(" and ")} tokens`,
};
if (result.ok) {
this.cachedResult = result;
}
if (result.ok) {
this.cachedResult = result;
}
return result;
} catch (e) {
logger.error(
{ mint: poolKeys.baseMint },
`RenouncedFreeze -> Failed to check if creator can ${this.errorMessage.join(' and ')} tokens`,
);
}
return result;
} catch (e) {
logger.error(
{ mint: poolKeys.baseMint },
`RenouncedFreeze -> Failed to check if creator can ${this.errorMessage.join(" and ")} tokens`,
);
}
return {
ok: false,
message: `RenouncedFreeze -> Failed to check if creator can ${this.errorMessage.join(' and ')} tokens`,
};
}
return {
ok: false,
message: `RenouncedFreeze -> Failed to check if creator can ${this.errorMessage.join(" and ")} tokens`,
};
}
}

63
helpers/constants.js Normal file
View File

@ -0,0 +1,63 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SNIPE_LIST_REFRESH_INTERVAL = exports.USE_SNIPE_LIST = exports.MAX_POOL_SIZE = exports.MIN_POOL_SIZE = exports.CHECK_IF_BURNED = exports.CHECK_IF_FREEZABLE = exports.CHECK_IF_MINT_IS_RENOUNCED = exports.CHECK_IF_SOCIALS = exports.CHECK_IF_MUTABLE = exports.CONSECUTIVE_FILTER_MATCHES = exports.FILTER_CHECK_DURATION = exports.FILTER_CHECK_INTERVAL = exports.SKIP_SELLING_IF_LOST_MORE_THAN = exports.SELL_SLIPPAGE = exports.PRICE_CHECK_DURATION = exports.PRICE_CHECK_INTERVAL = exports.TRAILING_STOP_LOSS = exports.STOP_LOSS = exports.TAKE_PROFIT = exports.MAX_SELL_RETRIES = exports.AUTO_SELL_DELAY = exports.AUTO_SELL = exports.BUY_SLIPPAGE = exports.MAX_BUY_RETRIES = exports.QUOTE_AMOUNT = exports.QUOTE_MINT = exports.AUTO_BUY_DELAY = exports.CUSTOM_FEE = exports.TRANSACTION_EXECUTOR = exports.CACHE_NEW_MARKETS = exports.PRE_LOAD_EXISTING_MARKETS = exports.COMPUTE_UNIT_PRICE = exports.COMPUTE_UNIT_LIMIT = exports.MAX_TOKENS_AT_THE_TIME = exports.LOG_LEVEL = exports.RPC_WEBSOCKET_ENDPOINT = exports.RPC_ENDPOINT = exports.COMMITMENT_LEVEL = exports.NETWORK = exports.PRIVATE_KEY = void 0;
const dotenv_1 = __importDefault(require("dotenv"));
const logger_1 = require("./logger");
dotenv_1.default.config();
const retrieveEnvVariable = (variableName, logger) => {
const variable = process.env[variableName] || "";
if (!variable) {
logger.error(`${variableName} is not set`);
process.exit(1);
}
return variable;
};
// Wallet
exports.PRIVATE_KEY = retrieveEnvVariable("PRIVATE_KEY", logger_1.logger);
// Connection
exports.NETWORK = "mainnet-beta";
exports.COMMITMENT_LEVEL = retrieveEnvVariable("COMMITMENT_LEVEL", logger_1.logger);
exports.RPC_ENDPOINT = retrieveEnvVariable("RPC_ENDPOINT", logger_1.logger);
exports.RPC_WEBSOCKET_ENDPOINT = retrieveEnvVariable("RPC_WEBSOCKET_ENDPOINT", logger_1.logger);
// Bot
exports.LOG_LEVEL = retrieveEnvVariable("LOG_LEVEL", logger_1.logger);
exports.MAX_TOKENS_AT_THE_TIME = Number(retrieveEnvVariable("MAX_TOKENS_AT_THE_TIME", logger_1.logger));
exports.COMPUTE_UNIT_LIMIT = Number(retrieveEnvVariable("COMPUTE_UNIT_LIMIT", logger_1.logger));
exports.COMPUTE_UNIT_PRICE = Number(retrieveEnvVariable("COMPUTE_UNIT_PRICE", logger_1.logger));
exports.PRE_LOAD_EXISTING_MARKETS = retrieveEnvVariable("PRE_LOAD_EXISTING_MARKETS", logger_1.logger) === "true";
exports.CACHE_NEW_MARKETS = retrieveEnvVariable("CACHE_NEW_MARKETS", logger_1.logger) === "true";
exports.TRANSACTION_EXECUTOR = retrieveEnvVariable("TRANSACTION_EXECUTOR", logger_1.logger);
exports.CUSTOM_FEE = retrieveEnvVariable("CUSTOM_FEE", logger_1.logger);
// Buy
exports.AUTO_BUY_DELAY = Number(retrieveEnvVariable("AUTO_BUY_DELAY", logger_1.logger));
exports.QUOTE_MINT = retrieveEnvVariable("QUOTE_MINT", logger_1.logger);
exports.QUOTE_AMOUNT = retrieveEnvVariable("QUOTE_AMOUNT", logger_1.logger);
exports.MAX_BUY_RETRIES = Number(retrieveEnvVariable("MAX_BUY_RETRIES", logger_1.logger));
exports.BUY_SLIPPAGE = Number(retrieveEnvVariable("BUY_SLIPPAGE", logger_1.logger));
// Sell
exports.AUTO_SELL = retrieveEnvVariable("AUTO_SELL", logger_1.logger) === "true";
exports.AUTO_SELL_DELAY = Number(retrieveEnvVariable("AUTO_SELL_DELAY", logger_1.logger));
exports.MAX_SELL_RETRIES = Number(retrieveEnvVariable("MAX_SELL_RETRIES", logger_1.logger));
exports.TAKE_PROFIT = Number(retrieveEnvVariable("TAKE_PROFIT", logger_1.logger));
exports.STOP_LOSS = Number(retrieveEnvVariable("STOP_LOSS", logger_1.logger));
exports.TRAILING_STOP_LOSS = retrieveEnvVariable("TRAILING_STOP_LOSS", logger_1.logger) === "true";
exports.PRICE_CHECK_INTERVAL = Number(retrieveEnvVariable("PRICE_CHECK_INTERVAL", logger_1.logger));
exports.PRICE_CHECK_DURATION = Number(retrieveEnvVariable("PRICE_CHECK_DURATION", logger_1.logger));
exports.SELL_SLIPPAGE = Number(retrieveEnvVariable("SELL_SLIPPAGE", logger_1.logger));
exports.SKIP_SELLING_IF_LOST_MORE_THAN = Number(retrieveEnvVariable("SKIP_SELLING_IF_LOST_MORE_THAN", logger_1.logger));
// Filters
exports.FILTER_CHECK_INTERVAL = Number(retrieveEnvVariable("FILTER_CHECK_INTERVAL", logger_1.logger));
exports.FILTER_CHECK_DURATION = Number(retrieveEnvVariable("FILTER_CHECK_DURATION", logger_1.logger));
exports.CONSECUTIVE_FILTER_MATCHES = Number(retrieveEnvVariable("CONSECUTIVE_FILTER_MATCHES", logger_1.logger));
exports.CHECK_IF_MUTABLE = retrieveEnvVariable("CHECK_IF_MUTABLE", logger_1.logger) === "true";
exports.CHECK_IF_SOCIALS = retrieveEnvVariable("CHECK_IF_SOCIALS", logger_1.logger) === "true";
exports.CHECK_IF_MINT_IS_RENOUNCED = retrieveEnvVariable("CHECK_IF_MINT_IS_RENOUNCED", logger_1.logger) === "true";
exports.CHECK_IF_FREEZABLE = retrieveEnvVariable("CHECK_IF_FREEZABLE", logger_1.logger) === "true";
exports.CHECK_IF_BURNED = retrieveEnvVariable("CHECK_IF_BURNED", logger_1.logger) === "true";
exports.MIN_POOL_SIZE = retrieveEnvVariable("MIN_POOL_SIZE", logger_1.logger);
exports.MAX_POOL_SIZE = retrieveEnvVariable("MAX_POOL_SIZE", logger_1.logger);
exports.USE_SNIPE_LIST = retrieveEnvVariable("USE_SNIPE_LIST", logger_1.logger) === "true";
exports.SNIPE_LIST_REFRESH_INTERVAL = Number(retrieveEnvVariable("SNIPE_LIST_REFRESH_INTERVAL", logger_1.logger));

View File

@ -1,67 +1,67 @@
import { Logger } from 'pino';
import dotenv from 'dotenv';
import { Commitment } from '@solana/web3.js';
import { logger } from './logger';
import { Logger } from "pino";
import dotenv from "dotenv";
import { Commitment } from "@solana/web3.js";
import { logger } from "./logger";
dotenv.config();
const retrieveEnvVariable = (variableName: string, logger: Logger) => {
const variable = process.env[variableName] || '';
if (!variable) {
logger.error(`${variableName} is not set`);
process.exit(1);
}
return variable;
const variable = process.env[variableName] || "";
if (!variable) {
logger.error(`${variableName} is not set`);
process.exit(1);
}
return variable;
};
// Wallet
export const PRIVATE_KEY = retrieveEnvVariable('PRIVATE_KEY', logger);
export const PRIVATE_KEY = retrieveEnvVariable("PRIVATE_KEY", logger);
// Connection
export const NETWORK = 'mainnet-beta';
export const COMMITMENT_LEVEL: Commitment = retrieveEnvVariable('COMMITMENT_LEVEL', logger) as Commitment;
export const RPC_ENDPOINT = retrieveEnvVariable('RPC_ENDPOINT', logger);
export const RPC_WEBSOCKET_ENDPOINT = retrieveEnvVariable('RPC_WEBSOCKET_ENDPOINT', logger);
export const NETWORK = "mainnet-beta";
export const COMMITMENT_LEVEL: Commitment = retrieveEnvVariable("COMMITMENT_LEVEL", logger) as Commitment;
export const RPC_ENDPOINT = retrieveEnvVariable("RPC_ENDPOINT", logger);
export const RPC_WEBSOCKET_ENDPOINT = retrieveEnvVariable("RPC_WEBSOCKET_ENDPOINT", logger);
// Bot
export const LOG_LEVEL = retrieveEnvVariable('LOG_LEVEL', logger);
export const MAX_TOKENS_AT_THE_TIME = Number(retrieveEnvVariable('MAX_TOKENS_AT_THE_TIME', logger));
export const COMPUTE_UNIT_LIMIT = Number(retrieveEnvVariable('COMPUTE_UNIT_LIMIT', logger));
export const COMPUTE_UNIT_PRICE = Number(retrieveEnvVariable('COMPUTE_UNIT_PRICE', logger));
export const PRE_LOAD_EXISTING_MARKETS = retrieveEnvVariable('PRE_LOAD_EXISTING_MARKETS', logger) === 'true';
export const CACHE_NEW_MARKETS = retrieveEnvVariable('CACHE_NEW_MARKETS', logger) === 'true';
export const TRANSACTION_EXECUTOR = retrieveEnvVariable('TRANSACTION_EXECUTOR', logger);
export const CUSTOM_FEE = retrieveEnvVariable('CUSTOM_FEE', logger);
export const LOG_LEVEL = retrieveEnvVariable("LOG_LEVEL", logger);
export const MAX_TOKENS_AT_THE_TIME = Number(retrieveEnvVariable("MAX_TOKENS_AT_THE_TIME", logger));
export const COMPUTE_UNIT_LIMIT = Number(retrieveEnvVariable("COMPUTE_UNIT_LIMIT", logger));
export const COMPUTE_UNIT_PRICE = Number(retrieveEnvVariable("COMPUTE_UNIT_PRICE", logger));
export const PRE_LOAD_EXISTING_MARKETS = retrieveEnvVariable("PRE_LOAD_EXISTING_MARKETS", logger) === "true";
export const CACHE_NEW_MARKETS = retrieveEnvVariable("CACHE_NEW_MARKETS", logger) === "true";
export const TRANSACTION_EXECUTOR = retrieveEnvVariable("TRANSACTION_EXECUTOR", logger);
export const CUSTOM_FEE = retrieveEnvVariable("CUSTOM_FEE", logger);
// Buy
export const AUTO_BUY_DELAY = Number(retrieveEnvVariable('AUTO_BUY_DELAY', logger));
export const QUOTE_MINT = retrieveEnvVariable('QUOTE_MINT', logger);
export const QUOTE_AMOUNT = retrieveEnvVariable('QUOTE_AMOUNT', logger);
export const MAX_BUY_RETRIES = Number(retrieveEnvVariable('MAX_BUY_RETRIES', logger));
export const BUY_SLIPPAGE = Number(retrieveEnvVariable('BUY_SLIPPAGE', logger));
export const AUTO_BUY_DELAY = Number(retrieveEnvVariable("AUTO_BUY_DELAY", logger));
export const QUOTE_MINT = retrieveEnvVariable("QUOTE_MINT", logger);
export const QUOTE_AMOUNT = retrieveEnvVariable("QUOTE_AMOUNT", logger);
export const MAX_BUY_RETRIES = Number(retrieveEnvVariable("MAX_BUY_RETRIES", logger));
export const BUY_SLIPPAGE = Number(retrieveEnvVariable("BUY_SLIPPAGE", logger));
// Sell
export const AUTO_SELL = retrieveEnvVariable('AUTO_SELL', logger) === 'true';
export const AUTO_SELL_DELAY = Number(retrieveEnvVariable('AUTO_SELL_DELAY', logger));
export const MAX_SELL_RETRIES = Number(retrieveEnvVariable('MAX_SELL_RETRIES', logger));
export const TAKE_PROFIT = Number(retrieveEnvVariable('TAKE_PROFIT', logger));
export const STOP_LOSS = Number(retrieveEnvVariable('STOP_LOSS', logger));
export const TRAILING_STOP_LOSS = retrieveEnvVariable('TRAILING_STOP_LOSS', logger) === 'true';
export const PRICE_CHECK_INTERVAL = Number(retrieveEnvVariable('PRICE_CHECK_INTERVAL', logger));
export const PRICE_CHECK_DURATION = Number(retrieveEnvVariable('PRICE_CHECK_DURATION', logger));
export const SELL_SLIPPAGE = Number(retrieveEnvVariable('SELL_SLIPPAGE', logger));
export const SKIP_SELLING_IF_LOST_MORE_THAN = Number(retrieveEnvVariable('SKIP_SELLING_IF_LOST_MORE_THAN', logger));
export const AUTO_SELL = retrieveEnvVariable("AUTO_SELL", logger) === "true";
export const AUTO_SELL_DELAY = Number(retrieveEnvVariable("AUTO_SELL_DELAY", logger));
export const MAX_SELL_RETRIES = Number(retrieveEnvVariable("MAX_SELL_RETRIES", logger));
export const TAKE_PROFIT = Number(retrieveEnvVariable("TAKE_PROFIT", logger));
export const STOP_LOSS = Number(retrieveEnvVariable("STOP_LOSS", logger));
export const TRAILING_STOP_LOSS = retrieveEnvVariable("TRAILING_STOP_LOSS", logger) === "true";
export const PRICE_CHECK_INTERVAL = Number(retrieveEnvVariable("PRICE_CHECK_INTERVAL", logger));
export const PRICE_CHECK_DURATION = Number(retrieveEnvVariable("PRICE_CHECK_DURATION", logger));
export const SELL_SLIPPAGE = Number(retrieveEnvVariable("SELL_SLIPPAGE", logger));
export const SKIP_SELLING_IF_LOST_MORE_THAN = Number(retrieveEnvVariable("SKIP_SELLING_IF_LOST_MORE_THAN", logger));
// Filters
export const FILTER_CHECK_INTERVAL = Number(retrieveEnvVariable('FILTER_CHECK_INTERVAL', logger));
export const FILTER_CHECK_DURATION = Number(retrieveEnvVariable('FILTER_CHECK_DURATION', logger));
export const CONSECUTIVE_FILTER_MATCHES = Number(retrieveEnvVariable('CONSECUTIVE_FILTER_MATCHES', logger));
export const CHECK_IF_MUTABLE = retrieveEnvVariable('CHECK_IF_MUTABLE', logger) === 'true';
export const CHECK_IF_SOCIALS = retrieveEnvVariable('CHECK_IF_SOCIALS', logger) === 'true';
export const CHECK_IF_MINT_IS_RENOUNCED = retrieveEnvVariable('CHECK_IF_MINT_IS_RENOUNCED', logger) === 'true';
export const CHECK_IF_FREEZABLE = retrieveEnvVariable('CHECK_IF_FREEZABLE', logger) === 'true';
export const CHECK_IF_BURNED = retrieveEnvVariable('CHECK_IF_BURNED', logger) === 'true';
export const MIN_POOL_SIZE = retrieveEnvVariable('MIN_POOL_SIZE', logger);
export const MAX_POOL_SIZE = retrieveEnvVariable('MAX_POOL_SIZE', logger);
export const USE_SNIPE_LIST = retrieveEnvVariable('USE_SNIPE_LIST', logger) === 'true';
export const SNIPE_LIST_REFRESH_INTERVAL = Number(retrieveEnvVariable('SNIPE_LIST_REFRESH_INTERVAL', logger));
export const FILTER_CHECK_INTERVAL = Number(retrieveEnvVariable("FILTER_CHECK_INTERVAL", logger));
export const FILTER_CHECK_DURATION = Number(retrieveEnvVariable("FILTER_CHECK_DURATION", logger));
export const CONSECUTIVE_FILTER_MATCHES = Number(retrieveEnvVariable("CONSECUTIVE_FILTER_MATCHES", logger));
export const CHECK_IF_MUTABLE = retrieveEnvVariable("CHECK_IF_MUTABLE", logger) === "true";
export const CHECK_IF_SOCIALS = retrieveEnvVariable("CHECK_IF_SOCIALS", logger) === "true";
export const CHECK_IF_MINT_IS_RENOUNCED = retrieveEnvVariable("CHECK_IF_MINT_IS_RENOUNCED", logger) === "true";
export const CHECK_IF_FREEZABLE = retrieveEnvVariable("CHECK_IF_FREEZABLE", logger) === "true";
export const CHECK_IF_BURNED = retrieveEnvVariable("CHECK_IF_BURNED", logger) === "true";
export const MIN_POOL_SIZE = retrieveEnvVariable("MIN_POOL_SIZE", logger);
export const MAX_POOL_SIZE = retrieveEnvVariable("MAX_POOL_SIZE", logger);
export const USE_SNIPE_LIST = retrieveEnvVariable("USE_SNIPE_LIST", logger) === "true";
export const SNIPE_LIST_REFRESH_INTERVAL = Number(retrieveEnvVariable("SNIPE_LIST_REFRESH_INTERVAL", logger));

8
helpers/helper.cache.js Normal file

File diff suppressed because one or more lines are too long

23
helpers/index.js Normal file
View File

@ -0,0 +1,23 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./market"), exports);
__exportStar(require("./liquidity"), exports);
__exportStar(require("./logger"), exports);
__exportStar(require("./constants"), exports);
__exportStar(require("./token"), exports);
__exportStar(require("./wallet"), exports);
__exportStar(require("./promises"), exports);

View File

@ -1,7 +1,7 @@
export * from './market';
export * from './liquidity';
export * from './logger';
export * from './constants';
export * from './token';
export * from './wallet';
export * from './promises'
export * from "./market";
export * from "./liquidity";
export * from "./logger";
export * from "./constants";
export * from "./token";
export * from "./wallet";
export * from "./promises";

41
helpers/liquidity.js Normal file
View File

@ -0,0 +1,41 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createPoolKeys = void 0;
const web3_js_1 = require("@solana/web3.js");
const raydium_sdk_1 = require("@raydium-io/raydium-sdk");
function createPoolKeys(id, accountData, minimalMarketLayoutV3) {
return {
id,
baseMint: accountData.baseMint,
quoteMint: accountData.quoteMint,
lpMint: accountData.lpMint,
baseDecimals: accountData.baseDecimal.toNumber(),
quoteDecimals: accountData.quoteDecimal.toNumber(),
lpDecimals: 5,
version: 4,
programId: raydium_sdk_1.MAINNET_PROGRAM_ID.AmmV4,
authority: raydium_sdk_1.Liquidity.getAssociatedAuthority({
programId: raydium_sdk_1.MAINNET_PROGRAM_ID.AmmV4,
}).publicKey,
openOrders: accountData.openOrders,
targetOrders: accountData.targetOrders,
baseVault: accountData.baseVault,
quoteVault: accountData.quoteVault,
marketVersion: 3,
marketProgramId: accountData.marketProgramId,
marketId: accountData.marketId,
marketAuthority: raydium_sdk_1.Market.getAssociatedAuthority({
programId: accountData.marketProgramId,
marketId: accountData.marketId,
}).publicKey,
marketBaseVault: accountData.baseVault,
marketQuoteVault: accountData.quoteVault,
marketBids: minimalMarketLayoutV3.bids,
marketAsks: minimalMarketLayoutV3.asks,
marketEventQueue: minimalMarketLayoutV3.eventQueue,
withdrawQueue: accountData.withdrawQueue,
lpVault: accountData.lpVault,
lookupTableAccount: web3_js_1.PublicKey.default,
};
}
exports.createPoolKeys = createPoolKeys;

View File

@ -1,43 +1,43 @@
import { PublicKey } from '@solana/web3.js';
import { Liquidity, LiquidityPoolKeys, LiquidityStateV4, MAINNET_PROGRAM_ID, Market } from '@raydium-io/raydium-sdk';
import { MinimalMarketLayoutV3 } from './market';
import { PublicKey } from "@solana/web3.js";
import { Liquidity, LiquidityPoolKeys, LiquidityStateV4, MAINNET_PROGRAM_ID, Market } from "@raydium-io/raydium-sdk";
import { MinimalMarketLayoutV3 } from "./market";
export function createPoolKeys(
id: PublicKey,
accountData: LiquidityStateV4,
minimalMarketLayoutV3: MinimalMarketLayoutV3,
id: PublicKey,
accountData: LiquidityStateV4,
minimalMarketLayoutV3: MinimalMarketLayoutV3,
): LiquidityPoolKeys {
return {
id,
baseMint: accountData.baseMint,
quoteMint: accountData.quoteMint,
lpMint: accountData.lpMint,
baseDecimals: accountData.baseDecimal.toNumber(),
quoteDecimals: accountData.quoteDecimal.toNumber(),
lpDecimals: 5,
version: 4,
programId: MAINNET_PROGRAM_ID.AmmV4,
authority: Liquidity.getAssociatedAuthority({
programId: MAINNET_PROGRAM_ID.AmmV4,
}).publicKey,
openOrders: accountData.openOrders,
targetOrders: accountData.targetOrders,
baseVault: accountData.baseVault,
quoteVault: accountData.quoteVault,
marketVersion: 3,
marketProgramId: accountData.marketProgramId,
marketId: accountData.marketId,
marketAuthority: Market.getAssociatedAuthority({
programId: accountData.marketProgramId,
marketId: accountData.marketId,
}).publicKey,
marketBaseVault: accountData.baseVault,
marketQuoteVault: accountData.quoteVault,
marketBids: minimalMarketLayoutV3.bids,
marketAsks: minimalMarketLayoutV3.asks,
marketEventQueue: minimalMarketLayoutV3.eventQueue,
withdrawQueue: accountData.withdrawQueue,
lpVault: accountData.lpVault,
lookupTableAccount: PublicKey.default,
};
return {
id,
baseMint: accountData.baseMint,
quoteMint: accountData.quoteMint,
lpMint: accountData.lpMint,
baseDecimals: accountData.baseDecimal.toNumber(),
quoteDecimals: accountData.quoteDecimal.toNumber(),
lpDecimals: 5,
version: 4,
programId: MAINNET_PROGRAM_ID.AmmV4,
authority: Liquidity.getAssociatedAuthority({
programId: MAINNET_PROGRAM_ID.AmmV4,
}).publicKey,
openOrders: accountData.openOrders,
targetOrders: accountData.targetOrders,
baseVault: accountData.baseVault,
quoteVault: accountData.quoteVault,
marketVersion: 3,
marketProgramId: accountData.marketProgramId,
marketId: accountData.marketId,
marketAuthority: Market.getAssociatedAuthority({
programId: accountData.marketProgramId,
marketId: accountData.marketId,
}).publicKey,
marketBaseVault: accountData.baseVault,
marketQuoteVault: accountData.quoteVault,
marketBids: minimalMarketLayoutV3.bids,
marketAsks: minimalMarketLayoutV3.asks,
marketEventQueue: minimalMarketLayoutV3.eventQueue,
withdrawQueue: accountData.withdrawQueue,
lpVault: accountData.lpVault,
lookupTableAccount: PublicKey.default,
};
}

18
helpers/logger.js Normal file
View File

@ -0,0 +1,18 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.logger = void 0;
const pino_1 = __importDefault(require("pino"));
const transport = pino_1.default.transport({
target: "pino-pretty",
});
exports.logger = (0, pino_1.default)({
level: "info",
redact: ["poolKeys"],
serializers: {
error: pino_1.default.stdSerializers.err,
},
base: undefined,
}, transport);

View File

@ -1,17 +1,17 @@
import pino from 'pino';
import pino from "pino";
const transport = pino.transport({
target: 'pino-pretty',
target: "pino-pretty",
});
export const logger = pino(
{
level: 'info',
redact: ['poolKeys'],
serializers: {
error: pino.stdSerializers.err,
},
base: undefined,
},
transport,
{
level: "info",
redact: ["poolKeys"],
serializers: {
error: pino.stdSerializers.err,
},
base: undefined,
},
transport,
);

27
helpers/market.js Normal file
View File

@ -0,0 +1,27 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getMinimalMarketV3 = exports.MINIMAL_MARKET_STATE_LAYOUT_V3 = void 0;
const raydium_sdk_1 = require("@raydium-io/raydium-sdk");
exports.MINIMAL_MARKET_STATE_LAYOUT_V3 = (0, raydium_sdk_1.struct)([(0, raydium_sdk_1.publicKey)("eventQueue"), (0, raydium_sdk_1.publicKey)("bids"), (0, raydium_sdk_1.publicKey)("asks")]);
function getMinimalMarketV3(connection, marketId, commitment) {
return __awaiter(this, void 0, void 0, function* () {
const marketInfo = yield connection.getAccountInfo(marketId, {
commitment,
dataSlice: {
offset: raydium_sdk_1.MARKET_STATE_LAYOUT_V3.offsetOf("eventQueue"),
length: 32 * 3,
},
});
return exports.MINIMAL_MARKET_STATE_LAYOUT_V3.decode(marketInfo.data);
});
}
exports.getMinimalMarketV3 = getMinimalMarketV3;

View File

@ -1,22 +1,22 @@
import { Commitment, Connection, PublicKey } from '@solana/web3.js';
import { GetStructureSchema, MARKET_STATE_LAYOUT_V3, publicKey, struct } from '@raydium-io/raydium-sdk';
import { Commitment, Connection, PublicKey } from "@solana/web3.js";
import { GetStructureSchema, MARKET_STATE_LAYOUT_V3, publicKey, struct } from "@raydium-io/raydium-sdk";
export const MINIMAL_MARKET_STATE_LAYOUT_V3 = struct([publicKey('eventQueue'), publicKey('bids'), publicKey('asks')]);
export const MINIMAL_MARKET_STATE_LAYOUT_V3 = struct([publicKey("eventQueue"), publicKey("bids"), publicKey("asks")]);
export type MinimalMarketStateLayoutV3 = typeof MINIMAL_MARKET_STATE_LAYOUT_V3;
export type MinimalMarketLayoutV3 = GetStructureSchema<MinimalMarketStateLayoutV3>;
export async function getMinimalMarketV3(
connection: Connection,
marketId: PublicKey,
commitment?: Commitment,
connection: Connection,
marketId: PublicKey,
commitment?: Commitment,
): Promise<MinimalMarketLayoutV3> {
const marketInfo = await connection.getAccountInfo(marketId, {
commitment,
dataSlice: {
offset: MARKET_STATE_LAYOUT_V3.offsetOf('eventQueue'),
length: 32 * 3,
},
});
const marketInfo = await connection.getAccountInfo(marketId, {
commitment,
dataSlice: {
offset: MARKET_STATE_LAYOUT_V3.offsetOf("eventQueue"),
length: 32 * 3,
},
});
return MINIMAL_MARKET_STATE_LAYOUT_V3.decode(marketInfo!.data);
return MINIMAL_MARKET_STATE_LAYOUT_V3.decode(marketInfo!.data);
}

5
helpers/promises.js Normal file
View File

@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sleep = void 0;
const sleep = (ms = 0) => new Promise((resolve) => setTimeout(resolve, ms));
exports.sleep = sleep;

20
helpers/token.js Normal file
View File

@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getToken = void 0;
const raydium_sdk_1 = require("@raydium-io/raydium-sdk");
const spl_token_1 = require("@solana/spl-token");
const web3_js_1 = require("@solana/web3.js");
function getToken(token) {
switch (token) {
case "WSOL": {
return raydium_sdk_1.Token.WSOL;
}
case "USDC": {
return new raydium_sdk_1.Token(spl_token_1.TOKEN_PROGRAM_ID, new web3_js_1.PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"), 6, "USDC", "USDC");
}
default: {
throw new Error(`Unsupported quote mint "${token}". Supported values are USDC and WSOL`);
}
}
}
exports.getToken = getToken;

View File

@ -1,23 +1,23 @@
import { Token } from '@raydium-io/raydium-sdk';
import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
import { PublicKey } from '@solana/web3.js';
import { Token } from "@raydium-io/raydium-sdk";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import { PublicKey } from "@solana/web3.js";
export function getToken(token: string) {
switch (token) {
case 'WSOL': {
return Token.WSOL;
}
case 'USDC': {
return new Token(
TOKEN_PROGRAM_ID,
new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'),
6,
'USDC',
'USDC',
);
}
default: {
throw new Error(`Unsupported quote mint "${token}". Supported values are USDC and WSOL`);
}
}
switch (token) {
case "WSOL": {
return Token.WSOL;
}
case "USDC": {
return new Token(
TOKEN_PROGRAM_ID,
new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"),
6,
"USDC",
"USDC",
);
}
default: {
throw new Error(`Unsupported quote mint "${token}". Supported values are USDC and WSOL`);
}
}
}

25
helpers/wallet.js Normal file
View File

@ -0,0 +1,25 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getWallet = void 0;
const web3_js_1 = require("@solana/web3.js");
const bs58_1 = __importDefault(require("bs58"));
const bip39_1 = require("bip39");
const ed25519_hd_key_1 = require("ed25519-hd-key");
function getWallet(wallet) {
// most likely someone pasted the private key in binary format
if (wallet.startsWith("[")) {
return web3_js_1.Keypair.fromSecretKey(JSON.parse(wallet));
}
// most likely someone pasted mnemonic
if (wallet.split(" ").length > 1) {
const seed = (0, bip39_1.mnemonicToSeedSync)(wallet, "");
const path = `m/44'/501'/0'/0'`; // we assume it's first path
return web3_js_1.Keypair.fromSeed((0, ed25519_hd_key_1.derivePath)(path, seed.toString("hex")).key);
}
// most likely someone pasted base58 encoded private key
return web3_js_1.Keypair.fromSecretKey(bs58_1.default.decode(wallet));
}
exports.getWallet = getWallet;

View File

@ -1,21 +1,21 @@
import { Keypair } from '@solana/web3.js';
import bs58 from 'bs58';
import { mnemonicToSeedSync } from 'bip39';
import { derivePath } from 'ed25519-hd-key';
import { Keypair } from "@solana/web3.js";
import bs58 from "bs58";
import { mnemonicToSeedSync } from "bip39";
import { derivePath } from "ed25519-hd-key";
export function getWallet(wallet: string): Keypair {
// most likely someone pasted the private key in binary format
if (wallet.startsWith('[')) {
return Keypair.fromSecretKey(JSON.parse(wallet));
}
// most likely someone pasted the private key in binary format
if (wallet.startsWith("[")) {
return Keypair.fromSecretKey(JSON.parse(wallet));
}
// most likely someone pasted mnemonic
if (wallet.split(' ').length > 1) {
const seed = mnemonicToSeedSync(wallet, '');
const path = `m/44'/501'/0'/0'`; // we assume it's first path
return Keypair.fromSeed(derivePath(path, seed.toString('hex')).key);
}
// most likely someone pasted mnemonic
if (wallet.split(" ").length > 1) {
const seed = mnemonicToSeedSync(wallet, "");
const path = `m/44'/501'/0'/0'`; // we assume it's first path
return Keypair.fromSeed(derivePath(path, seed.toString("hex")).key);
}
// most likely someone pasted base58 encoded private key
return Keypair.fromSecretKey(bs58.decode(wallet));
// most likely someone pasted base58 encoded private key
return Keypair.fromSecretKey(bs58.decode(wallet));
}

189
index.js Normal file
View File

@ -0,0 +1,189 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const cache_1 = require("./cache");
const listeners_1 = require("./listeners");
const web3_js_1 = require("@solana/web3.js");
const raydium_sdk_1 = require("@raydium-io/raydium-sdk");
const spl_token_1 = require("@solana/spl-token");
const bot_1 = require("./bot");
const transactions_1 = require("./transactions");
const helpers_1 = require("./helpers");
const package_json_1 = require("./package.json");
const warp_transaction_executor_1 = require("./transactions/warp-transaction-executor");
const jito_rpc_transaction_executor_1 = require("./transactions/jito-rpc-transaction-executor");
const connection = new web3_js_1.Connection(helpers_1.RPC_ENDPOINT, {
wsEndpoint: helpers_1.RPC_WEBSOCKET_ENDPOINT,
commitment: helpers_1.COMMITMENT_LEVEL,
});
function printDetails(wallet, quoteToken, bot) {
helpers_1.logger.info(`
.. :-===++++-
.-==+++++++- =+++++++++-
..:::--===+=.=: .+++++++++++:=+++++++++:
.==+++++++++++++++=:+++: .+++++++++++.=++++++++-.
.-+++++++++++++++=:=++++- .+++++++++=:.=+++++-::-.
-:+++++++++++++=:+++++++- .++++++++-:- =+++++=-:
-:++++++=++++=:++++=++++= .++++++++++- =+++++:
-:++++-:=++=:++++=:-+++++:+++++====--:::::::.
::=+-:::==:=+++=::-:--::::::::::---------::.
::-: .::::::::. --------:::..
:- .:.-:::.
WARP DRIVE ACTIVATED 🚀🐟
Made with ❤️ by humans.
Version: ${package_json_1.version}
`);
const botConfig = bot.config;
helpers_1.logger.info('------- CONFIGURATION START -------');
helpers_1.logger.info(`Wallet: ${wallet.publicKey.toString()}`);
helpers_1.logger.info('- Bot -');
helpers_1.logger.info(`Using transaction executor: ${helpers_1.TRANSACTION_EXECUTOR}`);
if (bot.isWarp || bot.isJito) {
helpers_1.logger.info(`${helpers_1.TRANSACTION_EXECUTOR} fee: ${helpers_1.CUSTOM_FEE}`);
}
else {
helpers_1.logger.info(`Compute Unit limit: ${botConfig.unitLimit}`);
helpers_1.logger.info(`Compute Unit price (micro lamports): ${botConfig.unitPrice}`);
}
helpers_1.logger.info(`Max tokens at the time: ${botConfig.maxTokensAtTheTime}`);
helpers_1.logger.info(`Pre load existing markets: ${helpers_1.PRE_LOAD_EXISTING_MARKETS}`);
helpers_1.logger.info(`Cache new markets: ${helpers_1.CACHE_NEW_MARKETS}`);
helpers_1.logger.info(`Log level: ${helpers_1.LOG_LEVEL}`);
helpers_1.logger.info('- Buy -');
helpers_1.logger.info(`Buy amount: ${botConfig.quoteAmount.toFixed()} ${botConfig.quoteToken.name}`);
helpers_1.logger.info(`Auto buy delay: ${botConfig.autoBuyDelay} ms`);
helpers_1.logger.info(`Max buy retries: ${botConfig.maxBuyRetries}`);
helpers_1.logger.info(`Buy amount (${quoteToken.symbol}): ${botConfig.quoteAmount.toFixed()}`);
helpers_1.logger.info(`Buy slippage: ${botConfig.buySlippage}%`);
helpers_1.logger.info('- Sell -');
helpers_1.logger.info(`Auto sell: ${helpers_1.AUTO_SELL}`);
helpers_1.logger.info(`Auto sell delay: ${botConfig.autoSellDelay} ms`);
helpers_1.logger.info(`Max sell retries: ${botConfig.maxSellRetries}`);
helpers_1.logger.info(`Sell slippage: ${botConfig.sellSlippage}%`);
helpers_1.logger.info(`Price check interval: ${botConfig.priceCheckInterval} ms`);
helpers_1.logger.info(`Price check duration: ${botConfig.priceCheckDuration} ms`);
helpers_1.logger.info(`Take profit: ${botConfig.takeProfit}%`);
helpers_1.logger.info(`Stop loss: ${botConfig.stopLoss}%`);
helpers_1.logger.info(`Trailing stop loss: ${botConfig.trailingStopLoss}`);
helpers_1.logger.info(`Skip selling if lost more than: ${botConfig.skipSellingIfLostMoreThan}%`);
helpers_1.logger.info('- Snipe list -');
helpers_1.logger.info(`Snipe list: ${botConfig.useSnipeList}`);
helpers_1.logger.info(`Snipe list refresh interval: ${helpers_1.SNIPE_LIST_REFRESH_INTERVAL} ms`);
if (botConfig.useSnipeList) {
helpers_1.logger.info('- Filters -');
helpers_1.logger.info(`Filters are disabled when snipe list is on`);
}
else {
helpers_1.logger.info('- Filters -');
helpers_1.logger.info(`Filter check interval: ${botConfig.filterCheckInterval} ms`);
helpers_1.logger.info(`Filter check duration: ${botConfig.filterCheckDuration} ms`);
helpers_1.logger.info(`Consecutive filter matches: ${botConfig.consecutiveMatchCount}`);
helpers_1.logger.info(`Check renounced: ${helpers_1.CHECK_IF_MINT_IS_RENOUNCED}`);
helpers_1.logger.info(`Check freezable: ${helpers_1.CHECK_IF_FREEZABLE}`);
helpers_1.logger.info(`Check burned: ${helpers_1.CHECK_IF_BURNED}`);
helpers_1.logger.info(`Check mutable: ${helpers_1.CHECK_IF_MUTABLE}`);
helpers_1.logger.info(`Check socials: ${helpers_1.CHECK_IF_SOCIALS}`);
helpers_1.logger.info(`Min pool size: ${botConfig.minPoolSize.toFixed()}`);
helpers_1.logger.info(`Max pool size: ${botConfig.maxPoolSize.toFixed()}`);
}
helpers_1.logger.info('------- CONFIGURATION END -------');
helpers_1.logger.info('Bot is running! Press CTRL + C to stop it.');
}
const runListener = () => __awaiter(void 0, void 0, void 0, function* () {
helpers_1.logger.level = helpers_1.LOG_LEVEL;
helpers_1.logger.info('Bot is starting...');
const marketCache = new cache_1.MarketCache(connection);
const poolCache = new cache_1.PoolCache();
let txExecutor;
switch (helpers_1.TRANSACTION_EXECUTOR) {
case 'warp': {
txExecutor = new warp_transaction_executor_1.WarpTransactionExecutor(helpers_1.CUSTOM_FEE);
break;
}
case 'jito': {
txExecutor = new jito_rpc_transaction_executor_1.JitoTransactionExecutor(helpers_1.CUSTOM_FEE, connection);
break;
}
default: {
txExecutor = new transactions_1.DefaultTransactionExecutor(connection);
break;
}
}
const wallet = (0, helpers_1.getWallet)(helpers_1.PRIVATE_KEY.trim());
const quoteToken = (0, helpers_1.getToken)(helpers_1.QUOTE_MINT);
const botConfig = {
wallet,
quoteAta: (0, spl_token_1.getAssociatedTokenAddressSync)(quoteToken.mint, wallet.publicKey),
minPoolSize: new raydium_sdk_1.TokenAmount(quoteToken, helpers_1.MIN_POOL_SIZE, false),
maxPoolSize: new raydium_sdk_1.TokenAmount(quoteToken, helpers_1.MAX_POOL_SIZE, false),
quoteToken,
quoteAmount: new raydium_sdk_1.TokenAmount(quoteToken, helpers_1.QUOTE_AMOUNT, false),
maxTokensAtTheTime: helpers_1.MAX_TOKENS_AT_THE_TIME,
useSnipeList: helpers_1.USE_SNIPE_LIST,
autoSell: helpers_1.AUTO_SELL,
autoSellDelay: helpers_1.AUTO_SELL_DELAY,
maxSellRetries: helpers_1.MAX_SELL_RETRIES,
autoBuyDelay: helpers_1.AUTO_BUY_DELAY,
maxBuyRetries: helpers_1.MAX_BUY_RETRIES,
unitLimit: helpers_1.COMPUTE_UNIT_LIMIT,
unitPrice: helpers_1.COMPUTE_UNIT_PRICE,
takeProfit: helpers_1.TAKE_PROFIT,
stopLoss: helpers_1.STOP_LOSS,
trailingStopLoss: helpers_1.TRAILING_STOP_LOSS,
skipSellingIfLostMoreThan: helpers_1.SKIP_SELLING_IF_LOST_MORE_THAN,
buySlippage: helpers_1.BUY_SLIPPAGE,
sellSlippage: helpers_1.SELL_SLIPPAGE,
priceCheckInterval: helpers_1.PRICE_CHECK_INTERVAL,
priceCheckDuration: helpers_1.PRICE_CHECK_DURATION,
filterCheckInterval: helpers_1.FILTER_CHECK_INTERVAL,
filterCheckDuration: helpers_1.FILTER_CHECK_DURATION,
consecutiveMatchCount: helpers_1.CONSECUTIVE_FILTER_MATCHES,
};
const bot = new bot_1.Bot(connection, marketCache, poolCache, txExecutor, botConfig);
const valid = yield bot.validate();
if (!valid) {
helpers_1.logger.info('Bot is exiting...');
process.exit(1);
}
if (helpers_1.PRE_LOAD_EXISTING_MARKETS) {
yield marketCache.init({ quoteToken });
}
const runTimestamp = Math.floor(new Date().getTime() / 1000);
const listeners = new listeners_1.Listeners(connection);
yield listeners.start({
walletPublicKey: wallet.publicKey,
quoteToken,
autoSell: helpers_1.AUTO_SELL,
cacheNewMarkets: helpers_1.CACHE_NEW_MARKETS,
});
listeners.on('market', (updatedAccountInfo) => {
const marketState = raydium_sdk_1.MARKET_STATE_LAYOUT_V3.decode(updatedAccountInfo.accountInfo.data);
marketCache.save(updatedAccountInfo.accountId.toString(), marketState);
});
listeners.on('pool', (updatedAccountInfo) => __awaiter(void 0, void 0, void 0, function* () {
const poolState = raydium_sdk_1.LIQUIDITY_STATE_LAYOUT_V4.decode(updatedAccountInfo.accountInfo.data);
const poolOpenTime = parseInt(poolState.poolOpenTime.toString());
const exists = yield poolCache.get(poolState.baseMint.toString());
if (!exists && poolOpenTime > runTimestamp) {
poolCache.save(updatedAccountInfo.accountId.toString(), poolState);
yield bot.buy(updatedAccountInfo.accountId, poolState);
}
}));
listeners.on('wallet', (updatedAccountInfo) => __awaiter(void 0, void 0, void 0, function* () {
const accountData = spl_token_1.AccountLayout.decode(updatedAccountInfo.accountInfo.data);
if (accountData.mint.equals(quoteToken.mint)) {
return;
}
yield bot.sell(updatedAccountInfo.accountId, accountData);
}));
printDetails(wallet, quoteToken, bot);
});
runListener();

17
listeners/index.js Normal file
View File

@ -0,0 +1,17 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./listeners"), exports);

View File

@ -1 +1 @@
export * from './listeners';
export * from "./listeners";

109
listeners/listeners.js Normal file
View File

@ -0,0 +1,109 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Listeners = void 0;
const raydium_sdk_1 = require("@raydium-io/raydium-sdk");
const bs58_1 = __importDefault(require("bs58"));
const spl_token_1 = require("@solana/spl-token");
const events_1 = require("events");
class Listeners extends events_1.EventEmitter {
constructor(connection) {
super();
this.connection = connection;
this.subscriptions = [];
}
start(config) {
return __awaiter(this, void 0, void 0, function* () {
if (config.cacheNewMarkets) {
const openBookSubscription = yield this.subscribeToOpenBookMarkets(config);
this.subscriptions.push(openBookSubscription);
}
const raydiumSubscription = yield this.subscribeToRaydiumPools(config);
this.subscriptions.push(raydiumSubscription);
if (config.autoSell) {
const walletSubscription = yield this.subscribeToWalletChanges(config);
this.subscriptions.push(walletSubscription);
}
});
}
subscribeToOpenBookMarkets(config) {
return __awaiter(this, void 0, void 0, function* () {
return this.connection.onProgramAccountChange(raydium_sdk_1.MAINNET_PROGRAM_ID.OPENBOOK_MARKET, (updatedAccountInfo) => __awaiter(this, void 0, void 0, function* () {
this.emit("market", updatedAccountInfo);
}), this.connection.commitment, [
{ dataSize: raydium_sdk_1.MARKET_STATE_LAYOUT_V3.span },
{
memcmp: {
offset: raydium_sdk_1.MARKET_STATE_LAYOUT_V3.offsetOf("quoteMint"),
bytes: config.quoteToken.mint.toBase58(),
},
},
]);
});
}
subscribeToRaydiumPools(config) {
return __awaiter(this, void 0, void 0, function* () {
return this.connection.onProgramAccountChange(raydium_sdk_1.MAINNET_PROGRAM_ID.AmmV4, (updatedAccountInfo) => __awaiter(this, void 0, void 0, function* () {
this.emit("pool", updatedAccountInfo);
}), this.connection.commitment, [
{ dataSize: raydium_sdk_1.LIQUIDITY_STATE_LAYOUT_V4.span },
{
memcmp: {
offset: raydium_sdk_1.LIQUIDITY_STATE_LAYOUT_V4.offsetOf("quoteMint"),
bytes: config.quoteToken.mint.toBase58(),
},
},
{
memcmp: {
offset: raydium_sdk_1.LIQUIDITY_STATE_LAYOUT_V4.offsetOf("marketProgramId"),
bytes: raydium_sdk_1.MAINNET_PROGRAM_ID.OPENBOOK_MARKET.toBase58(),
},
},
{
memcmp: {
offset: raydium_sdk_1.LIQUIDITY_STATE_LAYOUT_V4.offsetOf("status"),
bytes: bs58_1.default.encode([6, 0, 0, 0, 0, 0, 0, 0]),
},
},
]);
});
}
subscribeToWalletChanges(config) {
return __awaiter(this, void 0, void 0, function* () {
return this.connection.onProgramAccountChange(spl_token_1.TOKEN_PROGRAM_ID, (updatedAccountInfo) => __awaiter(this, void 0, void 0, function* () {
this.emit("wallet", updatedAccountInfo);
}), this.connection.commitment, [
{
dataSize: 165,
},
{
memcmp: {
offset: 32,
bytes: config.walletPublicKey.toBase58(),
},
},
]);
});
}
stop() {
return __awaiter(this, void 0, void 0, function* () {
for (let i = this.subscriptions.length; i >= 0; --i) {
const subscription = this.subscriptions[i];
yield this.connection.removeAccountChangeListener(subscription);
this.subscriptions.splice(i, 1);
}
});
}
}
exports.Listeners = Listeners;

View File

@ -1,112 +1,112 @@
import { LIQUIDITY_STATE_LAYOUT_V4, MAINNET_PROGRAM_ID, MARKET_STATE_LAYOUT_V3, Token } from '@raydium-io/raydium-sdk';
import bs58 from 'bs58';
import { Connection, PublicKey } from '@solana/web3.js';
import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
import { EventEmitter } from 'events';
import { LIQUIDITY_STATE_LAYOUT_V4, MAINNET_PROGRAM_ID, MARKET_STATE_LAYOUT_V3, Token } from "@raydium-io/raydium-sdk";
import bs58 from "bs58";
import { Connection, PublicKey } from "@solana/web3.js";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import { EventEmitter } from "events";
export class Listeners extends EventEmitter {
private subscriptions: number[] = [];
private subscriptions: number[] = [];
constructor(private readonly connection: Connection) {
super();
}
constructor(private readonly connection: Connection) {
super();
}
public async start(config: {
walletPublicKey: PublicKey;
quoteToken: Token;
autoSell: boolean;
cacheNewMarkets: boolean;
}) {
if (config.cacheNewMarkets) {
const openBookSubscription = await this.subscribeToOpenBookMarkets(config);
this.subscriptions.push(openBookSubscription);
}
public async start(config: {
walletPublicKey: PublicKey;
quoteToken: Token;
autoSell: boolean;
cacheNewMarkets: boolean;
}) {
if (config.cacheNewMarkets) {
const openBookSubscription = await this.subscribeToOpenBookMarkets(config);
this.subscriptions.push(openBookSubscription);
}
const raydiumSubscription = await this.subscribeToRaydiumPools(config);
this.subscriptions.push(raydiumSubscription);
const raydiumSubscription = await this.subscribeToRaydiumPools(config);
this.subscriptions.push(raydiumSubscription);
if (config.autoSell) {
const walletSubscription = await this.subscribeToWalletChanges(config);
this.subscriptions.push(walletSubscription);
}
}
if (config.autoSell) {
const walletSubscription = await this.subscribeToWalletChanges(config);
this.subscriptions.push(walletSubscription);
}
}
private async subscribeToOpenBookMarkets(config: { quoteToken: Token }) {
return this.connection.onProgramAccountChange(
MAINNET_PROGRAM_ID.OPENBOOK_MARKET,
async (updatedAccountInfo) => {
this.emit('market', updatedAccountInfo);
},
this.connection.commitment,
[
{ dataSize: MARKET_STATE_LAYOUT_V3.span },
{
memcmp: {
offset: MARKET_STATE_LAYOUT_V3.offsetOf('quoteMint'),
bytes: config.quoteToken.mint.toBase58(),
},
},
],
);
}
private async subscribeToOpenBookMarkets(config: { quoteToken: Token }) {
return this.connection.onProgramAccountChange(
MAINNET_PROGRAM_ID.OPENBOOK_MARKET,
async (updatedAccountInfo) => {
this.emit("market", updatedAccountInfo);
},
this.connection.commitment,
[
{ dataSize: MARKET_STATE_LAYOUT_V3.span },
{
memcmp: {
offset: MARKET_STATE_LAYOUT_V3.offsetOf("quoteMint"),
bytes: config.quoteToken.mint.toBase58(),
},
},
],
);
}
private async subscribeToRaydiumPools(config: { quoteToken: Token }) {
return this.connection.onProgramAccountChange(
MAINNET_PROGRAM_ID.AmmV4,
async (updatedAccountInfo) => {
this.emit('pool', updatedAccountInfo);
},
this.connection.commitment,
[
{ dataSize: LIQUIDITY_STATE_LAYOUT_V4.span },
{
memcmp: {
offset: LIQUIDITY_STATE_LAYOUT_V4.offsetOf('quoteMint'),
bytes: config.quoteToken.mint.toBase58(),
},
},
{
memcmp: {
offset: LIQUIDITY_STATE_LAYOUT_V4.offsetOf('marketProgramId'),
bytes: MAINNET_PROGRAM_ID.OPENBOOK_MARKET.toBase58(),
},
},
{
memcmp: {
offset: LIQUIDITY_STATE_LAYOUT_V4.offsetOf('status'),
bytes: bs58.encode([6, 0, 0, 0, 0, 0, 0, 0]),
},
},
],
);
}
private async subscribeToRaydiumPools(config: { quoteToken: Token }) {
return this.connection.onProgramAccountChange(
MAINNET_PROGRAM_ID.AmmV4,
async (updatedAccountInfo) => {
this.emit("pool", updatedAccountInfo);
},
this.connection.commitment,
[
{ dataSize: LIQUIDITY_STATE_LAYOUT_V4.span },
{
memcmp: {
offset: LIQUIDITY_STATE_LAYOUT_V4.offsetOf("quoteMint"),
bytes: config.quoteToken.mint.toBase58(),
},
},
{
memcmp: {
offset: LIQUIDITY_STATE_LAYOUT_V4.offsetOf("marketProgramId"),
bytes: MAINNET_PROGRAM_ID.OPENBOOK_MARKET.toBase58(),
},
},
{
memcmp: {
offset: LIQUIDITY_STATE_LAYOUT_V4.offsetOf("status"),
bytes: bs58.encode([6, 0, 0, 0, 0, 0, 0, 0]),
},
},
],
);
}
private async subscribeToWalletChanges(config: { walletPublicKey: PublicKey }) {
return this.connection.onProgramAccountChange(
TOKEN_PROGRAM_ID,
async (updatedAccountInfo) => {
this.emit('wallet', updatedAccountInfo);
},
this.connection.commitment,
[
{
dataSize: 165,
},
{
memcmp: {
offset: 32,
bytes: config.walletPublicKey.toBase58(),
},
},
],
);
}
private async subscribeToWalletChanges(config: { walletPublicKey: PublicKey }) {
return this.connection.onProgramAccountChange(
TOKEN_PROGRAM_ID,
async (updatedAccountInfo) => {
this.emit("wallet", updatedAccountInfo);
},
this.connection.commitment,
[
{
dataSize: 165,
},
{
memcmp: {
offset: 32,
bytes: config.walletPublicKey.toBase58(),
},
},
],
);
}
public async stop() {
for (let i = this.subscriptions.length; i >= 0; --i) {
const subscription = this.subscriptions[i];
await this.connection.removeAccountChangeListener(subscription);
this.subscriptions.splice(i, 1);
}
}
public async stop() {
for (let i = this.subscriptions.length; i >= 0; --i) {
const subscription = this.subscriptions[i];
await this.connection.removeAccountChangeListener(subscription);
this.subscriptions.splice(i, 1);
}
}
}

409
package-lock.json generated
View File

@ -24,7 +24,8 @@
"npm": "^10.5.2",
"pino": "^8.18.0",
"pino-pretty": "^10.3.1",
"pino-std-serializers": "^6.2.2"
"pino-std-serializers": "^6.2.2",
"request": "^2.88.2"
},
"devDependencies": {
"@types/bn.js": "^5.1.5",
@ -456,11 +457,45 @@
"node": ">= 8.0.0"
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/arg": {
"version": "4.1.3",
"dev": true,
"license": "MIT"
},
"node_modules/asn1": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
"license": "MIT",
"dependencies": {
"safer-buffer": "~2.1.0"
}
},
"node_modules/assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
"license": "MIT",
"engines": {
"node": ">=0.8"
}
},
"node_modules/async-mutex": {
"version": "0.5.0",
"license": "MIT",
@ -479,6 +514,21 @@
"node": ">=8.0.0"
}
},
"node_modules/aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
"license": "Apache-2.0",
"engines": {
"node": "*"
}
},
"node_modules/aws4": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
"integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==",
"license": "MIT"
},
"node_modules/axios": {
"version": "1.6.8",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
@ -511,6 +561,21 @@
],
"license": "MIT"
},
"node_modules/bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
"license": "BSD-3-Clause",
"dependencies": {
"tweetnacl": "^0.14.3"
}
},
"node_modules/bcrypt-pbkdf/node_modules/tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
"license": "Unlicense"
},
"node_modules/big.js": {
"version": "6.2.1",
"license": "MIT",
@ -622,6 +687,12 @@
"node": ">=6.14.2"
}
},
"node_modules/caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
"license": "Apache-2.0"
},
"node_modules/cipher-base": {
"version": "1.0.4",
"license": "MIT",
@ -648,6 +719,12 @@
"version": "2.20.3",
"license": "MIT"
},
"node_modules/core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
"license": "MIT"
},
"node_modules/create-hash": {
"version": "1.2.0",
"license": "MIT",
@ -676,6 +753,18 @@
"dev": true,
"license": "MIT"
},
"node_modules/dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
"license": "MIT",
"dependencies": {
"assert-plus": "^1.0.0"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/dateformat": {
"version": "4.6.3",
"license": "MIT",
@ -726,6 +815,16 @@
"url": "https://github.com/motdotla/dotenv?sponsor=1"
}
},
"node_modules/ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
"integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
"license": "MIT",
"dependencies": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
}
},
"node_modules/ed25519-hd-key": {
"version": "1.3.0",
"license": "MIT",
@ -770,6 +869,21 @@
"node": ">=0.8.x"
}
},
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"license": "MIT"
},
"node_modules/extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
"engines": [
"node >=0.6.0"
],
"license": "MIT"
},
"node_modules/eyes": {
"version": "0.1.8",
"engines": {
@ -780,6 +894,18 @@
"version": "3.0.1",
"license": "MIT"
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"license": "MIT"
},
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
"license": "MIT"
},
"node_modules/fast-redact": {
"version": "3.2.0",
"license": "MIT",
@ -827,6 +953,15 @@
}
}
},
"node_modules/forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
"license": "Apache-2.0",
"engines": {
"node": "*"
}
},
"node_modules/form-data": {
"version": "4.0.0",
"license": "MIT",
@ -839,6 +974,38 @@
"node": ">= 6"
}
},
"node_modules/getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
"license": "MIT",
"dependencies": {
"assert-plus": "^1.0.0"
}
},
"node_modules/har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
"license": "ISC",
"engines": {
"node": ">=4"
}
},
"node_modules/har-validator": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
"deprecated": "this library is no longer supported",
"license": "MIT",
"dependencies": {
"ajv": "^6.12.3",
"har-schema": "^2.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/hash-base": {
"version": "3.1.0",
"license": "MIT",
@ -867,6 +1034,21 @@
"version": "5.0.0",
"license": "MIT"
},
"node_modules/http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
"license": "MIT",
"dependencies": {
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
},
"engines": {
"node": ">=0.8",
"npm": ">=1.3.7"
}
},
"node_modules/humanize-ms": {
"version": "1.2.1",
"license": "MIT",
@ -902,6 +1084,12 @@
"version": "2.0.4",
"license": "ISC"
},
"node_modules/is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
"license": "MIT"
},
"node_modules/isomorphic-ws": {
"version": "4.0.1",
"license": "MIT",
@ -909,6 +1097,12 @@
"ws": "*"
}
},
"node_modules/isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
"license": "MIT"
},
"node_modules/jayson": {
"version": "4.1.0",
"license": "MIT",
@ -940,6 +1134,24 @@
"node": ">=10"
}
},
"node_modules/jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
"license": "MIT"
},
"node_modules/json-schema": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
"license": "(AFL-2.1 OR BSD-3-Clause)"
},
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"license": "MIT"
},
"node_modules/json-stringify-safe": {
"version": "5.0.1",
"license": "ISC"
@ -965,6 +1177,21 @@
"node": "*"
}
},
"node_modules/jsprim": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
"integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
"license": "MIT",
"dependencies": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.4.0",
"verror": "1.10.0"
},
"engines": {
"node": ">=0.6.0"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"license": "MIT"
@ -3605,6 +3832,15 @@
"inBundle": true,
"license": "ISC"
},
"node_modules/oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
"license": "Apache-2.0",
"engines": {
"node": "*"
}
},
"node_modules/on-exit-leak-free": {
"version": "2.1.0",
"license": "MIT"
@ -3616,6 +3852,12 @@
"wrappy": "1"
}
},
"node_modules/performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
"license": "MIT"
},
"node_modules/pino": {
"version": "8.18.0",
"license": "MIT",
@ -3700,6 +3942,12 @@
"version": "1.1.0",
"license": "MIT"
},
"node_modules/psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
"license": "MIT"
},
"node_modules/pump": {
"version": "3.0.0",
"license": "MIT",
@ -3708,6 +3956,24 @@
"once": "^1.3.1"
}
},
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/qs": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.6"
}
},
"node_modules/quick-format-unescaped": {
"version": "4.0.4",
"license": "MIT"
@ -3737,6 +4003,62 @@
"version": "0.14.1",
"license": "MIT"
},
"node_modules/request": {
"version": "2.88.2",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
"deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
"license": "Apache-2.0",
"dependencies": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.2",
"har-validator": "~5.1.3",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.5.0",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/request/node_modules/form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 0.12"
}
},
"node_modules/request/node_modules/uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
"license": "MIT",
"bin": {
"uuid": "bin/uuid"
}
},
"node_modules/ripemd160": {
"version": "2.0.2",
"license": "MIT",
@ -3807,6 +4129,12 @@
"node": ">=10"
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/secure-json-parse": {
"version": "2.7.0",
"license": "BSD-3-Clause"
@ -3836,6 +4164,37 @@
"node": ">= 10.x"
}
},
"node_modules/sshpk": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
"integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==",
"license": "MIT",
"dependencies": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
},
"bin": {
"sshpk-conv": "bin/sshpk-conv",
"sshpk-sign": "bin/sshpk-sign",
"sshpk-verify": "bin/sshpk-verify"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/sshpk/node_modules/tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
"license": "Unlicense"
},
"node_modules/string_decoder": {
"version": "1.3.0",
"license": "MIT",
@ -3875,6 +4234,19 @@
"version": "2.0.0",
"license": "MIT"
},
"node_modules/tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"license": "BSD-3-Clause",
"dependencies": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"license": "MIT"
@ -3925,6 +4297,18 @@
"version": "2.6.2",
"license": "0BSD"
},
"node_modules/tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
"license": "Apache-2.0",
"dependencies": {
"safe-buffer": "^5.0.1"
},
"engines": {
"node": "*"
}
},
"node_modules/tweetnacl": {
"version": "1.0.3",
"license": "Unlicense"
@ -3941,6 +4325,15 @@
"node": ">=14.17"
}
},
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"license": "BSD-2-Clause",
"dependencies": {
"punycode": "^2.1.0"
}
},
"node_modules/utf-8-validate": {
"version": "5.0.10",
"hasInstallScript": true,
@ -3969,6 +4362,20 @@
"dev": true,
"license": "MIT"
},
"node_modules/verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
"engines": [
"node >=0.6.0"
],
"license": "MIT",
"dependencies": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"license": "BSD-2-Clause"

View File

@ -4,8 +4,9 @@
"homepage": "https://warp.id",
"version": "2.0.2",
"scripts": {
"start": "ts-node index.ts",
"tsc": "tsc --noEmit"
"start": "npm run cache | node index.js",
"tsc": "tsc --noEmit",
"cache": "node helpers/helper.cache.js"
},
"dependencies": {
"@metaplex-foundation/mpl-token-metadata": "^3.2.1",
@ -24,7 +25,8 @@
"npm": "^10.5.2",
"pino": "^8.18.0",
"pino-pretty": "^10.3.1",
"pino-std-serializers": "^6.2.2"
"pino-std-serializers": "^6.2.2",
"request": "^2.88.2"
},
"devDependencies": {
"@types/bn.js": "^5.1.5",

View File

@ -0,0 +1,44 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DefaultTransactionExecutor = void 0;
const helpers_1 = require("../helpers");
class DefaultTransactionExecutor {
constructor(connection) {
this.connection = connection;
}
executeAndConfirm(transaction, payer, latestBlockhash) {
return __awaiter(this, void 0, void 0, function* () {
helpers_1.logger.debug("Executing transaction...");
const signature = yield this.execute(transaction);
helpers_1.logger.debug({ signature }, "Confirming transaction...");
return this.confirm(signature, latestBlockhash);
});
}
execute(transaction) {
return __awaiter(this, void 0, void 0, function* () {
return this.connection.sendRawTransaction(transaction.serialize(), {
preflightCommitment: this.connection.commitment,
});
});
}
confirm(signature, latestBlockhash) {
return __awaiter(this, void 0, void 0, function* () {
const confirmation = yield this.connection.confirmTransaction({
signature,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
blockhash: latestBlockhash.blockhash,
}, this.connection.commitment);
return { confirmed: !confirmation.value.err, signature };
});
}
}
exports.DefaultTransactionExecutor = DefaultTransactionExecutor;

View File

@ -1,44 +1,44 @@
import {
BlockhashWithExpiryBlockHeight,
Connection,
Keypair,
Transaction,
VersionedTransaction,
} from '@solana/web3.js';
import { TransactionExecutor } from './transaction-executor.interface';
import { logger } from '../helpers';
BlockhashWithExpiryBlockHeight,
Connection,
Keypair,
Transaction,
VersionedTransaction,
} from "@solana/web3.js";
import { TransactionExecutor } from "./transaction-executor.interface";
import { logger } from "../helpers";
export class DefaultTransactionExecutor implements TransactionExecutor {
constructor(private readonly connection: Connection) {}
constructor(private readonly connection: Connection) {}
public async executeAndConfirm(
transaction: VersionedTransaction,
payer: Keypair,
latestBlockhash: BlockhashWithExpiryBlockHeight,
): Promise<{ confirmed: boolean; signature?: string, error?: string }> {
logger.debug('Executing transaction...');
const signature = await this.execute(transaction);
public async executeAndConfirm(
transaction: VersionedTransaction,
payer: Keypair,
latestBlockhash: BlockhashWithExpiryBlockHeight,
): Promise<{ confirmed: boolean; signature?: string; error?: string }> {
logger.debug("Executing transaction...");
const signature = await this.execute(transaction);
logger.debug({ signature }, 'Confirming transaction...');
return this.confirm(signature, latestBlockhash);
}
logger.debug({ signature }, "Confirming transaction...");
return this.confirm(signature, latestBlockhash);
}
private async execute(transaction: Transaction | VersionedTransaction) {
return this.connection.sendRawTransaction(transaction.serialize(), {
preflightCommitment: this.connection.commitment,
});
}
private async execute(transaction: Transaction | VersionedTransaction) {
return this.connection.sendRawTransaction(transaction.serialize(), {
preflightCommitment: this.connection.commitment,
});
}
private async confirm(signature: string, latestBlockhash: BlockhashWithExpiryBlockHeight) {
const confirmation = await this.connection.confirmTransaction(
{
signature,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
blockhash: latestBlockhash.blockhash,
},
this.connection.commitment,
);
private async confirm(signature: string, latestBlockhash: BlockhashWithExpiryBlockHeight) {
const confirmation = await this.connection.confirmTransaction(
{
signature,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
blockhash: latestBlockhash.blockhash,
},
this.connection.commitment,
);
return { confirmed: !confirmation.value.err, signature };
}
return { confirmed: !confirmation.value.err, signature };
}
}

18
transactions/index.js Normal file
View File

@ -0,0 +1,18 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./default-transaction-executor"), exports);
__exportStar(require("./transaction-executor.interface"), exports);

View File

@ -1,2 +1,2 @@
export * from './default-transaction-executor';
export * from './transaction-executor.interface';
export * from "./default-transaction-executor";
export * from "./transaction-executor.interface";

View File

@ -0,0 +1,139 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.JitoTransactionExecutor = void 0;
const web3_js_1 = require("@solana/web3.js");
const helpers_1 = require("../helpers");
const axios_1 = __importStar(require("axios"));
const bs58_1 = __importDefault(require("bs58"));
const raydium_sdk_1 = require("@raydium-io/raydium-sdk");
class JitoTransactionExecutor {
constructor(jitoFee, connection) {
this.jitoFee = jitoFee;
this.connection = connection;
// https://jito-labs.gitbook.io/mev/searcher-resources/json-rpc-api-reference/bundles/gettipaccounts
this.jitpTipAccounts = [
"Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY",
"DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL",
"96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5",
"3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT",
"HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe",
"ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49",
"ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt",
"DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh",
];
this.JitoFeeWallet = this.getRandomValidatorKey();
}
getRandomValidatorKey() {
const randomValidator = this.jitpTipAccounts[Math.floor(Math.random() * this.jitpTipAccounts.length)];
return new web3_js_1.PublicKey(randomValidator);
}
executeAndConfirm(transaction, payer, latestBlockhash) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
helpers_1.logger.debug("Starting Jito transaction execution...");
this.JitoFeeWallet = this.getRandomValidatorKey(); // Update wallet key each execution
helpers_1.logger.trace(`Selected Jito fee wallet: ${this.JitoFeeWallet.toBase58()}`);
try {
const fee = new raydium_sdk_1.CurrencyAmount(raydium_sdk_1.Currency.SOL, this.jitoFee, false).raw.toNumber();
helpers_1.logger.trace(`Calculated fee: ${fee} lamports`);
const jitTipTxFeeMessage = new web3_js_1.TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: latestBlockhash.blockhash,
instructions: [
web3_js_1.SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: this.JitoFeeWallet,
lamports: fee,
}),
],
}).compileToV0Message();
const jitoFeeTx = new web3_js_1.VersionedTransaction(jitTipTxFeeMessage);
jitoFeeTx.sign([payer]);
const jitoTxsignature = bs58_1.default.encode(jitoFeeTx.signatures[0]);
// Serialize the transactions once here
const serializedjitoFeeTx = bs58_1.default.encode(jitoFeeTx.serialize());
const serializedTransaction = bs58_1.default.encode(transaction.serialize());
const serializedTransactions = [serializedjitoFeeTx, serializedTransaction];
// https://jito-labs.gitbook.io/mev/searcher-resources/json-rpc-api-reference/url
const endpoints = [
"https://mainnet.block-engine.jito.wtf/api/v1/bundles",
"https://amsterdam.mainnet.block-engine.jito.wtf/api/v1/bundles",
"https://frankfurt.mainnet.block-engine.jito.wtf/api/v1/bundles",
"https://ny.mainnet.block-engine.jito.wtf/api/v1/bundles",
"https://tokyo.mainnet.block-engine.jito.wtf/api/v1/bundles",
];
const requests = endpoints.map((url) => axios_1.default.post(url, {
jsonrpc: "2.0",
id: 1,
method: "sendBundle",
params: [serializedTransactions],
}));
helpers_1.logger.trace("Sending transactions to endpoints...");
const results = yield Promise.all(requests.map((p) => p.catch((e) => e)));
const successfulResults = results.filter((result) => !(result instanceof Error));
if (successfulResults.length > 0) {
helpers_1.logger.trace(`At least one successful response`);
helpers_1.logger.debug(`Confirming jito transaction...`);
return yield this.confirm(jitoTxsignature, latestBlockhash);
}
else {
helpers_1.logger.debug(`No successful responses received for jito`);
}
return { confirmed: false };
}
catch (error) {
if (error instanceof axios_1.AxiosError) {
helpers_1.logger.trace({ error: (_a = error.response) === null || _a === void 0 ? void 0 : _a.data }, "Failed to execute jito transaction");
}
helpers_1.logger.error("Error during transaction execution", error);
return { confirmed: false };
}
});
}
confirm(signature, latestBlockhash) {
return __awaiter(this, void 0, void 0, function* () {
const confirmation = yield this.connection.confirmTransaction({
signature,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
blockhash: latestBlockhash.blockhash,
}, this.connection.commitment);
return { confirmed: !confirmation.value.err, signature };
});
}
}
exports.JitoTransactionExecutor = JitoTransactionExecutor;

View File

@ -1,131 +1,131 @@
import {
BlockhashWithExpiryBlockHeight,
Keypair,
PublicKey,
SystemProgram,
Connection,
TransactionMessage,
VersionedTransaction,
} from '@solana/web3.js';
import { TransactionExecutor } from './transaction-executor.interface';
import { logger } from '../helpers';
import axios, { AxiosError } from 'axios';
import bs58 from 'bs58';
import { Currency, CurrencyAmount } from '@raydium-io/raydium-sdk';
BlockhashWithExpiryBlockHeight,
Keypair,
PublicKey,
SystemProgram,
Connection,
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
import { TransactionExecutor } from "./transaction-executor.interface";
import { logger } from "../helpers";
import axios, { AxiosError } from "axios";
import bs58 from "bs58";
import { Currency, CurrencyAmount } from "@raydium-io/raydium-sdk";
export class JitoTransactionExecutor implements TransactionExecutor {
// https://jito-labs.gitbook.io/mev/searcher-resources/json-rpc-api-reference/bundles/gettipaccounts
private jitpTipAccounts = [
'Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY',
'DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL',
'96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5',
'3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT',
'HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe',
'ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49',
'ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt',
'DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh',
];
// https://jito-labs.gitbook.io/mev/searcher-resources/json-rpc-api-reference/bundles/gettipaccounts
private jitpTipAccounts = [
"Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY",
"DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL",
"96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5",
"3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT",
"HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe",
"ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49",
"ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt",
"DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh",
];
private JitoFeeWallet: PublicKey;
private JitoFeeWallet: PublicKey;
constructor(
private readonly jitoFee: string,
private readonly connection: Connection,
) {
this.JitoFeeWallet = this.getRandomValidatorKey();
}
constructor(
private readonly jitoFee: string,
private readonly connection: Connection,
) {
this.JitoFeeWallet = this.getRandomValidatorKey();
}
private getRandomValidatorKey(): PublicKey {
const randomValidator = this.jitpTipAccounts[Math.floor(Math.random() * this.jitpTipAccounts.length)];
return new PublicKey(randomValidator);
}
private getRandomValidatorKey(): PublicKey {
const randomValidator = this.jitpTipAccounts[Math.floor(Math.random() * this.jitpTipAccounts.length)];
return new PublicKey(randomValidator);
}
public async executeAndConfirm(
transaction: VersionedTransaction,
payer: Keypair,
latestBlockhash: BlockhashWithExpiryBlockHeight,
): Promise<{ confirmed: boolean; signature?: string; error?: string }> {
logger.debug('Starting Jito transaction execution...');
this.JitoFeeWallet = this.getRandomValidatorKey(); // Update wallet key each execution
logger.trace(`Selected Jito fee wallet: ${this.JitoFeeWallet.toBase58()}`);
public async executeAndConfirm(
transaction: VersionedTransaction,
payer: Keypair,
latestBlockhash: BlockhashWithExpiryBlockHeight,
): Promise<{ confirmed: boolean; signature?: string; error?: string }> {
logger.debug("Starting Jito transaction execution...");
this.JitoFeeWallet = this.getRandomValidatorKey(); // Update wallet key each execution
logger.trace(`Selected Jito fee wallet: ${this.JitoFeeWallet.toBase58()}`);
try {
const fee = new CurrencyAmount(Currency.SOL, this.jitoFee, false).raw.toNumber();
logger.trace(`Calculated fee: ${fee} lamports`);
try {
const fee = new CurrencyAmount(Currency.SOL, this.jitoFee, false).raw.toNumber();
logger.trace(`Calculated fee: ${fee} lamports`);
const jitTipTxFeeMessage = new TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: latestBlockhash.blockhash,
instructions: [
SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: this.JitoFeeWallet,
lamports: fee,
}),
],
}).compileToV0Message();
const jitTipTxFeeMessage = new TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: latestBlockhash.blockhash,
instructions: [
SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: this.JitoFeeWallet,
lamports: fee,
}),
],
}).compileToV0Message();
const jitoFeeTx = new VersionedTransaction(jitTipTxFeeMessage);
jitoFeeTx.sign([payer]);
const jitoFeeTx = new VersionedTransaction(jitTipTxFeeMessage);
jitoFeeTx.sign([payer]);
const jitoTxsignature = bs58.encode(jitoFeeTx.signatures[0]);
const jitoTxsignature = bs58.encode(jitoFeeTx.signatures[0]);
// Serialize the transactions once here
const serializedjitoFeeTx = bs58.encode(jitoFeeTx.serialize());
const serializedTransaction = bs58.encode(transaction.serialize());
const serializedTransactions = [serializedjitoFeeTx, serializedTransaction];
// Serialize the transactions once here
const serializedjitoFeeTx = bs58.encode(jitoFeeTx.serialize());
const serializedTransaction = bs58.encode(transaction.serialize());
const serializedTransactions = [serializedjitoFeeTx, serializedTransaction];
// https://jito-labs.gitbook.io/mev/searcher-resources/json-rpc-api-reference/url
const endpoints = [
'https://mainnet.block-engine.jito.wtf/api/v1/bundles',
'https://amsterdam.mainnet.block-engine.jito.wtf/api/v1/bundles',
'https://frankfurt.mainnet.block-engine.jito.wtf/api/v1/bundles',
'https://ny.mainnet.block-engine.jito.wtf/api/v1/bundles',
'https://tokyo.mainnet.block-engine.jito.wtf/api/v1/bundles',
];
// https://jito-labs.gitbook.io/mev/searcher-resources/json-rpc-api-reference/url
const endpoints = [
"https://mainnet.block-engine.jito.wtf/api/v1/bundles",
"https://amsterdam.mainnet.block-engine.jito.wtf/api/v1/bundles",
"https://frankfurt.mainnet.block-engine.jito.wtf/api/v1/bundles",
"https://ny.mainnet.block-engine.jito.wtf/api/v1/bundles",
"https://tokyo.mainnet.block-engine.jito.wtf/api/v1/bundles",
];
const requests = endpoints.map((url) =>
axios.post(url, {
jsonrpc: '2.0',
id: 1,
method: 'sendBundle',
params: [serializedTransactions],
}),
);
const requests = endpoints.map((url) =>
axios.post(url, {
jsonrpc: "2.0",
id: 1,
method: "sendBundle",
params: [serializedTransactions],
}),
);
logger.trace('Sending transactions to endpoints...');
const results = await Promise.all(requests.map((p) => p.catch((e) => e)));
logger.trace("Sending transactions to endpoints...");
const results = await Promise.all(requests.map((p) => p.catch((e) => e)));
const successfulResults = results.filter((result) => !(result instanceof Error));
const successfulResults = results.filter((result) => !(result instanceof Error));
if (successfulResults.length > 0) {
logger.trace(`At least one successful response`);
logger.debug(`Confirming jito transaction...`);
return await this.confirm(jitoTxsignature, latestBlockhash);
} else {
logger.debug(`No successful responses received for jito`);
}
if (successfulResults.length > 0) {
logger.trace(`At least one successful response`);
logger.debug(`Confirming jito transaction...`);
return await this.confirm(jitoTxsignature, latestBlockhash);
} else {
logger.debug(`No successful responses received for jito`);
}
return { confirmed: false };
} catch (error) {
if (error instanceof AxiosError) {
logger.trace({ error: error.response?.data }, 'Failed to execute jito transaction');
}
logger.error('Error during transaction execution', error);
return { confirmed: false };
}
}
return { confirmed: false };
} catch (error) {
if (error instanceof AxiosError) {
logger.trace({ error: error.response?.data }, "Failed to execute jito transaction");
}
logger.error("Error during transaction execution", error);
return { confirmed: false };
}
}
private async confirm(signature: string, latestBlockhash: BlockhashWithExpiryBlockHeight) {
const confirmation = await this.connection.confirmTransaction(
{
signature,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
blockhash: latestBlockhash.blockhash,
},
this.connection.commitment,
);
private async confirm(signature: string, latestBlockhash: BlockhashWithExpiryBlockHeight) {
const confirmation = await this.connection.confirmTransaction(
{
signature,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
blockhash: latestBlockhash.blockhash,
},
this.connection.commitment,
);
return { confirmed: !confirmation.value.err, signature };
}
return { confirmed: !confirmation.value.err, signature };
}
}

View File

@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@ -1,9 +1,9 @@
import { BlockhashWithExpiryBlockHeight, Keypair, VersionedTransaction } from '@solana/web3.js';
import { BlockhashWithExpiryBlockHeight, Keypair, VersionedTransaction } from "@solana/web3.js";
export interface TransactionExecutor {
executeAndConfirm(
transaction: VersionedTransaction,
payer: Keypair,
latestBlockHash: BlockhashWithExpiryBlockHeight,
): Promise<{ confirmed: boolean; signature?: string, error?: string }>;
executeAndConfirm(
transaction: VersionedTransaction,
payer: Keypair,
latestBlockHash: BlockhashWithExpiryBlockHeight,
): Promise<{ confirmed: boolean; signature?: string; error?: string }>;
}

View File

@ -0,0 +1,85 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WarpTransactionExecutor = void 0;
const web3_js_1 = require("@solana/web3.js");
const helpers_1 = require("../helpers");
const axios_1 = __importStar(require("axios"));
const bs58_1 = __importDefault(require("bs58"));
const raydium_sdk_1 = require("@raydium-io/raydium-sdk");
class WarpTransactionExecutor {
constructor(warpFee) {
this.warpFee = warpFee;
this.warpFeeWallet = new web3_js_1.PublicKey("WARPzUMPnycu9eeCZ95rcAUxorqpBqHndfV3ZP5FSyS");
}
executeAndConfirm(transaction, payer, latestBlockhash) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
helpers_1.logger.debug("Executing transaction...");
try {
const fee = new raydium_sdk_1.CurrencyAmount(raydium_sdk_1.Currency.SOL, this.warpFee, false).raw.toNumber();
const warpFeeMessage = new web3_js_1.TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: latestBlockhash.blockhash,
instructions: [
web3_js_1.SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: this.warpFeeWallet,
lamports: fee,
}),
],
}).compileToV0Message();
const warpFeeTx = new web3_js_1.VersionedTransaction(warpFeeMessage);
warpFeeTx.sign([payer]);
const response = yield axios_1.default.post("https://tx.warp.id/transaction/execute", {
transactions: [bs58_1.default.encode(warpFeeTx.serialize()), bs58_1.default.encode(transaction.serialize())],
latestBlockhash,
}, {
timeout: 100000,
});
return response.data;
}
catch (error) {
if (error instanceof axios_1.AxiosError) {
helpers_1.logger.trace({ error: (_a = error.response) === null || _a === void 0 ? void 0 : _a.data }, "Failed to execute warp transaction");
}
}
return { confirmed: false };
});
}
}
exports.WarpTransactionExecutor = WarpTransactionExecutor;

View File

@ -1,64 +1,64 @@
import {
BlockhashWithExpiryBlockHeight,
Keypair,
PublicKey,
SystemProgram,
TransactionMessage,
VersionedTransaction,
} from '@solana/web3.js';
import { TransactionExecutor } from './transaction-executor.interface';
import { logger } from '../helpers';
import axios, { AxiosError } from 'axios';
import bs58 from 'bs58';
import { Currency, CurrencyAmount } from '@raydium-io/raydium-sdk';
BlockhashWithExpiryBlockHeight,
Keypair,
PublicKey,
SystemProgram,
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
import { TransactionExecutor } from "./transaction-executor.interface";
import { logger } from "../helpers";
import axios, { AxiosError } from "axios";
import bs58 from "bs58";
import { Currency, CurrencyAmount } from "@raydium-io/raydium-sdk";
export class WarpTransactionExecutor implements TransactionExecutor {
private readonly warpFeeWallet = new PublicKey('WARPzUMPnycu9eeCZ95rcAUxorqpBqHndfV3ZP5FSyS');
private readonly warpFeeWallet = new PublicKey("WARPzUMPnycu9eeCZ95rcAUxorqpBqHndfV3ZP5FSyS");
constructor(private readonly warpFee: string) {}
constructor(private readonly warpFee: string) {}
public async executeAndConfirm(
transaction: VersionedTransaction,
payer: Keypair,
latestBlockhash: BlockhashWithExpiryBlockHeight,
): Promise<{ confirmed: boolean; signature?: string; error?: string }> {
logger.debug('Executing transaction...');
public async executeAndConfirm(
transaction: VersionedTransaction,
payer: Keypair,
latestBlockhash: BlockhashWithExpiryBlockHeight,
): Promise<{ confirmed: boolean; signature?: string; error?: string }> {
logger.debug("Executing transaction...");
try {
const fee = new CurrencyAmount(Currency.SOL, this.warpFee, false).raw.toNumber();
const warpFeeMessage = new TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: latestBlockhash.blockhash,
instructions: [
SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: this.warpFeeWallet,
lamports: fee,
}),
],
}).compileToV0Message();
try {
const fee = new CurrencyAmount(Currency.SOL, this.warpFee, false).raw.toNumber();
const warpFeeMessage = new TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: latestBlockhash.blockhash,
instructions: [
SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: this.warpFeeWallet,
lamports: fee,
}),
],
}).compileToV0Message();
const warpFeeTx = new VersionedTransaction(warpFeeMessage);
warpFeeTx.sign([payer]);
const warpFeeTx = new VersionedTransaction(warpFeeMessage);
warpFeeTx.sign([payer]);
const response = await axios.post<{ confirmed: boolean; signature: string; error?: string }>(
'https://tx.warp.id/transaction/execute',
{
transactions: [bs58.encode(warpFeeTx.serialize()), bs58.encode(transaction.serialize())],
latestBlockhash,
},
{
timeout: 100000,
},
);
const response = await axios.post<{ confirmed: boolean; signature: string; error?: string }>(
"https://tx.warp.id/transaction/execute",
{
transactions: [bs58.encode(warpFeeTx.serialize()), bs58.encode(transaction.serialize())],
latestBlockhash,
},
{
timeout: 100000,
},
);
return response.data;
} catch (error) {
if (error instanceof AxiosError) {
logger.trace({ error: error.response?.data }, 'Failed to execute warp transaction');
}
}
return response.data;
} catch (error) {
if (error instanceof AxiosError) {
logger.trace({ error: error.response?.data }, "Failed to execute warp transaction");
}
}
return { confirmed: false };
}
return { confirmed: false };
}
}