# Table of Contents - [HelloMoon](#hellomoon) - [RPC Quickstart](#rpc-quickstart) - [Get Your API Key 🚀](#get-your-api-key-) - [Solana JSON RPC calls](#solana-json-rpc-calls) - [Prioritization Fee Endpoint](#prioritization-fee-endpoint) - [Sei Endpoints RPC calls](#sei-endpoints-rpc-calls) - [Swap API and SDK](#swap-api-and-sdk) - [Dedicated RPC Nodes](#dedicated-rpc-nodes) - [Stake-Weighted Quality Of Service Plugin](#stake-weighted-quality-of-service-plugin) - [Lunar Lander](#lunar-lander) - [Dedicated Node VM](#dedicated-node-vm) - [gRPC Streaming](#grpc-streaming) - [gRPC Example](#grpc-example) --- # HelloMoon 🔑 First things first: get your API key [here](https://hellomoon.readme.io/reference/get-your-api-key) [](https://docs.hellomoon.io/#-first-things-first-get-your-api-key-here) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ➡️ You can access our Solana RPC endpoint at: [https://rpc.hellomoon.io](https://rpc.hellomoon.io/) ➡️ You can access our Sei RPC endpoint at: [https://sei.hellomoon.io](https://sei.hellomoon.io/) ➡️ You can access our Movement RPC endpoint at: [https://movement.hellomoon.io](https://movement.hellomoon.io/) * * * Quickstart [](https://docs.hellomoon.io/#quickstart) -------------------------------------------------------- Learn how to get up and running with Hello Moon [View Quickstart →](https://docs.hellomoon.io/docs/your-first-data-stream) RPC Reference [](https://docs.hellomoon.io/#rpc-reference) -------------------------------------------------------------- Explore Hellomoon's RPC offerings [View RPC Reference →](https://docs.hellomoon.io/reference/rpc-quickstart) API Reference [](https://docs.hellomoon.io/#api-reference) -------------------------------------------------------------- Explore server side API libraries and integrate with API endpoints [View API Reference →](https://hellomoon.readme.io/reference) --- # RPC Quickstart Our RPC endpoints: [](https://docs.hellomoon.io/reference/rpc-quickstart#our-rpc-endpoints) ----------------------------------------------------------------------------------------------- ### Solana [](https://docs.hellomoon.io/reference/rpc-quickstart#solana) * Mainnet beta: [https://rpc.hellomoon.io](https://rpc.hellomoon.io/) * Devnet: [https://rpc-devnet.hellomoon.io](https://rpc-devnet.hellomoon.io/) ### Sei [](https://docs.hellomoon.io/reference/rpc-quickstart#sei) * Mainnet: [https://sei.hellomoon.io](https://sei.hellomoon.io/) * Archive: [https://archive.sei.hellomoon.io](https://archive.sei.hellomoon.io/) ### Movement [](https://docs.hellomoon.io/reference/rpc-quickstart#movement) * Mainnet: [https://movement.hellomoon.io/](https://movement.hellomoon.io/) * GRPC: [https://grpc.movement.hellomoon.io/](https://grpc.movement.hellomoon.io/) ### Avalanche [](https://docs.hellomoon.io/reference/rpc-quickstart#avalanche) * Mainnet: [https://avalanche.hellomoon.io/](https://avalanche.hellomoon.io/) > 🔎 > > ### > > 1 RPC call = 1 Credit > > [](https://docs.hellomoon.io/reference/rpc-quickstart#1-rpc-call--1-credit) Our standard RPC nodes are a fleet of multiple machines that are shared by our different users. We also offer Dedicated RPC nodes. These machines are just for your use and no one else. They can provide you with better reliability and increased performance for your applications. Learn more about them [here](https://docs.hellomoon.io/reference/dedicated-rpc-nodes) . Table of Contents [](https://docs.hellomoon.io/reference/rpc-quickstart#table-of-contents) ============================================================================================== | | | --- | | [Authentication](https://docs.hellomoon.io/reference/rpc-quickstart#authentication) | | [Build via your favorite programming language](https://docs.hellomoon.io/reference/rpc-quickstart#build-via-your-favorite-programming-language) | | [Test an RPC Method via Command Line and Websocket](https://docs.hellomoon.io/reference/rpc-quickstart#test-via-websocket-and-command-line) | | [List of supported Solana RPC method Calls](https://docs.hellomoon.io/reference/rpc-quickstart#list-of-supported-solana-rpc-method-calls) | Authentication [](https://docs.hellomoon.io/reference/rpc-quickstart#authentication) ======================================================================================== All you need to get your **free** Hello Moon API Key is a Solana wallet and browser extension for this product. > There are two ways to get your Hello Moon API Key 1. Visit [https://www.hellomoon.io/dashboard](https://www.hellomoon.io/dashboard) and connect your wallet to get your free API key. > For a detailed guide on getting your API Key visit: [Get your API Key](https://docs.hellomoon.io/reference/get-your-api-key) ![](https://files.readme.io/3f74624-image.png) 2. Check the top right corner of readme (only visible for API request pages) ![](https://files.readme.io/33f7c37-image.png) 3. To pass the API key to the RPC, add it to the end of the url like this: [https://rpc.hellomoon.io/``](https://rpc.hellomoon.io/) Building with Hello Moon SDK & Programming Languages [](https://docs.hellomoon.io/reference/rpc-quickstart#building-with-hello-moon-sdk--programming-languages) =================================================================================================================================================================== * * * ### Build via your favorite programming language [](https://docs.hellomoon.io/reference/rpc-quickstart#build-via-your-favorite-programming-language) JavaScript ``require("dotenv").config(); const { Connection, PublicKey, LAMPORTS_PER_SOL } = require("@solana/web3.js"); const run = async () => { const connection = new Connection( `https://rpc.hellomoon.io/${process.env.HELLOMOON_API_KEY}`, // REPLACE process.env.HELLOMOON_API_KEY with your API key ); const balance = await connection.getBalance( new PublicKey("ANY_PUBLIC_KEY") ); console.log(`Your Solana Balance is ${balance / LAMPORTS_PER_SOL} SOL`); }; run().then().catch();`` **Success!**, After a couple of seconds you should see a response. Shell `{ "jsonrpc":"2.0", "result": { "context": { "apiVersion": "1.14.13", "slot": 203993889 // block id }, "value": 999995000 }, "id":1 }` ### Test via Websocket and Command Line [](https://docs.hellomoon.io/reference/rpc-quickstart#test-via-websocket-and-command-line) 1. Install wscat - [https://www.npmjs.com/package/wscat](https://www.npmjs.com/package/wscat) globally Shell `npm install -g wscat` 2. Open a websocket connection with a persisted HELLOMOON\_API\_KEY Shell `wscat -c wss://kiki-stream.hellomoon.io --auth user:REPLACE_HELLOMOON_API_KEY_HERE` 3. Once you see `Connected (press CTRL+C to quit)` you can enter the code below. Shell `{ "jsonrpc": "2.0", "id": 1, "method": "getBalance", "params": [ "8VrQeSRxymJBTsP6cd59dE5VGKECnsHo5nen3vCe631x" ] }` 4. **Success!**, After a couple of seconds you should see a response. Shell `{ "jsonrpc":"2.0", "result": { "context": { "apiVersion": "1.14.13", "slot": 203993889 // block id }, "value": 999995000 }, "id":1 }` ### List of supported Solana RPC method calls [](https://docs.hellomoon.io/reference/rpc-quickstart#list-of-supported-solana-rpc-method-calls) > Some RPC method calls are supported, if you want a method to be added or other requests please visit [https://discord.gg/hellomoon](https://discord.gg/hellomoon) > and checkout the #developer-support channel to request for help. | RPC Method Type | | | --- | --- | | [HTTP Method](https://docs.solana.com/api/http) | ✅ | | [Websocket Method](https://docs.solana.com/api/websocket) | ✅ | | Historical and Archived RPC data | ❌ | --- # Get Your API Key 🚀 ### Requirements [](https://docs.hellomoon.io/reference/get-your-api-key#requirements) Our API has open CORs, which means you can start making requests from your dApps and Webapps without any additional configuration! All you need to get your free Hello Moon API Key is a Solana wallet and browser extension for this product. ### Steps [](https://docs.hellomoon.io/reference/get-your-api-key#steps) 1. Click on the "Log In" button in the top right of the page circled in the image. ![](https://files.readme.io/f21ca89-Screen_Shot_2023-01-17_at_10.36.57_AM.png) 2. You should be redirected to a page that looks like this. Click the "connect wallet" button. ![](https://files.readme.io/fb35685-Screen_Shot_2023-01-17_at_10.40.29_AM.png) 3. Once you click "connect wallet" you'll be prompted to sign a message using your wallet. **NOTE:** this is not asking you to sign a transaction and will affect nothing on chain. This is just asking you to sign a message to verify that you own the public key associated with your wallet. ![](https://files.readme.io/65b8bd5-Screen_Shot_2023-01-17_at_10.46.49_AM.png) 4. Once signed you should be redirected to our ReadMe! You can check if it worked by visiting any of our api endpoints documentation and seeing you key next to "Bearer" circled in the image below ![](https://files.readme.io/b8670fd-Screen_Shot_2023-01-17_at_10.48.46_AM.png) > ℹ️ > > If you're developing a web application in Javascript or Typescript, use our SDK to cut down on boilerplate: > > `npm install --save @hellomoon/api@latest` --- # Solana JSON RPC calls ShellNodeRubyPHPPython Click `Try It!` to start a request and see the response here! --- # Prioritization Fee Endpoint Prioritization Fees [](https://docs.hellomoon.io/reference/rpc-prioritization-fee-endpoint#prioritization-fees) =================================================================================================================== In the Solana network, blocks can only include a transactions up to a maximum limit of compute resources necessary to process. Submitted transactions can include a prioritization fee to enhance their chances of being included in a block. This is particularly beneficial in situations where network congestion is high or when transacting with highly sought-after account resources (e.g., during a popular NFT mint). Understanding and setting appropriate priority fees is essential due to the fluctuating nature of network conditions on Solana. getPrioritizationFee [](https://docs.hellomoon.io/reference/rpc-prioritization-fee-endpoint#getprioritizationfee) ===================================================================================================================== This is an RPC method designed to provide a more straightforward approach for developers and users to gauge the effective priority fee for their transactions based on recent network activity. Parameters [](https://docs.hellomoon.io/reference/rpc-prioritization-fee-endpoint#parameters) ------------------------------------------------------------------------------------------------- **writableAccounts**: Accounts which are considered writable from the perspective of the transaction. **percentiles**: The percentiles (0-100) at which to evaluate the prioritization fee. 100th percentile = maximum, 50th = median, etc. **lookbackSlots**: The number of recent blocks to consider for calculating the percentile value. Defaults to a maximum value of 150 slots. Example Json body: JSON `{ "jsonrpc": "2.0", "id": 1, "method": "getPrioritizationFee", "params": { "writableAccounts": ["EabfmmUuZt9S7SRqquTxVy5drnh2Biy6AtENHCH6cyig", "6eWQfY5UYWHAWTMWMwrMJutv2vtx62uvxG29awFCHqhu", "8MGLs1sy6BjnrqrgjMFWRMwUE2CrT3xX6MwUK8A1PEJk", "4K57AR7vQu9SXMqFLMPwPmq4idWCz1eQB2pSRr9eVKvy", "ARDViSantp6z6oDcW3ZvciE8GEStcpgpQzRFhtV2XXU9", "22drD3suAwf2MHW63brem8P1ZcsrHaSkud7mjSTerhDK", "B1ogNbmMCMfeK7xGyaeQGs7RdiEgArFMe9xn6AzwKkCJ", "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1", "7BTLKmZzTnqebLCNh5GxJoHUfuZ3d8TZGeGpQyeR2R6U", "3BQNs3uyUMEh3ENnbjQ32XWr3qhLeSVnANtnS4EfXBeb", "HajscijXiYZRLU6t11ymNCj9xxwN8gafEJFg99YwsHZu", "GzhqSTtTTbXfGtUkBgVtJq8hSJ4j9v73aDFBDs9bKwKT", "srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX", "9ueofRFvXGUE5rojbsrGmGEnT7nrS6Jad9SCY15reBCY", "2u37VVRK4DMyydsS8e3bNYmfbTVa7qfJhHKVTQkon7wo", "FJxYHvwoPvE5JRVC4dgEvDRpDXa2HAvbetsCuXJXF5SN"], "percentiles": [0,25,50, 75, 95, 100], "lookbackSlots": 100 } }` Example response: JSON `{ "jsonrpc": "2.0", "id": "1", "result": { "percentileToFee": { "0": 0, "25": 5, "50": 55, "75": 100, "95": 2000, "100": 14291, } } }` --- # Sei Endpoints RPC calls Authenticating [](https://docs.hellomoon.io/reference/sei-endpoints#authenticating) ======================================================================================= To authenticate when using Sei RPCs, you need to include an authorization header with your API key as the bearer token. As an example: `curl "https://" -H 'Authorization: Bearer '` SEI Supported RPC Method Endpoints [](https://docs.hellomoon.io/reference/sei-endpoints#sei-supported-rpc-method-endpoints) =============================================================================================================================== You can use the different Sei RPC methods through different paths on your endpoint. You can view your specific endpoint on the [dashboard](https://hellomoon.io/dashboard) . | RPC Methods | HTTP Endpoint | WebSocket Endpoint | | --- | --- | --- | | Sei | `https:///sei` | `wss:///sei/websocket` | | Ethereum | `https:///eth` | `wss:///eth/websocket` | | Tendermint | `https:///tendermint` | `wss:///tendermint/websocket` | | Cosmos | `https:///cosmos` | N/A | | CosmWasm | `https:///cosmwasm` | N/A | Please refer to the full Sei documentation for the latest methods available through these method sets. WebSocket Connections [](https://docs.hellomoon.io/reference/sei-endpoints#websocket-connections) ----------------------------------------------------------------------------------------------------- WebSocket connections are available for Ethereum RPC methods, enabling real-time event subscriptions and streaming data. **Endpoints:** * `wss:///eth/websocket` * `wss:///sei/websocket` (alias to eth/websocket) **Authentication:** Include your API key in the connection headers: JavaScript `const WebSocket = require('ws'); const ws = new WebSocket('wss:///websocket', { headers: { 'Authorization': 'Bearer ' } }); ws.on('open', () => { // Send JSON-RPC requests ws.send(JSON.stringify({ jsonrpc: '2.0', method: 'eth_blockNumber', params: [], id: 1 })); }); ws.on('message', (data) => { const response = JSON.parse(data); console.log('Response:', response.result); });` **Supported Methods:** All standard Ethereum JSON-RPC methods are supported over WebSocket, including subscriptions via `eth_subscribe`. Archival Data [](https://docs.hellomoon.io/reference/sei-endpoints#archival-data) ===================================================================================== You can access archival data by prepending `archive.` to your endpoint. Such as `https://archive.` . --- # Swap API and SDK Dedicated Nodes can optionally use the Jupiter Swap API plug-in. When enabled, this allows you to build transactions and get on-chain prices for any token on major DEXs with slippage protection. Select your preferred Swap API plug-in when you purchase a dedicated node to use it. You then interact with it via HTTP requests or using an SDK. **Note:** Including a Swap API on your dedicated node can impact performance. We recommend only enabling it if your application requires real-time swap capabilities. Swap API Options [](https://docs.hellomoon.io/reference/swap-api#swap-api-options) ====================================================================================== Jupiter Swap API [](https://docs.hellomoon.io/reference/swap-api#jupiter-swap-api) -------------------------------------------------------------------------------------- ### Using the SDK [](https://docs.hellomoon.io/reference/swap-api#using-the-sdk) Our Jupiter Swap API integration uses the official Jupiter API package available at [https://www.npmjs.com/package/@jup-ag/api](https://www.npmjs.com/package/@jup-ag/api) . This package provides simple methods to retrieve quotes and execute swap transactions. ### Connecting to the Jupiter Swap API [](https://docs.hellomoon.io/reference/swap-api#connecting-to-the-jupiter-swap-api) The Jupiter Swap API is accessible through your dedicated node at the base URL of `/api/jup/`. Use this base URL with the endpoints described below. ### Authorization [](https://docs.hellomoon.io/reference/swap-api#authorization) Include your RPC token in the authorization header of your POST requests. For example, if your dedicated node RPC URL is [https://raging-river.hellomoon.io/hf0e87h7ewh98](https://raging-river.hellomoon.io/hf0e87h7ewh98) , set an authorization header like `{ Authorization: "Bearer hf0e87h7ewh98" }` on all routes. ### Get a quote [](https://docs.hellomoon.io/reference/swap-api#get-a-quote) You can retrieve a quote for a token swap by using the `quoteGet` method from the Jupiter SDK. #### Example Using the SDK [](https://docs.hellomoon.io/reference/swap-api#example-using-the-sdk) TypeScript `import { createJupiterApiClient } from "@jup-ag/api"; import { inspect } from "util"; const main = async () => { const jupiter = createJupiterApiClient({ basePath: "https://raging-river.hellomoon.io/api/jup", headers: { Authorization: "Bearer hf0e87h7ewh98", }, }); const quote = await jupiter.quoteGet({ inputMint: "So11111111111111111111111111111111111111112", // SOL outputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC amount: 100000000, // 0.1 SOL (100000000 lamports) slippageBps: 100, // 1% slippage tolerance }); console.log(inspect(quote)); }; if (require.main === module) { main().catch(console.error); }` #### Response [](https://docs.hellomoon.io/reference/swap-api#response) This will return a response in the following format: `{ inputMint: 'So11111111111111111111111111111111111111112', inAmount: '100000000', outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', outAmount: '13778298', otherAmountThreshold: '13640516', swapMode: 'ExactIn', slippageBps: 100, platformFee: undefined, priceImpactPct: '0', routePlan: [ { swapInfo: [Object], percent: 100 }, { swapInfo: [Object], percent: 100 } ], contextSlot: 329349748, timeTaken: 0.002020169 }` ### Create a swap transaction [](https://docs.hellomoon.io/reference/swap-api#create-a-swap-transaction) You can create a swap transaction by using the `swapPost` method from the Jupiter SDK: TypeScript `import { createJupiterApiClient } from "@jup-ag/api"; import { Connection, Keypair, VersionedTransaction } from "@solana/web3.js"; import bs58 from "bs58"; import { inspect } from "util"; // Replace with your actual private key const BS58_PRIVATE_KEY = "YOUR_PRIVATE_KEY"; const main = async () => { // Initialize Jupiter API client const jupiter = createJupiterApiClient({ basePath: "https://raging-river.hellomoon.io/api/jup", headers: { Authorization: "Bearer hf0e87h7ewh98", }, }); // Step 1: Get a quote const quote = await jupiter.quoteGet({ inputMint: "So11111111111111111111111111111111111111112", // SOL outputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC amount: 100000000, // 0.1 SOL (100000000 lamports) slippageBps: 100, // 1% slippage tolerance }); console.log("Quote obtained:", inspect(quote, { depth: null })); // Step 2: Create a wallet for transaction (replace with your actual wallet) // Note: In production, use a more secure way to handle private keys const privateKey = bs58.decode(BS58_PRIVATE_KEY); const wallet = Keypair.fromSecretKey(privateKey); // Step 3: Connect to Solana const connection = new Connection( "https://raging-river.hellomoon.io/hf0e87h7ewh98", "confirmed", ); // Step 4: Create the swap transaction const swapTransaction = await jupiter.swapPost({ swapRequest: { quoteResponse: quote, userPublicKey: wallet.publicKey.toString(), }, }); console.log( "Swap transaction created:", inspect(swapTransaction, { depth: null }), ); // Step 5: Deserialize the transaction const swapTransactionBuf = Buffer.from( swapTransaction.swapTransaction, "base64", ); const transaction = VersionedTransaction.deserialize(swapTransactionBuf); // Step 6: Sign the transaction transaction.sign([wallet]); // Step 7: Execute the transaction const signature = await connection.sendTransaction(transaction); console.log("Transaction submitted:", signature); // Step 8: Confirm the transaction const confirmation = await connection.confirmTransaction( signature, "confirmed", ); console.log("Transaction confirmed:", confirmation); }; if (require.main === module) { main().catch(console.error); }` #### Response [](https://docs.hellomoon.io/reference/swap-api#response-1) The output from this sample will look something like the following: `Quote obtained: { inputMint: 'So11111111111111111111111111111111111111112', inAmount: '100000000', outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', outAmount: '13949101', otherAmountThreshold: '13809610', swapMode: 'ExactIn', slippageBps: 100, platformFee: undefined, priceImpactPct: '0', routePlan: [ { swapInfo: { ammKey: '71GHcjkwmtM7HSWBuqzjEp96prcNNwu1wpUywXiytREU', label: 'Lifinity V2', inputMint: 'So11111111111111111111111111111111111111112', outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', inAmount: '100000000', outAmount: '13949101', feeAmount: '0', feeMint: 'So11111111111111111111111111111111111111112' }, percent: 100 } ], contextSlot: 329537341, timeTaken: 0.002056727 } Swap transaction created: { swapTransaction: '', lastValidBlockHeight: 307787472, prioritizationFeeLamports: 99999 } Transaction submitted: Transaction confirmed: { context: { slot: 329537344 }, value: { err: null } }` --- # Dedicated RPC Nodes Our standard RPC nodes are a fleet of multiple machines that are shared by our different users. We also offer Solana Dedicated RPC nodes for you to use. These machines are just for your use and no one else. They can provide you with better reliability and increased performance for your applications. Usage Metering and Pricing [](https://docs.hellomoon.io/reference/dedicated-rpc-nodes#usage-metering-and-pricing) ===================================================================================================================== You can purchase a node on a monthly or annual basis. Once purchased, you may make as many calls as you want on them without worrying about credit usage. Getting a Dedicated Node [](https://docs.hellomoon.io/reference/dedicated-rpc-nodes#getting-a-dedicated-node) ================================================================================================================= To get a Dedicated node, go to the developer dashboard and click the `New Dedicated Node` button. You will then see the available node types in various regions that you can select. ![](https://files.readme.io/b1718a35e64b705f21e4d29f3f061f906195c0f10268b479aa515861e92c966d-Screenshot_2025-02-07_at_12.42.27_PM.png) Plugins [](https://docs.hellomoon.io/reference/dedicated-rpc-nodes#plugins) =============================================================================== You can install optional plug-ins on your dedicated node. Select these during purchase time. Swap API [](https://docs.hellomoon.io/reference/dedicated-rpc-nodes#swap-api) --------------------------------------------------------------------------------- The Swap API allows you to get quotes for token swaps across all major DEXs and create transactions. It includes advanced features like slippage protection and more. Available to use via an API or through our SDK. Read more on the [Swap API and SDK](https://docs.hellomoon.io/reference/swap-api) page. Using your Dedicated Node [](https://docs.hellomoon.io/reference/dedicated-rpc-nodes#using-your-dedicated-node) =================================================================================================================== Once you have purchased a dedicated node, the developer dashboard will include the information you need to connect to and manage the node. This includes the node status, name, region, URL, gRPC URL, and more. Endpoints [](https://docs.hellomoon.io/reference/dedicated-rpc-nodes#endpoints) ----------------------------------------------------------------------------------- You will have several endpoints on your dedicated node, depending on what type of data you want from it. `RPC_URL="https://" WEBSOCKET_URL="wss://" RPC_ACCESS_TOKEN="" GRPC_URL="https://:2083" GRPC_ACCESS_TOKEN=""` Ensure that you use the correct endpoint and port for your application. * Ensure you are using HTTPS and WSS, instead of HTTP or WS! --- # Stake-Weighted Quality Of Service Plugin What is Stake-Weighted Quality of Service (SWQoS)? [](https://docs.hellomoon.io/reference/stake-weighted-quality-of-service-plugin#what-is-stake-weighted-quality-of-service-swqos) ======================================================================================================================================================================================= Stake-Weighted Quality of Service (SWQoS) is a plug-in available on HelloMoon’s Dedicated Nodes that leverages our voting validator to prioritize your transactions on the Solana blockchain. By leveraging Solana’s [stake-weighted mechanism](https://solana.com/developers/guides/advanced/stake-weighted-qos) , SWQoS ensures faster transaction processing, reduced latency, and higher transaction inclusion rates, especially during network congestion. Essentially, it means that each voting validator is allocated some share of transactions to include in a block, based on how much stake that voting validator has. This feature is designed to enhance the performance of high-frequency trading, decentralized applications, and enterprise-grade operations requiring reliable, low-latency transaction execution. Why SWQoS Matters [](https://docs.hellomoon.io/reference/stake-weighted-quality-of-service-plugin#why-swqos-matters) ======================================================================================================================== In Solana’s high-throughput environment, network congestion can lead to delays or failed transactions, impacting time-sensitive operations like trading or real-time dApp functionality. SWQoS matters because it: * **Boosts Transaction Reliability**: Guarantees higher chances of transaction inclusion in blocks, critical for trading firms and dApps. This is especially relevant during periods of network congestion. * **Reduces Latency**: Minimizes processing delays, enabling faster execution for high-frequency trading and time-sensitive workflows. * **Maximizes Performance**: Provides a competitive edge during peak network activity, ensuring your operations remain efficient and cost-effective. For users with demanding performance requirements, SWQoS transforms Solana’s scalability into a predictable, high-performance advantage. Performance Benchmarks [](https://docs.hellomoon.io/reference/stake-weighted-quality-of-service-plugin#performance-benchmarks) ================================================================================================================================== Our nodes have incredibly high performance and low latency. We beat many other providers in head-to-head comparisons. Please reach out and we can give you a node to conduct a speed test. How HelloMoon Implements SWQoS [](https://docs.hellomoon.io/reference/stake-weighted-quality-of-service-plugin#how-hellomoon-implements-swqos) ================================================================================================================================================== HelloMoon powers SWQoS through our high-performance, highly-staked voting validator on the Solana network. Our validator is engineered for optimal uptime, low latency, and maximum throughput, backed by a substantial SOL stake that ensures significant influence within Solana’s consensus mechanism. This stake-weighted prioritization allows us to allocate dedicated bandwidth and processing priority to your transactions, delivering measurable improvements in transaction speed and reliability. Steps to Use SWQoS [](https://docs.hellomoon.io/reference/stake-weighted-quality-of-service-plugin#steps-to-use-swqos) ========================================================================================================================== To use the Stake-Weighted Quality of Service features, you need to connect to a different endpoint on your dedicated node than you typically connect to. The general form is `https:///swqos/` Look on the Developer Dashboard to view your node and get the specific URL. Bandwidth [](https://docs.hellomoon.io/reference/stake-weighted-quality-of-service-plugin#bandwidth) -------------------------------------------------------------------------------------------------------- When you add Stake-Weighted Quality of Service to your Dedicated Node, you are allocated 5 Transactions per Second. If you need higher bandwidth than that, please contact us. --- # Lunar Lander Overview [](https://docs.hellomoon.io/reference/lunar-lander#overview) ========================================================================== Landing Solana transactions quickly is critical to ensure that you get the best pricing and execution. Our **Lunar Lander** product is designed to land transactions as fast as possible How it works [](https://docs.hellomoon.io/reference/lunar-lander#how-it-works) ================================================================================== Lunar Lander uses advanced optimizations and performance enhancements to land Solana transactions quicker than a normal RPC endpoint. You construct your Solana transaction as normal, add a "tip" for Lunar Lander, and send it to our endpoint. We then submit it to the blockchain and land it as fast as possible. You add a tip to your transactions by using a Solana transfer instruction. Send the amount that you wish to tip to one of our tip accounts, which are specified below. Endpoints [](https://docs.hellomoon.io/reference/lunar-lander#endpoints) ---------------------------------------------------------------------------- * `http://lunar-lander.hellomoon.io/send` Use this endpoint with `sendTransaction` like you would with a normal Solana RPC endpoint. Tip accounts [](https://docs.hellomoon.io/reference/lunar-lander#tip-accounts) ---------------------------------------------------------------------------------- To use Lunar Lander, you must send your tip to one of the following accounts: * `moon17L6BgxXRX5uHKudAmqVF96xia9h8ygcmG2sL3F` * `moon26Sek222Md7ZydcAGxoKG832DK36CkLrS3PQY4c` * `moon7fwyajcVstMoBnVy7UBcTx87SBtNoGGAaH2Cb8V` * `moonBtH9HvLHjLqi9ivyrMVKgFUsSfrz9BwQ9khhn1u` * `moonCJg8476LNFLptX1qrK8PdRsA1HD1R6XWyu9MB93` * `moonF2sz7qwAtdETnrgxNbjonnhGGjd6r4W4UC9284s` * `moonKfftMiGSak3cezvhEqvkPSzwrmQxQHXuspC96yj` * `moonQBUKBpkifLcTd78bfxxt4PYLwmJ5admLW6cBBs8` * `moonXwpKwoVkMegt5Bc776cSW793X1irL5hHV1vJ3JA` * `moonZ6u9E2fgk6eWd82621eLPHt9zuJuYECXAYjMY1C` The minimum tip amount is 0.001 SOL. Sending higher tips is a way to ensure that your transaction is landed even faster in times of congestion, since we process transactions in order of received as well as by tip amount. Example [](https://docs.hellomoon.io/reference/lunar-lander#example) ======================================================================== Python `# Construct a transfer instruction to send the tip to Lunar Lander tip_instruction = transfer( TransferParams( from_pubkey=payer.pubkey(), # your wallet to_pubkey=tip_wallet, # our tip account lamports=tip_amount # the tip amount ) ) # Build the message with both instructions message = Message.new_with_blockhash( [ other_instruction, # The other instruction(s) in your transaction you want to submit tip_instruction # The tip instruction you made above ], payer.pubkey(), # your wallet recent_blockhash # the recent blockhash ) # ... now sign the messsage and send it to our endpoint!` Frequently Asked Questions [](https://docs.hellomoon.io/reference/lunar-lander#frequently-asked-questions) ============================================================================================================== Do I pay anything if my transaction doesn't land? [](https://docs.hellomoon.io/reference/lunar-lander#do-i-pay-anything-if-my-transaction-doesnt-land) ---------------------------------------------------------------------------------------------------------------------------------------------------------- No! Because you pay for Lunar Lander using a transfer instruction in your own transaction, if the transaction does not land successfully, you won't pay anything. Are there any limits in place? [](https://docs.hellomoon.io/reference/lunar-lander#are-there-any-limits-in-place) --------------------------------------------------------------------------------------------------------------------- You can send as many transactions as you like through the Lunar Lander system. Rate limits are in place to prevent abuse and repeatedly failing transactions. If you need higher limits, please contact us. --- # Dedicated Node VM Your zero overhead micro‑VM exposes a clean, one‑to‑one set of entry points while keeping the actual Solana services running on ports inside the host. The micro-VM runs a full Ubuntu 24.04 distribution and Linux kernel, so you get all of the power and control you’re used to with zero latency to the node server. Moving your workloads to run directly on your dedicated ensures that there is as minimal of latency as possible between your apps, the gRPC streams, and RPC calls that are being done on your dedicated node. Compared to connecting to your dedicated node over the internet, where messages may take milliseconds to arrive, communication between the VM and gRPC is near instantaneous. ![](https://files.readme.io/7215d14064c1db722e085227b91d9abee3767c856f7f718d6112c118178b0424-Screenshot_2025-04-22_at_3.42.56_PM.png) Services and Interfaces [](https://docs.hellomoon.io/reference/dedicated-node-vm#services-and-interfaces) ============================================================================================================= You can access the gRPC and RPC features of the Dedicated Node from within the VM using the IP and ports below. You can also interact with the VM from the world using HTTP, HTTPs, and custom ports defined below. Available services inside of VM [](https://docs.hellomoon.io/reference/dedicated-node-vm#available-services-inside-of-vm) ----------------------------------------------------------------------------------------------------------------------------- | Service | VM IP:Port | Protocol | | --- | --- | --- | | RPC | 172.16.0.1:100 | HTTP | | RPC WS | 172.16.0.1:101 | WS | | SWQOS | 172.16.0.1:102 | HTTP | | gRPC | 172.16.0.1:2083 | HTTP2 | | Moon Beam | 172.16.0.1:2096 | HTTP2 | Note that the services are available through `172.16.0.1` and not `localhost` . Exposed VM ports [](https://docs.hellomoon.io/reference/dedicated-node-vm#exposed-vm-ports) ----------------------------------------------------------------------------------------------- | Port | Note | | --- | --- | | 80 | Standard HTTP | | 443 | Standard HTTPS | | 10000-10020 | General purpose | Default HTTP and HTTPS ports are available, as well as more in the 10000s on which you can host any services you'd like. Logging into the VM [](https://docs.hellomoon.io/reference/dedicated-node-vm#logging-into-the-vm) ===================================================================================================== SSH Access [](https://docs.hellomoon.io/reference/dedicated-node-vm#ssh-access) ----------------------------------------------------------------------------------- Port: 10022 _Private keys are provided for each node_ Once the traffic crosses the VM boundary, layer4 networking configuration forwards traffic with sub-millisecond latency to the Solana processes that continue to listen, so you don’t have to touch your existing launch scripts. Any unused external port above is already wired through to the same port number in the VM—you can bind new services there without further network changes. SSH lands on the ubuntu user account (key‑only, password‑less sudo), giving you full control over the VM to change networking rules and system configuration. Basic NGINX routing script [](https://docs.hellomoon.io/reference/dedicated-node-vm#basic-nginx-routing-script) ------------------------------------------------------------------------------------------------------------------- When logging in, you should see a `setup-nginx-proxy.sh` in your home folder. Running this will create a basic NGINX server to expose things externally as follows: | Service | Port | Path | Example URL | | --- | --- | --- | --- | | RPC | 80 | / | [http://vibrant-hussar.fleet.hellomoon.io/](http://vibrant-hussar.fleet.hellomoon.io/) | | WS | 80 | / | ws://vibrant-hussar.fleet.hellomoon.io/ | | SWQOS | 80 | /swqos | [http://vibrant-hussar.fleet.hellomoon.io/swqos](http://vibrant-hussar.fleet.hellomoon.io/swqos) | | GRPC | 2083 | / | [http://vibrant-hussar.fleet.hellomoon.io:2083/](http://vibrant-hussar.fleet.hellomoon.io:2083/) | Run with the following command `./setup-nginx-proxy.sh` Upon completion, the script will also emit a random API key that can be passed via the `X-Token`header. This will provide some basic security right out of the gate so that your endpoints are not accessible without it. This is just a basic example to demonstrate how to expose things externally. Low-latency DNAT routing [](https://docs.hellomoon.io/reference/dedicated-node-vm#low-latency-dnat-routing) --------------------------------------------------------------------------------------------------------------- When logging in, you should see `setup-nat-proxy.sh` in your home folder. Run the script using the following command `./setup-nat-proxy.sh`. This will enable a direct, low-overhead path to your node's gRPC service, providing better latency than using NGINX. You should be able to access this through the following command: `curl -v --http2-prior-knowledge http://:10000/` We use the following routing rule to directly send traffic from port 10000, a general-purpose port, to the gRPC service on 172.16.0.1:2083. This uses HTTP/2 without TLS, eliminating overhead. `iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 10000 -j DNAT --to-destination 172.16.0.1:2083` > ⚠️ > > ### > > **Warning** > > [](https://docs.hellomoon.io/reference/dedicated-node-vm#warning) > > The DNAT endpoint is unauthenticated, configure firewall rules to prevent unauthorized access. --- # gRPC Streaming This document outlines how to interact with the gRPC-based streaming service for Solana data. Unlike a traditional JSON RPC, gRPC lets you subscribe to a variety of Solana events—such as slots, account changes, blocks, and transactions—in real time through long-lived streams. Overview [](https://docs.hellomoon.io/reference/grpc-streaming#overview) ---------------------------------------------------------------------------- * **Real-time Solana Data**: Stream blocks, slots, transactions, and account updates directly to your application. * **Flexible Filters**: Narrow down data by setting filters on account addresses, owners, program data size, transaction types, and more. * **Keep-Alive Mechanisms**: Use a ping/pong approach to prevent your connection from timing out behind certain load balancers or cloud providers. * **Unary (Single-Request) Methods**: In addition to subscriptions, gRPC offers single-request calls (e.g., getting a blockhash or checking Solana version). To use this product, you'll have to purchase a dedicated node here: [https://hellomoon.io/dedicated-nodes](https://hellomoon.io/dedicated-nodes) * * * Getting Started [](https://docs.hellomoon.io/reference/grpc-streaming#getting-started) ------------------------------------------------------------------------------------------ 1. **Generate gRPC stubs** (if necessary): You’ll need client libraries in the programming language of your choice. Example clients may already be available in the project’s source (e.g., Go, Rust, TypeScript). 2. **Establish a Connection**: Point your gRPC client to the service endpoint. 3. **Build a Subscribe Request**: Specify what data you want to receive (slots, accounts, transactions, blocks, etc.) and which filters to apply. 4. **Listen for Streaming Updates**: Handle incoming notifications according to your application’s needs (e.g., updating a database or triggering application logic). * * * Subscription Structure [](https://docs.hellomoon.io/reference/grpc-streaming#subscription-structure) -------------------------------------------------------------------------------------------------------- ### Common Fields [](https://docs.hellomoon.io/reference/grpc-streaming#common-fields) * **commitment**: Defines the desired commitment level (`processed`, `confirmed`, or `finalized`). * **accounts\_data\_slice**: An optional array specifying `{ offset, length }` for partial account data retrieval. Useful when you only need specific parts of large account data. * **ping**: If set to `true`, the server will periodically respond with a “pong” message. This helps keep connections alive where idle streams might otherwise be closed by network providers. ### Slots [](https://docs.hellomoon.io/reference/grpc-streaming#slots) A slots subscription notifies you when a new Solana slot is processed. You can also filter by commitment level to receive only certain confirmations. ### Accounts [](https://docs.hellomoon.io/reference/grpc-streaming#accounts) An accounts subscription sends updates whenever a specified account or set of accounts changes. You can filter: * **account**: An array of public keys. Receives changes for any matching key. * **owner**: An array of public keys corresponding to account owners. * **filters**: Similar to the classic Solana getProgramAccounts filters, supporting dataSize and memcmp constraints (in bytes, base58, or base64 format). If no fields are set, changes to all accounts will be streamed. If fields are present, they act as a logical AND, and multiple values within each field act as OR (except for filters, which individually act as logical AND). ### Transactions [](https://docs.hellomoon.io/reference/grpc-streaming#transactions) Transaction subscriptions can include or exclude various categories and specific accounts: * **vote**: Include or exclude vote transactions. * **failed**: Include or exclude failed transactions. * **signature**: Only receive transactions matching a specific signature. * **account\_include**: Receive transactions that involve at least one account from the list. * **account\_exclude**: Exclude transactions that involve any account from the list. * **account\_required**: Only receive transactions that include all listed accounts. By default, all transactions are included if no filter fields are set. ### Blocks [](https://docs.hellomoon.io/reference/grpc-streaming#blocks) Block subscriptions deliver reconstructed blocks (including transactions, account changes, and entries) as soon as they are available. You can specify: * **account\_include**: Return block data only if it contains transactions or updates involving specific accounts. * **include\_transactions**: When set, the block’s transactions are provided in the message. * **include\_accounts**: When set, the block’s account updates are included in the message. * **include\_entries**: When set, any “entries” that make up the block are included. _Note_: There’s a known limitation in block reconstruction for some validator-generated blocks, where the number of block entries can show as zero due to incomplete metadata. This may result in partial or missing transaction data. ### Block Metadata [](https://docs.hellomoon.io/reference/grpc-streaming#block-metadata) Similar to Blocks but primarily for higher-level metadata. This subscription does not include full transactions or account updates. ### Keep-Alive with Ping/Pong [](https://docs.hellomoon.io/reference/grpc-streaming#keep-alive-with-pingpong) Some infrastructure layers (e.g., load balancers, reverse proxies) drop gRPC connections that remain idle. To counter this, set the ping field in your subscription request to true. You will periodically receive a “pong” message from the server, and you can respond (or simply process it) to keep the stream active. Unary RPC Methods [](https://docs.hellomoon.io/reference/grpc-streaming#unary-rpc-methods) ---------------------------------------------------------------------------------------------- Besides streaming subscriptions, there are a few single-request methods that can simplify routine queries: * **Ping**: Check connectivity (often used internally; not always necessary). * **GetLatestBlockhash**: Retrieve the network’s most recently processed blockhash. * **GetBlockHeight**: Query the current block height. * **GetSlot**: Request the current slot. * **IsBlockhashValid**: Verify if a given blockhash is still valid. * **GetVersion**: Return information about the Solana version. Use these lightweight calls when you only need a single piece of information rather than a continuous stream. Connection Tips [](https://docs.hellomoon.io/reference/grpc-streaming#connection-tips) ------------------------------------------------------------------------------------------ **Idle Timeout**: If your application is behind a load balancer or a service with idle timeouts, leverage the ping subscription field so the server can regularly respond with pong messages. **Filter Usage**: Use filters judiciously. Overly broad filters can generate high message volume, while overly restrictive ones may miss data you need. **Handling Errors**: Be prepared for partial blocks or missing transaction entries on certain edge cases, due to upstream issues in Solana block metadata. ### Additional Resources [](https://docs.hellomoon.io/reference/grpc-streaming#additional-resources) [Official gRPC Subscriptions Reference](https://github.com/rpcpool/yellowstone-grpc/) --- # gRPC Example Below is an example of how to connect to a gRPC endpoint. You can use this to confirm that you can connect to your node properly and start building your application. Running the demo [](https://docs.hellomoon.io/reference/grpc-example#running-the-demo) ------------------------------------------------------------------------------------------ 1. Save the three files below into a directory 2. Set your dedicated node's gRPC endpoint and x-token in the `.env` file. 3. Install required packages with `npm install` 4. Run the script with `npm run yellowstone`. You will see output from the script similar to the screenshot below ![](https://files.readme.io/a3eee7f6e826ce42aab82eb9434117b32137b9e4bdd4587fabafa9659da2b4eb-image.png) yellowstone-grpc-demo.jspackage.json.env ``import YellowstoneGrpc, { CommitmentLevel } from '@triton-one/yellowstone-grpc'; const Client = YellowstoneGrpc.default || YellowstoneGrpc; import dotenv from 'dotenv'; dotenv.config(); // gRPC Configuration // Please set GRPC_ENDPOINT environment variable with your gRPC endpoint const GRPC_ENDPOINT = process.env.GRPC_ENDPOINT || ''; // Please set GRPC_XTOKEN environment variable with your gRPC authentication token if required const GRPC_XTOKEN = process.env.GRPC_XTOKEN || ''; class SolanaYellowstoneClient { constructor() { this.client = null; this.stream = null; this.pingInterval = null; this.pingId = 0; } async initialize() { console.log('🚀 Initializing Solana Yellowstone gRPC Client...\n'); console.log(`📡 Endpoint: ${GRPC_ENDPOINT}`); console.log(`🔑 X-Token: ${GRPC_XTOKEN.substring(0, 10)}...`); console.log(''); try { // Create the Yellowstone client with configuration this.client = new Client(GRPC_ENDPOINT, GRPC_XTOKEN, { "grpc.max_receive_message_length": 64 * 1024 * 1024, // 64MiB "grpc.max_send_message_length": 64 * 1024 * 1024 // 64MiB }); console.log('✅ Yellowstone gRPC client initialized successfully\n'); } catch (error) { console.error('❌ Failed to initialize Yellowstone gRPC client:', error.message); throw error; } } async getVersion() { console.log('📋 Getting server version...'); try { const version = await this.client.getVersion(); console.log('✅ Server version:', version); return version; } catch (error) { console.error('❌ Failed to get version:', error.message); throw error; } } async startSubscription() { console.log('📊 Starting subscription stream via Yellowstone gRPC...\n'); // Example accounts to monitor (System Program and Token Program) const accountsToMonitor = [ '11111111111111111111111111111111', 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' ]; // Create subscription request for slots only (simplified to start) const request = { slots: { 'client': {} }, commitment: CommitmentLevel.CONFIRMED }; console.log('📤 Setting up subscription with:'); console.log(` - Slots: monitoring all slots`); console.log(` - Accounts: ${accountsToMonitor.join(', ')}`); console.log(` - Transactions: non-vote, successful only`); console.log(` - Commitment: CONFIRMED`); console.log(''); try { // Use subscribeOnce with explicit parameters this.stream = await this.client.subscribeOnce( {}, // accounts { 'client': {} }, // slots {}, // transactions {}, // transactionsStatus {}, // entry {}, // blocks {}, // blocksMeta CommitmentLevel.CONFIRMED, // commitment [] // accountsDataSlice ); // Set up event handlers this.stream.on('data', (data) => { this.handleStreamData(data); }); this.stream.on('error', (error) => { console.error('❌ Yellowstone stream error:', error.message); if (error.message.includes('Unauthenticated') || error.message.includes('401')) { console.error('Authentication failed. Check your X-Token.'); } else if (error.message.includes('Internal')) { console.error('Internal error details:', error); } else if (error.message.includes('Unavailable')) { console.error('Service unavailable. Check endpoint and network connection.'); } }); this.stream.on('end', () => { console.log('⚠️ Stream ended by server'); this.stopPingInterval(); }); this.stream.on('close', () => { console.log('⚠️ Stream closed'); this.stopPingInterval(); }); this.stream.on('status', (status) => { console.log('Stream status update:', status); }); console.log('✅ Subscription request sent\n'); console.log('👀 Listening for events... (Press Ctrl+C to stop)\n'); } catch (error) { console.error('❌ Failed to start subscription:', error); throw error; } } handleStreamData(data) { // Get the filter label if available const filterLabel = data.filters && data.filters.length > 0 ? data.filters[0] : ''; if (data.slot) { console.log(`[Slot Update${filterLabel ? ' - ' + filterLabel : ''}]`); console.log(` Slot: ${data.slot.slot}`); console.log(` Parent: ${data.slot.parent || 'N/A'}`); console.log(` Status: ${this.getCommitmentName(data.slot.status)}`); console.log(''); } if (data.account) { const account = data.account; console.log(`[Account Update${filterLabel ? ' - ' + filterLabel : ''}]`); console.log(` Pubkey: ${account.account.pubkey}`); console.log(` Lamports: ${account.account.lamports}`); console.log(` Owner: ${account.account.owner}`); console.log(` Slot: ${account.slot}`); console.log(` Executable: ${account.account.executable}`); console.log(` Data Length: ${account.account.data ? account.account.data.length : 0} bytes`); console.log(''); } if (data.transaction) { const tx = data.transaction; console.log(`[Transaction${filterLabel ? ' - ' + filterLabel : ''}]`); console.log(` Signature: ${tx.transaction.signature}`); console.log(` Slot: ${tx.slot}`); console.log(` Is Vote: ${tx.transaction.isVote}`); if (tx.transaction.meta) { console.log(` Success: ${!tx.transaction.meta.err}`); console.log(` Fee: ${tx.transaction.meta.fee} lamports`); const logCount = tx.transaction.meta.logMessages ? tx.transaction.meta.logMessages.length : 0; console.log(` Log Messages: ${logCount}`); } console.log(''); } if (data.block) { const block = data.block; console.log(`[Block${filterLabel ? ' - ' + filterLabel : ''}]`); console.log(` Slot: ${block.slot}`); console.log(` Blockhash: ${block.blockhash}`); console.log(` Parent Slot: ${block.parentSlot}`); console.log(` Transactions Count: ${block.transactions ? block.transactions.length : 0}`); console.log(''); } if (data.blockMeta) { const blockMeta = data.blockMeta; console.log(`[Block Meta${filterLabel ? ' - ' + filterLabel : ''}]`); console.log(` Slot: ${blockMeta.slot}`); console.log(` Blockhash: ${blockMeta.blockhash}`); console.log(` Parent Slot: ${blockMeta.parentSlot}`); console.log(` Executed Transactions: ${blockMeta.executedTransactionCount}`); console.log(''); } if (data.ping) { console.log(`[Ping] Keepalive ping sent`); } if (data.pong) { console.log(`[Pong] Keepalive response received (id: ${data.pong.id})`); } } startPingInterval() { // Send ping every 30 seconds to keep connection alive this.pingInterval = setInterval(() => { if (this.stream && !this.stream.destroyed) { const pingRequest = { ping: { id: this.pingId++ } }; try { this.stream.write(pingRequest, (err) => { if (!err) { console.log(`[Keepalive] Ping sent (id: ${this.pingId - 1})`); } else { console.error('Failed to send ping:', err.message); } }); } catch (error) { console.error('Failed to send ping:', error.message); } } }, 30000); // 30 seconds } stopPingInterval() { if (this.pingInterval) { clearInterval(this.pingInterval); this.pingInterval = null; } } getCommitmentName(value) { // Handle string values and numeric values if (typeof value === 'string') { return value.toUpperCase(); } const commitments = { 0: 'PROCESSED', 1: 'CONFIRMED', 2: 'FINALIZED' }; return commitments[value] || `UNKNOWN(${value})`; } async shutdown() { console.log('\n🛑 Shutting down Yellowstone gRPC client...'); this.stopPingInterval(); if (this.stream) { try { this.stream.end(); this.stream.destroy(); } catch (error) { console.error('Error closing stream:', error.message); } } // Yellowstone client doesn't need explicit closure like raw gRPC console.log('✅ Yellowstone gRPC client shutdown complete'); } } // Main execution async function main() { const client = new SolanaYellowstoneClient(); try { await client.initialize(); // Test connection with version check await client.getVersion(); console.log('\n' + '='.repeat(60)); console.log('Starting Yellowstone gRPC subscription stream...'); console.log('='.repeat(60) + '\n'); // Start the subscription stream await client.startSubscription(); // Start keepalive ping client.startPingInterval(); // Handle graceful shutdown process.on('SIGINT', async () => { await client.shutdown(); process.exit(0); }); // Keep process running await new Promise(() => {}); } catch (error) { console.error('Fatal error:', error); process.exit(1); } } main();`` `{ "name": "solana-rpc-demo", "version": "1.0.0", "type": "module", "description": "Demo script for connecting to Solana RPC", "main": "yellowstone-grpc-demo.js", "scripts": { "yellowstone": "node yellowstone-grpc-demo.js" }, "dependencies": { "@grpc/grpc-js": "^1.9.14", "@grpc/proto-loader": "^0.7.10", "@solana/web3.js": "^1.98.4", "@triton-one/yellowstone-grpc": "^0.6.0", "dotenv": "^17.2.1", "node-fetch": "^3.3.2" }, "devDependencies": { "bs58": "^6.0.0" } }` `# These are available in your developer dashboard at https://www.hellomoon.io/dashboard GRPC_ENDPOINT= GRPC_XTOKEN=` ---