123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- 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);
- }
- }
- }
|