I'm a newby on Solana and 0 understanding of RUST and Typescript. I'm looking for a solution to simulate swap on Raydium using Python, and then also the code to execute the swap. I've been trying to use solana-py and solders and all the examples I could find online but to no avail.. If anybody has such code, would you be so kind to share it here or on a repo on github? Eternally grateful! :D
2 Answers
I went through this same struggle some time ago. Unfortunately the raydium swap SDK only supports Javascript but there is some way around it where you can do it all in python but it can become very tedious. I know that user kokiez had found a way to do it all in python and had it published on github, but since then I haven't been able to find it, you can perhaps try to message him and find out.
But anyways, what I did was I created all the raydium swap instructions, transactions and simulations using Javascript and then I used a websocket to send the parameters from python to the Javascript function. I know its a hassle buts thats currently the easiest way to do it in my opinion.
This is a good place to get started: https://github.com/precious-void/raydium-swap
And regarding the pool keys, I have found two ways to get it reliably:
- FalconHit API ( costs 0.12 SOL per month): https://docs.valguibs.com/
- Using typescript to get the pool keys almost instantly only requiring the input and output token addresses. I had used some inspiration from this post. Here is what the code somewhat looks like:
import { PublicKey, Commitment, Connection } from '@solana/web3.js'
import {
LIQUIDITY_STATE_LAYOUT_V4,
Liquidity,
LiquidityPoolKeysV4,
MARKET_STATE_LAYOUT_V3,
Market,
SPL_MINT_LAYOUT
} from '@raydium-io/raydium-sdk'
import dotenv from 'dotenv';
dotenv.config()
// const rpcCon = new Connection(process.env.WEB3_SOL_PROVIDER, { commitment: 'finalized' })
async function getPoolKeys(connection: Connection, base: PublicKey, quote: PublicKey, commitment: Commitment = 'finalized') {
const rsp = await fetchMarketAccounts(connection, base, quote, commitment)
const poolKeys = await formatAmmKeysById(rsp[0].id, connection)
return poolKeys
}
async function formatAmmKeysById(id: string, connection: Connection): Promise<LiquidityPoolKeysV4> {
const account = await connection.getAccountInfo(new PublicKey(id))
if (account === null) throw Error(' get id info error ')
const info = LIQUIDITY_STATE_LAYOUT_V4.decode(account.data)
const marketId = info.marketId
const marketAccount = await connection.getAccountInfo(marketId)
if (marketAccount === null) throw Error(' get market info error')
const marketInfo = MARKET_STATE_LAYOUT_V3.decode(marketAccount.data)
const lpMint = info.lpMint
const lpMintAccount = await connection.getAccountInfo(lpMint)
if (lpMintAccount === null) throw Error(' get lp mint info error')
const lpMintInfo = SPL_MINT_LAYOUT.decode(lpMintAccount.data)
return {
id: new PublicKey(id),
baseMint: info.baseMint,
quoteMint: info.quoteMint,
lpMint: info.lpMint,
baseDecimals: info.baseDecimal.toNumber(),
quoteDecimals: info.quoteDecimal.toNumber(),
lpDecimals: lpMintInfo.decimals,
version: 4,
programId: account.owner,
authority: Liquidity.getAssociatedAuthority({ programId: account.owner }).publicKey,
openOrders: info.openOrders,
targetOrders: info.targetOrders,
baseVault: info.baseVault,
quoteVault: info.quoteVault,
withdrawQueue: info.withdrawQueue,
lpVault: info.lpVault,
marketVersion: 3,
marketProgramId: info.marketProgramId,
marketId: info.marketId,
marketAuthority: Market.getAssociatedAuthority({ programId: info.marketProgramId, marketId: info.marketId }).publicKey,
marketBaseVault: marketInfo.baseVault,
marketQuoteVault: marketInfo.quoteVault,
marketBids: marketInfo.bids,
marketAsks: marketInfo.asks,
marketEventQueue: marketInfo.eventQueue,
lookupTableAccount: PublicKey.default,
}
}
async function fetchMarketAccounts(connection: Connection, base: PublicKey, quote: PublicKey, commitment: Commitment = 'finalized') {
const marketProgramId = new PublicKey('675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8')
const accounts = await connection.getProgramAccounts(
marketProgramId,
{
commitment,
filters: [
{ dataSize: LIQUIDITY_STATE_LAYOUT_V4.span },
{
memcmp: {
offset: LIQUIDITY_STATE_LAYOUT_V4.offsetOf("baseMint"),
bytes: base.toBase58(),
},
},
{
memcmp: {
offset: LIQUIDITY_STATE_LAYOUT_V4.offsetOf("quoteMint"),
bytes: quote.toBase58(),
},
},
],
}
);
return accounts.map(({ pubkey, account }) => ({
id: pubkey.toString(),
...LIQUIDITY_STATE_LAYOUT_V4.decode(account.data),
}));
}
// getPoolKeys(rpcCon, new PublicKey('HZ4Qund5mESBvNngcGNGXrsjAUjvZGP8pNcVwANnQMRG'), new PublicKey('So11111111111111111111111111111111111111112'))
export default getPoolKeys
If you have any question, don't hesitate to ask.
-
hi, i am currently trying to learn how to interact with the raydium api in python. unfortunately, i am a newbie in javascript and typescript, but am very fluent in python. i was wondering if i could add you on discord or telegram. this is my discord handle: putsncalls23 and my telegram handle is @pepepray888 Commented Apr 6 at 14:42
Not that fluent in Python, but if implementing using Javascript/Typescript there is a rpc method called simulateTransaction that can be used to simulate an onchain transaction. I have successfully used it in its Typescript implementation to simulate swaps using Jupiter ( which is pretty similar to executing a swap on Raydium ). Maybe you can look into that and see if you can use it in Python.