From 643002ae8a45e1f424afcf7a09cf9cbedebc6c50 Mon Sep 17 00:00:00 2001 From: Filip Dunder Date: Mon, 15 Apr 2024 15:27:22 +0200 Subject: [PATCH 1/5] feat: complete rewrite --- .env.copy | 44 +- bot.ts | 393 +++ buy.ts | 555 ---- cache/index.ts | 3 + cache/market.cache.ts | 58 + cache/pool.cache.ts | 20 + cache/snipe-list.cache.ts | 34 + constants/constants.ts | 20 - constants/index.ts | 1 - filters/burn.filter.ts | 24 + filters/index.ts | 4 + filters/pool-filters.ts | 61 + filters/pool-size.filter.ts | 36 + filters/renounced.filter.ts | 26 + helpers/constants.ts | 57 + helpers/index.ts | 7 + {liquidity => helpers}/liquidity.ts | 55 +- {utils => helpers}/logger.ts | 2 +- {market => helpers}/market.ts | 7 +- helpers/promises.ts | 1 + helpers/token.ts | 23 + helpers/wallet.ts | 21 + index.ts | 192 ++ liquidity/index.ts | 1 - listeners/index.ts | 1 + listeners/listeners.ts | 112 + market/index.ts | 1 - package-lock.json | 2727 +++++++++++++++++ package.json | 10 +- transactions/default-transaction-executor.ts | 37 + transactions/index.ts | 2 + .../transaction-executor.interface.ts | 8 + types/index.ts | 1 - types/mint.ts | 44 - utils/index.ts | 2 - utils/utils.ts | 13 - 36 files changed, 3898 insertions(+), 705 deletions(-) create mode 100644 bot.ts delete mode 100644 buy.ts create mode 100644 cache/index.ts create mode 100644 cache/market.cache.ts create mode 100644 cache/pool.cache.ts create mode 100644 cache/snipe-list.cache.ts delete mode 100644 constants/constants.ts delete mode 100644 constants/index.ts create mode 100644 filters/burn.filter.ts create mode 100644 filters/index.ts create mode 100644 filters/pool-filters.ts create mode 100644 filters/pool-size.filter.ts create mode 100644 filters/renounced.filter.ts create mode 100644 helpers/constants.ts create mode 100644 helpers/index.ts rename {liquidity => helpers}/liquidity.ts (50%) rename {utils => helpers}/logger.ts (90%) rename {market => helpers}/market.ts (64%) create mode 100644 helpers/promises.ts create mode 100644 helpers/token.ts create mode 100644 helpers/wallet.ts create mode 100644 index.ts delete mode 100644 liquidity/index.ts create mode 100644 listeners/index.ts create mode 100644 listeners/listeners.ts delete mode 100644 market/index.ts create mode 100644 transactions/default-transaction-executor.ts create mode 100644 transactions/index.ts create mode 100644 transactions/transaction-executor.interface.ts delete mode 100644 types/index.ts delete mode 100644 types/mint.ts delete mode 100644 utils/index.ts delete mode 100644 utils/utils.ts diff --git a/.env.copy b/.env.copy index 0c298e3..c4be1c4 100644 --- a/.env.copy +++ b/.env.copy @@ -1,16 +1,40 @@ +# Wallet PRIVATE_KEY= + +# Connection RPC_ENDPOINT=https://api.mainnet-beta.solana.com RPC_WEBSOCKET_ENDPOINT=wss://api.mainnet-beta.solana.com +COMMITMENT_LEVEL=confirmed + +# Bot +LOG_LEVEL=debug +ONE_TOKEN_AT_A_TIME=true +COMPUTE_UNIT_LIMIT=421197 +COMPUTE_UNIT_PRICE=101337 +PRE_LOAD_EXISTING_MARKETS=false +CACHE_NEW_MARKETS=false + +# Buy QUOTE_MINT=WSOL -QUOTE_AMOUNT=0.01 -COMMITMENT_LEVEL=finalized +QUOTE_AMOUNT=0.001 +AUTO_BUY_DELAY=0 +MAX_BUY_RETRIES=10 +BUY_SLIPPAGE=5 + +# Sell +AUTO_SELL=true +MAX_SELL_RETRIES=10 +AUTO_SELL_DELAY=0 +PRICE_CHECK_INTERVAL=2000 +PRICE_CHECK_DURATION=60000 +TAKE_PROFIT=25 +STOP_LOSS=15 +SELL_SLIPPAGE=5 + +# Filters USE_SNIPE_LIST=false SNIPE_LIST_REFRESH_INTERVAL=30000 -CHECK_IF_MINT_IS_RENOUNCED=false -AUTO_SELL=true -MAX_SELL_RETRIES=5 -AUTO_SELL_DELAY=1000 -LOG_LEVEL=info -MIN_POOL_SIZE=10 -MAX_POOL_SIZE=50 -ONE_TOKEN_AT_A_TIME=true +CHECK_IF_MINT_IS_RENOUNCED=true +CHECK_IF_BURNED=false +MIN_POOL_SIZE=5 +MAX_POOL_SIZE=50 \ No newline at end of file diff --git a/bot.ts b/bot.ts new file mode 100644 index 0000000..fa2c5d8 --- /dev/null +++ b/bot.ts @@ -0,0 +1,393 @@ +import { + ComputeBudgetProgram, + Connection, + Keypair, + PublicKey, + TransactionMessage, + VersionedTransaction, +} from '@solana/web3.js'; +import { + createAssociatedTokenAccountIdempotentInstruction, + createCloseAccountInstruction, + getAccount, + getAssociatedTokenAddress, + RawAccount, + TOKEN_PROGRAM_ID, +} from '@solana/spl-token'; +import { + Liquidity, + LiquidityPoolKeysV4, + LiquidityStateV4, + Percent, + Token, + TokenAmount, +} from '@raydium-io/raydium-sdk'; +import { MarketCache, PoolCache, SnipeListCache } from './cache'; +import { PoolFilters } from './filters'; +import { TransactionExecutor } from './transactions'; +import { createPoolKeys, logger, NETWORK, sleep } from './helpers'; +import { Mutex } from 'async-mutex'; +import BN from 'bn.js'; + +export interface BotConfig { + wallet: Keypair; + checkRenounced: boolean; + checkBurned: boolean; + minPoolSize: TokenAmount; + maxPoolSize: TokenAmount; + quoteToken: Token; + quoteAmount: TokenAmount; + quoteAta: PublicKey; + oneTokenAtATime: boolean; + useSnipeList: boolean; + autoSell: boolean; + autoBuyDelay: number; + autoSellDelay: number; + maxBuyRetries: number; + maxSellRetries: number; + unitLimit: number; + unitPrice: number; + takeProfit: number; + stopLoss: number; + buySlippage: number; + sellSlippage: number; + priceCheckInterval: number; + priceCheckDuration: number; +} + +export class Bot { + private readonly poolFilters: PoolFilters; + + // snipe list + private readonly snipeListCache?: SnipeListCache; + + // one token at the time + private readonly mutex: Mutex; + private sellExecutionCount = 0; + + constructor( + private readonly connection: Connection, + private readonly marketStorage: MarketCache, + private readonly poolStorage: PoolCache, + private readonly txExecutor: TransactionExecutor, + private readonly config: BotConfig, + ) { + this.mutex = new Mutex(); + this.poolFilters = new PoolFilters(connection, { + quoteToken: this.config.quoteToken, + minPoolSize: this.config.minPoolSize, + maxPoolSize: this.config.maxPoolSize, + }); + + if (this.config.useSnipeList) { + this.snipeListCache = new SnipeListCache(); + this.snipeListCache.init(); + } + } + + async validate() { + try { + await getAccount(this.connection, this.config.quoteAta, this.connection.commitment); + } catch (error) { + logger.error( + `${this.config.quoteToken.symbol} token account not found in wallet: ${this.config.wallet.publicKey.toString()}`, + ); + return false; + } + + return true; + } + + public async buy(accountId: PublicKey, poolState: LiquidityStateV4) { + logger.trace({ mint: poolState.baseMint }, `Processing buy...`); + + if (this.config.useSnipeList && !this.snipeListCache?.isInList(poolState.baseMint.toString())) { + logger.debug({ mint: poolState.baseMint.toString() }, `Skipping buy because token is not in a snipe list`); + return; + } + + if (this.config.autoBuyDelay > 0) { + logger.debug({ mint: poolState.baseMint }, `Waiting for ${this.config.autoBuyDelay} ms before buy`); + await sleep(this.config.autoBuyDelay); + } + + if (this.config.oneTokenAtATime) { + if (this.mutex.isLocked() || this.sellExecutionCount > 0) { + logger.debug( + { mint: poolState.baseMint.toString() }, + `Skipping buy because one token at a time is turned on and token is already being processed`, + ); + return; + } + + await this.mutex.acquire(); + } + + try { + const shouldBuy = await this.poolFilters.execute(poolState); + + if (!shouldBuy) { + logger.debug({ mint: poolState.baseMint.toString() }, `Skipping buy because pool doesn't match filters`); + return; + } + + for (let i = 0; i < this.config.maxBuyRetries; i++) { + try { + const [market, mintAta] = await Promise.all([ + this.marketStorage.get(poolState.marketId.toString()), + getAssociatedTokenAddress(poolState.baseMint, this.config.wallet.publicKey), + ]); + const poolKeys: LiquidityPoolKeysV4 = createPoolKeys(accountId, poolState, market); + + logger.info( + { mint: poolState.baseMint.toString() }, + `Send buy transaction attempt: ${i + 1}/${this.config.maxBuyRetries}`, + ); + const tokenOut = new Token(TOKEN_PROGRAM_ID, poolKeys.baseMint, poolKeys.baseDecimals); + const result = await this.swap( + poolKeys, + this.config.quoteAta, + mintAta, + this.config.quoteToken, + tokenOut, + this.config.quoteAmount, + this.config.buySlippage, + this.config.wallet, + 'buy', + ); + + if (result.confirmed) { + logger.info( + { + mint: poolState.baseMint.toString(), + signature: result.signature, + url: `https://solscan.io/tx/${result.signature}?cluster=${NETWORK}`, + }, + `Confirmed buy tx`, + ); + + break; + } + + logger.debug( + { + mint: poolState.baseMint.toString(), + signature: result.signature, + }, + `Error confirming buy tx`, + ); + } catch (error) { + logger.debug({ mint: poolState.baseMint.toString(), error }, `Error confirming buy transaction`); + } + } + } catch (error) { + logger.error({ mint: poolState.baseMint.toString(), error }, `Failed to buy token`); + } finally { + if (this.config.oneTokenAtATime) { + this.mutex.release(); + } + } + } + + public async sell(accountId: PublicKey, rawAccount: RawAccount) { + if (this.config.oneTokenAtATime) { + this.sellExecutionCount++; + } + + try { + logger.trace({ mint: rawAccount.mint }, `Processing sell...`); + + const poolData = await this.poolStorage.get(rawAccount.mint.toString()); + + if (!poolData) { + logger.trace({ mint: rawAccount.mint.toString() }, `Token pool data is not found, can't sell`); + return; + } + + const tokenIn = new Token(TOKEN_PROGRAM_ID, poolData.state.baseMint, poolData.state.baseDecimal.toNumber()); + const tokenAmountIn = new TokenAmount(tokenIn, rawAccount.amount, true); + + if (tokenAmountIn.isZero()) { + logger.info({ mint: rawAccount.mint.toString() }, `Empty balance, can't sell`); + return; + } + + if (this.config.autoSellDelay > 0) { + logger.debug({ mint: rawAccount.mint }, `Waiting for ${this.config.autoSellDelay} ms before sell`); + await sleep(this.config.autoSellDelay); + } + + for (let i = 0; i < this.config.maxSellRetries; i++) { + try { + const market = await this.marketStorage.get(poolData.state.marketId.toString()); + const poolKeys: LiquidityPoolKeysV4 = createPoolKeys(new PublicKey(poolData.id), poolData.state, market); + + await this.priceMatch(tokenAmountIn, poolKeys); + + logger.info( + { mint: rawAccount.mint }, + `Send sell transaction attempt: ${i + 1}/${this.config.maxSellRetries}`, + ); + + const result = await this.swap( + poolKeys, + accountId, + this.config.quoteAta, + tokenIn, + this.config.quoteToken, + tokenAmountIn, + this.config.sellSlippage, + this.config.wallet, + 'sell', + ); + + if (result.confirmed) { + 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=${NETWORK}`, + }, + `Confirmed sell tx`, + ); + break; + } + + logger.info( + { + mint: rawAccount.mint.toString(), + signature: result.signature, + }, + `Error confirming sell tx`, + ); + } catch (error) { + logger.debug({ mint: rawAccount.mint.toString(), error }, `Error confirming sell transaction`); + } + } + } catch (error) { + logger.debug({ mint: rawAccount.mint.toString(), error }, `Failed to sell token`); + } finally { + if (this.config.oneTokenAtATime) { + this.sellExecutionCount--; + } + } + } + + private async swap( + poolKeys: LiquidityPoolKeysV4, + ataIn: PublicKey, + ataOut: PublicKey, + tokenIn: Token, + tokenOut: Token, + amountIn: TokenAmount, + slippage: number, + wallet: Keypair, + direction: 'buy' | 'sell', + ) { + const slippagePercent = new Percent(slippage, 100); + const poolInfo = await Liquidity.fetchInfo({ + connection: this.connection, + poolKeys, + }); + + const computedAmountOut = Liquidity.computeAmountOut({ + poolKeys, + poolInfo, + amountIn, + currencyOut: tokenOut, + slippage: slippagePercent, + }); + + const latestBlockhash = await this.connection.getLatestBlockhash(); + const { innerTransaction } = Liquidity.makeSwapFixedInInstruction( + { + poolKeys: poolKeys, + userKeys: { + tokenAccountIn: ataIn, + tokenAccountOut: ataOut, + owner: wallet.publicKey, + }, + amountIn: amountIn.raw, + minAmountOut: computedAmountOut.minAmountOut.raw, + }, + poolKeys.version, + ); + + const messageV0 = new TransactionMessage({ + payerKey: wallet.publicKey, + recentBlockhash: latestBlockhash.blockhash, + instructions: [ + ComputeBudgetProgram.setComputeUnitPrice({ microLamports: this.config.unitPrice }), + ComputeBudgetProgram.setComputeUnitLimit({ units: this.config.unitLimit }), + ...(direction === 'buy' + ? [ + createAssociatedTokenAccountIdempotentInstruction( + wallet.publicKey, + ataOut, + wallet.publicKey, + tokenOut.mint, + ), + ] + : []), + ...innerTransaction.instructions, + ...(direction === 'sell' ? [createCloseAccountInstruction(ataIn, wallet.publicKey, wallet.publicKey)] : []), + ], + }).compileToV0Message(); + + const transaction = new VersionedTransaction(messageV0); + transaction.sign([wallet, ...innerTransaction.signers]); + + return this.txExecutor.executeAndConfirm(transaction, latestBlockhash); + } + + private async priceMatch(amountIn: TokenAmount, poolKeys: LiquidityPoolKeysV4) { + const profitFraction = this.config.quoteAmount.mul(this.config.takeProfit).numerator.div(new BN(100)); + const profitAmount = new TokenAmount(this.config.quoteToken, profitFraction, true); + const takeProfit = this.config.quoteAmount.add(profitAmount); + + const lossFraction = this.config.quoteAmount.mul(this.config.stopLoss).numerator.div(new BN(100)); + const lossAmount = new TokenAmount(this.config.quoteToken, lossFraction, true); + const stopLoss = this.config.quoteAmount.subtract(lossAmount); + const slippage = new Percent(this.config.sellSlippage, 100); + + const timesToCheck = this.config.priceCheckDuration / this.config.priceCheckInterval; + let timesChecked = 0; + + do { + try { + const poolInfo = await Liquidity.fetchInfo({ + connection: this.connection, + poolKeys, + }); + + const amountOut = Liquidity.computeAmountOut({ + poolKeys, + poolInfo, + amountIn: amountIn, + currencyOut: this.config.quoteToken, + slippage, + }).amountOut; + + logger.debug( + { mint: poolKeys.baseMint.toString() }, + `Take profit: ${takeProfit.toFixed()} | Stop loss: ${stopLoss.toFixed()} | Current: ${amountOut.toFixed()}`, + ); + + if (amountOut.lt(stopLoss)){ + break; + } + + if (amountOut.gt(takeProfit)){ + break; + } + + await sleep(this.config.priceCheckInterval); + } catch (e) { + logger.trace({ mint: poolKeys.baseMint.toString(), e }, `Failed to check token price`); + } finally { + timesChecked++; + } + } while (timesChecked < timesToCheck); + } +} diff --git a/buy.ts b/buy.ts deleted file mode 100644 index 071701f..0000000 --- a/buy.ts +++ /dev/null @@ -1,555 +0,0 @@ -import { - BigNumberish, - Liquidity, - LIQUIDITY_STATE_LAYOUT_V4, - LiquidityPoolKeys, - LiquidityStateV4, - MARKET_STATE_LAYOUT_V3, - MarketStateV3, - Token, - TokenAmount, -} from '@raydium-io/raydium-sdk'; -import { - AccountLayout, - createAssociatedTokenAccountIdempotentInstruction, - createCloseAccountInstruction, - getAssociatedTokenAddressSync, - TOKEN_PROGRAM_ID, -} from '@solana/spl-token'; -import { - Keypair, - Connection, - PublicKey, - ComputeBudgetProgram, - KeyedAccountInfo, - TransactionMessage, - VersionedTransaction, -} from '@solana/web3.js'; -import { getTokenAccounts, RAYDIUM_LIQUIDITY_PROGRAM_ID_V4, OPENBOOK_PROGRAM_ID, createPoolKeys } from './liquidity'; -import { logger } from './utils'; -import { getMinimalMarketV3, MinimalMarketLayoutV3 } from './market'; -import { MintLayout } from './types'; -import bs58 from 'bs58'; -import * as fs from 'fs'; -import * as path from 'path'; -import { - AUTO_SELL, - AUTO_SELL_DELAY, - CHECK_IF_MINT_IS_RENOUNCED, - COMMITMENT_LEVEL, - LOG_LEVEL, - MAX_SELL_RETRIES, - NETWORK, - PRIVATE_KEY, - QUOTE_AMOUNT, - QUOTE_MINT, - RPC_ENDPOINT, - RPC_WEBSOCKET_ENDPOINT, - SNIPE_LIST_REFRESH_INTERVAL, - USE_SNIPE_LIST, - MIN_POOL_SIZE, - MAX_POOL_SIZE, - ONE_TOKEN_AT_A_TIME, -} from './constants'; - -const solanaConnection = new Connection(RPC_ENDPOINT, { - wsEndpoint: RPC_WEBSOCKET_ENDPOINT, -}); - -export interface MinimalTokenAccountData { - mint: PublicKey; - address: PublicKey; - poolKeys?: LiquidityPoolKeys; - market?: MinimalMarketLayoutV3; -} - -const existingLiquidityPools: Set = new Set(); -const existingOpenBookMarkets: Set = new Set(); -const existingTokenAccounts: Map = new Map(); - -let wallet: Keypair; -let quoteToken: Token; -let quoteTokenAssociatedAddress: PublicKey; -let quoteAmount: TokenAmount; -let quoteMinPoolSizeAmount: TokenAmount; -let quoteMaxPoolSizeAmount: TokenAmount; -let processingToken: Boolean = false; - - - -let snipeList: string[] = []; - -async function init(): Promise { - logger.level = LOG_LEVEL; - - // get wallet - wallet = Keypair.fromSecretKey(bs58.decode(PRIVATE_KEY)); - logger.info(`Wallet Address: ${wallet.publicKey}`); - - // get quote mint and amount - switch (QUOTE_MINT) { - case 'WSOL': { - quoteToken = Token.WSOL; - quoteAmount = new TokenAmount(Token.WSOL, QUOTE_AMOUNT, false); - quoteMinPoolSizeAmount = new TokenAmount(quoteToken, MIN_POOL_SIZE, false); - quoteMaxPoolSizeAmount = new TokenAmount(quoteToken, MAX_POOL_SIZE, false); - break; - } - case 'USDC': { - quoteToken = new Token( - TOKEN_PROGRAM_ID, - new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'), - 6, - 'USDC', - 'USDC', - ); - quoteAmount = new TokenAmount(quoteToken, QUOTE_AMOUNT, false); - quoteMinPoolSizeAmount = new TokenAmount(quoteToken, MIN_POOL_SIZE, false); - quoteMaxPoolSizeAmount = new TokenAmount(quoteToken, MAX_POOL_SIZE, false); - break; - } - default: { - throw new Error(`Unsupported quote mint "${QUOTE_MINT}". Supported values are USDC and WSOL`); - } - } - - logger.info(`Snipe list: ${USE_SNIPE_LIST}`); - logger.info(`Check mint renounced: ${CHECK_IF_MINT_IS_RENOUNCED}`); - logger.info( - `Min pool size: ${quoteMinPoolSizeAmount.isZero() ? 'false' : quoteMinPoolSizeAmount.toFixed()} ${quoteToken.symbol}`, - ); - logger.info( - `Max pool size: ${quoteMaxPoolSizeAmount.isZero() ? 'false' : quoteMaxPoolSizeAmount.toFixed()} ${quoteToken.symbol}`, - ); - logger.info(`One token at a time: ${ONE_TOKEN_AT_A_TIME}`); - logger.info(`Buy amount: ${quoteAmount.toFixed()} ${quoteToken.symbol}`); - logger.info(`Auto sell: ${AUTO_SELL}`); - logger.info(`Sell delay: ${AUTO_SELL_DELAY === 0 ? 'false' : AUTO_SELL_DELAY}`); - - // check existing wallet for associated token account of quote mint - const tokenAccounts = await getTokenAccounts(solanaConnection, wallet.publicKey, COMMITMENT_LEVEL); - - for (const ta of tokenAccounts) { - existingTokenAccounts.set(ta.accountInfo.mint.toString(), { - mint: ta.accountInfo.mint, - address: ta.pubkey, - }); - } - - const tokenAccount = tokenAccounts.find((acc) => acc.accountInfo.mint.toString() === quoteToken.mint.toString())!; - - if (!tokenAccount) { - throw new Error(`No ${quoteToken.symbol} token account found in wallet: ${wallet.publicKey}`); - } - - quoteTokenAssociatedAddress = tokenAccount.pubkey; - - // load tokens to snipe - loadSnipeList(); -} - -function saveTokenAccount(mint: PublicKey, accountData: MinimalMarketLayoutV3) { - const ata = getAssociatedTokenAddressSync(mint, wallet.publicKey); - const tokenAccount = { - address: ata, - mint: mint, - market: { - bids: accountData.bids, - asks: accountData.asks, - eventQueue: accountData.eventQueue, - }, - }; - existingTokenAccounts.set(mint.toString(), tokenAccount); - return tokenAccount; -} - -export async function processRaydiumPool(id: PublicKey, poolState: LiquidityStateV4) { - if (!shouldBuy(poolState.baseMint.toString())) { - return; - } - - if (!quoteMinPoolSizeAmount.isZero()) { - const poolSize = new TokenAmount(quoteToken, poolState.swapQuoteInAmount, true); - logger.info(`Processing pool: ${id.toString()} with ${poolSize.toFixed()} ${quoteToken.symbol} in liquidity`); - - if (poolSize.lt(quoteMinPoolSizeAmount)) { - logger.warn( - { - mint: poolState.baseMint, - pooled: `${poolSize.toFixed()} ${quoteToken.symbol}`, - }, - `Skipping pool, smaller than ${quoteMinPoolSizeAmount.toFixed()} ${quoteToken.symbol}`, - `Swap quote in amount: ${poolSize.toFixed()}`, - ); - logger.info(`-------------------🤖🔧------------------- \n`); - return; - } - } - - if (!quoteMaxPoolSizeAmount.isZero()) { - const poolSize = new TokenAmount(quoteToken, poolState.swapQuoteInAmount, true); - - if (poolSize.gt(quoteMaxPoolSizeAmount)) { - logger.warn( - { - mint: poolState.baseMint, - pooled: `${poolSize.toFixed()} ${quoteToken.symbol}`, - }, - `Skipping pool, bigger than ${quoteMaxPoolSizeAmount.toFixed()} ${quoteToken.symbol}`, - `Swap quote in amount: ${poolSize.toFixed()}`, - ); - logger.info(`-------------------🤖🔧------------------- \n`); - return; - } - } - - if (CHECK_IF_MINT_IS_RENOUNCED) { - const mintOption = await checkMintable(poolState.baseMint); - - if (mintOption !== true) { - logger.warn({ mint: poolState.baseMint }, 'Skipping, owner can mint tokens!'); - return; - } - } - - await buy(id, poolState); -} - -export async function checkMintable(vault: PublicKey): Promise { - try { - let { data } = (await solanaConnection.getAccountInfo(vault)) || {}; - if (!data) { - return; - } - const deserialize = MintLayout.decode(data); - return deserialize.mintAuthorityOption === 0; - } catch (e) { - logger.debug(e); - logger.error({ mint: vault }, `Failed to check if mint is renounced`); - } -} - -export async function processOpenBookMarket(updatedAccountInfo: KeyedAccountInfo) { - let accountData: MarketStateV3 | undefined; - try { - accountData = MARKET_STATE_LAYOUT_V3.decode(updatedAccountInfo.accountInfo.data); - - // to be competitive, we collect market data before buying the token... - if (existingTokenAccounts.has(accountData.baseMint.toString())) { - return; - } - - saveTokenAccount(accountData.baseMint, accountData); - } catch (e) { - logger.debug(e); - logger.error({ mint: accountData?.baseMint }, `Failed to process market`); - } -} - -async function buy(accountId: PublicKey, accountData: LiquidityStateV4): Promise { - try { - let tokenAccount = existingTokenAccounts.get(accountData.baseMint.toString()); - - if (!tokenAccount) { - // it's possible that we didn't have time to fetch open book data - const market = await getMinimalMarketV3(solanaConnection, accountData.marketId, COMMITMENT_LEVEL); - tokenAccount = saveTokenAccount(accountData.baseMint, market); - } - - tokenAccount.poolKeys = createPoolKeys(accountId, accountData, tokenAccount.market!); - const { innerTransaction } = Liquidity.makeSwapFixedInInstruction( - { - poolKeys: tokenAccount.poolKeys, - userKeys: { - tokenAccountIn: quoteTokenAssociatedAddress, - tokenAccountOut: tokenAccount.address, - owner: wallet.publicKey, - }, - amountIn: quoteAmount.raw, - minAmountOut: 0, - }, - tokenAccount.poolKeys.version, - ); - - const latestBlockhash = await solanaConnection.getLatestBlockhash({ - commitment: COMMITMENT_LEVEL, - }); - const messageV0 = new TransactionMessage({ - payerKey: wallet.publicKey, - recentBlockhash: latestBlockhash.blockhash, - instructions: [ - ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 421197 }), - ComputeBudgetProgram.setComputeUnitLimit({ units: 101337 }), - createAssociatedTokenAccountIdempotentInstruction( - wallet.publicKey, - tokenAccount.address, - wallet.publicKey, - accountData.baseMint, - ), - ...innerTransaction.instructions, - ], - }).compileToV0Message(); - const transaction = new VersionedTransaction(messageV0); - transaction.sign([wallet, ...innerTransaction.signers]); - const signature = await solanaConnection.sendRawTransaction(transaction.serialize(), { - preflightCommitment: COMMITMENT_LEVEL, - }); - logger.info({ mint: accountData.baseMint, signature }, `Sent buy tx`); - processingToken = true; - - const confirmation = await solanaConnection.confirmTransaction( - { - signature, - lastValidBlockHeight: latestBlockhash.lastValidBlockHeight, - blockhash: latestBlockhash.blockhash, - }, - COMMITMENT_LEVEL, - ); - if (!confirmation.value.err) { - logger.info(`-------------------🟢------------------- `); - logger.info( - { - mint: accountData.baseMint, - signature, - url: `https://solscan.io/tx/${signature}?cluster=${NETWORK}`, - }, - `Confirmed buy tx`, - ); - } else { - logger.debug(confirmation.value.err); - logger.info({ mint: accountData.baseMint, signature }, `Error confirming buy tx`); - } - } catch (e) { - logger.debug(e); - processingToken = false; - logger.error({ mint: accountData.baseMint }, `Failed to buy token`); - } -} - -async function sell(accountId: PublicKey, mint: PublicKey, amount: BigNumberish): Promise { - let sold = false; - let retries = 0; - - if (AUTO_SELL_DELAY > 0) { - await new Promise((resolve) => setTimeout(resolve, AUTO_SELL_DELAY)); - } - - do { - try { - const tokenAccount = existingTokenAccounts.get(mint.toString()); - - if (!tokenAccount) { - return; - } - - if (!tokenAccount.poolKeys) { - logger.warn({ mint }, 'No pool keys found'); - return; - } - - if (amount === 0) { - logger.info( - { - mint: tokenAccount.mint, - }, - `Empty balance, can't sell`, - ); - return; - } - - const { innerTransaction } = Liquidity.makeSwapFixedInInstruction( - { - poolKeys: tokenAccount.poolKeys!, - userKeys: { - tokenAccountOut: quoteTokenAssociatedAddress, - tokenAccountIn: tokenAccount.address, - owner: wallet.publicKey, - }, - amountIn: amount, - minAmountOut: 0, - }, - tokenAccount.poolKeys!.version, - ); - - const latestBlockhash = await solanaConnection.getLatestBlockhash({ - commitment: COMMITMENT_LEVEL, - }); - const messageV0 = new TransactionMessage({ - payerKey: wallet.publicKey, - recentBlockhash: latestBlockhash.blockhash, - instructions: [ - ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 421197 }), - ComputeBudgetProgram.setComputeUnitLimit({ units: 101337 }), - ...innerTransaction.instructions, - createCloseAccountInstruction(tokenAccount.address, wallet.publicKey, wallet.publicKey), - ], - }).compileToV0Message(); - const transaction = new VersionedTransaction(messageV0); - transaction.sign([wallet, ...innerTransaction.signers]); - const signature = await solanaConnection.sendRawTransaction(transaction.serialize(), { - preflightCommitment: COMMITMENT_LEVEL, - }); - logger.info({ mint, signature }, `Sent sell tx`); - const confirmation = await solanaConnection.confirmTransaction( - { - signature, - lastValidBlockHeight: latestBlockhash.lastValidBlockHeight, - blockhash: latestBlockhash.blockhash, - }, - COMMITMENT_LEVEL, - ); - if (confirmation.value.err) { - logger.debug(confirmation.value.err); - logger.info({ mint, signature }, `Error confirming sell tx`); - continue; - } - logger.info(`-------------------🔴------------------- `); - logger.info( - { - dex: `https://dexscreener.com/solana/${mint}?maker=${wallet.publicKey}`, - mint, - signature, - url: `https://solscan.io/tx/${signature}?cluster=${NETWORK}`, - }, - `Confirmed sell tx`, - ); - sold = true; - processingToken = false; - } catch (e: any) { - // wait for a bit before retrying - await new Promise((resolve) => setTimeout(resolve, 100)); - retries++; - logger.debug(e); - logger.error({ mint }, `Failed to sell token, retry: ${retries}/${MAX_SELL_RETRIES}`); - } - } while (!sold && retries < MAX_SELL_RETRIES); - processingToken = false; -} - -function loadSnipeList() { - if (!USE_SNIPE_LIST) { - return; - } - - const count = snipeList.length; - const data = fs.readFileSync(path.join(__dirname, 'snipe-list.txt'), 'utf-8'); - snipeList = data - .split('\n') - .map((a) => a.trim()) - .filter((a) => a); - - if (snipeList.length != count) { - logger.info(`Loaded snipe list: ${snipeList.length}`); - } -} - -function shouldBuy(key: string): boolean { - logger.info(`-------------------🤖🔧------------------- `); - logger.info(`Processing token: ${processingToken}`) - return USE_SNIPE_LIST ? snipeList.includes(key) : ONE_TOKEN_AT_A_TIME ? !processingToken : true -} - -const runListener = async () => { - await init(); - const runTimestamp = Math.floor(new Date().getTime() / 1000); - const raydiumSubscriptionId = solanaConnection.onProgramAccountChange( - RAYDIUM_LIQUIDITY_PROGRAM_ID_V4, - async (updatedAccountInfo) => { - const key = updatedAccountInfo.accountId.toString(); - const poolState = LIQUIDITY_STATE_LAYOUT_V4.decode(updatedAccountInfo.accountInfo.data); - const poolOpenTime = parseInt(poolState.poolOpenTime.toString()); - const existing = existingLiquidityPools.has(key); - - if (poolOpenTime > runTimestamp && !existing) { - existingLiquidityPools.add(key); - const _ = processRaydiumPool(updatedAccountInfo.accountId, poolState); - } - }, - COMMITMENT_LEVEL, - [ - { dataSize: LIQUIDITY_STATE_LAYOUT_V4.span }, - { - memcmp: { - offset: LIQUIDITY_STATE_LAYOUT_V4.offsetOf('quoteMint'), - bytes: quoteToken.mint.toBase58(), - }, - }, - { - memcmp: { - offset: LIQUIDITY_STATE_LAYOUT_V4.offsetOf('marketProgramId'), - bytes: OPENBOOK_PROGRAM_ID.toBase58(), - }, - }, - { - memcmp: { - offset: LIQUIDITY_STATE_LAYOUT_V4.offsetOf('status'), - bytes: bs58.encode([6, 0, 0, 0, 0, 0, 0, 0]), - }, - }, - ], - ); - - const openBookSubscriptionId = solanaConnection.onProgramAccountChange( - OPENBOOK_PROGRAM_ID, - async (updatedAccountInfo) => { - const key = updatedAccountInfo.accountId.toString(); - const existing = existingOpenBookMarkets.has(key); - if (!existing) { - existingOpenBookMarkets.add(key); - const _ = processOpenBookMarket(updatedAccountInfo); - } - }, - COMMITMENT_LEVEL, - [ - { dataSize: MARKET_STATE_LAYOUT_V3.span }, - { - memcmp: { - offset: MARKET_STATE_LAYOUT_V3.offsetOf('quoteMint'), - bytes: quoteToken.mint.toBase58(), - }, - }, - ], - ); - - if (AUTO_SELL) { - const walletSubscriptionId = solanaConnection.onProgramAccountChange( - TOKEN_PROGRAM_ID, - async (updatedAccountInfo) => { - const accountData = AccountLayout.decode(updatedAccountInfo.accountInfo!.data); - - if (updatedAccountInfo.accountId.equals(quoteTokenAssociatedAddress)) { - return; - } - - const _ = sell(updatedAccountInfo.accountId, accountData.mint, accountData.amount); - }, - COMMITMENT_LEVEL, - [ - { - dataSize: 165, - }, - { - memcmp: { - offset: 32, - bytes: wallet.publicKey.toBase58(), - }, - }, - ], - ); - - logger.info(`Listening for wallet changes: ${walletSubscriptionId}`); - } - - logger.info(`Listening for raydium changes: ${raydiumSubscriptionId}`); - logger.info(`Listening for open book changes: ${openBookSubscriptionId}`); - - logger.info('------------------- 🚀 ---------------------'); - logger.info('Bot is running! Press CTRL + C to stop it.'); - logger.info('------------------- 🚀 ---------------------'); - - if (USE_SNIPE_LIST) { - setInterval(loadSnipeList, SNIPE_LIST_REFRESH_INTERVAL); - } -}; - -runListener(); diff --git a/cache/index.ts b/cache/index.ts new file mode 100644 index 0000000..4bd079e --- /dev/null +++ b/cache/index.ts @@ -0,0 +1,3 @@ +export * from './market.cache'; +export * from './pool.cache'; +export * from './snipe-list.cache'; diff --git a/cache/market.cache.ts b/cache/market.cache.ts new file mode 100644 index 0000000..b360c46 --- /dev/null +++ b/cache/market.cache.ts @@ -0,0 +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'; + +export class MarketCache { + private readonly keys: Map = new Map(); + constructor(private readonly connection: Connection) {} + + 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(), + }, + }, + ], + }); + + 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`); + } + + 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 { + 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; + } + + private fetch(marketId: string): Promise { + return getMinimalMarketV3(this.connection, new PublicKey(marketId), this.connection.commitment); + } +} diff --git a/cache/pool.cache.ts b/cache/pool.cache.ts new file mode 100644 index 0000000..8139427 --- /dev/null +++ b/cache/pool.cache.ts @@ -0,0 +1,20 @@ +import { LiquidityStateV4 } from '@raydium-io/raydium-sdk'; +import { logger } from '../helpers'; + +export class PoolCache { + private readonly keys: Map = 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 async get(mint: string): Promise<{ id: string; state: LiquidityStateV4 }> { + return this.keys.get(mint)!; + } +} diff --git a/cache/snipe-list.cache.ts b/cache/snipe-list.cache.ts new file mode 100644 index 0000000..ea3a2b3 --- /dev/null +++ b/cache/snipe-list.cache.ts @@ -0,0 +1,34 @@ +import fs from 'fs'; +import path from 'path'; +import { logger, SNIPE_LIST_REFRESH_INTERVAL } from '../helpers'; + +export class SnipeListCache { + private snipeList: string[] = []; + + constructor() { + setInterval(this.loadSnipeList, SNIPE_LIST_REFRESH_INTERVAL); + } + + public init() { + this.loadSnipeList(); + } + + public isInList(mint: string) { + return this.snipeList.includes(mint); + } + + private loadSnipeList() { + logger.trace('Refreshing snipe list...'); + + const count = this.snipeList.length; + const data = fs.readFileSync(path.join(__dirname, 'snipe-list.txt'), '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}`); + } + } +} diff --git a/constants/constants.ts b/constants/constants.ts deleted file mode 100644 index eb97806..0000000 --- a/constants/constants.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Commitment } from "@solana/web3.js"; -import { logger, retrieveEnvVariable } from "../utils"; - -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 LOG_LEVEL = retrieveEnvVariable('LOG_LEVEL', logger); -export const CHECK_IF_MINT_IS_RENOUNCED = retrieveEnvVariable('CHECK_IF_MINT_IS_RENOUNCED', logger) === 'true'; -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 AUTO_SELL = retrieveEnvVariable('AUTO_SELL', logger) === 'true'; -export const MAX_SELL_RETRIES = Number(retrieveEnvVariable('MAX_SELL_RETRIES', logger)); -export const AUTO_SELL_DELAY = Number(retrieveEnvVariable('AUTO_SELL_DELAY', logger)); -export const PRIVATE_KEY = retrieveEnvVariable('PRIVATE_KEY', logger); -export const QUOTE_MINT = retrieveEnvVariable('QUOTE_MINT', logger); -export const QUOTE_AMOUNT = retrieveEnvVariable('QUOTE_AMOUNT', logger); -export const MIN_POOL_SIZE = retrieveEnvVariable('MIN_POOL_SIZE', logger); -export const MAX_POOL_SIZE = retrieveEnvVariable('MAX_POOL_SIZE', logger); -export const ONE_TOKEN_AT_A_TIME = retrieveEnvVariable('ONE_TOKEN_AT_A_TIME', logger) === 'true'; diff --git a/constants/index.ts b/constants/index.ts deleted file mode 100644 index e94e4b1..0000000 --- a/constants/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './constants'; \ No newline at end of file diff --git a/filters/burn.filter.ts b/filters/burn.filter.ts new file mode 100644 index 0000000..18acc5c --- /dev/null +++ b/filters/burn.filter.ts @@ -0,0 +1,24 @@ +import { Filter, FilterResult } from './pool-filters'; +import { Connection } from '@solana/web3.js'; +import { LiquidityStateV4 } from '@raydium-io/raydium-sdk'; +import { logger } from '../helpers'; + +export class BurnFilter implements Filter { + constructor(private readonly connection: Connection) {} + + async execute(poolState: LiquidityStateV4): Promise { + try { + const amount = await this.connection.getTokenSupply(poolState.lpMint, this.connection.commitment); + const burned = amount.value.uiAmount === 0; + return { ok: burned, message: burned ? undefined : "Burned -> Creator didn't burn LP" }; + } catch (e: any) { + if (e.code == -32602) { + return { ok: true }; + } + + logger.error({ mint: poolState.baseMint }, `Failed to check if LP is burned`); + } + + return { ok: false, message: 'Failed to check if LP is burned' }; + } +} diff --git a/filters/index.ts b/filters/index.ts new file mode 100644 index 0000000..d2ba963 --- /dev/null +++ b/filters/index.ts @@ -0,0 +1,4 @@ +export * from './burn.filter'; +export * from './pool-filters'; +export * from './pool-size.filter'; +export * from './renounced.filter'; diff --git a/filters/pool-filters.ts b/filters/pool-filters.ts new file mode 100644 index 0000000..3a6e91d --- /dev/null +++ b/filters/pool-filters.ts @@ -0,0 +1,61 @@ +import { Connection } from '@solana/web3.js'; +import { LiquidityStateV4, Token, TokenAmount } from '@raydium-io/raydium-sdk'; +import { BurnFilter } from './burn.filter'; +import { RenouncedFilter } from './renounced.filter'; +import { PoolSizeFilter } from './pool-size.filter'; +import { CHECK_IF_BURNED, CHECK_IF_MINT_IS_RENOUNCED, logger } from '../helpers'; + +export interface Filter { + execute(poolState: LiquidityStateV4): Promise; +} + +export interface FilterResult { + ok: boolean; + message?: string; +} + +export interface PoolFilterArgs { + minPoolSize: TokenAmount; + maxPoolSize: TokenAmount; + quoteToken: Token; +} + +export class PoolFilters { + private readonly filters: Filter[] = []; + + constructor( + readonly connection: Connection, + readonly args: PoolFilterArgs, + ) { + if (CHECK_IF_BURNED) { + this.filters.push(new BurnFilter(connection)); + } + + if (CHECK_IF_MINT_IS_RENOUNCED) { + this.filters.push(new RenouncedFilter(connection)); + } + + if (!args.minPoolSize.isZero() || !args.maxPoolSize.isZero()) { + this.filters.push(new PoolSizeFilter(connection, args.quoteToken, args.minPoolSize, args.maxPoolSize)); + } + } + + public async execute(poolState: LiquidityStateV4): Promise { + if (this.filters.length === 0) { + return true; + } + + const result = await Promise.all(this.filters.map((f) => f.execute(poolState))); + const pass = result.every((r) => r.ok); + + if (pass) { + return true; + } + + for (const filterResult of result.filter((r) => !r.ok)) { + logger.info(filterResult.message); + } + + return false; + } +} diff --git a/filters/pool-size.filter.ts b/filters/pool-size.filter.ts new file mode 100644 index 0000000..b1377c4 --- /dev/null +++ b/filters/pool-size.filter.ts @@ -0,0 +1,36 @@ +import { Filter, FilterResult } from './pool-filters'; +import { LiquidityStateV4, Token, TokenAmount } from '@raydium-io/raydium-sdk'; +import { Connection } from '@solana/web3.js'; + +export class PoolSizeFilter implements Filter { + constructor( + private readonly connection: Connection, + private readonly quoteToken: Token, + private readonly minPoolSize: TokenAmount, + private readonly maxPoolSize: TokenAmount, + ) {} + + async execute(poolState: LiquidityStateV4): Promise { + const response = await this.connection.getTokenAccountBalance(poolState.quoteVault, this.connection.commitment); + const poolSize = new TokenAmount(this.quoteToken, response.value.amount, true); + let inRange = true; + + if (!this.maxPoolSize?.isZero()) { + inRange = poolSize.lt(this.maxPoolSize); + + if (!inRange) { + return { ok: false, message: `PoolSize -> Pool size ${poolSize.toFixed()} > ${this.maxPoolSize.toFixed()}` }; + } + } + + if (!this.minPoolSize?.isZero()) { + inRange = poolSize.gt(this.minPoolSize); + + if (!inRange) { + return { ok: false, message: `PoolSize -> Pool size ${poolSize.toFixed()} < ${this.minPoolSize.toFixed()}` }; + } + } + + return { ok: inRange }; + } +} diff --git a/filters/renounced.filter.ts b/filters/renounced.filter.ts new file mode 100644 index 0000000..56ece08 --- /dev/null +++ b/filters/renounced.filter.ts @@ -0,0 +1,26 @@ +import { Filter, FilterResult } from './pool-filters'; +import { MintLayout } from '@solana/spl-token'; +import { Connection } from '@solana/web3.js'; +import { LiquidityStateV4 } from '@raydium-io/raydium-sdk'; +import { logger } from '../helpers'; + +export class RenouncedFilter implements Filter { + constructor(private readonly connection: Connection) {} + + async execute(poolState: LiquidityStateV4): Promise { + try { + const accountInfo = await this.connection.getAccountInfo(poolState.baseMint, this.connection.commitment); + if (!accountInfo?.data) { + return { ok: false, message: 'Renounced -> Failed to fetch account data' }; + } + + const deserialize = MintLayout.decode(accountInfo.data); + const renounced = deserialize.mintAuthorityOption === 0; + return { ok: renounced, message: renounced ? undefined : 'Renounced -> Creator can mint more tokens' }; + } catch (e) { + logger.error({ mint: poolState.baseMint }, `Failed to check if mint is renounced`); + } + + return { ok: false, message: 'Renounced -> Failed to check if mint is renounced' }; + } +} diff --git a/helpers/constants.ts b/helpers/constants.ts new file mode 100644 index 0000000..c860a72 --- /dev/null +++ b/helpers/constants.ts @@ -0,0 +1,57 @@ +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; +}; + +// Wallet +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); + +// Bot +export const LOG_LEVEL = retrieveEnvVariable('LOG_LEVEL', logger); +export const ONE_TOKEN_AT_A_TIME = retrieveEnvVariable('ONE_TOKEN_AT_A_TIME', logger) === 'true'; +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'; + +// 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)); + +// 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 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)); + +// Filters +export const CHECK_IF_MINT_IS_RENOUNCED = retrieveEnvVariable('CHECK_IF_MINT_IS_RENOUNCED', 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)); diff --git a/helpers/index.ts b/helpers/index.ts new file mode 100644 index 0000000..3ff8cee --- /dev/null +++ b/helpers/index.ts @@ -0,0 +1,7 @@ +export * from './market'; +export * from './liquidity'; +export * from './logger'; +export * from './constants'; +export * from './token'; +export * from './wallet'; +export * from './promises' diff --git a/liquidity/liquidity.ts b/helpers/liquidity.ts similarity index 50% rename from liquidity/liquidity.ts rename to helpers/liquidity.ts index 38667a3..971586d 100644 --- a/liquidity/liquidity.ts +++ b/helpers/liquidity.ts @@ -1,26 +1,6 @@ -import { Commitment, Connection, PublicKey } from '@solana/web3.js'; -import { - Liquidity, - LiquidityPoolKeys, - Market, - TokenAccount, - SPL_ACCOUNT_LAYOUT, - publicKey, - struct, - MAINNET_PROGRAM_ID, - LiquidityStateV4, -} from '@raydium-io/raydium-sdk'; -import { TOKEN_PROGRAM_ID } from '@solana/spl-token'; -import { MinimalMarketLayoutV3 } from '../market'; - -export const RAYDIUM_LIQUIDITY_PROGRAM_ID_V4 = MAINNET_PROGRAM_ID.AmmV4; -export const OPENBOOK_PROGRAM_ID = MAINNET_PROGRAM_ID.OPENBOOK_MARKET; - -export const MINIMAL_MARKET_STATE_LAYOUT_V3 = struct([ - publicKey('eventQueue'), - publicKey('bids'), - publicKey('asks'), -]); +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, @@ -36,9 +16,9 @@ export function createPoolKeys( quoteDecimals: accountData.quoteDecimal.toNumber(), lpDecimals: 5, version: 4, - programId: RAYDIUM_LIQUIDITY_PROGRAM_ID_V4, + programId: MAINNET_PROGRAM_ID.AmmV4, authority: Liquidity.getAssociatedAuthority({ - programId: RAYDIUM_LIQUIDITY_PROGRAM_ID_V4, + programId: MAINNET_PROGRAM_ID.AmmV4, }).publicKey, openOrders: accountData.openOrders, targetOrders: accountData.targetOrders, @@ -61,28 +41,3 @@ export function createPoolKeys( lookupTableAccount: PublicKey.default, }; } - -export async function getTokenAccounts( - connection: Connection, - owner: PublicKey, - commitment?: Commitment, -) { - const tokenResp = await connection.getTokenAccountsByOwner( - owner, - { - programId: TOKEN_PROGRAM_ID, - }, - commitment, - ); - - const accounts: TokenAccount[] = []; - for (const { pubkey, account } of tokenResp.value) { - accounts.push({ - pubkey, - programId: account.owner, - accountInfo: SPL_ACCOUNT_LAYOUT.decode(account.data), - }); - } - - return accounts; -} diff --git a/utils/logger.ts b/helpers/logger.ts similarity index 90% rename from utils/logger.ts rename to helpers/logger.ts index 393068e..53c6bf9 100644 --- a/utils/logger.ts +++ b/helpers/logger.ts @@ -1,4 +1,4 @@ -import pino from "pino"; +import pino from 'pino'; const transport = pino.transport({ target: 'pino-pretty', diff --git a/market/market.ts b/helpers/market.ts similarity index 64% rename from market/market.ts rename to helpers/market.ts index 0593e35..54734f9 100644 --- a/market/market.ts +++ b/helpers/market.ts @@ -1,10 +1,9 @@ import { Commitment, Connection, PublicKey } from '@solana/web3.js'; -import { GetStructureSchema, MARKET_STATE_LAYOUT_V3 } from '@raydium-io/raydium-sdk'; -import { MINIMAL_MARKET_STATE_LAYOUT_V3 } from '../liquidity'; +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 type MinimalMarketStateLayoutV3 = typeof MINIMAL_MARKET_STATE_LAYOUT_V3; -export type MinimalMarketLayoutV3 = - GetStructureSchema; +export type MinimalMarketLayoutV3 = GetStructureSchema; export async function getMinimalMarketV3( connection: Connection, diff --git a/helpers/promises.ts b/helpers/promises.ts new file mode 100644 index 0000000..dfdc54a --- /dev/null +++ b/helpers/promises.ts @@ -0,0 +1 @@ +export const sleep = (ms = 0) => new Promise((resolve) => setTimeout(resolve, ms)); diff --git a/helpers/token.ts b/helpers/token.ts new file mode 100644 index 0000000..0731245 --- /dev/null +++ b/helpers/token.ts @@ -0,0 +1,23 @@ +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`); + } + } +} diff --git a/helpers/wallet.ts b/helpers/wallet.ts new file mode 100644 index 0000000..3f6f7df --- /dev/null +++ b/helpers/wallet.ts @@ -0,0 +1,21 @@ +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 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)); +} diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..d4f25aa --- /dev/null +++ b/index.ts @@ -0,0 +1,192 @@ +import { MarketCache, PoolCache } from './cache'; +import { Listeners } from './listeners'; +import { Connection, KeyedAccountInfo, Keypair } from '@solana/web3.js'; +import { LIQUIDITY_STATE_LAYOUT_V4, MARKET_STATE_LAYOUT_V3, Token, TokenAmount } from '@raydium-io/raydium-sdk'; +import { AccountLayout, getAssociatedTokenAddressSync } from '@solana/spl-token'; +import { Bot, BotConfig } from './bot'; +import { DefaultTransactionExecutor } from './transactions'; +import { + getToken, + getWallet, + logger, + COMMITMENT_LEVEL, + RPC_ENDPOINT, + RPC_WEBSOCKET_ENDPOINT, + PRE_LOAD_EXISTING_MARKETS, + LOG_LEVEL, + CHECK_IF_MINT_IS_RENOUNCED, + CHECK_IF_BURNED, + QUOTE_MINT, + MAX_POOL_SIZE, + MIN_POOL_SIZE, + QUOTE_AMOUNT, + PRIVATE_KEY, + USE_SNIPE_LIST, + ONE_TOKEN_AT_A_TIME, + AUTO_SELL_DELAY, + MAX_SELL_RETRIES, + AUTO_SELL, + MAX_BUY_RETRIES, + AUTO_BUY_DELAY, + COMPUTE_UNIT_LIMIT, + COMPUTE_UNIT_PRICE, + CACHE_NEW_MARKETS, + TAKE_PROFIT, + STOP_LOSS, + BUY_SLIPPAGE, + SELL_SLIPPAGE, + PRICE_CHECK_DURATION, + PRICE_CHECK_INTERVAL, SNIPE_LIST_REFRESH_INTERVAL, +} from './helpers'; +import { version } from './package.json'; + +const connection = new Connection(RPC_ENDPOINT, { + wsEndpoint: RPC_WEBSOCKET_ENDPOINT, + commitment: COMMITMENT_LEVEL, +}); + +function printDetails(wallet: Keypair, quoteToken: Token, botConfig: BotConfig) { + logger.info(` + .. :-===++++- + .-==+++++++- =+++++++++- + ..:::--===+=.=: .+++++++++++:=+++++++++: + .==+++++++++++++++=:+++: .+++++++++++.=++++++++-. + .-+++++++++++++++=:=++++- .+++++++++=:.=+++++-::-. + -:+++++++++++++=:+++++++- .++++++++-:- =+++++=-: + -:++++++=++++=:++++=++++= .++++++++++- =+++++: + -:++++-:=++=:++++=:-+++++:+++++====--:::::::. + ::=+-:::==:=+++=::-:--::::::::::---------::. + ::-: .::::::::. --------:::.. + :- .:.-:::. + + WARP DRIVE ACTIVATED 🚀🐟 + Made with ❤️ by humans. + Version: ${version} + `); + + logger.info('------- CONFIGURATION START -------'); + logger.info(`Wallet: ${wallet.publicKey.toString()}`); + + logger.info('- Bot -'); + logger.info(`Compute Unit limit: ${botConfig.unitLimit}`); + logger.info(`Compute Unit price (micro lamports): ${botConfig.unitPrice}`); + logger.info(`Single token at the time: ${botConfig.oneTokenAtATime}`); + logger.info(`Pre load existing markets: ${PRE_LOAD_EXISTING_MARKETS}`); + logger.info(`Cache new markets: ${CACHE_NEW_MARKETS}`); + logger.info(`Log level: ${LOG_LEVEL}`); + + logger.info('- Buy -'); + logger.info(`Buy amount: ${botConfig.quoteAmount.toFixed()} ${botConfig.quoteToken.name}`); + logger.info(`Auto buy delay: ${botConfig.autoBuyDelay} ms`); + logger.info(`Max buy retries: ${botConfig.maxBuyRetries}`); + logger.info(`Buy amount (${quoteToken.symbol}): ${botConfig.quoteAmount.toFixed()}`); + logger.info(`Buy slippage: ${botConfig.buySlippage}%`); + + logger.info('- Sell -'); + logger.info(`Auto sell: ${AUTO_SELL}`); + logger.info(`Auto sell delay: ${botConfig.autoSellDelay} ms`); + logger.info(`Max sell retries: ${botConfig.maxSellRetries}`); + logger.info(`Sell slippage: ${botConfig.sellSlippage}%`); + logger.info(`Price check interval: ${botConfig.priceCheckInterval} ms`); + logger.info(`Price check duration: ${botConfig.priceCheckDuration} ms`); + logger.info(`Take profit: ${botConfig.takeProfit}%`); + logger.info(`Stop loss: ${botConfig.stopLoss}%`); + + logger.info('- Filters -'); + logger.info(`Snipe list: ${botConfig.useSnipeList}`); + logger.info(`Snipe list refresh interval: ${SNIPE_LIST_REFRESH_INTERVAL} ms`); + logger.info(`Check renounced: ${botConfig.checkRenounced}`); + logger.info(`Check burned: ${botConfig.checkBurned}`); + logger.info(`Min pool size: ${botConfig.minPoolSize.toFixed()}`); + logger.info(`Max pool size: ${botConfig.maxPoolSize.toFixed()}`); + + logger.info('------- CONFIGURATION END -------'); + + logger.info('Bot is running! Press CTRL + C to stop it.'); +} + +const runListener = async () => { + logger.level = LOG_LEVEL; + logger.info('Bot is starting...'); + + const marketCache = new MarketCache(connection); + const poolCache = new PoolCache(); + const txExecutor = new DefaultTransactionExecutor(connection); + const wallet = getWallet(PRIVATE_KEY.trim()); + const quoteToken = getToken(QUOTE_MINT); + const botConfig = { + wallet, + quoteAta: getAssociatedTokenAddressSync(quoteToken.mint, wallet.publicKey), + checkRenounced: CHECK_IF_MINT_IS_RENOUNCED, + checkBurned: CHECK_IF_BURNED, + minPoolSize: new TokenAmount(quoteToken, MIN_POOL_SIZE, false), + maxPoolSize: new TokenAmount(quoteToken, MAX_POOL_SIZE, false), + quoteToken, + quoteAmount: new TokenAmount(quoteToken, QUOTE_AMOUNT, false), + oneTokenAtATime: ONE_TOKEN_AT_A_TIME, + useSnipeList: USE_SNIPE_LIST, + autoSellDelay: AUTO_SELL_DELAY, + maxSellRetries: MAX_SELL_RETRIES, + autoBuyDelay: AUTO_BUY_DELAY, + maxBuyRetries: MAX_BUY_RETRIES, + unitLimit: COMPUTE_UNIT_LIMIT, + unitPrice: COMPUTE_UNIT_PRICE, + takeProfit: TAKE_PROFIT, + stopLoss: STOP_LOSS, + buySlippage: BUY_SLIPPAGE, + sellSlippage: SELL_SLIPPAGE, + priceCheckInterval: PRICE_CHECK_INTERVAL, + priceCheckDuration: PRICE_CHECK_DURATION, + }; + + const bot = new Bot(connection, marketCache, poolCache, txExecutor, botConfig); + const valid = await bot.validate(); + + if (!valid) { + logger.info('Bot is exiting...'); + process.exit(1); + } + + if (PRE_LOAD_EXISTING_MARKETS) { + await marketCache.init({ quoteToken }); + } + + const runTimestamp = Math.floor(new Date().getTime() / 1000); + const listeners = new Listeners(connection); + await listeners.start({ + walletPublicKey: wallet.publicKey, + quoteToken, + autoSell: AUTO_SELL, + cacheNewMarkets: CACHE_NEW_MARKETS, + }); + + listeners.on('market', (updatedAccountInfo: KeyedAccountInfo) => { + const marketState = MARKET_STATE_LAYOUT_V3.decode(updatedAccountInfo.accountInfo.data); + marketCache.save(updatedAccountInfo.accountId.toString(), marketState); + }); + + listeners.on('pool', async (updatedAccountInfo: KeyedAccountInfo) => { + const poolState = LIQUIDITY_STATE_LAYOUT_V4.decode(updatedAccountInfo.accountInfo.data); + const poolOpenTime = parseInt(poolState.poolOpenTime.toString()); + const exists = await poolCache.get(poolState.baseMint.toString()); + + if (!exists && poolOpenTime > runTimestamp) { + poolCache.save(updatedAccountInfo.accountId.toString(), poolState); + await bot.buy(updatedAccountInfo.accountId, poolState); + } + }); + + listeners.on('wallet', async (updatedAccountInfo: KeyedAccountInfo) => { + const accountData = AccountLayout.decode(updatedAccountInfo.accountInfo.data); + + if (accountData.mint.equals(quoteToken.mint)) { + return; + } + + await bot.sell(updatedAccountInfo.accountId, accountData); + }); + + printDetails(wallet, quoteToken, botConfig); +}; + +runListener(); diff --git a/liquidity/index.ts b/liquidity/index.ts deleted file mode 100644 index c6c4dbe..0000000 --- a/liquidity/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './liquidity'; diff --git a/listeners/index.ts b/listeners/index.ts new file mode 100644 index 0000000..52f405a --- /dev/null +++ b/listeners/index.ts @@ -0,0 +1 @@ +export * from './listeners'; diff --git a/listeners/listeners.ts b/listeners/listeners.ts new file mode 100644 index 0000000..0c191ec --- /dev/null +++ b/listeners/listeners.ts @@ -0,0 +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'; + +export class Listeners extends EventEmitter { + private subscriptions: number[] = []; + + 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); + } + + const raydiumSubscription = await this.subscribeToRaydiumPools(config); + this.subscriptions.push(raydiumSubscription); + + 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 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(), + }, + }, + ], + ); + } + + 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); + } + } +} diff --git a/market/index.ts b/market/index.ts deleted file mode 100644 index 9fc9e36..0000000 --- a/market/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './market'; diff --git a/package-lock.json b/package-lock.json index df907b2..a5dc331 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,15 @@ "@raydium-io/raydium-sdk": "^1.3.1-beta.47", "@solana/spl-token": "^0.4.0", "@solana/web3.js": "^1.89.1", + "async-mutex": "^0.5.0", "bigint-buffer": "^1.1.5", + "bip39": "^3.1.0", "bn.js": "^5.2.1", "bs58": "^5.0.0", "dotenv": "^16.4.1", + "ed25519-hd-key": "^1.3.0", + "i": "^0.3.7", + "npm": "^10.5.2", "pino": "^8.18.0", "pino-pretty": "^10.3.1", "pino-std-serializers": "^6.2.2" @@ -406,6 +411,14 @@ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, + "node_modules/async-mutex": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", + "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -493,6 +506,14 @@ "file-uri-to-path": "1.0.0" } }, + "node_modules/bip39": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", + "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", + "dependencies": { + "@noble/hashes": "^1.2.0" + } + }, "node_modules/bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", @@ -568,6 +589,15 @@ "node": ">=6.14.2" } }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -589,6 +619,31 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -652,6 +707,15 @@ "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, + "node_modules/ed25519-hd-key": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ed25519-hd-key/-/ed25519-hd-key-1.3.0.tgz", + "integrity": "sha512-IWwAyiiuJQhgu3L8NaHb68eJxTu2pgCwxIBdgpLJdKpYZM46+AXePSVTr7fkNKaUOfOL4IrjEUaQvyVRIDP7fg==", + "dependencies": { + "create-hmac": "1.1.7", + "tweetnacl": "1.0.3" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -773,6 +837,32 @@ "node": ">= 6" } }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/help-me": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", @@ -786,6 +876,14 @@ "ms": "^2.0.0" } }, + "node_modules/i": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz", + "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -805,6 +903,11 @@ } ] }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, "node_modules/isomorphic-ws": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", @@ -885,6 +988,16 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -928,6 +1041,2584 @@ "node-gyp-build-test": "build-test.js" } }, + "node_modules/npm": { + "version": "10.5.2", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.5.2.tgz", + "integrity": "sha512-cHVG7QEJwJdZyOrK0dKX5uf3R5Fd0E8AcmSES1jLtO52UT1enUKZ96Onw/xwq4CbrTZEnDuu2Vf9kCQh/Sd12w==", + "bundleDependencies": [ + "@isaacs/string-locale-compare", + "@npmcli/arborist", + "@npmcli/config", + "@npmcli/fs", + "@npmcli/map-workspaces", + "@npmcli/package-json", + "@npmcli/promise-spawn", + "@npmcli/redact", + "@npmcli/run-script", + "@sigstore/tuf", + "abbrev", + "archy", + "cacache", + "chalk", + "ci-info", + "cli-columns", + "cli-table3", + "columnify", + "fastest-levenshtein", + "fs-minipass", + "glob", + "graceful-fs", + "hosted-git-info", + "ini", + "init-package-json", + "is-cidr", + "json-parse-even-better-errors", + "libnpmaccess", + "libnpmdiff", + "libnpmexec", + "libnpmfund", + "libnpmhook", + "libnpmorg", + "libnpmpack", + "libnpmpublish", + "libnpmsearch", + "libnpmteam", + "libnpmversion", + "make-fetch-happen", + "minimatch", + "minipass", + "minipass-pipeline", + "ms", + "node-gyp", + "nopt", + "normalize-package-data", + "npm-audit-report", + "npm-install-checks", + "npm-package-arg", + "npm-pick-manifest", + "npm-profile", + "npm-registry-fetch", + "npm-user-validate", + "npmlog", + "p-map", + "pacote", + "parse-conflict-json", + "proc-log", + "qrcode-terminal", + "read", + "semver", + "spdx-expression-parse", + "ssri", + "supports-color", + "tar", + "text-table", + "tiny-relative-date", + "treeverse", + "validate-npm-package-name", + "which", + "write-file-atomic" + ], + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^7.2.1", + "@npmcli/config": "^8.0.2", + "@npmcli/fs": "^3.1.0", + "@npmcli/map-workspaces": "^3.0.6", + "@npmcli/package-json": "^5.0.2", + "@npmcli/promise-spawn": "^7.0.1", + "@npmcli/redact": "^1.1.0", + "@npmcli/run-script": "^7.0.4", + "@sigstore/tuf": "^2.3.2", + "abbrev": "^2.0.0", + "archy": "~1.0.0", + "cacache": "^18.0.2", + "chalk": "^5.3.0", + "ci-info": "^4.0.0", + "cli-columns": "^4.0.0", + "cli-table3": "^0.6.4", + "columnify": "^1.6.0", + "fastest-levenshtein": "^1.0.16", + "fs-minipass": "^3.0.3", + "glob": "^10.3.12", + "graceful-fs": "^4.2.11", + "hosted-git-info": "^7.0.1", + "ini": "^4.1.2", + "init-package-json": "^6.0.2", + "is-cidr": "^5.0.5", + "json-parse-even-better-errors": "^3.0.1", + "libnpmaccess": "^8.0.1", + "libnpmdiff": "^6.0.3", + "libnpmexec": "^7.0.4", + "libnpmfund": "^5.0.1", + "libnpmhook": "^10.0.0", + "libnpmorg": "^6.0.1", + "libnpmpack": "^6.0.3", + "libnpmpublish": "^9.0.2", + "libnpmsearch": "^7.0.0", + "libnpmteam": "^6.0.0", + "libnpmversion": "^5.0.1", + "make-fetch-happen": "^13.0.0", + "minimatch": "^9.0.4", + "minipass": "^7.0.4", + "minipass-pipeline": "^1.2.4", + "ms": "^2.1.2", + "node-gyp": "^10.1.0", + "nopt": "^7.2.0", + "normalize-package-data": "^6.0.0", + "npm-audit-report": "^5.0.0", + "npm-install-checks": "^6.3.0", + "npm-package-arg": "^11.0.1", + "npm-pick-manifest": "^9.0.0", + "npm-profile": "^9.0.0", + "npm-registry-fetch": "^16.2.0", + "npm-user-validate": "^2.0.0", + "npmlog": "^7.0.1", + "p-map": "^4.0.0", + "pacote": "^17.0.6", + "parse-conflict-json": "^3.0.1", + "proc-log": "^3.0.0", + "qrcode-terminal": "^0.12.0", + "read": "^3.0.1", + "semver": "^7.6.0", + "spdx-expression-parse": "^4.0.0", + "ssri": "^10.0.5", + "supports-color": "^9.4.0", + "tar": "^6.2.1", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^3.0.0", + "validate-npm-package-name": "^5.0.0", + "which": "^4.0.0", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "npm": "bin/npm-cli.js", + "npx": "bin/npx-cli.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@colors/colors": { + "version": "1.5.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui": { + "version": "8.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/@npmcli/agent": { + "version": "2.2.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/arborist": { + "version": "7.4.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^3.1.0", + "@npmcli/installed-package-contents": "^2.0.2", + "@npmcli/map-workspaces": "^3.0.2", + "@npmcli/metavuln-calculator": "^7.0.0", + "@npmcli/name-from-folder": "^2.0.0", + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.0.0", + "@npmcli/query": "^3.1.0", + "@npmcli/redact": "^1.1.0", + "@npmcli/run-script": "^7.0.2", + "bin-links": "^4.0.1", + "cacache": "^18.0.0", + "common-ancestor-path": "^1.0.1", + "hosted-git-info": "^7.0.1", + "json-parse-even-better-errors": "^3.0.0", + "json-stringify-nice": "^1.1.4", + "minimatch": "^9.0.4", + "nopt": "^7.0.0", + "npm-install-checks": "^6.2.0", + "npm-package-arg": "^11.0.1", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^16.2.0", + "npmlog": "^7.0.1", + "pacote": "^17.0.4", + "parse-conflict-json": "^3.0.0", + "proc-log": "^3.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^3.0.1", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^10.0.5", + "treeverse": "^3.0.0", + "walk-up-path": "^3.0.1" + }, + "bin": { + "arborist": "bin/index.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/config": { + "version": "8.2.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/map-workspaces": "^3.0.2", + "ci-info": "^4.0.0", + "ini": "^4.1.2", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.5", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/disparity-colors": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "ansi-styles": "^4.3.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles": { + "version": "4.3.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/@npmcli/fs": { + "version": "3.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/git": { + "version": "5.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/promise-spawn": "^7.0.0", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^9.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/installed-package-contents": { + "version": "2.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "bin": { + "installed-package-contents": "lib/index.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/map-workspaces": { + "version": "3.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/name-from-folder": "^2.0.0", + "glob": "^10.2.2", + "minimatch": "^9.0.0", + "read-package-json-fast": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { + "version": "7.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "cacache": "^18.0.0", + "json-parse-even-better-errors": "^3.0.0", + "pacote": "^17.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/name-from-folder": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/node-gyp": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/package-json": { + "version": "5.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.0", + "glob": "^10.2.2", + "hosted-git-info": "^7.0.0", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/promise-spawn": { + "version": "7.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/query": { + "version": "3.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/redact": { + "version": "1.1.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/run-script": { + "version": "7.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.0.0", + "@npmcli/promise-spawn": "^7.0.0", + "node-gyp": "^10.0.0", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/@sigstore/bundle": { + "version": "2.3.1", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/core": { + "version": "1.1.0", + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/protobuf-specs": { + "version": "0.3.1", + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/sign": { + "version": "2.3.0", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.3.0", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.1", + "make-fetch-happen": "^13.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/tuf": { + "version": "2.3.2", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.0", + "tuf-js": "^2.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/verify": { + "version": "1.2.0", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.3.1", + "@sigstore/core": "^1.1.0", + "@sigstore/protobuf-specs": "^0.3.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@tufjs/models": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/abbrev": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/agent-base": { + "version": "7.1.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/aggregate-error": { + "version": "3.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-regex": { + "version": "5.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-styles": { + "version": "6.2.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/aproba": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/archy": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/are-we-there-yet": { + "version": "4.0.2", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/balanced-match": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/bin-links": { + "version": "4.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "cmd-shim": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "read-cmd-shim": "^4.0.0", + "write-file-atomic": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/binary-extensions": { + "version": "2.3.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/brace-expansion": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/npm/node_modules/builtins": { + "version": "5.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/npm/node_modules/cacache": { + "version": "18.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/chalk": { + "version": "5.3.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/npm/node_modules/chownr": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ci-info": { + "version": "4.0.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/cidr-regex": { + "version": "4.0.5", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "ip-regex": "^5.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/clean-stack": { + "version": "2.2.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/cli-columns": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/cli-table3": { + "version": "0.6.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/npm/node_modules/clone": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/npm/node_modules/cmd-shim": { + "version": "6.0.2", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/color-convert": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/npm/node_modules/color-name": { + "version": "1.1.4", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/color-support": { + "version": "1.1.3", + "inBundle": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/npm/node_modules/columnify": { + "version": "1.6.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "strip-ansi": "^6.0.1", + "wcwidth": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/npm/node_modules/common-ancestor-path": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/console-control-strings": { + "version": "1.1.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/cross-spawn": { + "version": "7.0.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cssesc": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/debug": { + "version": "4.3.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/npm/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/defaults": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/diff": { + "version": "5.2.0", + "inBundle": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/npm/node_modules/eastasianwidth": { + "version": "0.2.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/emoji-regex": { + "version": "8.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/encoding": { + "version": "0.1.13", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/npm/node_modules/env-paths": { + "version": "2.2.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/err-code": { + "version": "2.0.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/exponential-backoff": { + "version": "3.1.1", + "inBundle": true, + "license": "Apache-2.0" + }, + "node_modules/npm/node_modules/fastest-levenshtein": { + "version": "1.0.16", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/npm/node_modules/foreground-child": { + "version": "3.1.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/fs-minipass": { + "version": "3.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/function-bind": { + "version": "1.1.2", + "inBundle": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/npm/node_modules/gauge": { + "version": "5.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^4.0.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/glob": { + "version": "10.3.12", + "inBundle": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/graceful-fs": { + "version": "4.2.11", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/has-unicode": { + "version": "2.0.1", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/hasown": { + "version": "2.0.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/npm/node_modules/hosted-git-info": { + "version": "7.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/http-cache-semantics": { + "version": "4.1.1", + "inBundle": true, + "license": "BSD-2-Clause" + }, + "node_modules/npm/node_modules/http-proxy-agent": { + "version": "7.0.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/https-proxy-agent": { + "version": "7.0.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/iconv-lite": { + "version": "0.6.3", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm/node_modules/ignore-walk": { + "version": "6.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/imurmurhash": { + "version": "0.1.4", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/npm/node_modules/indent-string": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ini": { + "version": "4.1.2", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/init-package-json": { + "version": "6.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/package-json": "^5.0.0", + "npm-package-arg": "^11.0.0", + "promzard": "^1.0.0", + "read": "^3.0.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/ip-address": { + "version": "9.0.5", + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/npm/node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "inBundle": true, + "license": "BSD-3-Clause" + }, + "node_modules/npm/node_modules/ip-regex": { + "version": "5.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/is-cidr": { + "version": "5.0.5", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "cidr-regex": "^4.0.4" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/is-core-module": { + "version": "2.13.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/npm/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/is-lambda": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/isexe": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/jackspeak": { + "version": "2.3.6", + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/npm/node_modules/jsbn": { + "version": "1.1.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/json-parse-even-better-errors": { + "version": "3.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/json-stringify-nice": { + "version": "1.1.4", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/jsonparse": { + "version": "1.3.1", + "engines": [ + "node >= 0.2.0" + ], + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff": { + "version": "6.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff-apply": { + "version": "5.5.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/libnpmaccess": { + "version": "8.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-package-arg": "^11.0.1", + "npm-registry-fetch": "^16.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmdiff": { + "version": "6.0.9", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.2.1", + "@npmcli/disparity-colors": "^3.0.0", + "@npmcli/installed-package-contents": "^2.0.2", + "binary-extensions": "^2.3.0", + "diff": "^5.1.0", + "minimatch": "^9.0.4", + "npm-package-arg": "^11.0.1", + "pacote": "^17.0.4", + "tar": "^6.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmexec": { + "version": "7.0.10", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.2.1", + "@npmcli/run-script": "^7.0.2", + "ci-info": "^4.0.0", + "npm-package-arg": "^11.0.1", + "npmlog": "^7.0.1", + "pacote": "^17.0.4", + "proc-log": "^3.0.0", + "read": "^3.0.1", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmfund": { + "version": "5.0.7", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmhook": { + "version": "10.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^16.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmorg": { + "version": "6.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^16.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmpack": { + "version": "6.0.9", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.2.1", + "@npmcli/run-script": "^7.0.2", + "npm-package-arg": "^11.0.1", + "pacote": "^17.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmpublish": { + "version": "9.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "ci-info": "^4.0.0", + "normalize-package-data": "^6.0.0", + "npm-package-arg": "^11.0.1", + "npm-registry-fetch": "^16.2.0", + "proc-log": "^3.0.0", + "semver": "^7.3.7", + "sigstore": "^2.2.0", + "ssri": "^10.0.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmsearch": { + "version": "7.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^16.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmteam": { + "version": "6.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^16.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmversion": { + "version": "5.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.3", + "@npmcli/run-script": "^7.0.2", + "json-parse-even-better-errors": "^3.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/lru-cache": { + "version": "10.2.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/npm/node_modules/make-fetch-happen": { + "version": "13.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/minimatch": { + "version": "9.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/minipass": { + "version": "7.0.4", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm/node_modules/minipass-collect": { + "version": "2.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm/node_modules/minipass-fetch": { + "version": "3.0.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/npm/node_modules/minipass-flush": { + "version": "1.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-json-stream": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/npm/node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline": { + "version": "1.2.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized": { + "version": "1.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minizlib": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/mkdirp": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ms": { + "version": "2.1.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/mute-stream": { + "version": "1.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/negotiator": { + "version": "0.6.3", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/npm/node_modules/node-gyp": { + "version": "10.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^4.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/nopt": { + "version": "7.2.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/normalize-package-data": { + "version": "6.0.0", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-audit-report": { + "version": "5.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-bundled": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-install-checks": { + "version": "6.3.0", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-package-arg": { + "version": "11.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-packlist": { + "version": "8.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "ignore-walk": "^6.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-pick-manifest": { + "version": "9.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^11.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-profile": { + "version": "9.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-registry-fetch": { + "version": "16.2.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/redact": "^1.1.0", + "make-fetch-happen": "^13.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^11.0.0", + "proc-log": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-user-validate": { + "version": "2.0.0", + "inBundle": true, + "license": "BSD-2-Clause", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npmlog": { + "version": "7.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^4.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^5.0.0", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/p-map": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/pacote": { + "version": "17.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^7.0.0", + "@npmcli/run-script": "^7.0.0", + "cacache": "^18.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^11.0.0", + "npm-packlist": "^8.0.0", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^7.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^2.2.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/parse-conflict-json": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/path-key": { + "version": "3.1.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/path-scurry": { + "version": "1.10.2", + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/postcss-selector-parser": { + "version": "6.0.16", + "inBundle": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/proc-log": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/promise-all-reject-late": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-call-limit": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-inflight": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/promise-retry": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/promzard": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "read": "^3.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/qrcode-terminal": { + "version": "0.12.0", + "inBundle": true, + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/npm/node_modules/read": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "mute-stream": "^1.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-cmd-shim": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-package-json": { + "version": "7.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-package-json-fast": { + "version": "3.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/retry": { + "version": "0.12.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm/node_modules/safer-buffer": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/npm/node_modules/semver": { + "version": "7.6.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/set-blocking": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/shebang-command": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/shebang-regex": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/signal-exit": { + "version": "4.1.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/sigstore": { + "version": "2.3.0", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.3.1", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.1", + "@sigstore/sign": "^2.3.0", + "@sigstore/tuf": "^2.3.1", + "@sigstore/verify": "^1.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/smart-buffer": { + "version": "4.2.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks": { + "version": "2.8.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks-proxy-agent": { + "version": "8.0.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/spdx-correct": { + "version": "3.2.0", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-exceptions": { + "version": "2.5.0", + "inBundle": true, + "license": "CC-BY-3.0" + }, + "node_modules/npm/node_modules/spdx-expression-parse": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-license-ids": { + "version": "3.0.17", + "inBundle": true, + "license": "CC0-1.0" + }, + "node_modules/npm/node_modules/ssri": { + "version": "10.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/string-width": { + "version": "4.2.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/supports-color": { + "version": "9.4.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/npm/node_modules/tar": { + "version": "6.2.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/text-table": { + "version": "0.2.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/tiny-relative-date": { + "version": "1.3.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/treeverse": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/tuf-js": { + "version": "2.2.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/models": "2.0.0", + "debug": "^4.3.4", + "make-fetch-happen": "^13.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/unique-filename": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/unique-slug": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/util-deprecate": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/validate-npm-package-license": { + "version": "3.0.4", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-name": { + "version": "5.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/walk-up-path": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/wcwidth": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/npm/node_modules/which": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/which/node_modules/isexe": { + "version": "3.1.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/npm/node_modules/wide-align": { + "version": "1.1.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/npm/node_modules/wrap-ansi": { + "version": "8.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/write-file-atomic": { + "version": "5.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/yallist": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC" + }, "node_modules/on-exit-leak-free": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz", @@ -1075,6 +3766,15 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, "node_modules/rpc-websockets": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.9.0.tgz", @@ -1146,6 +3846,18 @@ "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, "node_modules/sonic-boom": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", @@ -1257,6 +3969,16 @@ } } }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, "node_modules/typescript": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", @@ -1283,6 +4005,11 @@ "node": ">=6.14.2" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", diff --git a/package.json b/package.json index 75ea9c1..159ef17 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,24 @@ { "name": "solana-sniper-bot", "author": "Filip Dundjer", + "version": "2.0.0", "scripts": { - "buy": "ts-node buy.ts", + "start": "ts-node index.ts", "tsc": "tsc --noEmit" }, "dependencies": { "@raydium-io/raydium-sdk": "^1.3.1-beta.47", "@solana/spl-token": "^0.4.0", "@solana/web3.js": "^1.89.1", + "async-mutex": "^0.5.0", "bigint-buffer": "^1.1.5", + "bip39": "^3.1.0", "bn.js": "^5.2.1", "bs58": "^5.0.0", "dotenv": "^16.4.1", + "ed25519-hd-key": "^1.3.0", + "i": "^0.3.7", + "npm": "^10.5.2", "pino": "^8.18.0", "pino-pretty": "^10.3.1", "pino-std-serializers": "^6.2.2" @@ -23,4 +29,4 @@ "ts-node": "^10.9.2", "typescript": "^5.3.3" } -} \ No newline at end of file +} diff --git a/transactions/default-transaction-executor.ts b/transactions/default-transaction-executor.ts new file mode 100644 index 0000000..fdb4311 --- /dev/null +++ b/transactions/default-transaction-executor.ts @@ -0,0 +1,37 @@ +import { BlockhashWithExpiryBlockHeight, Connection, 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) {} + + public async executeAndConfirm( + transaction: Transaction | VersionedTransaction, + latestBlockhash: BlockhashWithExpiryBlockHeight, + ): Promise<{ confirmed: boolean; signature: string }> { + logger.debug('Executing transaction...'); + const signature = await this.execute(transaction); + + 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 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 }; + } +} diff --git a/transactions/index.ts b/transactions/index.ts new file mode 100644 index 0000000..b376e26 --- /dev/null +++ b/transactions/index.ts @@ -0,0 +1,2 @@ +export * from './default-transaction-executor'; +export * from './transaction-executor.interface'; diff --git a/transactions/transaction-executor.interface.ts b/transactions/transaction-executor.interface.ts new file mode 100644 index 0000000..1871ae1 --- /dev/null +++ b/transactions/transaction-executor.interface.ts @@ -0,0 +1,8 @@ +import { BlockhashWithExpiryBlockHeight, Transaction, VersionedTransaction } from '@solana/web3.js'; + +export interface TransactionExecutor { + executeAndConfirm( + transaction: Transaction | VersionedTransaction, + latestBlockhash: BlockhashWithExpiryBlockHeight, + ): Promise<{ confirmed: boolean; signature: string }>; +} diff --git a/types/index.ts b/types/index.ts deleted file mode 100644 index e3ef92b..0000000 --- a/types/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './mint'; \ No newline at end of file diff --git a/types/mint.ts b/types/mint.ts deleted file mode 100644 index 270e3c1..0000000 --- a/types/mint.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { struct, u32, u8 } from '@solana/buffer-layout'; -import { bool, publicKey, u64 } from '@solana/buffer-layout-utils'; -import { Commitment, Connection, PublicKey } from '@solana/web3.js'; - -/** Information about a mint */ -export interface Mint { - /** Address of the mint */ - address: PublicKey; - /** - * Optional authority used to mint new tokens. The mint authority may only be provided during mint creation. - * If no mint authority is present then the mint has a fixed supply and no further tokens may be minted. - */ - mintAuthority: PublicKey | null; - /** Total supply of tokens */ - supply: bigint; - /** Number of base 10 digits to the right of the decimal place */ - decimals: number; - /** Is this mint initialized */ - isInitialized: boolean; - /** Optional authority to freeze token accounts */ - freezeAuthority: PublicKey | null; -} - -/** Mint as stored by the program */ -export interface RawMint { - mintAuthorityOption: 1 | 0; - mintAuthority: PublicKey; - supply: bigint; - decimals: number; - isInitialized: boolean; - freezeAuthorityOption: 1 | 0; - freezeAuthority: PublicKey; -} - -/** Buffer layout for de/serializing a mint */ -export const MintLayout = struct([ - u32('mintAuthorityOption'), - publicKey('mintAuthority'), - u64('supply'), - u8('decimals'), - bool('isInitialized'), - u32('freezeAuthorityOption'), - publicKey('freezeAuthority'), -]); \ No newline at end of file diff --git a/utils/index.ts b/utils/index.ts deleted file mode 100644 index d90cdf8..0000000 --- a/utils/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './utils'; -export * from './logger'; \ No newline at end of file diff --git a/utils/utils.ts b/utils/utils.ts deleted file mode 100644 index 09128d2..0000000 --- a/utils/utils.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Logger } from 'pino'; -import dotenv from 'dotenv'; - -dotenv.config(); - -export const retrieveEnvVariable = (variableName: string, logger: Logger) => { - const variable = process.env[variableName] || ''; - if (!variable) { - logger.error(`${variableName} is not set`); - process.exit(1); - } - return variable; -}; From d17dc6000e92a63a68e741579053ca191135cdf2 Mon Sep 17 00:00:00 2001 From: Filip Dunder Date: Mon, 15 Apr 2024 15:29:27 +0200 Subject: [PATCH 2/5] cleanup: package json --- package-lock.json | 660 ++++++++++++++++++---------------------------- package.json | 3 +- 2 files changed, 259 insertions(+), 404 deletions(-) diff --git a/package-lock.json b/package-lock.json index a5dc331..ccafdd8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,10 +1,12 @@ { - "name": "solana-sniper-bot", + "name": "warp-solana-bot", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "solana-sniper-bot", + "name": "warp-solana-bot", + "version": "2.0.0", "dependencies": { "@raydium-io/raydium-sdk": "^1.3.1-beta.47", "@solana/spl-token": "^0.4.0", @@ -31,8 +33,7 @@ }, "node_modules/@babel/runtime": { "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", - "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", + "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -42,9 +43,8 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -54,24 +54,21 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -79,8 +76,7 @@ }, "node_modules/@noble/curves": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", - "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "license": "MIT", "dependencies": { "@noble/hashes": "1.3.3" }, @@ -90,8 +86,7 @@ }, "node_modules/@noble/hashes": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", - "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "license": "MIT", "engines": { "node": ">= 16" }, @@ -101,8 +96,7 @@ }, "node_modules/@raydium-io/raydium-sdk": { "version": "1.3.1-beta.47", - "resolved": "https://registry.npmjs.org/@raydium-io/raydium-sdk/-/raydium-sdk-1.3.1-beta.47.tgz", - "integrity": "sha512-vrUcFNq4lgkDHririlv83a2Sq/s438OZOYAsT56MWiVqoQLfC2u2muXMJhgp01M1OhXIqfsM5YSN/9/CrNnTvw==", + "license": "GPL-3.0", "dependencies": { "@solana/buffer-layout": "^4.0.1", "@solana/spl-token": "^0.3.9", @@ -121,8 +115,7 @@ }, "node_modules/@raydium-io/raydium-sdk/node_modules/@solana/spl-token": { "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.3.11.tgz", - "integrity": "sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ==", + "license": "Apache-2.0", "dependencies": { "@solana/buffer-layout": "^4.0.0", "@solana/buffer-layout-utils": "^0.2.0", @@ -138,8 +131,7 @@ }, "node_modules/@solana/buffer-layout": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", - "integrity": "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==", + "license": "MIT", "dependencies": { "buffer": "~6.0.3" }, @@ -149,8 +141,7 @@ }, "node_modules/@solana/buffer-layout-utils": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz", - "integrity": "sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==", + "license": "Apache-2.0", "dependencies": { "@solana/buffer-layout": "^4.0.0", "@solana/web3.js": "^1.32.0", @@ -163,13 +154,11 @@ }, "node_modules/@solana/codecs-core": { "version": "2.0.0-experimental.8618508", - "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.0.0-experimental.8618508.tgz", - "integrity": "sha512-JCz7mKjVKtfZxkuDtwMAUgA7YvJcA2BwpZaA1NOLcted4OMC4Prwa3DUe3f3181ixPYaRyptbF0Ikq2MbDkYEA==" + "license": "MIT" }, "node_modules/@solana/codecs-data-structures": { "version": "2.0.0-experimental.8618508", - "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-experimental.8618508.tgz", - "integrity": "sha512-sLpjL9sqzaDdkloBPV61Rht1tgaKq98BCtIKRuyscIrmVPu3wu0Bavk2n/QekmUzaTsj7K1pVSniM0YqCdnEBw==", + "license": "MIT", "dependencies": { "@solana/codecs-core": "2.0.0-experimental.8618508", "@solana/codecs-numbers": "2.0.0-experimental.8618508" @@ -177,16 +166,14 @@ }, "node_modules/@solana/codecs-numbers": { "version": "2.0.0-experimental.8618508", - "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.0.0-experimental.8618508.tgz", - "integrity": "sha512-EXQKfzFr3CkKKNzKSZPOOOzchXsFe90TVONWsSnVkonO9z+nGKALE0/L9uBmIFGgdzhhU9QQVFvxBMclIDJo2Q==", + "license": "MIT", "dependencies": { "@solana/codecs-core": "2.0.0-experimental.8618508" } }, "node_modules/@solana/codecs-strings": { "version": "2.0.0-experimental.8618508", - "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.0.0-experimental.8618508.tgz", - "integrity": "sha512-b2yhinr1+oe+JDmnnsV0641KQqqDG8AQ16Z/x7GVWO+AWHMpRlHWVXOq8U1yhPMA4VXxl7i+D+C6ql0VGFp0GA==", + "license": "MIT", "dependencies": { "@solana/codecs-core": "2.0.0-experimental.8618508", "@solana/codecs-numbers": "2.0.0-experimental.8618508" @@ -197,8 +184,7 @@ }, "node_modules/@solana/options": { "version": "2.0.0-experimental.8618508", - "resolved": "https://registry.npmjs.org/@solana/options/-/options-2.0.0-experimental.8618508.tgz", - "integrity": "sha512-fy/nIRAMC3QHvnKi63KEd86Xr/zFBVxNW4nEpVEU2OT0gCEKwHY4Z55YHf7XujhyuM3PNpiBKg/YYw5QlRU4vg==", + "license": "MIT", "dependencies": { "@solana/codecs-core": "2.0.0-experimental.8618508", "@solana/codecs-numbers": "2.0.0-experimental.8618508" @@ -206,8 +192,7 @@ }, "node_modules/@solana/spl-token": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.4.0.tgz", - "integrity": "sha512-jjBIBG9IsclqQVl5Y82npGE6utdCh7Z9VFcF5qgJa5EUq2XgspW3Dt1wujWjH/vQDRnkp9zGO+BqQU/HhX/3wg==", + "license": "Apache-2.0", "dependencies": { "@solana/buffer-layout": "^4.0.0", "@solana/buffer-layout-utils": "^0.2.0", @@ -223,8 +208,7 @@ }, "node_modules/@solana/spl-token-metadata": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@solana/spl-token-metadata/-/spl-token-metadata-0.1.2.tgz", - "integrity": "sha512-hJYnAJNkDrtkE2Q41YZhCpeOGU/0JgRFXbtrtOuGGeKc3pkEUHB9DDoxZAxx+XRno13GozUleyBi0qypz4c3bw==", + "license": "Apache-2.0", "dependencies": { "@solana/codecs-core": "2.0.0-experimental.8618508", "@solana/codecs-data-structures": "2.0.0-experimental.8618508", @@ -242,8 +226,7 @@ }, "node_modules/@solana/spl-type-length-value": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@solana/spl-type-length-value/-/spl-type-length-value-0.1.0.tgz", - "integrity": "sha512-JBMGB0oR4lPttOZ5XiUGyvylwLQjt1CPJa6qQ5oM+MBCndfjz2TKKkw0eATlLLcYmq1jBVsNlJ2cD6ns2GR7lA==", + "license": "Apache-2.0", "dependencies": { "buffer": "^6.0.3" }, @@ -253,8 +236,7 @@ }, "node_modules/@solana/web3.js": { "version": "1.89.1", - "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.89.1.tgz", - "integrity": "sha512-t9TTLtPQxtQB3SAf/5E8xPXfVDsC6WGOsgKY02l2cbe0HLymT7ynE8Hu48Lk5qynHCquj6nhISfEHcjMkYpu/A==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.23.4", "@noble/curves": "^1.2.0", @@ -275,24 +257,21 @@ }, "node_modules/@solana/web3.js/node_modules/base-x": { "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "license": "MIT", "dependencies": { "safe-buffer": "^5.0.1" } }, "node_modules/@solana/web3.js/node_modules/bs58": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "license": "MIT", "dependencies": { "base-x": "^3.0.2" } }, "node_modules/@solana/web3.js/node_modules/node-fetch": { "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -310,62 +289,53 @@ }, "node_modules/@tsconfig/node10": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/bn.js": { "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", - "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/connect": { "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + "license": "MIT" }, "node_modules/@types/ws": { "version": "7.4.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", - "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/abort-controller": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", "dependencies": { "event-target-shim": "^5.0.0" }, @@ -375,9 +345,8 @@ }, "node_modules/acorn": { "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -387,17 +356,15 @@ }, "node_modules/acorn-walk": { "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/agentkeepalive": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "license": "MIT", "dependencies": { "humanize-ms": "^1.2.1" }, @@ -407,35 +374,30 @@ }, "node_modules/arg": { "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/async-mutex": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", - "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", + "license": "MIT", "dependencies": { "tslib": "^2.4.0" } }, "node_modules/asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "license": "MIT" }, "node_modules/atomic-sleep": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", "engines": { "node": ">=8.0.0" } }, "node_modules/axios": { "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.4", "form-data": "^4.0.0", @@ -444,119 +406,10 @@ }, "node_modules/base-x": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", - "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" + "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/big.js": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-6.2.1.tgz", - "integrity": "sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ==", - "engines": { - "node": "*" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/bigjs" - } - }, - "node_modules/bigint-buffer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz", - "integrity": "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==", - "hasInstallScript": true, - "dependencies": { - "bindings": "^1.3.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", - "engines": { - "node": "*" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bip39": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", - "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", - "dependencies": { - "@noble/hashes": "^1.2.0" - } - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - }, - "node_modules/borsh": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", - "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", - "dependencies": { - "bn.js": "^5.2.0", - "bs58": "^4.0.0", - "text-encoding-utf-8": "^1.0.2" - } - }, - "node_modules/borsh/node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/borsh/node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", - "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", - "dependencies": { - "base-x": "^4.0.0" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { "type": "github", @@ -571,6 +424,102 @@ "url": "https://feross.org/support" } ], + "license": "MIT" + }, + "node_modules/big.js": { + "version": "6.2.1", + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/bigjs" + } + }, + "node_modules/bigint-buffer": { + "version": "1.1.5", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "bindings": "^1.3.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bip39": { + "version": "3.1.0", + "license": "ISC", + "dependencies": { + "@noble/hashes": "^1.2.0" + } + }, + "node_modules/bn.js": { + "version": "5.2.1", + "license": "MIT" + }, + "node_modules/borsh": { + "version": "0.7.0", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.0", + "bs58": "^4.0.0", + "text-encoding-utf-8": "^1.0.2" + } + }, + "node_modules/borsh/node_modules/base-x": { + "version": "3.0.9", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/borsh/node_modules/bs58": { + "version": "4.0.1", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/bs58": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "base-x": "^4.0.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -578,9 +527,8 @@ }, "node_modules/bufferutil": { "version": "4.0.8", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", - "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==", "hasInstallScript": true, + "license": "MIT", "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" @@ -591,8 +539,7 @@ }, "node_modules/cipher-base": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "license": "MIT", "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -600,13 +547,11 @@ }, "node_modules/colorette": { "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -616,13 +561,11 @@ }, "node_modules/commander": { "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "license": "MIT" }, "node_modules/create-hash": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "license": "MIT", "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -633,8 +576,7 @@ }, "node_modules/create-hmac": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "license": "MIT", "dependencies": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -646,32 +588,27 @@ }, "node_modules/create-require": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/dateformat": { "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "license": "MIT", "engines": { "node": "*" } }, "node_modules/decimal.js": { "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + "license": "MIT" }, "node_modules/decimal.js-light": { "version": "2.5.1", - "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", - "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" + "license": "MIT" }, "node_modules/delay": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", - "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -681,25 +618,22 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/diff": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/dotenv": { "version": "16.4.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.1.tgz", - "integrity": "sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, @@ -709,8 +643,7 @@ }, "node_modules/ed25519-hd-key": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ed25519-hd-key/-/ed25519-hd-key-1.3.0.tgz", - "integrity": "sha512-IWwAyiiuJQhgu3L8NaHb68eJxTu2pgCwxIBdgpLJdKpYZM46+AXePSVTr7fkNKaUOfOL4IrjEUaQvyVRIDP7fg==", + "license": "MIT", "dependencies": { "create-hmac": "1.1.7", "tweetnacl": "1.0.3" @@ -718,103 +651,87 @@ }, "node_modules/end-of-stream": { "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", "dependencies": { "once": "^1.4.0" } }, "node_modules/es6-promise": { "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + "license": "MIT" }, "node_modules/es6-promisify": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "license": "MIT", "dependencies": { "es6-promise": "^4.0.3" } }, "node_modules/event-target-shim": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/eventemitter3": { "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + "license": "MIT" }, "node_modules/events": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", "engines": { "node": ">=0.8.x" } }, "node_modules/eyes": { "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", "engines": { "node": "> 0.1.90" } }, "node_modules/fast-copy": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", - "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==" + "license": "MIT" }, "node_modules/fast-redact": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.2.0.tgz", - "integrity": "sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/fast-safe-stringify": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + "license": "MIT" }, "node_modules/fast-stable-stringify": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz", - "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==" + "license": "MIT" }, "node_modules/fastestsmallesttextencoderdecoder": { "version": "1.0.22", - "resolved": "https://registry.npmjs.org/fastestsmallesttextencoderdecoder/-/fastestsmallesttextencoderdecoder-1.0.22.tgz", - "integrity": "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==", + "license": "CC0-1.0", "peer": true }, "node_modules/fecha": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", - "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + "license": "MIT" }, "node_modules/file-uri-to-path": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + "license": "MIT" }, "node_modules/follow-redirects": { "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -826,8 +743,7 @@ }, "node_modules/form-data": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -839,8 +755,7 @@ }, "node_modules/hash-base": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", @@ -852,8 +767,7 @@ }, "node_modules/hash-base/node_modules/readable-stream": { "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -865,29 +779,23 @@ }, "node_modules/help-me": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" + "license": "MIT" }, "node_modules/humanize-ms": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", "dependencies": { "ms": "^2.0.0" } }, "node_modules/i": { "version": "0.3.7", - "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz", - "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==", "engines": { "node": ">=0.4" } }, "node_modules/ieee754": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "funding": [ { "type": "github", @@ -901,25 +809,23 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "license": "ISC" }, "node_modules/isomorphic-ws": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "license": "MIT", "peerDependencies": { "ws": "*" } }, "node_modules/jayson": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz", - "integrity": "sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==", + "license": "MIT", "dependencies": { "@types/connect": "^3.4.33", "@types/node": "^12.12.54", @@ -943,29 +849,25 @@ }, "node_modules/joycon": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/json-stringify-safe": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + "license": "ISC" }, "node_modules/jsonparse": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", "engines": [ "node >= 0.2.0" - ] + ], + "license": "MIT" }, "node_modules/JSONStream": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "license": "(MIT OR Apache-2.0)", "dependencies": { "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" @@ -979,19 +881,16 @@ }, "node_modules/lodash": { "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "license": "MIT" }, "node_modules/make-error": { "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/md5.js": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "license": "MIT", "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -1000,16 +899,14 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -1019,21 +916,18 @@ }, "node_modules/minimist": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/ms": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "license": "MIT" }, "node_modules/node-gyp-build": { "version": "4.8.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", - "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", + "license": "MIT", "optional": true, "bin": { "node-gyp-build": "bin.js", @@ -1043,8 +937,6 @@ }, "node_modules/npm": { "version": "10.5.2", - "resolved": "https://registry.npmjs.org/npm/-/npm-10.5.2.tgz", - "integrity": "sha512-cHVG7QEJwJdZyOrK0dKX5uf3R5Fd0E8AcmSES1jLtO52UT1enUKZ96Onw/xwq4CbrTZEnDuu2Vf9kCQh/Sd12w==", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", @@ -1118,6 +1010,14 @@ "which", "write-file-atomic" ], + "license": "Artistic-2.0", + "workspaces": [ + "docs", + "smoke-tests", + "mock-globals", + "mock-registry", + "workspaces/*" + ], "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/arborist": "^7.2.1", @@ -3621,21 +3521,18 @@ }, "node_modules/on-exit-leak-free": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz", - "integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==" + "license": "MIT" }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", "dependencies": { "wrappy": "1" } }, "node_modules/pino": { "version": "8.18.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.18.0.tgz", - "integrity": "sha512-Mz/gKiRyuXu4HnpHgi1YWdHQCoWMufapzooisvFn78zl4dZciAxS+YeRkUxXl1ee/SzU80YCz1zpECCh4oC6Aw==", + "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", @@ -3655,8 +3552,7 @@ }, "node_modules/pino-abstract-transport": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz", - "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==", + "license": "MIT", "dependencies": { "readable-stream": "^4.0.0", "split2": "^4.0.0" @@ -3664,8 +3560,7 @@ }, "node_modules/pino-pretty": { "version": "10.3.1", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.3.1.tgz", - "integrity": "sha512-az8JbIYeN/1iLj2t0jR9DV48/LQ3RC6hZPpapKPkb84Q+yTidMCpgWxIT3N0flnBDilyBQ1luWNpOeJptjdp/g==", + "license": "MIT", "dependencies": { "colorette": "^2.0.7", "dateformat": "^4.6.3", @@ -3688,14 +3583,12 @@ }, "node_modules/pino-std-serializers": { "version": "6.2.2", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", - "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" + "license": "MIT" }, "node_modules/prettier": { "version": "3.2.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", - "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -3708,26 +3601,22 @@ }, "node_modules/process": { "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", "engines": { "node": ">= 0.6.0" } }, "node_modules/process-warning": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", - "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" + "license": "MIT" }, "node_modules/proxy-from-env": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "license": "MIT" }, "node_modules/pump": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -3735,13 +3624,11 @@ }, "node_modules/quick-format-unescaped": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + "license": "MIT" }, "node_modules/readable-stream": { "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "license": "MIT", "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", @@ -3755,21 +3642,18 @@ }, "node_modules/real-require": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", - "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", "engines": { "node": ">= 12.13.0" } }, "node_modules/regenerator-runtime": { "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + "license": "MIT" }, "node_modules/ripemd160": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "license": "MIT", "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -3777,8 +3661,7 @@ }, "node_modules/rpc-websockets": { "version": "7.9.0", - "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.9.0.tgz", - "integrity": "sha512-DwKewQz1IUA5wfLvgM8wDpPRcr+nWSxuFxx5CbrI2z/MyyZ4nXLM86TvIA+cI1ZAdqC8JIBR1mZR55dzaLU+Hw==", + "license": "LGPL-3.0-only", "dependencies": { "@babel/runtime": "^7.17.2", "eventemitter3": "^4.0.7", @@ -3796,8 +3679,7 @@ }, "node_modules/rpc-websockets/node_modules/ws": { "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -3816,8 +3698,6 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -3831,25 +3711,23 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safe-stable-stringify": { "version": "2.4.3", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", - "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/secure-json-parse": { "version": "2.7.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", - "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" + "license": "BSD-3-Clause" }, "node_modules/sha.js": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "license": "(MIT AND BSD-3-Clause)", "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -3860,32 +3738,28 @@ }, "node_modules/sonic-boom": { "version": "3.8.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", - "integrity": "sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==", + "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0" } }, "node_modules/split2": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", "engines": { "node": ">= 10.x" } }, "node_modules/string_decoder": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } }, "node_modules/strip-json-comments": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -3895,42 +3769,34 @@ }, "node_modules/superstruct": { "version": "0.14.2", - "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.14.2.tgz", - "integrity": "sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ==" + "license": "MIT" }, "node_modules/text-encoding-utf-8": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", - "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" + "version": "1.0.2" }, "node_modules/thread-stream": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.3.0.tgz", - "integrity": "sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==", + "license": "MIT", "dependencies": { "real-require": "^0.2.0" } }, "node_modules/through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + "license": "MIT" }, "node_modules/toformat": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/toformat/-/toformat-2.0.0.tgz", - "integrity": "sha512-03SWBVop6nU8bpyZCx7SodpYznbZF5R4ljwNLBcTQzKOD9xuihRo/psX58llS1BMFhhAI08H3luot5GoXJz2pQ==" + "license": "MIT" }, "node_modules/tr46": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "license": "MIT" }, "node_modules/ts-node": { "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, + "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -3971,19 +3837,16 @@ }, "node_modules/tslib": { "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "license": "0BSD" }, "node_modules/tweetnacl": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + "license": "Unlicense" }, "node_modules/typescript": { "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3994,9 +3857,8 @@ }, "node_modules/utf-8-validate": { "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", "hasInstallScript": true, + "license": "MIT", "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" @@ -4007,32 +3869,27 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "license": "MIT" }, "node_modules/uuid": { "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/webidl-conversions": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -4040,13 +3897,11 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "license": "ISC" }, "node_modules/ws": { "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "license": "MIT", "engines": { "node": ">=8.3.0" }, @@ -4065,9 +3920,8 @@ }, "node_modules/yn": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } diff --git a/package.json b/package.json index 159ef17..3008a18 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { - "name": "solana-sniper-bot", + "name": "warp-solana-bot", "author": "Filip Dundjer", + "homepage": "https://warp.id", "version": "2.0.0", "scripts": { "start": "ts-node index.ts", From 0c5786ca1cfdb882d5f2467de3ad919bde717d3c Mon Sep 17 00:00:00 2001 From: Filip Dunder Date: Mon, 15 Apr 2024 15:45:35 +0200 Subject: [PATCH 3/5] fix: update pool size filter --- filters/pool-size.filter.ts | 39 ++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/filters/pool-size.filter.ts b/filters/pool-size.filter.ts index b1377c4..02626e2 100644 --- a/filters/pool-size.filter.ts +++ b/filters/pool-size.filter.ts @@ -1,6 +1,7 @@ import { Filter, FilterResult } from './pool-filters'; import { LiquidityStateV4, Token, TokenAmount } from '@raydium-io/raydium-sdk'; import { Connection } from '@solana/web3.js'; +import { logger } from '../helpers'; export class PoolSizeFilter implements Filter { constructor( @@ -11,26 +12,32 @@ export class PoolSizeFilter implements Filter { ) {} async execute(poolState: LiquidityStateV4): Promise { - const response = await this.connection.getTokenAccountBalance(poolState.quoteVault, this.connection.commitment); - const poolSize = new TokenAmount(this.quoteToken, response.value.amount, true); - let inRange = true; + try { + const response = await this.connection.getTokenAccountBalance(poolState.quoteVault, this.connection.commitment); + const poolSize = new TokenAmount(this.quoteToken, response.value.amount, true); + let inRange = true; - if (!this.maxPoolSize?.isZero()) { - inRange = poolSize.lt(this.maxPoolSize); + if (!this.maxPoolSize?.isZero()) { + inRange = poolSize.lt(this.maxPoolSize); - 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.gt(this.minPoolSize); + + if (!inRange) { + return { ok: false, message: `PoolSize -> Pool size ${poolSize.toFixed()} < ${this.minPoolSize.toFixed()}` }; + } + } + + return { ok: inRange }; + } catch (error) { + logger.error({ mint: poolState.baseMint }, `Failed to check pool size`); } - if (!this.minPoolSize?.isZero()) { - inRange = poolSize.gt(this.minPoolSize); - - if (!inRange) { - return { ok: false, message: `PoolSize -> Pool size ${poolSize.toFixed()} < ${this.minPoolSize.toFixed()}` }; - } - } - - return { ok: inRange }; + return { ok: false, message: 'PoolSize -> Failed to check pool size' }; } } From 83f4bf9a4bd5560e5bc318a5a980c51c71f18773 Mon Sep 17 00:00:00 2001 From: Filip Dunder Date: Tue, 16 Apr 2024 00:01:12 +0200 Subject: [PATCH 4/5] feat: update readme --- README.md | 86 ++++++++++++++++++++++++++++------------------ readme/output.png | Bin 32294 -> 47781 bytes 2 files changed, 52 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 9594037..c53f8b8 100644 --- a/README.md +++ b/README.md @@ -14,55 +14,68 @@ To run the script you need to: - Convert some SOL to USDC or WSOL. - You need USDC or WSOL depending on the configuration set below. - Configure the script by updating `.env.copy` file (remove the .copy from the file name when done). - - PRIVATE_KEY (your wallet private key) - - RPC_ENDPOINT (https RPC endpoint) - - RPC_WEBSOCKET_ENDPOINT (websocket RPC endpoint) - - QUOTE_MINT (which pools to snipe, USDC or WSOL) - - QUOTE_AMOUNT (amount used to buy each new token) - - COMMITMENT_LEVEL - - USE_SNIPE_LIST (buy only tokens listed in snipe-list.txt) - - SNIPE_LIST_REFRESH_INTERVAL (how often snipe list should be refreshed in milliseconds) - - CHECK_IF_MINT_IS_RENOUNCED (script will buy only if mint is renounced) - - MIN_POOL_SIZE (EXPERIMENTAL) (script will buy only if pool size is greater than specified amount) - - set to 0 to disable pool size check + - Check [Configuration](#configuration) section bellow - Install dependencies by typing: `npm install` -- Run the script by typing: `npm run buy` in terminal +- Run the script by typing: `npm run start` in terminal You should see the following output: ![output](readme/output.png) -## Snipe list -By default, script buys each token which has a new liquidity pool created and open for trading. -There are scenarios when you want to buy one specific token as soon as possible during the launch event. -To achieve this, you'll have to use snipe list. -- Change variable `USE_SNIPE_LIST` to `true` -- Add token mint addresses you wish to buy in `snipe-list.txt` file - - Add each address as a new line +### Configuration -This will prevent script from buying everything, and instead it will buy just listed tokens. -You can update the list while script is running. Script will check for new values in specified interval (`SNIPE_LIST_REFRESH_INTERVAL`). +#### Wallet +- `PRIVATE_KEY` - Your wallet's private key. -Pool must not exist before the script starts. -It will buy only when new pool is open for trading. If you want to buy token that will be launched in the future, make sure that script is running before the launch. +#### Connection +- `RPC_ENDPOINT` - HTTPS RPC endpoint for interacting with the Solana network. +- `RPC_WEBSOCKET_ENDPOINT` - WebSocket RPC endpoint for real-time updates from the Solana network. +- `COMMITMENT_LEVEL`- The commitment level of transactions (e.g., "finalized" for the highest level of security). -## Auto Sell -By default, auto sell is enabled. If you want to disable it, you need to: -- Change variable `AUTO_SELL` to `false` -- Update `MAX_SELL_RETRIES` to set the maximum number of retries for selling token -- Update `AUTO_SELL_DELAY` to the number of milliseconds you want to wait before selling the token - - This will sell the token after the specified delay. (+- RPC node speed) +#### Bot +- `LOG_LEVEL` - Set logging level, e.g., `info`, `debug`, `trace`, etc. +- `ONE_TOKEN_AT_A_TIME` - Set to `true` to process buying one token at a time. +- `COMPUTE_UNIT_LIMIT` - Compute limit used to calculate fees. +- `COMPUTE_UNIT_PRICE` - Compute price used to calculate fees. +- `PRE_LOAD_EXISTING_MARKETS` - Bot will load all existing markets in memory on start. + - This option should not be used with public RPC. +- `CACHE_NEW_MARKETS` - Set to `true` to cache new markets. + - This option should not be used with public RPC. -If you set AUTO_SELL_DELAY to 0, token will be sold immediately after it is bought. +#### Buy +- `QUOTE_MINT` - Amount used to buy each new token. +- `QUOTE_AMOUNT` - Which pools to snipe, USDC or WSOL. +- `AUTO_BUY_DELAY` - Delay in milliseconds before buying a token. +- `MAX_BUY_RETRIES` - Maximum number of retries for buying a token. +- `BUY_SLIPPAGE` - Slippage % -There is no guarantee that the token will be sold at a profit or even sold at all. The developer is not responsible for any losses incurred by using this feature. +#### Sell +- `AUTO_SELL` - Set to `true` to enable automatic selling of tokens. +- `MAX_SELL_RETRIES` - Maximum number of retries for selling a token. +- `AUTO_SELL_DELAY` - Delay in milliseconds before auto-selling a token. +- `PRICE_CHECK_INTERVAL` - Interval in milliseconds for checking the take profit and stop loss conditions. +- `PRICE_CHECK_DURATION` - Time in milliseconds to wait for stop loss/take profit conditions. + - If you don't reach profit or loss bot will auto sell after this time. +- `TAKE_PROFIT` - Percentage profit at which to take profit. + - Take profit is calculated based on quote mint. +- `STOP_LOSS` - Percentage loss at which to stop the loss. + - Stop loss is calculated based on quote mint. +- `SELL_SLIPPAGE` - Slippage %. + +#### Filters +- `USE_SNIPE_LIST` - Set to `true` to enable buying only tokens listed in `snipe-list.txt`. + - Pool must not exist before the script starts. +- `SNIPE_LIST_REFRESH_INTERVAL` - Interval in milliseconds to refresh the snipe list. +- `CHECK_IF_MINT_IS_RENOUNCED` - Set to `true` to buy tokens only if their mint is renounced. +- `CHECK_IF_BURNED` - Set to `true` to buy tokens only if their liqudity pool is burned. +- `MIN_POOL_SIZE` - Bot will buy only if the pool size is greater than the specified amount. + - Set `0` to disable. +- `MAX_POOL_SIZE` - Bot will buy only if the pool size is less than the specified amount. + - Set `0` to disable. ## Common issues If you have an error which is not listed here, please create a new issue in this repository. To collect more information on an issue, please change `LOG_LEVEL` to `debug`. -### Empty transaction -- If you see empty transactions on SolScan most likely fix is to change commitment level to `finalized`. - ### Unsupported RPC node - If you see following error in your log file: `Error: 410 Gone: {"jsonrpc":"2.0","error":{"code": 410, "message":"The RPC call or parameters have been disabled."}, "id": "986f3599-b2b7-47c4-b951-074c19842bad" }` @@ -80,6 +93,11 @@ To collect more information on an issue, please change `LOG_LEVEL` to `debug`. ## Contact [![](https://img.shields.io/discord/1201826085655023616?color=5865F2&logo=Discord&style=flat-square)](https://discord.gg/xYUETCA2aP) +- If you want to leave a tip, you can send it to the following address: +`7gm6BPQrSBaTAYaJheuRevBNXcmKsgbkfBCVSjBnt9aP` + +- If you need custom features or assistance, feel free to contact the admin team on discord for dedicated support. + ## Disclaimer Use this script at your own risk. diff --git a/readme/output.png b/readme/output.png index 0bb4ddfd0d74516e7044077ee61ce326721e8178..cc301719c24ad7e50ac6e9c439d45609126cdfca 100644 GIT binary patch literal 47781 zcmcG#XHe5$^zJJnpwdL8mk3A`q_dgccIWiNF83ukL+wXU<_JGdtfmWOjC*^{mf&cC3+s7X5XO>z6KFqSw(@e{$&( z#Ul9yyGl)dlCsJ{dFfKvB^~vLrv6sjKi6Q~TF1MbGq&~F0_I{lIXSOVb8_q)930Zw zDbrpF%A_sn3Fh?f4>Td6dqC1~^VW;Mb8lu-cP7n!$Kx=?RTsWy6^1Gh_pD4ckTQbx9zZV)D9>$&uef<(%5u|fM#WMeF9Pynk zX8txy2KBM=PpYMyQzQAYE(giVZA-v zcr9(C21b&wZ1qZG;88L-KV$UOtEjDr&`ipC5Ol&_q^4zH)KM8=`sAgc;MMSK8FyaS zg}SUCZZrDkKX!`-&HYAZ1L9t~*lOEtH|l(ICqb0_PZbAWh5z!Mc|{K&Aja&o%luTy ztVIzcAFJYL+VOdEL9MHduMP90;(oZy2n36g=31dO7Iu$u?zFE5t!pEmRZTsxpMBnh z1BcqG?kKn6!QSy@`fz~(^r^Dvi0L$JUzpp*3S9MT$;j1GV){GgQUTB}_TpdyHavX< zc;aRSStNeEw`-uPW%}n&Q-*BgFQ;{c?xtLGyHp=&Mbv5Wo9?|Gw}A#7Ol;u(#nj^-gTz8I$g6L$kzxs zr$*%G6cv8;M4xcCO_;K*-e&?#gzkZK5xxc2odXe;w;o-5v63OxMI3(FQary{+9>An zt@$uk+%3G(u5s_lt!JOCbcU%_LT`o;Fv!uE6gy#2Wt0?+`b!y3^q+|ZVr1w69<|Y1 zZ@7V4AejtYr=|)$Jbit(>}WmQ4ZlbSkv1gO!K5wHp9J%h%Yu--Jyk!c!NU5mi_`MG zjZsuFOTs z1p#@1A&m&^I<2mgfEn0+wv1jp zalpDZ{o-(LVZE~(K3XgU7;OlymfMoQ9?o+A#V_LCAy&w`2h>BWH`~fG8@HVwoESkE zc88tN16n?H288!A6j*E28%~TY�=`qsB&h?4Oz@yYG5-U|+t(me3q=yfDB6=bV10 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⩔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 literal 32294 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 From 6c708ea706e93f123b80eeec5606ec1c063003af Mon Sep 17 00:00:00 2001 From: Filip Dunder Date: Tue, 16 Apr 2024 00:06:02 +0200 Subject: [PATCH 5/5] fix: snipe list --- cache/snipe-list.cache.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cache/snipe-list.cache.ts b/cache/snipe-list.cache.ts index ea3a2b3..ed20430 100644 --- a/cache/snipe-list.cache.ts +++ b/cache/snipe-list.cache.ts @@ -4,9 +4,10 @@ import { logger, SNIPE_LIST_REFRESH_INTERVAL } from '../helpers'; export class SnipeListCache { private snipeList: string[] = []; + private fileLocation = path.join(__dirname, '../snipe-list.txt'); constructor() { - setInterval(this.loadSnipeList, SNIPE_LIST_REFRESH_INTERVAL); + setInterval(() => this.loadSnipeList(), SNIPE_LIST_REFRESH_INTERVAL); } public init() { @@ -18,10 +19,10 @@ export class SnipeListCache { } private loadSnipeList() { - logger.trace('Refreshing snipe list...'); + logger.trace(`Refreshing snipe list...`); const count = this.snipeList.length; - const data = fs.readFileSync(path.join(__dirname, 'snipe-list.txt'), 'utf-8'); + const data = fs.readFileSync(this.fileLocation, 'utf-8'); this.snipeList = data .split('\n') .map((a) => a.trim())