Team Shyft
· January 22, 2026
Ultimate guide to launch Raydium tokens and preventing price manipulation with pre-purchase strategies

Raydium is a decentralized exchange built on Solana, offering high-speed token swaps. By leveraging automated market makers (AMMs), users can efficiently trade various tokens without relying on centralized intermediaries.
However, new Liquidity Pools on Raydium always face the threat of trading bots manipulating the market, leading to artificial price spikes and followed by sudden dumps, which negatively impacts investor confidence. To prevent this,
In this article, we will explore a counter-acting strategy to this problem by making the initial purchases ourselves. This will mislead the bots into thinking the token is already too expensive and risky to buy, thereby adding price stability.
The entire code is available here on GitHub for you to follow along, feel free to clone the project and try it out.
Before diving into the implementation, it’s essential to have the following tools and libraries installed:
While the overall process might seem complex initially, the following steps will provide a clear understanding of each stage.
To begin, create a new Node.js project and install the required dependencies:
npm install @solana/web3.js @raydium-io/raydium-sdk jito-solana typescript
To effectively interact with the Solana network and Raydium, we need to set up essential configuration parameters. Create a file named config.ts in your project directory and add the following code:
import {
Connection,
Keypair,
PublicKey,
} from '@solana/web3.js';
import {
ENDPOINT as _ENDPOINT,
Currency,
LOOKUP_TABLE_CACHE,
MAINNET_PROGRAM_ID,
RAYDIUM_MAINNET,
Token,
TOKEN_PROGRAM_ID,
TxVersion,
} from '@raydium-io/raydium-sdk';
export const rpcUrl: string = 'A Jito RPC Node URL'
export const rpcToken: string | undefined = undefined
export const wallet = Keypair.fromSecretKey(
new Uint8Array([
...key here
])
)
export const lpCreateWallet = new Keypair.fromSecretKey(new Uint8Array([...]));
export const connection = new Connection(
rpcUrl,
'confirmed'
)
export const PROGRAMIDS = MAINNET_PROGRAM_ID
export const ENDPOINT = _ENDPOINT
export const RAYDIUM_MAINNET_API = RAYDIUM_MAINNET
export const makeTxVersion = TxVersion.V0 // LEGACY
export const addLookupTableInfo = LOOKUP_TABLE_CACHE // only mainnet. other = undefined
These are mostly just configurations that are required to run the project. The rpcUrl takes in the url of an RPC node running Jito. wallet is your solana wallet which you will use to send transactions, and lpCreateWallet is the wallet that will create the Liquidity Pool. We’ll add more configuration details as needed throughout the guide.
Note: For security reasons, it’s highly recommended to use environment variables or a secure configuration management system to store private keys. Avoid hardcoding them directly in your code.
Now we will go on and define the token information. There are a few helper objects which can be imported from the Raydium SDK, in order to define these:
//continuing the config.ts
export const DEFAULT_TOKEN = {
SOL: new Currency(9, "USDC", "USDC"),
WSOL: new Token(
TOKEN_PROGRAM_ID,
new PublicKey("So11111111111111111111111111111111111111112"),
9,
"WSOL",
"WSOL"
),
USDC: new Token(
TOKEN_PROGRAM_ID,
new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"),
6,
"USDC",
"USDC"
),
};
The token class imported from Raydium SDK has been used to define the tokens involved. SOL is the quote mint being used for this example, which is generally a part of most swaps on the platform. The base mint token used here is USDC, however you can replace its details with the token you want to swap. Once successfully initialized, we move on towards the swapping process.
Once we have established the total configuration required for the process to run, we now move forward with the actual pool creation and swapping process.
This will be the starting point of the actual process, and for that we will define this inside index.ts file in the root directory of the project.
import { TokenAmount } from "@raydium-io/raydium-sdk";
import { DEFAULT_TOKEN, connection, wallet } from "./config";
import { getWalletTokenAccount } from "./utils";
import BN from "bn.js";
import { createPoolIx } from "./lpCreate";
import { PublicKey } from "@solana/web3.js";
import createLookupTable from "./createLookupTable";
import createSwapIx from "./swapCreate";
import submitJitoBundle from "./submitJitoBundle";
async function main() {
.....//rest of the code
Token and Amount Definitions
Within the main function, define the base and quote tokens for the liquidity pool:
const inputToken = DEFAULT_TOKEN.WSOL; // replace with base token
const outputToken = DEFAULT_TOKEN.USDC; // replace with quote token
const createLpBaseAmount = new BN(100000000000000); //amount of base token
const createLpQuoteAmount = new BN(100000000000000); //amount of quote
The input and output token here are defined in the config.ts file, and you can use your own tokens as per requirement.
OpenBook Market ID and Swap Amount
Obtain the OpenBook market ID corresponding to your desired token pair (not covered in this guide). Specify the initial swap amount using the TokenAmount class from the Raydium SDK:
// Openbook market ID
const marketId = "marketId";
const inputTokenAmount = new TokenAmount(inputToken, 10000); // Amount of SOL to use per swap
For this example, we are setting 10000 (in lamports) as an arbtitrary account for first N Swaps.
Fetching Wallet Token Accounts
Raydium SDK functions uses TokenAccount objects, so we need a tool to convert Solana Wallets to TokenAccount Objects. The following utility function does the above specified task (defined in utils.ts under src/)
export async function getWalletTokenAccount(
connection: Connection,
wallet: PublicKey
): Promise<TokenAccount[]> {
const walletTokenAccount = await connection.getTokenAccountsByOwner(wallet, {
programId: TOKEN_PROGRAM_ID,
});
return walletTokenAccount.value.map((i) => ({
pubkey: i.pubkey,
programId: i.account.owner,
accountInfo: SPL_ACCOUNT_LAYOUT.decode(i.account.data),
}));
}
This function retrieves token accounts associated with the specified wallet address.
Creating Liquidity Pool Instructions
Since we have already setup a wallet token account enumerator (in the previous step), we can now dive into the code of Create Pool instruction:
createPoolIx FunctionLet’s expand on the createPoolIx function introduced in the previous section:
import {
LOOKUP_TABLE_CACHE,
Liquidity,
LiquidityPoolKeys,
MAINNET_PROGRAM_ID,
MARKET_STATE_LAYOUT_V3,
Percent,
TokenAccount,
TokenAmount,
TxVersion,
jsonInfo2PoolKeys,
InnerSimpleV0Transaction,
LiquidityPoolKeysV4,
} from "@raydium-io/raydium-sdk";
import { getComputeBudgetConfig, getWalletTokenAccount } from "./utils";
import { DEFAULT_TOKEN, connection } from "./config";
import {
Keypair,
PublicKey,
PublicKeyInitData,
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
import { unpackMint } from "@solana/spl-token";
import BN from "bn.js";
const inputToken = DEFAULT_TOKEN.WSOL; // USDC
const outputToken = DEFAULT_TOKEN.USDC; // RAY
interface createPoolIxReturnType {
poolKeys: LiquidityPoolKeysV4;
createPoolTx: VersionedTransaction;
}
// openbook market id
const marketId = "marketId here";
// raydium create pool instructions
export async function createPoolIx(
marketId: PublicKey,
wallet: Keypair,
tokenAccounts: TokenAccount[],
baseMint: PublicKey,
quoteMint: PublicKey,
baseAmount: BN,
quoteAmount: BN
): Promise<void | createPoolIxReturnType> {
The createPoolIx function requires specific inputs: OpenBook market ID, LP creator wallet, token account information, base and quote mint details, and desired token amounts. It returns either a set of pool keys and a transaction, or an error. To construct the necessary pool keys, we must perform on-chain lookups.
const tokenAccountInfo = await getWalletTokenAccount(
connection,
wallet.publicKey
);
const marketBufferInfo = await connection.getAccountInfo(marketId);
if (!marketBufferInfo) throw Error("no marketBufferInfo");
const {
baseVault: marketBaseVault,
quoteVault: marketQuoteVault,
bids: marketBids,
asks: marketAsks,
eventQueue: marketEventQueue,
} = MARKET_STATE_LAYOUT_V3.decode(marketBufferInfo.data);
console.log("Base mint: ", baseMint.toString());
console.log("Quote mint: ", quoteMint.toString());
const accountInfo_base = await connection.getAccountInfo(baseMint);
if (!accountInfo_base) throw Error("no accountInfo_base");
const baseTokenProgramId = accountInfo_base.owner;
const baseDecimals = unpackMint(
baseMint,
accountInfo_base,
baseTokenProgramId
).decimals;
console.log("Base Decimals: ", baseDecimals);
We extract essential data from the OpenBook market account using the MARKET_STATE_LAYOUT_V3 decoder. This is basically an account layout, which helps us to decode the OpenBook account data. This information, combined with token details, is used to create a comprehensive pool keys object.
This is pretty much the first few steps of how we can get started with pool creation process, and the first steps. Do checkout the next part of this article where we go on to complete the create pool function and setting up the swaps using Jito bundle.
Up Next: Launching liquidity pool on Raydium and Safeguarding Strategies to Counter Bot Manipulation — Part 2

In this article you will learn how to implement a reconnect logic for your Solana gRPC streams with replay functionality...
January 24, 2026

Learn how to modify your yellowstone gRPC Subscribe Requests on Solana without stopping your stream or losing data ...
January 24, 2026

A comprehensive guide on how to stream Transactions, Accounts, and Block updates swiftly using Shyft’s gRPC Services ...
January 22, 2026
Get in touch with our discord community and keep up with the latest feature
releases. Get help from our developers who are always here to help you take off.