liquidity.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import { Commitment, Connection, PublicKey } from '@solana/web3.js';
  2. import {
  3. Liquidity,
  4. LIQUIDITY_STATE_LAYOUT_V4,
  5. LiquidityPoolKeys,
  6. Market,
  7. TokenAccount,
  8. SPL_ACCOUNT_LAYOUT,
  9. publicKey,
  10. struct,
  11. MAINNET_PROGRAM_ID,
  12. LiquidityStateV4,
  13. } from '@raydium-io/raydium-sdk';
  14. import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
  15. import { USDC_TOKEN_ID } from '../common';
  16. export const RAYDIUM_LIQUIDITY_PROGRAM_ID_V4 = MAINNET_PROGRAM_ID.AmmV4;
  17. export const OPENBOOK_PROGRAM_ID = MAINNET_PROGRAM_ID.OPENBOOK_MARKET;
  18. export const MINIMAL_MARKET_STATE_LAYOUT_V3 = struct([
  19. publicKey('eventQueue'),
  20. publicKey('bids'),
  21. publicKey('asks'),
  22. ]);
  23. export type MinimalLiquidityAccountData = {
  24. id: PublicKey;
  25. version: 4;
  26. programId: PublicKey;
  27. };
  28. export async function getAllAccountsV4(
  29. connection: Connection,
  30. ): Promise<MinimalLiquidityAccountData[]> {
  31. const { span } = LIQUIDITY_STATE_LAYOUT_V4;
  32. const accounts = await connection.getProgramAccounts(
  33. RAYDIUM_LIQUIDITY_PROGRAM_ID_V4,
  34. {
  35. dataSlice: { offset: 0, length: 0 },
  36. commitment: 'processed',
  37. filters: [
  38. { dataSize: span },
  39. {
  40. memcmp: {
  41. offset: LIQUIDITY_STATE_LAYOUT_V4.offsetOf('quoteMint'),
  42. bytes: USDC_TOKEN_ID.toBase58(),
  43. },
  44. },
  45. {
  46. memcmp: {
  47. offset: LIQUIDITY_STATE_LAYOUT_V4.offsetOf('marketProgramId'),
  48. bytes: OPENBOOK_PROGRAM_ID.toBase58(),
  49. },
  50. },
  51. ],
  52. },
  53. );
  54. return accounts.map(
  55. (info) =>
  56. <MinimalLiquidityAccountData>{
  57. id: info.pubkey,
  58. version: 4,
  59. programId: RAYDIUM_LIQUIDITY_PROGRAM_ID_V4,
  60. },
  61. );
  62. }
  63. export async function getAccountPoolKeysFromAccountDataV4(
  64. connection: Connection,
  65. id: PublicKey,
  66. accountData: LiquidityStateV4,
  67. commitment?: Commitment,
  68. ): Promise<LiquidityPoolKeys> {
  69. const marketInfo = await connection.getAccountInfo(accountData.marketId, {
  70. commitment: commitment ?? 'processed',
  71. dataSlice: {
  72. offset: 253, // eventQueue
  73. length: 32 * 3,
  74. },
  75. });
  76. const minimalMarketData = MINIMAL_MARKET_STATE_LAYOUT_V3.decode(
  77. marketInfo!.data,
  78. );
  79. return {
  80. id,
  81. baseMint: accountData.baseMint,
  82. quoteMint: accountData.quoteMint,
  83. lpMint: accountData.lpMint,
  84. baseDecimals: accountData.baseDecimal.toNumber(),
  85. quoteDecimals: accountData.quoteDecimal.toNumber(),
  86. lpDecimals: 5,
  87. version: 4,
  88. programId: RAYDIUM_LIQUIDITY_PROGRAM_ID_V4,
  89. authority: Liquidity.getAssociatedAuthority({
  90. programId: RAYDIUM_LIQUIDITY_PROGRAM_ID_V4,
  91. }).publicKey,
  92. openOrders: accountData.openOrders,
  93. targetOrders: accountData.targetOrders,
  94. baseVault: accountData.baseVault,
  95. quoteVault: accountData.quoteVault,
  96. marketVersion: 3,
  97. marketProgramId: accountData.marketProgramId,
  98. marketId: accountData.marketId,
  99. marketAuthority: Market.getAssociatedAuthority({
  100. programId: accountData.marketProgramId,
  101. marketId: accountData.marketId,
  102. }).publicKey,
  103. marketBaseVault: accountData.baseVault,
  104. marketQuoteVault: accountData.quoteVault,
  105. marketBids: minimalMarketData.bids,
  106. marketAsks: minimalMarketData.asks,
  107. marketEventQueue: minimalMarketData.eventQueue,
  108. withdrawQueue: accountData.withdrawQueue,
  109. lpVault: accountData.lpVault,
  110. lookupTableAccount: PublicKey.default,
  111. };
  112. }
  113. export async function getTokenAccounts(
  114. connection: Connection,
  115. owner: PublicKey,
  116. ) {
  117. const tokenResp = await connection.getTokenAccountsByOwner(owner, {
  118. programId: TOKEN_PROGRAM_ID,
  119. });
  120. const accounts: TokenAccount[] = [];
  121. for (const { pubkey, account } of tokenResp.value) {
  122. accounts.push({
  123. pubkey,
  124. programId: account.owner,
  125. accountInfo: SPL_ACCOUNT_LAYOUT.decode(account.data),
  126. });
  127. }
  128. return accounts;
  129. }