arrow-left

Only this pageAll pages
gitbookPowered by GitBook
triangle-exclamation
Couldn't generate the PDF for 3262 pages, generation stopped at 100.
Extend with 50 more pages.
1 of 100

GitHub sync

Loading...

GETTING STARTED

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

BSC Advanced Tooling

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Solana Advanced Data Tools

Loading...

Loading...

Loading...

Loading...

ADD-ONS

Loading...

Loading...

Loading...

GUIDES

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

API REFERENCE

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Welcome

Welcome to GetBlock! We make it easy for developers and businesses to connect to 100+ blockchain networks.

With our tools and services, you can focus on building your Web3 project without worrying about the technical details of setting up and managing blockchain nodes.

From DeFi apps and NFT platforms to analytics tools, AppChains, and more, GetBlock provides the infrastructure to help you build, test, and scale your blockchain-powered solutions.


hashtag
Core GetBlock features

  • Plug-and-Play access

    Our ready-to-use blockchain nodes and APIs help you get started immediately.

  • 99.9% uptime Reliable 24/7 connection to multiple blockchain networks.

  • Multi-chain support

    Connect to Bitcoin, Ethereum, BNB Chain, Polygon, Solana, TON, and 100+ other networks. (And we support new protocols before anyone else!)

  • Flexible plans

    From free access to enterprise-grade solutions, we’ve got options for every stage of your project.

  • Custom solutions

    Need something unique? We can build tailored solutions for your specific blockchain needs.

  • 24/7 Expert support

    Our team is here to help with integrations, troubleshooting, and scaling.



hashtag
Discover GetBlock


hashtag
Popular chains

Get started with our most in-demand blockchain networks.


hashtag
GetBlock Product Demo

Testing RPC connection

This section provides simple examples to help you test your connection to the blockchain, using Ethereum API as a reference.

Using Web3 libraries

Learn how to interact with blockchain networks through GetBlock’s node infrastructure using popular web3 libraries.

Here you'll find step-by-step instructions on how to integrate popular developer libraries like Web3.js, Ethers.js, and others with GetBlock API.

These libraries allow developers to interact with Ethereum and other EVM-compatible blockchains to read data, send transactions, and deploy smart contracts.

The guide covers setting up your connection to GetBlock and performing basic operations.

Endpoint setup

Configure and manage blockchain node endpoints through GetBlock, offering easy creation of shared nodes

Set up and manage blockchain node endpoints with GetBlock. This section covers creating shared node endpoints, generating access tokens, and configuring dedicated nodes with customizable settings.

Plans and limits

GetBlock offers scalable plans tailored to developers and businesses, providing flexible solutions for both small projects and high-traffic platforms.

GetBlock offers flexible plans and features to support developers and businesses at any stage, from small projects to high-traffic platforms. This section covers available plans, scaling features, and managing subscriptions and payments.


Ethereum

Tron

Arbitrum

BNB Smart Chain

Solana

Optimism

Polygon

Avalanche

Base

Cover

Getting Started

Create your account, explore plans & features, and make your first API call

Cover

Guides

Set up endpoints, manage access tokens, and integrate GetBlock APIs step-by-step

Cover

API Reference

View supported networks, available endpoints, and full API specifications

Cover

Explorer API

Track transactions and monitor network activity with real-time blockchain data

Access token management

GetBlock uses a secure authentication method based on access tokens to ensure that only authorized users can interact with blockchain nodes.

Every you create is assigned a unique access token:

The <ACCESS_TOKEN> authenticates requests directly through the endpoint URL.


hashtag
Making an authenticated request

To make a request, include your full endpoint URL with the access token in the path.

Top up CUs and boost limits

GetBlock users can top up their CU balance or upgrade to higher limits directly from their Dashboard, with a few click.

The current CU balance for Shared Node users is displayed on the Dashboard. This shows how many Compute Units (CUs) are left before running out.

With the "Top Up" feature, users can add more Compute Units to their account or upgrade to higher monthly limits.


hashtag
Add Compute Units: Paid plan users

Monitoring and analytics

Track and manage your usage and node service subscriptions with GetBlock.

These tools help ensure optimal use of GetBlock’s services and keep you informed of key metrics and events related to your account.

hashtag
Dashboard

The Dashboard provides a quick snapshot of key metrics:

Postman Collection

Download the Postman GetBlock’s collection to test our service. It includes all the accessible endpoints of our nodes and ready-to-go examples.

Import the collection into your Postman workspace: .

  1. Once the page loads, you'll find a 'Run in Postman' button in the top-right corner. Click this button to open the collection directly in your Postman application.

  2. Select the desired network from the drop-down list on the sidebar.

db_getHex {disallowed} - Arbitrum

Example code for the db_getHex JSON RPC method. Сomplete guide on how to use db_getHex JSON RPC in GetBlock Web3 documentation.

hashtag
Parameters

database - string

Database name

key - string

db_putString {disallowed} - Arbitrum

Example code for the db_putString JSON RPC method. Сomplete guide on how to use db_putString JSON RPC in GetBlock Web3 documentation.

hashtag
Parameters

database - string

database name

key - string

eth_coinbase {disallowed} - Arbitrum

Example code for the eth_coinbase JSON RPC method. Сomplete guide on how to use eth_coinbase JSON RPC in GetBlock.io Web3 documentation.

hashtag
Parameters

-

hashtag

db_getString {disallowed} - Arbitrum

Example code for the db_getString JSON RPC method. Сomplete guide on how to use db_getString JSON RPC in GetBlock Web3 documentation.

hashtag
Parameters

database - string

database name

key - string

db_putHex {disallowed} - Arbitrum

Example code for the db_putHex JSON RPC method. Сomplete guide on how to use db_putHex JSON RPC in GetBlock Web3 documentation.

hashtag
Parameters

database - string

database name

key - string

key name

hashtag
Request

hashtag
Response

curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/' 
--header 'Content-Type: application/json' 
--data-raw '{"jsonrpc": "2.0", "method": "db_getHex", "params": [null, null], "id": "getblock.io"}'
{
    "result": "null",
    "id": "getblock.io",
    "status_code": 405,
    "message": "Method not allowed"
}
key name

string - string

string to store.

hashtag
Request

hashtag
Response

curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/' 
--header 'Content-Type: application/json' 
--data-raw '{"jsonrpc": "2.0", "method": "db_putString", "params": [null, null, null], "id": "getblock.io"}'
Request

hashtag
Response

curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/' 
--header 'Content-Type: application/json' 
--data-raw '{"jsonrpc": "2.0", "method": "eth_coinbase", "params": [], "id": "getblock.io"}'
{
    "result": "null",
    "id": "getblock.io",
    "status_code": 405,
    "message": "Method not allowed"
}
key name

hashtag
Request

hashtag
Response

curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/' 
--header 'Content-Type: application/json' 
--data-raw '{"jsonrpc": "2.0", "method": "db_getString", "params": [null, null], "id": "getblock.io"}'
{
    "result": "null",
    "id": "getblock.io",
    "status_code": 405,
    "message": "Method not allowed"
}
key name

data - data

data to store.

hashtag
Request

hashtag
Response

curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/' 
--header 'Content-Type: application/json' 
--data-raw '{"jsonrpc": "2.0", "method": "db_putHex", "params": [null, null, null], "id": "getblock.io"}'
{
    "result": "null",
    "id": "getblock.io",
    "status_code": 405,
    "message": "Method not allowed"
}
{
    "result": "null",
    "id": "getblock.io",
    "status_code": 405,
    "message": "Method not allowed"
}
circle-info

Access tokens cannot be sent in headers.

For example, here’s how to fetch the latest Ethereum block number:

Response:


hashtag
Access Token security

Always store your access tokens securely. Avoid exposing them in publicly accessible code repositories or logs.

If a token is compromised, you can quickly roll or delete it without disrupting other endpoints:

  1. Go to your GetBlock Dashboard.

  2. Locate the endpoint associated with the token.

  3. Click the three-dot icon () next to the endpoint.

  4. Select the option to either roll (regenerate) or delete the token.

Regenerate or delete your access token

This authentication method ensures that all your interactions with GetBlock’s services remain secure, reliable, and easy to manage.

endpoint

Starter, Pro & Enterprise users can refill their CU balance or switch to another plan for increased limits:

  1. Click the "Top Up" button on the Dashboard.

  2. Select the number of CUs you’d like to add or choose the recommended plan (if prompted) based on your usage needs.

  3. Confirm and finalize your purchase.

Your account balance will be updated immediately upon successful payment.


hashtag
Increase CU limits: Free plan users

Free plan users cannot top up their Compute Units directly. Instead, you have the option to upgrade to one of our monthly paid plans, providing significantly higher limits and extra features.


hashtag
Boost CU, RPS, and Access Token limits

If you're on the Enterprise plan (our customizable Shared Node plan), you can additionally request higher RPS and Access Token limits. Here’s how:

  1. Click "Change" on the Dashboard next to the Rate Limit section.

  1. Fill out and submit a request form, choosing your desired RPS limit, CU amount, and number of Access Tokens.

  1. Our team will review your request and reach out to you with next steps shortly.

circle-check

This feature is perfect for users who need higher transaction throughput without changing their plan. For more demanding needs, consider Dedicated Nodesarrow-up-right.

Your current plan details

  • Remaining CU balance

  • Rate limit based on your plan

  • Total requests made in the last 24 hours


  • hashtag
    Detailed statistics

    For more detailed analysis, visit the Statistics tab in the dashboard.

    circle-info

    Customize the data view by parameters or by access tokens using the dropdown menu.

    Select the time period, protocol name, networks (mainnet/testnet), region, and API interfaces to analyze the data by parameters.

    The Statistics tab shows more in-depth and customizable data analysis for your endpoints

    All data is displayed through infographics, including:

    • Number of requests and CUs

    • Response statuses

    • Method call distribution

    • Rate limit rejections


    hashtag
    Notifications and email communication

    GetBlock provides automated email updates for key account and subscription events:

    • Account registration

    • Successful order payments (Shared, Dedicated services, and Top-Ups)

    • Start of grace period

    • Subscription expiration

    • Dedicated node deployed and activated

    • Recurring payment cancelled

    circle-exclamation

    Email notifications are delivered only to accounts with a verified email address provided during registration.

    Users who registered using third-party authentication methods, such as MetaMask login, may not receive email notifications.

    Users can also choose whether to receive marketing communications from GetBlock. This preference can be managed in Account Settings → General by enabling or disabling the “I want to receive marketing offers” option.

    How to track your blockchain node service usage statistics
    Paste the access token copied from your account instead of {YOUR_ACCESS_TOKEN}.
    Using Postman to send a JSON-RPC request to an Ethereum node via GetBlock

    This token will grant you the necessary permissions to explore our node functionalities.

    https://documenter.getpostman.com/view/28751185/2s9YRDzqcXarrow-up-right

    Using cURL for testing

    These examples provide a starting point for testing your connection and querying blockchain data using cURL commands.

    Before you start:

    1. Create a JSON-RPC endpoint for the Ethereum blockchain from your GetBlock account.

    2. Replace <ACCESS_TOKEN> in the examples below with your actual Access Token.

    hashtag
    Fetch the current block number

    Run the following command to retrieve the latest block number:

    If successful, the response will include the current block number in hexadecimal value:

    hashtag
    Get the chain ID

    Identify the blockchain network with the eth_chainId method:

    Response example:

    In this example, 0x1 indicates the Ethereum Mainnet. The chain ID helps confirm which blockchain network you are interacting with.

    hashtag
    Check account balance by address

    Retrieve the balance of an Ethereum address using eth_getBalance. Replace <ACCOUNT_ADDRESS> with the target wallet address:

    Example response:

    The result field shows the account balance in wei (1 ether = 10¹⁸ wei).

    circle-info

    For a list of supported RPC methods with examples, navigate to .

    Sending Transactions to Private Mempool (Priority Fee)

    Learn how to add tips to transaction while sending to private mempool

    Priority fees incentivize builders to include your transaction faster and position it more favorably within a block. Adding a tip to your private transaction provides three key benefits:

    • Higher inclusion probability: Builders prioritize transactions with higher fees

    • Better block positioning: Achieve positions 1–2 more reliably

    • Faster confirmation: Reduce waiting time for transaction inclusion

    hashtag
    Choosing a Method

    They are Two approaches exist for adding priority fees to private transactions:

    Method
    Best For
    Trade-offs

    hashtag
    Different Between Bundles and Transactions

    Choose the appropriate method based on your use case:

    hashtag
    Next Steps

    Learn how to submit transactions via or method to the private mempool.

    Payment methods

    GetBlock supports both fiat and crypto payments.

    hashtag
    Fiat payments

    Users can pay for subscriptions using traditional fiat currency via Paddle.

    How it works:

    • Recurring payments enabled by default: Payment is automatically deducted on the billing date.

    • Fees: VAT is applied to Paddle payments and varies depending on your region

    • If the card balance is insufficient: GetBlock will retry the payment after three days. If the retry fails, the plan will be frozen until the payment is resolved.

    circle-exclamation

    Please, account for VAT when planning your payments.


    hashtag
    Updating your payment details

    To update your payment information while you have an active subscription:

    1. Go to Pricing → Manage Plans.

    2. Click ‘Edit Payment Method’.

    3. Enter your updated payment details and save the changes.


    hashtag
    Crypto payments

    Users can top up their accounts with cryptocurrency through NOWPayments.

    How it works:

    • Payments are processed as one-time transactions: add funds as needed.

    • Supported cryptocurrencies: any token on any network available through NOWPayments at the time of payment.

    • Fees: blockchain network fees apply.

    circle-exclamation

    If the network fees are insufficient or the transaction fails, the payment will not be processed and the subscription plan will not be activated. Please, include enough gas fees to ensure the transaction processes successfully.

    TronWeb integration

    In this guide, we will show you how to get started with TronWeb to connect to GetBlock.

    TronWeb is a JavaScript library of TRON full node’s API functions that is used to deploy smart contracts, query blockchain and contract information, trade on the decentralized exchanges and change the blockchain state.

    Firstly, you will need to add the TronWeb library to your project.

    • Npm:

    • Yarn:

    In your javascript file, define TronWeb:

    When you instantiate TronWeb you can define:

    • fullNode

    • solidityNode

    • eventServer

    • privateKey

    you can also set a

    • fullHost

    Which works as a jolly. If you do so, though, the more precise specification has priority. Supposing you are using a server which provides everything, like TronGrid, you can instantiate TronWeb as:

    For retro-compatibility, though, you can continue to use the old approach, where any parameter is passed separately (using the GetBlock node as an example here):

    After this you can call any TronWeb method:

    All API references can be found in the project documentation at

    hashtag
    Method response:

    How to set up an account

    To start using GetBlock's services, you need to register an account. You’ll be ready to go in just a few clicks!

    1

    Go to GetBlock

    Visit the homepagearrow-up-right and click on the 'Dashboard' button in the upper-right corner, or use this direct linkarrow-up-right.

    2

    Choose the sign-up method

    • Register with Email

      Enter your name and email address, then verify your email to activate the account.

    • Sign in via Google

      Google will share your name, email, language preferences, and profile picture with GetBlock.

    3

    Review and accept policies

    During registration, you will be asked to accept our and .

    hashtag
    Access the dashboard

    Once you've created an account and signed in, you'll be directed to the GetBlock Dashboard. Here, you can create endpoints, monitor your usage plan, and access statistics.

    hashtag
    Check your User ID

    Find your GetBlock user ID located in the ‘Settings’ section or simply click your account icon to view and copy it. Please use it when contacting GetBlock’s team so we can identify your account and help you faster.

    Ethers.js integration

    Set up GetBlock as a provider using Ethers.js library to interact with the blockchain and streamline your dApp development process.

    Ethers.js is a lightweight JavaScript library for interacting with Ethereum and other EVM-compatible blockchains. It is commonly used by developers to build decentralized applications (dApps) and manage Ethereum-based operations like deploying smart contracts, interacting with them, and managing user wallets.

    hashtag
    Install Ethers.js

    Add Ethers.js to your project using your preferred package manager:

    • npm

    • yarn

    hashtag
    Set GetBlock as a provider

    For further details and advanced usage, explore the .

    Errors and troubleshooting

    This page provides a guide to common JSON-RPC and HTTP errors when testing your connection with GetBlock's API.

    hashtag
    Connection issues

    Code
    Error message
    Solution

    hashtag
    JSON-RPC errors

    Code
    Error message
    Solution

    Web3.js integration

    Learn how to use Web3.js, a widely-used JavaScript library for connecting to GetBlock nodes.

    Web3.js is a JavaScript library built for interacting with the Ethereum blockchain and other EVM-compatible chains. It is used to send JSON-RPC calls to the Ethereum node via HTTP, IPC, or WebSocket connection to read data from the blockchain, make transactions, or deploy smart contracts.

    hashtag
    Install Web3.js

    Use your preferred package manager:

    npm install web3
    yarn add web3

    hashtag
    Set up your connection to GetBlock

    For additional methods and options, refer to the official .

    Choosing your plan

    Compare GetBlock's subscription options to find the one that fits your project.

    GetBlock offers three main service options—Shared Nodes, Dedicated Nodes, and Enterprise Solutions. This page provides a high-level overview of these services.

    You can explore detailed pricing and plans from your dashboard in the “Pricing” section or via .


    hashtag
    Shared nodes

    How to generate accounts and send transactions

    This guide explains how GetBlock users can connect to blockchain nodes to create accounts and send transactions.

    In blockchains, ‘account’ should be referred to as a pair of private and public keys. Blockchains ‘recognize’ their users and balances by these keypairs.

    Unlike login/password pairs in traditional computational solutions, in modern blockchains, every account can be restored with a private key only.

    So, to broadcast transactions to a decentralized network, we need first to create (or restore) our account. The whole set of interactions is organized via Web3.js library.

    hashtag
    Creating accounts

    https://go.getblock.io/<ACCESS_TOKEN>/
    curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "jsonrpc": "2.0",
        "method": "eth_blockNumber",
        "params": [],
        "id": "getblock.io"
    }'
    {"jsonrpc":"2.0","id":"getblock.io","result":"0x1449641"}
    npm install tronweb
    yarn add tronweb
    How to pay with fiat on GetBlock
    Selecting fiat as a payment method
    changing billing data in GetBlock accounts
    How to pay for RPC nodes with crypto
    Crypto payments
    Connect with MetaMask

    Use a MetaMask wallet browser extension to sign up – no email or password required. If you don’t have a wallet extension installed, you’ll be prompted to add one.

  • Sign up with GitHub

    Use your GitHub credentials to set up an account.

  • Terms of Servicearrow-up-right
    Privacy Policyarrow-up-right
    How to create an account on GetBlock
    GetBlock's Sign-Up page, where users can register to access blockchain services
    GetBlock user dashboard for managing blockchain node access
    GetBlock user Dashboard
    How to find GetBlock user ID
    Where to find the GetBlock user ID
    How to manage GetBlock access tokens
    managing GetBlock CU balance
    How to add CU to your GetBlock RPC node package balance
    Switching from free GetBlock free plan to higher limit plans
    Increasing RPC node limits
    Customizing GetBlock's Enterprise plan usage limits
    How to track your blokchain API usage
    Managing your blockchain RPC node usage with notifications
    Using Postman Collection for Ethereum JSON-RPC request

    Simple transfers, individual swaps

    Arbitrage, multi-step operations

    Adding priority fees

    Via Multicall3

    Separate transaction in bundle

    mev_builders format

    Array: ["all"]

    Object: {"all": ""}

    Multicall3

    Most use cases

    Single nonce, atomic execution, slightly higher gas

    Bundle

    Advanced scenarios requiring separate transactions

    Two nonces, more complex setup

    Method

    bsc_privateTx

    mev_sendBundle

    Transaction count

    Single

    Multiple

    Atomicity

    Not applicable

    All-or-nothing execution

    Multicall3
    Bundle

    Use cases

    Parse error

    Double-check your JSON syntax. Ensure your request is properly formatted.

    401

    Access denied

    Double-check that <ACCESS_TOKEN> is correctly replaced with your actual token. Ensure there are no trailing spaces.

    404

    Could not resolve host

    Verify that the URL https://go.getblock.io/<ACCESS_TOKEN>/ is correct.

    429

    Too many requests

    Check your GetBlock account for usage limits. Upgrade your plan if necessary.

    32601

    The method does not exist/is not available

    Verify the method name (eth_blockNumber, eth_getBalance, etc.) against the blockchain's JSON-RPC specificationsarrow-up-right.

    32602

    Invalid argument

    Ensure the parameters in the params array match the expected format for the method.

    32700

    API Referencearrow-up-right
    npm install ethers
    yarn add ethers
    Ethers.js documentationarrow-up-right
    Web3.js documentationarrow-up-right
    dist/web3.min.js
    First, initialize the Web3.js library and set up the connection to a blockchain node:

    Next, we can create an account on the BNB Smart Chainarrow-up-right testnet:

    We can also restore an account from an existing private key:

    You may ask what does ‘eth’ mean when we’re interacting with BNB Chain? No mistake, it reflects the fact that BNB Smart Chain is fully compatible with Ethereum Virtual Machine.

    hashtag
    Sending transactions

    In blockchains, transactions should be signed (authorized) to be ‘included’ into blockchains (confirmed by its consensus of miners or validators).

    Here’s how our transactions are created. 0.01 ETH is used for demo.

    That’s how the transaction looks before being included in the blockchain. Once signed, it can be sent to the network of nodes.

    That’s it: your account is good to go and its transaction is submitted successfully!

    const Web3 = require('web3');
    
    //Set up the provider (replace ACCESS-TOKEN with your actual token)
    const web3 = new Web3('https://go.getblock.io/<ACCESS-TOKEN>/');
    curl --location --request POST 'https://go.getblock.io/<ACCESS_TOKEN>/' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "jsonrpc": "2.0",
        "method": "eth_blockNumber",
        "params": [],
        "id": "getblock.io"
    }'
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": "0x1449641"
    }
    curl --location --request POST 'https://go.getblock.io/<ACCESS_TOKEN>/' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "jsonrpc": "2.0",
        "method": "eth_chainId",
        "params": [],
        "id": "getblock.io"
    }'
    {
      "jsonrpc": "2.0",
      "id": "getblock.io",
      "result": "0x1"
    }
    curl --location --request POST 'https://go.getblock.io/<ACCESS_TOKEN>/' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "jsonrpc": "2.0",
        "method": "eth_getBalance",
        "params": ["<ACCOUNT_ADDRESS>", "latest"],
        "id": "getblock.io"
    }'
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": "0x5a70dac3910910"
    }
    // Import the Ethers library
    const { ethers } = require('ethers');
    
    // Set up the provider (replace ACCESS_TOKEN with your actual token)
    const provider = new ethers.JsonRpcProvider('https://go.getblock.io/ACCESS_TOKEN');
    
    //Call a method using the provider
    const main = async () => {
      const blockNumber = await provider.getBlockNumber();
      console.log("Latest Block Number:", blockNumber);
    };
    
    // Call the main function
    main();
    // Import the Web3 library
    const Web3 = require('web3');
    
    // Set GetBlock as the provider (replace ACCESS_TOKEN with your actual token)
    var web3 = new Web3('https://go.getblock.io/ACCESS_TOKEN');
    
    // Initialize web3 method
    web3.eth.getBlockNumber().then(console.log);
    // Generate new address and private key
    const accountTo = web3.eth.accounts.create();
    console.log('Generated account:', accountTo);
    // Restore account from private key
    const privateKey = process.env['privateKey'];
    const accountFrom = web3.eth.accounts.privateKeyToAccount(privateKey);
    const createSignedTx = async (rawTx) => {
    rawTx.gas = await web3.eth.estimateGas(rawTx);
    return await accountFrom.signTransaction(rawTx);
    }
    
    const sendSignedTx = async (signedTx) => {
    // You can use signedTx.rawTransaction as params for
    // calling eth_sendRawTransaction JSON-RPC method
    web3.eth.sendSignedTransaction(signedTx.rawTransaction).then(
    console.log
    );
    }
    
    const amountTo = "0.01" // ether
    const rawTx = {
    to: accountTo.address,
    value: web3.utils.toWei(amountTo, 'ether'),
    chainId: chainId
    };
    
    createSignedTx(rawTx).then(sendSignedTx)
    Shared nodes operate on a resource-sharing model, where multiple clients access the same underlying node infrastructure maintained by GetBlock.
    GetBlock shared node service options

    Our Shared Nodes deliver the perfect balance between affordability and performance:

    • Cost efficiency: Benefit from our pricing model based on Compute Units (CU), so you only pay for the resources needed for your current workload.

    • Flexible pricing: Options range from a free to high-volume plans — accessible for individual developers and smaller teams while supporting the scaling needs of growing dApps.

    • Consistent performance: Each plan enforces a Requests Per Second (RPS) limit, preventing individual spikes from impacting overall quality.

    • Multi-chain accessibility: Prototype, test, and deploy applications across different networks without the complexities of deploying infrastructure for each blockchain individually.

    • Regional endpoints: Connect to the nearest datacenter — Frankfurt (EU), New York (US), Singapore (APAC) — to minimize network latency.

    • Archive data access: Run full historical blockchain queries.

    • Tiered support levels: Support options adapt to your requirements, from basic help to priority support when you need it most.

    circle-check

    This option is ideal for developers and teams looking for reliable connectivity to various blockchain networks without the higher costs of dedicated server resources.


    hashtag
    Dedicated nodes

    A Dedicated Node is a private RPC server deployed solely for your use case. That means consistent throughput, no API rate throttling due to other users, and better uptime guarantees.

    circle-check

    If your project demands the fastest, most reliable blockchain infrastructure, a Dedicated Node from GetBlock is a perfect choice.

    GetBlock private node features and pricing

    This option is ideal for users that require high performance, full control over node configuration, and a flawless connection to the blockchain without any limitations:

    • Mission-critical reliability: Maximized uptime and robust failover mechanisms for even more reliable service.

    • Unlimited usage: No per-second request caps or CU tracking.

    • Low latency: With servers available in Europe, Asia, and the USA, choose the optimal server location to minimize latency and enhance performance for your users.

    • Fully customizable: Complete control over your node configurations, including access to archive data.

    • Predictable pricing:

      • Full Node: from $1,000/month;

      • Archive Node: from $1,500/ month.

    • Expert support: 24/7 coverage and immediate issue resolution.

    circle-info

    A few high-resource blockchain settings (e.g., Solana mainnet, Arbitrum mainnet, NEAR mainnet) may come with custom pricing due to their intense infrastructure requirements.


    hashtag
    Enterprise solutions

    This option is designed to meet the needs of organizations operating at scale or applications that require extra resources, features, and dedicated support.

    What’s included:

    • 99.9% uptime guarantee

    • Customizable node configurations and integrations

    • Performance optimization via load balancers

    • Advanced analytics and alert systems

    • Priority assistance from GetBlock experts

    Visit the Enterprise Solutions pagearrow-up-right to learn more about how we tailor services to fit complex, high-demand environments.

    https://getblock.io/pricing/arrow-up-right
    https://developers.tron.network/referencearrow-up-right
    tronWeb.trx.getBlock(blockNumberOrBlockId) method response

    Enabling archive mode

    Enable Archive Mode on your GetBlock Shared Node API to access the full blockchain history and run historical queries

    GetBlock provides direct access to blockchain historical states through both the Dedicated Nodes service and archive-enabled Shared RPC endpoints.

    This page covers Archive Mode – a setting that turns on archive-node access within GetBlock’s Shared Nodes subscription.

    Common RPC use cases enabled by Archive Mode:

    • Read contract/account state at any past block, not just latest , using methods like eth_getBalance(address, blockNumber), (contract, slot, blockNumber), (address, blockNumber), etc.

    • Call view functions against historical state: e.g. (..., blockNumber).

    • Run historical queries and debugging that rely on old state: forensics, audits, explorers, indexing, and retroactive analytics.

    • Support tracing and higher-fidelity debugging that may require historical state.

    This feature removes the need to run a dedicated archive infrastructure for some use cases, letting developers perform on-demand historical queries via GetBlock RPC API.


    hashtag
    Archive mode availability & coverage

    Archive functionality is included with all Shared Node subscriptions, excluding the Free plan. No additional fee required.

    Archive support is provided for a set of popular protocol mainnets, including Ethereum, BSC, Polygon, Base, Arbitrum, TRON, Sui, Cardano, etc.

    Look for the small history icon ( ) when picking a protocol during the . It indicates that Archive mode is available for that blockchain.

    circle-check

    If you need an archive data for a chain not covered by shared Archive mode, request a . Dedicated Nodes can be deployed in archive mode for any supported blockchain and come with additional benefits like:

    1. Full blockchain history at the highest throughput


    hashtag
    How to enable the Archive mode

    1. Sign in to your GetBlock dashboard and make sure you’re on the Shared Node tab.

    2. Click Get endpoint and choose a required blockchain protocol.

    1. Find the Mode toggle and switch the Archive mode on.

    1. Finish configuring endpoint details by choosing the API interface and server location as usual.

    After clicking Get, the new Archive endpoint appears in your Endpoints list. The endpoint URLs will follow the existing GetBlock format but point to archive nodes.


    hashtag
    CU billing for Shared Archive endpoints

    Archive endpoints usage remains subject to your plan’s .

    However, serving requests from archive infrastructure involves heavier storage and compute power compared to regular full nodes.

    Therefore, enabling the Archive mode affects how CU usage is calculated:

    • GetBlock applies a 2× Compute Unit (CU) multiplier to all requests made through the Archive endpoint.

    • The multiplier is applied to all requests made to an archive endpoint, even if the invoked RPC call does not require a historical state.

    You can review the per-chain CU values for each method on our page.

    Example:

    If eth_getBalance costs 20 CU on a standard shared endpoint for a given chain, the same call to an Archive-enabled shared endpoint will cost 40 CU.

    Plan accordingly and consider using standard Full mode endpoints for non-archive traffic to avoid unnecessary CU consumption.


    hashtag
    Best practices

    • Use archive endpoints only for workloads that require a historical state. For transactions or current state queries, use a standard Full mode to save CU.

    • Monitor CU consumption on the dashboard and set alerts for spikes or when usage nears your plan limit.

    • If you run sustained, high-volume archive queries, consider using a Dedicated Node.


    hashtag
    💬 Need help with archive blockchain data?

    what you’re building — our team can guide you to the most efficient archive node setup.

    Dedicated node performance tiers

    GetBlock’s Dedicated Nodes are available in two performance tiers – High and Standard. Choose the right balance of performance and cost for your private infrastructure

    Dedicated Nodes are fully private blockchain nodes deployed and managed for your team. With two distinct performance presets, you can balance throughput, SLA, and budget to fit your workload.

    Available tiers:

    1. High Performance Tier: Designed to provide maximum available resources, throughput, and reliability. It is intended for applications where performance and availability are critical. The focus is on delivering the highest service levels and supporting the most demanding production workloads.

    2. Standard Performance Tier: Designed to offer enterprise-grade performance sufficient for the majority of professional and business use cases, but at a more cost-efficient level. It targets demanding business applications and sustained usage, but without the additional (and sometimes excessive) headroom reserved for High Performance tier.

    By providing these options, GetBlock helps you to deploy Dedicated Nodes that are tailored to your application’s technical, operational, and budget requirements.


    hashtag
    Dedicated Node tiers overview

    When deploying a Dedicated Node, you can choose between High and Standard setups to align with your application’s resource needs and expected workload.

    • Select High if your workload is latency-sensitive, demands very high concurrent throughput, or is critical to business continuity.

    • Select Standard for typical production apps, where workload is within supported performance bounds.

    Configuring tiers is available for all supported protocols unless there are specific infrastructure limitations for a given network. In this case, a chain will only support a single tier.

    circle-check

    Always check available configurations in your dashboard

    hashtag
    Reference High vs Standard tier comparison

    Feature
    High Performance
    Standard Performance

    hashtag
    Dedicated Node pricing

    Dedicated Nodes are billed at a set monthly rate determined by configured settings:

    1. Performance tier: Total cost scales with the performance tier selected – High tier is priced at a premium relative to the Standard tier.

    2. Blockchain network: Each protocol has different hardware requirements, which impact both High and Standard tier pricing.

    3. Node mode: Full or Archive.

    Refer to your Dashboard for up-to-date pricing details and protocol-specific options.

    circle-check

    Monthly costs are always shown during configuration in the Dashboard for each supported network and region.


    hashtag
    Steps to configure dedicated node tiers

    To select a tier during node setup, open the Dedicated Node dashboard:

    1. Select protocol, network, deployment region, node mode, and a preferred client.

    2. As a final step, choose the Performance Tier (High or Standard).

    1. Review updated performance and pricing details.

    Your dedicated node will be ready for use upon activation. To switch between tiers after deploying, reach out to support.


    hashtag
    Need a more customized setup?

    For advanced workloads or unique requirements, our engineering team can help craft a custom private node solution beyond the High/Standard presets. for tailored deployments.

    Connect to GetBlock with MetaMask

    Learn how to set up custom RPC URL on MetaMask for faster, more reliable, and secure blockchain interactions.

    MetaMask is a blockchain wallet available as a mobile application and a browser extension. It allows you to interact with Ethereum-based decentralized applications (dApps) directly from your browser.

    circle-check

    Using GetBlock nodes with MetaMask makes your blockchain experience faster and more reliable than using default RPCs:

    • Connect directly to trusted nodes for secure transactions.

    • Enjoy quicker transactions and smoother dApp interactions.

    • Experience less downtime, even during busy network periods

    This step-by-step tutorial will guide you through connecting GetBlock’s powerful nodes to your MetaMask wallet.


    hashtag
    Before you start

    hashtag
    Set up your wallet

    If you don’t already have MetaMask, download and install it from the official website: .

    MetaMask extension is officially supported on Chrome, Brave, Firefox, Microsoft Edge, and Opera browsers.

    hashtag
    Get a custom RPC URL

    Generate a JSON-RPC URL for the selected network from your GetBlock and copy it.

    circle-info

    Rename your endpoints to clearly indicate their purpose.


    hashtag
    Add GetBlock RPC to an existing network

    If the network is already in your list but uses a default RPC provider, you can switch to GetBlock by following these steps:

    1. Click on the current network name in MetaMask to open the dropdown of networks.

    2. Find the network you want to edit and click the settings menunext to it. Select 'Edit'.

    1. Open the ‘Default RPC URL’ dropdown and select 'Add RPC URL'.

    2. Paste the JSON-RPC endpoint URL from your GetBlock account (https://go.getblock.io/<ACCESS_TOKEN>/).

    3. Name the new RPC URL for easier identification.

    1. Click 'Add URL', then 'Save' to confirm.

    You can now switch between RPC URLs for that network as needed.


    hashtag
    Add a new network to MetaMask

    If the network isn’t in your list, you can add it as a custom network. For this example, we will add the Polygon zkEVM to MetaMask.

    1. Click on the current network name.

    2. Select 'Add a custom network'.

    1. Fill in the required fields:

    Field
    Description
    Example
    1. Click 'Save', and the custom network will be added and selected as default.

    circle-info

    You can get the Chain ID of an EVM-compatible network (e.g. Polygon zkEVM) sending a request to your endpoint with this curl command:

    Creating node endpoints

    Follow the steps below to set up an endpoint and generate access tokens for your project.

    This short guide shows you how to create an RPC endpoint (an RPC URL) for any supported protocol in your GetBlock Shared Node dashboard to connect it to your app, script, or wallet.

    circle-check

    In GetBlock, an endpoint URL includes your unique Access Token — the credential that authenticates RPC requests. GetBlock’s UI sometimes labels the whole endpoint provisioning flow “Get Access Token” because a new RPC URL is created together with the token.

    Related:


    The steps below cover how to generate a new endpoint URL with an Access Token:

    1

    Log in to your GetBlock account and navigate to the Dashboard

    2

    Find the Endpoints section on the Dashboard

    3

    Generate and add as many access tokens as required for this protocol. Each token is a unique endpoint for you and your application to interact with the blockchain.

    circle-info

    All GetBlock endpoints follow a predictable format. The visible difference is the hostname reflecting the region selected during the setup.

    Endpoint examples:

    The token encodes the protocol, networks, and routing on the server — clients don’t need to specify a chain in the URL.


    hashtag
    Full vs Archive mode

    When creating an endpoint in your GetBlock Dashboard, for select protocols, you can choose between two node access modes – Full and Archive. This selection determines how much historical blockchain data your endpoint can access.

    • Full mode: Standard full (pruned) node behavior — current state lookups, sending transactions, reading blocks, etc.

    • Archive mode: Enables access to the historical chain state. Useful for querying balances, contract storage, UTXO sets, executing historical calls, simulating transactions at a past block, or reconstructing chain state for analytics and audits.

    circle-info

    Selecting the Archive mode for an endpoint changes how requests are billed in Compute Units (CU). Learn more in the .


    hashtag
    Viewing and managing endpoints

    The created URL is shown on the endpoints list so you can copy it and start calling the node. Use the right-side menu () to roll (regenerate) or delete the endpoint from the list.

    circle-exclamation

    Because the Access Token is embedded, the URL is the credential. Keep it secret and store securely. If the URL is exposed, regenerate or revoke it from your GetBlock account.

    Configuring dedicated nodes

    Deploy dedicated nodes from your GetBlock Dashboard. Fully self-service. This guide covers customizing your node settings and completing the setup process.

    To deploy a private blockchain server, switch over to the ‘Dedicated Nodes’ tab in the Dashboard.

    Select a blockchain protocol from the list or click Create new node to begin the setup process from scratch. A dedicated node setup modal will open.

    hashtag
    Step 1: Configure your node

    In the setup window:

    1. Select the blockchain protocol and the network type (e.g., mainnet, testnet, devnet, etc)

    2. Customize your dedicated node with the following options:

      1. Node type: Choose between Full Node or Archive Node

    Verify all selected configurations in the summary section and proceed to the next step.

    hashtag
    Step 2: Select add-ons

    On the Add-ons screen, you can extend your node with additional capabilities:

    • Included add-ons are available at no extra cost depending on your configuration

    • Advanced add-ons are billed in addition to the base node price

    Select any add-ons you need and click Next.

    hashtag
    Step 3: Payment

    On the final screen:

    1. Review the final pricing and node settings

    2. Billing Contact — Enter your contact information so the GetBlock team can notify you when your node is ready.

    3. Payment method — Choose between Credit Card or Crypto.

    Once payment is confirmed, the deployment status will be visible on your Dashboard → Dedicated Nodes tab and Pricing → Manage Plans. Track the payment status from Pricing → Payment History.

    circle-info

    You can also create additional dedicated nodes by repeating these steps. If additional support is required during setup, you can contact the GetBlock support team directly from your dashboard.


    hashtag
    Managing your dedicated node

    Once your node is deployed, it appears in the left-hand sidebar. Each node has its own page — select a node from the sidebar to open it.

    Three tabs are available for managing the node:

    1. Endpoints: lists all endpoints associated with your node. To add a new one, click + Get endpoint. You can create multiple endpoints per node with different API interfaces. Endpoints for add-ons can also be created from this tab.

    2. Add-ons: the central place to manage all add-ons. From here you can add a new add-on to an existing node, cancel an active add-on, create an endpoint.

    3. Statistics: provides a detailed breakdown of usage metrics for your node.

    Use the Invoices and Subscription buttons in the top-right corner of the node view to manage billing.

    StreamFirst

    An infrastructure for delivering the fastest on-chain updates by combining software-level acceleration (Fast Yellowstone) with optimized network traffic and routing (via shred-stream).

    StreamFirst is GetBlock's infrastructure solution for delivering faster (ultra-low latency) on-chain state updates from the Solana blockchain.

    By combining software-level acceleration with network-level optimization, StreamFirst enables developers to receive blockchain data faster than traditional RPC methods. This reduces the consistent polling updates, which either lead to timeouts or rate-limiting issues.

    Interested in building on Solana with StreamFirst? for more information.

    hashtag

    Solana Indexed Archive

    Solana indexed archive data that allows users to efficiently query any historical information.

    Solana Indexed Archive is a software development kit(SDK) that provides an indexed data layer, enabling instant access to the complete Solana blockchain history and real-time data through a single, high-performance API. Built on SQD Network infrastructure, it eliminates the need to work with raw Solana data, run archive nodes, or maintain complex indexing logic.

    Interested in building on Solana with Indexed Archive? for more information.

    hashtag
    The Indexed Archive Solution

    Using GetBlock configuration files

    GetBlock’s configuration file provides a more organized and flexible way to interact with blockchain nodes and networks without exposing sensitive API keys or credentials in the code.

    hashtag
    How to make HTTP requests with curl using JSON config file

    Using GetBlock’s JSON configuration file with curl is particularly helpful when you need to access various node endpoints without hardcoding API keys in the code:

    BSC Accelerated Dedicated Node

    GetBlock's BSC Accelerated Dedicated Node enables users to have direct access to fast, robust, and high-performance network layers.

    BSC accelerated node is a high-performance dedicated node deployed on top of high-speed networking layers via the Blockchain Distributed Network (BDN). It observes state changes, mempool activity, and block production events significantly faster than standard peer-to-peer setups, serving traders, validators, dApps, and more with low latency.

    Interested in building on BSC using an Accelerated Dedicated Node? for more information.

    hashtag
    How It Works

    /v1 - Aptos

    Example code for the /v1 JSON-RPC method. Сomplete guide on how to use /v1 json-rpc in GetBlock.io Web3 documentation.

    This endpoint retrieves the latest information from the Aptos blockchain ledger, such as current chain ID, node role, latest and oldest ledger versions, epoch, block height, and more. In short, it provides an overview of Aptos and its health status.

    hashtag
    Supported Network

    • Mainnet


    /v1/accounts/{account_hash} - Aptos

    Example code for the /v1/accounts/{account_hash} json-rpc method. Сomplete guide on how to use /v1/accounts/{account_hash} json-rpc in GetBlock.io Web3 documentation.

    This endpoint retrieves account details, such as the number of transactions submitted by an account and its authentication key.

    hashtag
    Supported Networks

    • Mainnet

    TradeFirst

    An infrastructure that combines other GetBlock and external infrastructures, specifically designed for high-frequency traders (HFT) on Solana.

    TradeFirst is an infrastructure that combines other GetBlock and external infrastructures, specifically designed for high-frequency traders (HFT) on Solana. It combines multiple performance optimizations:

    • fast data streaming (StreamFirst)

    • intelligent transaction routing (LandFirst)

    into a single, integrated solution for professional trading operations.

    Overview

    Yellowstone gRPC is a Solana Geyser plugin developed by Triton One that feeds your application a continuous, low-latency stream of on-chain data

    Solana applications often need live, high-throughput access to on-chain events. Solana gRPC plugin solves this core problem of real-time blockchain data access.

    hashtag
    What is Yellowstone gRPC?

    Yellowstone gRPC is the name given to the Dragon’s Mouth Geyser plugin’s gRPC interface in Triton One’s “Yellowstone” suite for Solana. It allows opening streams and subscribing to native Solana on-chain events, receiving every new update in real time, with millisecond-level latency.

    /v1/estimate_gas_price - Aptos

    Example code for the /v1/estimate_gas_price json-rpc method. Сomplete guide on how to use /v1/estimate_gas_price json-rpc in GetBlock.io Web3 documentation.

    This endpoint gets the estimated gas price for executing a transaction in the Aptos blockchain network.

    hashtag
    Supported Network

    • Mainnet

    const TronWeb = require('tronweb');
    const tronWeb = new TronWeb({
    fullHost: "https://go.getblock.io/<ACCESS-TOKEN>/"
    })
    const fullNode = new TronWeb.providers.HttpProvider("https://go.getblock.io/<ACCESS-TOKEN>/")
    const solidityNode = new TronWeb.providers.HttpProvider("https://go.getblock.io/<ACCESS-TOKEN>/")
    const eventServer = new TronWeb.providers.HttpProvider("https://go.getblock.io/<ACCESS-TOKEN>/")
    const tronWeb = new TronWeb(fullNode, solidityNode, eventServer)
    tronWeb.trx.getBlock('latest').then(result => {console.log(result)});
    By plugging directly into validators, it pushes new blocks, transactions, and account updates to your backend the moment they occur.

    hashtag
    How Yellowstone gRPC Geyser works

    The Geyser Plugin hooks into validator callbacks for ledger events and publishes those events to its own internal queues. A gRPC server then streams the queued events over the network to subscribed clients.

    hashtag
    Supported data streams & subscriptions

    Geyser gRPC supports streaming the full range of common Solana events:

    • Account updates (writes): Every time an account’s data changes, a notification is emitted.

    • Transactions: Each transaction processed by the leader generates a stream event with all associated account changes.

    • Ledger entries: Low‑level entry/shred events (raw blocks of ledger data) can also be streamed.

    • Block notifications: Clients can subscribe to be notified when a new block is completed.

    • Slot notifications: New slot boundaries (leaders or votes) can trigger slot events.

    Every update stream can include full transaction metadata, instruction details, and parsed logs – essentially everything you’d see in a getTransaction or getProgramAccounts call, but pushed in real time.

    In addition to streaming methods, Dragon’s Mouth also exposes several unary RPCs via the same gRPC interface for quick queries about:

    • The Slot;

    • Block height;

    • Latest blockhash;

    • Valid blockhash.

    Together, this provides a way to both fetch state on demand and receive updates in real time.


    hashtag
    Yellowstone gRPC API features

    • Near-zero latency: By streaming directly from leaders, Dragon’s Mouth delivers updates often hundreds of milliseconds faster than standard RPC/WebSocket APIs.

    • High throughput: The plugin can handle millions of events per minute under load, built for Solana’s high transaction volume. Optional compression can be applied for even more efficiency.

    • Built-in support for bi-directional streaming: Keep-alives, ping/pong frames help maintain long-lived connections.

    • Comprehensive streaming: Clients can monitor virtually anything: token mints, program interactions, votes, etc.

    • Protobuf/binary encoding: Each message arrives parsed and typed, not raw base64. Clients get structured fields (account diffs, token balance changes, parsed logs, etc.) instead of raw blobs.

    • Rich filtering: You can apply filters (by account key, owner program, data patterns, commitment level, etc.) so only matching updates are streamed.

    Overall, applications can keep pace with Solana’s peak TPS without data loss, receive only relevant updates, save bandwidth, and react faster.


    hashtag
    Solana Geyser gRPC plugin use cases

    Solana gRPC streaming capabilities are crucial for time-sensitive applications, apps that need to react the moment on-chain state changes without manual refreshes.

    gRPC API ideal use cases include:

    • High-frequency trading or arbitrage systems (e.g. MEV bots);

    • On-chain indexers & archives;

    • Live analytics;

    • Real-time monitors for DEXes, NFTs, wallets, etc.;

    • Alerting & notification systems;

    • DeFi strategy engines;

    • ..and any app that needs push‑style updates.

    circle-info

    Note that gRPC is not supported in browsers, so Yellowstone is intended for backend services.


    hashtag
    Why use Yellowstone gRPC API?

    Using Yellowstone gRPC for your Solana data means you get a high-throughput, low-latency, bidirectional streaming channel.

    Instead of polling REST endpoints every few seconds or using Solana’s WebSocket API (which typically only updates after a block finalizes), the gRPC interface allows tracking every new event down the wire as it happens.

    Overall, it removes much of the boilerplate: your backend code subscribes once, then simply reacts to incoming messages

    Unlimited query capacity
  • Custom node builds & tooling

  • eth_getStorageAt
    eth_getCode
    eth_call
    endpoint setup
    Dedicated Node
    CU limits and performance characteristicsarrow-up-right
    Compute Unitsarrow-up-right
    Tell usarrow-up-right
    Archive blockchain data access via GetBlock RPC endpoints
    Get RPC endpoint button on GetBlock's dashboard
    history/clock icon
    GetBlock shared RPC node pricing options
    What does it cost to deploy a private blockchain node
    Pick a deployment location: Germany (Frankfurt), USA (New York), Singapore
  • Node client: Choose your preferred node implementation (e.g., Geth)

  • API interface: Review available interface types

  • Under the Performance section, select a performance tier:

    1. High: premium specs, max throughput

    2. Standard: enterprise specs, optimized pricing for moderate-high loads

  • Choose a subscription length — 1, 6, or 12 months — at the top of the summary panel (available discounts are applied automatically)

  • Subscription — Enable the subscription toggle if you want to ensure your node renews automatically each billing cycle.

  • When ready, click Go to Payment.

  • GetBlock Dedicated RPC node add-ons
    GetBlock private blockchain server ordering
    How to use GetBlock dedicated nodes
    How to set up a private blockchain node with GetBlock
    GetBlock dedicated node configuration tool

    99.9% uptime

    99.5% uptime

    Recommended for

    Applications with high transaction volumes & large user bases, mission-critical systems, and any workflow where latency and throughput are the top priority

    Most production dApps, wallets, and enterprise tools or projects that need guaranteed resources but do not require the maximum performance tier

    Client parameters.

    Resource allocation

    Maximum hardware and bandwidth

    Balanced hardware profile

    Throughput

    Highest supported

    High

    Contact usarrow-up-right
    GetBlock private node configuration tool with pricing
    Dedicated Node pricing in the GetBlock Dashboard
    Setting up a Dedicated Node performance tier via GetBlock dashboard

    SLA

    GetBlock Product Demo

    Fetched automatically based on Chain ID

    Polygon zkEVM

    Currency symbol

    Suggested automatically based on Chain ID

    ETH

    Block explorer URL

    Optional field

    https://zkevm.polygonscan.com/

    RPC URL

    The network's JSON-RPC URL from your GetBlock account

    https://go.getblock.io/<ACCESS_TOKEN>/

    Chain ID

    The ID of the network

    1101

    https://metamask.io/downloadarrow-up-right
    accountarrow-up-right
    How to get a custom RPC URL for MetaMask
    Generate an RPC URL for MetaMask
    How to set up the custom RPC URL on MetaMask
    How to change the RPC URL on MetaMask
    Adding a new network to MetaMask using custom RPC URL

    Network name

    Download the getblock.config.json file from your GetBlock account;
  • Make sure you have jqarrow-up-right installed. jq is a versatile command-line tool that enables extracting values from JSON files;

  • Navigate to your workspace or directory where you have imported the getblock.config.json file and open a terminal;

  • Now, you can make a GET request to a selected node endpoint using the curl command:

  • hashtag
    How to use GetBlock’s JavaScript config with Web3.js

    Connect to Ethereum nodes and other EVM-compatible networks using web3.js and GetBlock’s JS configuration file.

    1. Make sure the web3.js library is added to your project. In order to do that, use one of the following methods:

    • Npm: npm install web3

    • Yarn: yarn add web3

    • Pure js link: dist/web3.min.js

    1. Download the getblock.config.js file from your GetBlock account. Add this file to your project directory.

    2. Import the getblock module to a .js file that configures a new Web3 instance:

    1. Connect to an Ethereum node and start sending API calls using web3.js over HTTP or WebSocket in the format below:

    Use go() method to access an entire endpoint or token() to fetch the token.

    hashtag
    How to use the JS config with Hardhat

    Set up GetBlock’s JS config file in Hardhat following the steps below:

    1. Ensure you have Hardhat installed as a dependency in your Node.js project or run the following command to do so:

    1. Navigate to your GetBlock account and install the getblock.config.js file. Copy and paste it into your working directory;

    2. Open the hardhat.config.js file from your project directory and import the getblock module:

    1. To set up GetBlock as a provider, modify the Hardhat configuration file with the credentials as shown below. Use go() method to access an entire endpoint or token() to fetch the token only.

    hashtag
    Parameters
    Parameter
    Data type
    Description
    Required
    In

    account_hash

    string

    Aptos account address

    Yes

    Path


    hashtag
    Request Example

    URL

    Example

    hashtag
    Response

    hashtag
    Response Definition

    Value
    Type
    Description

    sequence_number

    string

    The number of transactions that have been submitted and committed from the account.

    authentication_key

    string

    The authentication key associated with the account, in hex-encoded format.

    hashtag
    Use Cases

    This method can be used for:

    • Wallets to fetch sequence numbers before sending transactions (to prevent replay attacks).

    • Creating an account overview page or profile in a dApp.

    • Validating if an account exists on-chain to avoid sending assets to the wrong account.

    hashtag
    Code Examples

    hashtag
    Python (requests)

    hashtag
    Node.js (Axios)

    Replace <ACCESS_TOKEN> with your actual access token from GetBlock.

    hashtag
    Error Handling

    You may encounter responses like:

    This means the account hash is incorrect or the account does not exist on-chain at the current ledger state.

    • 403 → Access token is missing.

    hashtag
    Integration with Web3

    By integrating /v1/accounts/{account_hash}, developers can:

    • Fetch sequence numbers for transaction signing.

    • Validate account existence and state (useful for onboarding users).

    • Support wallet and dApp account management.

    • Enable reliable transaction pipelines.

    curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/' \
      --header 'Content-Type: application/json' \
      --data-raw '{
        "jsonrpc": "2.0",
        "method": "eth_chainId",
        "params": [],
        "id": "getblock.io"
      }'
    curl -X GET https://go.getblock.io/"$(jq -r '.shared.btc.mainnet.rest[0]' getblock.config.json)"/rest/chaininfo.json
    const { getblock } = require('./getblock.config.js');
    const { getblock } = require('./getblock.config.js');
    var Web3 = require('web3');
    
    // Create the JSON-RPC provider
    var web3Rpc = new Web3(new Web3.providers.HttpProvider(
            getblock.shared.eth.mainnet.rpc[0].go()
    ));
    
    // Create the WebSocket provider
    var web3Ws = new Web3.providers.WebsocketProvider(
            `wss://go.getblock.io/${getblock.shared.eth.mainnet.ws[0].token()}`
    ));
    npm install --save-dev hardhat
    const { getblock } = require('./getblock.config.js');
    const { getblock } = require('./getblock.config.js'); 
    
    module.exports = {
      defaultNetwork: "sepolia",
      networks: {
        hardhat: {
        },
        sepolia: {
          url: getblock.shared.eth.sepolia.rpc[0].go() // https://go.getblock.io/<ACCESS-TOKEN>/
        },
        goerli: {
          url: `https://go.getblock.io/${getblock.shared.eth.goerli.rpc[0].token()}` // <ACCESS-TOKEN>
        },
      },
      solidity: {
        version: "0.8.19",
        settings: {
          optimizer: {
            enabled: true,
            runs: 200
          }
        }
      },
      paths: {
        sources: "./contracts",
        tests: "./test",
        cache: "./cache",
        artifacts: "./artifacts"
      },
      mocha: {
        timeout: 40000
      }
    }
    https://go.getblock.io/<ACCESS-TOKEN>/
    curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f'
    {
      "sequence_number": "234541",
      "authentication_key": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f"
    }
    import requests
    
    url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f"
    
    response = requests.get(url)
    
    print(response.text)
    import axios from 'axios';
    
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f',
    };
    
    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });
    {
      "sequence_number": "0",
      "authentication_key": "0x00000000000000000000000bf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f"
    }
    Click Get endpoint to open the endpoint setup menu
    4

    In the modal that opens, select:

    • The desired blockchain protocol (Ethereum, BNB Chain, Polygon, etc.)

    • The network you want to interact with: mainnet or testnet

    • Node mode: full (default) or archive

    • The API interface that you need (JSON-RPC, WebSockets, GraphQL, etc.)

    • One of the available server locations (Frankfurt, New York, or Singapore)

    5

    Click 'Get' and have the endpoint URL with an access token generated.

    Access token management
    GetBlock Deploys Major Security Upgrade: Introducing Access Tokensarrow-up-right
    Archive mode guide
    Blockchain RPC nodes list within the GetBlock account
    Core Stack

    StreamFirst consists of two core optimization layers:

    1. Software-level acceleration: Accelerated Yellowstone gRPC implementation

    2. Network-level acceleration: Optimized shred-stream delivery via direct validator connections.

    StreamFirst optimizes the entire pipeline from validator broadcast to application delivery:

    • The network layer ensures the earliest possible data reception

    • Software layer ensures minimal processing latency

    • Result: Fastest end-to-end delivery of on-chain state updates

    hashtag
    How It Works

    hashtag
    Accelerated Yellowstone gRPC

    Yellowstone is a high-performance Geyser plugin that streams real-time blockchain data via gRPC interfaces. As a result of our partnership with the core Yellowstone team members, GetBlock's Accelerated Yellowstone implementation includes:

    • Optimized data serialization: Optimized the original version of the low-level logic to improve the speed of state updates compared to the original Yellowstone implementation, and reduced overhead in encoding and transmitting blockchain state.

    • Enhanced filtering mechanisms: More efficient subscription management for accounts, transactions, slots, and blocks

    • Improved connection handling: Better resource management for sustained high-throughput streams

    hashtag
    Shred-Stream Network Optimization

    Solana validators propagate blocks by breaking them into small fragments called "shreds" and distributing them via the Turbine protocol. StreamFirst taps into this raw data stream:

    • Direct shred reception: Receives block fragments (shreds) via UDP as validators broadcast them.

    • Early state reconstruction: Rebuilds block data before it's fully confirmed and distributed via standard RPC

    hashtag
    Frankfurt Data Center - Europe's Solana Hub

    GetBlock operates as a top-tier Solana node provider in Frankfurt, a zone with the highest density of Solana validator stake. This strategic positioning provides:

    • Proximity to major validators: Direct access to high-stake validators concentrated in the region

    • Ultra-low network latency: 6ms latency within Europe

    • Optimal shred reception: Positioned to receive validator broadcasts with minimal delay

    The combination means you get blockchain state updates as validators are producing blocks, not after they've been fully processed and distributed.

    hashtag
    Technical Architecture

    Data Flow:

    1. Block Production: Solana validators produce blocks and fragment them into "shreds."

    2. State Reconstruction: Shreds are decoded and reassembled into transactions and account updates

    3. Accelerated Processing: Optimized Yellowstone plugin processes data with reduced overhead

    4. Client Delivery: Structured blockchain data streams to your application via standard gRPC

    hashtag
    Why StreamFirst is Important for Developers

    hashtag
    Speed Advantages

    Traditional RPC methods introduce latency at multiple stages:

    • Waiting for block confirmation

    • HTTP request/response overhead

    • JSON parsing and serialization

    StreamFirst bypasses these bottlenecks by:

    • Receiving data at the validator propagation speed

    • Using binary gRPC protocol (faster than JSON)

    • Streaming continuously without polling

    circle-check

    Typical latency improvements: 25-30ms faster than standard Yellowstone gRPC

    hashtag
    Use Cases

    StreamFirst is ideal for applications where milliseconds matter:

    • High-frequency trading bots: React to price changes before slower competitors

    • MEV searchers: Identify arbitrage opportunities in real-time

    • DeFi protocols: Monitor liquidation events and oracle updates instantly

    • NFT sniping tools: Detect new listings and mints before they propagate widely

    • Analytics platforms: Collect comprehensive on-chain data with minimal delay

    • Wallet applications: Show users' balance and transaction updates in real-time

    hashtag
    Data Types Available

    StreamFirst supports all standard Yellowstone gRPC subscription types:

    • Account updates: Monitor balance changes, data modifications, and ownership transfers

    • Transaction streams: Receive all transactions or filter by program/account

    • Slot updates: Track block production and commitment levels

    • Block data: Full block information, including all transactions and metadata

    • Program logs: Subscribe to specific program execution logs

    hashtag
    Deployment and Availability

    StreamFirst is available as an add-on for GetBlock's dedicated Solana nodes. It's configured as a plugin in the node configurator and requires:

    • Dedicated node subscription

    • Geographic proximity to GetBlock's validator network for optimal performance

    • Additional fee based on data throughput requirements

    hashtag
    Conclusion

    StreamFirst gives developers a competitive edge by delivering Solana blockchain data at near-validator speed. The combination of accelerated Yellowstone software and optimized shard-stream networking, optimized shred-stream networking, and strategic Frankfurt positioning ensures low latency between your customer and dedicated node. This ensures your dApp has the earliest possible view of on-chain activity—critical for time-sensitive operations in DeFi, trading, and real-time analytics.


    For consultation on optimal deployment architecture for your specific use case, contact GetBlock support teamarrow-up-right

    Reach usarrow-up-right

    Complete historical index: Every block, transaction, instruction, log, and account update already parsed, normalized, and ready for queries

  • Unified access layer: Single endpoint for both historical queries and live subscriptions

  • Developer-friendly SDK: Typed queries, easy integration, no low-level Solana structures Zero operational overhead: GetBlock operates all infrastructure

  • Instant availability: Full Solana history accessible immediately, no setup or backfilling

  • Using the SDK, you can easily build ETL pipelines that extract and transform on-chain data without handling raw Solana events, decoding account structures, or maintaining complex indexing logic. All blockchain data has already been extracted, indexed, and is immediately ready to use. Your only task is to define the query and specify the required filter.

    hashtag
    Technical Architecture

    hashtag
    Layer 1: SQD Network - Decentralized Indexing

    SQD Network continuously processes Solana's blockstream in a decentralized manner:

    • Block processing: Every Solana block parsed immediately upon production

    • Data extraction: Transactions, instructions, logs, account updates extracted

    • Normalization: Raw data decoded and structured following standard schemas

    • Enrichment: Relationships between transactions, accounts, and programs established

    • Distributed storage: Indexed data stored across decentralized SQD infrastructure

    hashtag
    Layer 2: GetBlock Portal - High-Performance Access Layer

    GetBlock deploys and maintains a global network of Portal instances—high-performance gateways that:

    • Provide unified interface: Single API endpoint for historical data and real-time subscriptions

    • Ensure low latency: Geographically distributed clusters for fast global access

    • Guarantee high availability: Redundant instances with automatic failover

    • Handle scale: Optimized for large workloads and deep historical scans

    • Abstract complexity: Clean API hides underlying distributed storage complexity

    hashtag
    What the Indexed Archive Includes

    1. Blocks

      1. Block hash, slot number, parent slot

      2. Block time (Unix timestamp)

      3. Leader (validator) identity

      4. Transaction count

      5. Total compute units consumed

    2. Transactions

      1. Signature (unique identifier)

      2. Fee payer address

      3. Success/failure status

    3. Instructions

      1. Program ID (which program was called)

      2. Instruction index (order within transaction)

      3. Instruction data (decoded where possible)

    4. Logs

      1. Program log messages

      2. Associated transaction signature

      3. Log level and content

    5. Account Updates

      1. Account public key

      2. Pre-transaction balance (lamports)

      3. Post-transaction balance (lamports)

    hashtag
    Use Cases

    hashtag
    Analytics and Trading

    1. Deep historical analysis and backtesting

    2. Real-time liquidity and TVL monitoring

    3. Pattern recognition and signal generation

    hashtag
    dApps and Wallets

    1. Full transaction and asset history for any user

    2. Instant UI updates based on on-chain events

    3. Aggregation of data across DeFi and NFT protocols

    hashtag
    Infrastructure Providers and Enterprises

    1. Reliable data backbone for internal analytics

    2. Foundation for B2B data services

    3. No need to maintain validators or archive RPC setups


    For consultation on optimal deployment architecture for your specific use case, contact GetBlock support teamarrow-up-right.

    Reach usarrow-up-right
    In a standard setup, your node receives data through the BSC peer-to-peer gossip network:

    With BDN Gateway acceleration, your node receives data through two channels simultaneously:

    Your dedicated node receives data from both the BDN fast path and the standard P2P layer, ensuring it always has the freshest state available.

    hashtag
    Architecture Details

    1. Connection: We connect your dedicated node's P2P interface to the GetBlock Data center.

    2. Data Flow: The node receives transactions and blocks from both the standard P2P layer and the BDN propagation network.

    3. Automatic Selection: Your node automatically uses the first source to deliver data.

    hashtag
    What Accelerated Node Gets:

    The BDN Gateway improves the delivery speed of:

    Data Type
    Description
    Impact

    New Blocks

    Block headers and transactions

    React to state changes faster

    Mempool Updates

    Pending transactions

    See opportunities earlier

    hashtag
    Who is this for:

    1. Traders: To buy and sell tokens faster and submit transactions

    2. Developers: To build a lower-latency dApp, access fresher data, and deliver more responsive user experiences

    3. Validators: To receive transactions and block earlier than other validators and improve participation and rewards.

    hashtag
    Benefits for Your Workloads

    Node acceleration directly benefits latency-sensitive applications:

    • Trading Bots: React to price movements and arbitrage opportunities faster

    • Liquidation Systems: Monitor positions with fresher state data

    • Analytics Pipelines: Process blocks and transactions with minimal delay

    • MEV Strategies: Observe mempool activity before competitors

    circle-check

    No Action Required

    • Automatic: Enabled when you provision an accelerated dedicated node

    • Transparent: Your existing RPC calls work unchanged

    • Managed: GetBlock handles all Gateway maintenance and updates

    Your application code remains the same. The improvement happens at the infrastructure layer, giving you faster data without code changes.

    hashtag
    What to do With Accerelated Node

    While node acceleration improves data reception passively, you can further improve your dApp or workflow by:

    • Subscribing to real-time streams for direct access to BDN data

    • Submitting transactions to public mempool with accelerated propagation

    • Using private transactions for MEV protection or without MEV Protection

    Reach usarrow-up-right

    hashtag
    Parameters

    • None

    hashtag
    Request

    URL (endpoint)

    Example (cURL)

    hashtag
    Response

    hashtag
    Response Definition

    Value
    Data type
    Description

    chain_id

    integer

    ID of the blockchain

    epoch

    string

    Current epoch number

    hashtag
    Use Case

    The /v1/info endpoint is useful for checking if a node is online and responding. For example:

    • Developers can verify the latest block or ledger version to ensure the node is up-to-date.

    • Applications can notify users about the health of the blockchain, such as showing a modal alerting them to the current state when they log in to a dApp.

    hashtag
    Code Example (Axios)

    Replace <ACCESS_TOKEN> with your actual access token from GetBlock.

    hashtag
    Error Handling

    When using this endpoint, you may encounter:

    • 404 → Incorrect or incomplete access token.

    • 500 → Network issues.

    How to fix:

    • Use a stable and strong network connection.

    • Check or re-copy your access token.

    • Verify the URL to ensure it is correct and complete.

    hashtag
    Integration

    It is recommended to use this endpoint first to check the current status of the blockchain before integrating other endpoints into your application.

    Interested in building on Solana with TradeFirst? Reach usarrow-up-right for more information.

    hashtag
    Core Value Proposition

    TradeFirst provides two-sided latency optimization for Solana trading:

    1. Signal Detection Side: Faster awareness of on-chain events via StreamFirst (data streaming).

    2. Execution Side: Faster transaction delivery and inclusion via Blazar, SubSlot, and LandFirst routing

    By optimizing both sides, TradeFirst enables traders to see opportunities earlier and execute trades faster than competitors using standard infrastructure.

    hashtag
    Core Technology Stack

    1. StreamFirst (Data Streaming)

      1. Accelerated Yellowstone gRPC implementation

      2. Optimized shred-stream network access

      3. Fastest on-chain data delivery for signal detection

    2. LandFirst (Multi-Path Routing)

      1. SWQoS priority connections

    3. Jito integration

      1. Geo routing

      2. Stake density topology

      3. Leadership scheduling

    circle-check

    Future Addition:

    • Shred Stream Access (coming soon): Direct raw shred delivery for even earlier data access

    hashtag
    Technical Architecture

    hashtag
    How TradeFirst Works

    Complete Trading Cycle:

    1. Signal Detection: StreamFirst delivers on-chain updates 17ms faster than standard methods

    2. Strategy Execution: Your trading logic analyzes data and generates orders

    3. Transaction Submission: Blazar optimizes transaction structure and routing

    4. Timing Control: SubSlot precisely times submission within the slot window

    5. Path Selection: LandFirst routes via optimal path (SWQoS or Jito)

    6. Block Inclusion: Transaction lands in the current or next slot with high probability

    hashtag
    Use cases

    This is highly recommended for High-frequency trading (HFT) traders, which is specifically designed for:

    1. High-Frequency Trading Firms

    These are professional trading teams running large volumes of rapid-fire transactions on Solana, including cross-DEX arbitrage, statistical arbitrage across correlated token pairs, tight-spread market making, and fast liquidity rebalancing. For them, execution speed and reliability directly impact profitability, making this solution an essential part of their trading infrastructure.

    2. MEV Searchers

    MEV searchers rely on precise timing and high-priority execution for strategies like sandwich attacks, liquidation sniping, protocol arbitrage, or fast NFT flips. Since these opportunities exist for only seconds—and often compete with other searchers—having stronger execution reliability gives them a significant edge.

    3. Algorithmic Trading Operations

    Algorithmic trading systems continuously react to on-chain data, whether they're following momentum signals, trading based on oracle movements, optimizing yield across protocols, or executing automated rebalancing strategies. These systems need a consistent, low-latency execution layer to ensure their models perform as expected without disruptions.

    4. Proprietary Trading Desks

    Small teams and professional traders running their own capital depend on solid infrastructure without wanting to build it in-house. They benefit from flexible setups that support diverse strategies, predictable pricing so they know their cost structure, and reliable support for performance tuning or issue resolution.

    5. Institutional Crypto Traders

    Institutions executing high-volume Solana strategies require enterprise-level stability, compliance-friendly monitoring, volume-based pricing, and service-level guarantees. This solution gives them the dependable infrastructure and dedicated support needed to operate at scale while maintaining regulatory and operational standards.


    For consultation on optimal deployment architecture for your specific use case, contact GetBlock support teamarrow-up-right

    hashtag
    Parameter

    None

    hashtag
    Request

    Base URL

    Example(cURL)*

    hashtag
    Response Example

    hashtag
    Response parameter definition

    Field

    Type

    Description

    deprioritized_gas_estimate

    String

    Lower gas price estimate — slower inclusion, suitable for non-urgent txns.

    gas_estimate

    String

    Standard recommended gas price (balanced option).

    hashtag
    Use Cases

    This method can be used for:

    • Wallets can auto-suggest gas fees based on the user's urgency.

    • dApps can provide a “fast/normal/slow” fee slider to users.

    • Developers can programmatically ensure transactions won’t fail due to low gas.

    • Cost optimisation for batch transactions.

    hashtag
    Code example

    Node(axios)

    Python(Request)

    hashtag
    Error handling

    Status Code

    Error Message

    Cause

    403

    Forbidden

    Missing or invalid <ACCESS_TOKEN>.

    500

    Internal server error

    Node or network failure when estimating gas.

    hashtag
    Integration with Web3

    By integrating /v1/estimate_gas_price into dApp, developers can:

    • Provide real-time fee estimation inside wallets and dApps.

    • Improve transaction confirmation rates by suggesting optimal gas.

    • Enhance user experience with clear trade-offs (fast vs cheap).

    • Avoid failed transactions due to underpriced gas.

    LandFirst

    An infrastructure for fast transaction delivery in Solana through its own intelligent routing mechanism.

    LandFirst is GetBlock's intelligent transaction-routing technology for processing faster transactions on Solana. It works by routing your transactions through multiple optimized delivery paths, including GetBlock’s Stake-Weighted Quality of Service (SWQoS) connections and the Jito auction mechanism.

    Interested in building on Solana with LandFirst? Reach usarrow-up-right for more information.

    hashtag
    Core Technology Stack

    LandFirst automatically routes transactions through three complementary delivery mechanisms:

    1. GetBlock's Own SWQoS Connections

      1. Direct partnerships with high-stakes Solana validators

      2. Guaranteed priority capacity through stake-weighted allocation

    By combining all three paths, LandFirst provides the highest probability of fast transaction inclusion on Solana.

    hashtag
    Technical Architecture

    hashtag
    How It Works

    LandFirst maximizes transaction inclusion by combining SWQoS priority routing, low-latency leader targeting, and parallel Jito submission. When a user sends a transaction, LandFirst checks the current leader schedule and picks the fastest path through our and our partners’ staked SWQoS validators, using private, low-hop connections to deliver the transaction directly to the upcoming leader with priority TPU capacity. At the same time, the transaction is also sent to Jito, where it enters the tip auction for guaranteed execution if the bundle wins. Whichever path lands first becomes the confirmed transaction, ensuring the highest possible probability of fast, next-block inclusion even under heavy network congestion.

    hashtag
    Routing Intelligence:

    LandFirst analyzes each transaction and selects the optimal delivery path based on:

    • Leader Schedule: Which validator is currently/soon producing blocks

    • Network Conditions: Current congestion and validator responsiveness

    • Transaction Priority: Priority fee amount and urgency

    hashtag
    Use Cases

    1. HFT & Arbitrage

    Fast, reliable execution for high-frequency trading, arbitrage, market-making, and position rebalancing — especially when every millisecond counts.

    1. MEV & Keeper / Liquidation Bots

    Ensures deterministic transaction landing for backruns, front-runs, liquidation races, and other MEV or keeper-bot strategies.

    1. NFT Sniping & High-Demand Mints

    Gives an edge for time-sensitive NFT events such as limited-supply mints, snipes, and competitive auctions.

    1. Critical Time-Sensitive Transactions

    For urgent or large-value moves — e.g. multi-sig operations, time-bound transfers, or high-stakes governance — where failure or delay is too costly.

    hashtag
    Different Between Multi-Path Routing Advantage vs. Standard RPC Transaction Submission

    Standard RPC nodes submit transactions via single, unstaked TPU connections. During congestion, these transactions are deprioritized or dropped entirely.

    hashtag
    Available to Everyone

    LandFirst is available on:

    ✅ Shared Node Plans - All shared RPC users benefit automatically ✅ Dedicated Node Plans - Enhanced monitoring and configuration available ✅ No Additional Fee - Included in standard RPC access (tips are optional)


    For consultation on optimal deployment architecture for your specific use case, contact

    Aptos (APT)

    Aptos Network API Reference for seamless interaction with APT nodes, enabling fast, secure, and scalable transactions on a next-generation Layer 1 blockchain.

    hashtag
    Overview of Aptos Network Methods

    Aptos is a Layer 1 blockchain built with the Move programming languagearrow-up-right, designed to deliver a fast, secure, scalable, and upgradeable ecosystem. With its modular architecture, Aptos enables frequent upgrades, rapid adoption of new technologies, and strong support for emerging use cases. The Aptos API provides developers with the ability to interact with the blockchain seamlessly and possibly. You can do the following with the Aptos API:

    1. Query real-time blockchain data

    2. Manage and monitor accounts and balances

    3. Interact with smart contracts

    4. Submit and track transactions

    5. Monitor network activity in real-time

    Each method will provide you with the following:

    1. Clear description of functionality and use cases

    2. Required input parameters

    3. Sample requests and responses

    4. Supported network

    Note: This API is compatible only with Aptos Mainnet.

    hashtag
    Quickstart

    In this section, you will learn how to make your first call with either:

    • Axios

    • Python

    hashtag
    Quickstart with Axios

    Before you begin, you must have already installed npm or yarn on your local machine. If not, check out or .

    1. Set up your project using this command:

      For npm:

    Or yarn:

    This creates a project directory named aptos-api-quickstart and initialises a Node.js project within it.

    1. Install Axios using this command: Using npm:

      Using yarn:

    2. Create a new file and name it index.js. This is where you will make your first call.

    3. Set ES module "type": "module"

    hashtag
    Quickstart with Python and Requests

    Before you begin, you must have installed Python and Pip on your local machine.

    1. Set up your project using this command:

    2. Set up a virtual environment to isolate dependencies:

    3. Install the requests library:

    4. Create a new file called

    hashtag
    Endpoint Grouping

    1. Blockchain Information

      • /v1

    2. Account-Related

    Yellowstone gRPC API

    Power your Solana dApps and backends with the fastest, most reliable streaming data available. Yellowstone gRPC add-on is for apps that need every live event as fast as the network can deliver.

    hashtag
    Overview

    Yellowstone gRPC is a high-performance Solana Geyser plugin that provides real-time streaming access to on-chain data. Built by Triton One, it delivers blocks, transactions, and account updates with millisecond-level latency directly from Solana validators.

    GetBlock offers managed Yellowstone gRPC endpoints as an add-on to Dedicated Solana Node subscriptions, eliminating the need for infrastructure setup and maintenance.


    hashtag
    Key Features

    • Near-zero latency: Streams data directly from validators, often hundreds of milliseconds faster than standard RPC/WebSocket APIs

    • High throughput: Handles millions of events per minute under load

    • Comprehensive streaming: Monitor accounts, transactions, blocks, slots, and program interactions in real-time


    hashtag
    Supported Data Streams

    Yellowstone gRPC supports streaming the full range of Solana events:

    Stream Type
    Description

    hashtag
    Use Cases

    Yellowstone gRPC is ideal for time-sensitive applications that need to react instantly to on-chain state changes:

    • High-frequency trading and MEV bots

    • On-chain indexers and data archives

    • Real-time analytics dashboards

    circle-info

    Note: gRPC is not supported in browsers. Yellowstone is designed for backend services and server-side applications.


    hashtag
    Getting Started


    hashtag
    Prerequisites

    To use Yellowstone gRPC on GetBlock:

    • A GetBlock account (sign up at )

    • A subscription

    • Yellowstone gRPC add-on enabled (included at no extra cost with Dedicated Nodes)


    hashtag
    Quick Example

    Here's a minimal TypeScript example to start streaming account updates:


    hashtag
    Additional Resources


    hashtag
    Need Help?

    Our support team is available 24/7 to assist with:

    • Add-on activation and endpoint setup

    • Integration guidance and troubleshooting

    • Performance optimization

    Contact us through the or visit our .

    Connect Brave Wallet to GetBlock

    Explore how to add custom GetBlock RPC endpoints to Brave Wallet for greater security, transaction speed, and reliability

    Brave Wallet supports many networks and offers extensive customization options. However, each of its chains uses a public RPC API endpoint, which is very bad for privacy and efficiency.

    GetBlock’s private RPC nodes can solve this problem. After downloading the Brave browser and setting up the wallet, visit https://account.getblock.io/arrow-up-right and get one of the 100+ available chain endpoints.

    circle-check

    Using custom GetBlock nodes improves the Web3 experience in many ways:

    • Secure connections without privacy breaches

    • Lower latency and higher transaction speed

    • No overloads even during high chain activities

    Every wallet’s network can be modified this way, and this step-by-step guide shows how to do that.


    hashtag
    Before you start

    You need to set up the Brave wallet and prepare the GetBlock API endpoints.

    hashtag
    Download Brave and set up the wallet

    Brave Wallet is inseparable from the Brave browser. So, download and install the browser from the . It’s available for desktop, Android, and iOS.

    After opening the browser, look at the wallet icon in the upper right corner. Click on it to open the Brave Wallet. Import the account using a seed phrase or create a new one.

    Now, it’s time to prepare the working part: the GetBlock node.

    hashtag
    Get a custom RPC API endpoint

    1. Proceed to the GetBlock dashboard and create an account or log in.

    2. Click on the Get button to add a new RPC endpoint, and select the Ethereum mainnet.

    3. Pick the endpoint location. Currently, Frankfurt, Singapore, and New York endpoints are available for a free node. Selecting the physically closest one is usually the best option.

    It’s now available via the access token URL and can be used to perform transactions, deploy smart contracts, and much more.

    circle-info

    Without a subscription, you may have only 2 endpoints simultaneously. If you need more, consider deleting those you don’t need at the given moment.

    Free node endpoints offer a generous 50,000 free Compute Units per day with a 20 RPS limit. It’s more than enough for single-person activities.


    hashtag
    Modify an existing EVM network

    Brave Wallet supports a wide range of EVM and non-EVM networks. Let’s modify an Ethereum account.

    1

    Go to Brave Wallet settings

    In the upper right corner of the wallet interface, click on the three-dot options () button and select Settings. Here, a list of supported networks can be found.

    2

    Locate the network in the list

    Go to the wallet, and try to perform some actions with the Ethereum account:

    • Check the balance

    • Connect to dApps

    • Execute smart contracts

    • Make a transaction

    In the GetBlock dashboard, track the remaining balance.


    hashtag
    Add a new EVM network

    If a network of interest isn’t included in the network list, it can be added manually. Let’s add the Polygon zkEVM network, a zero-knowledge L2.

    circle-check

    Brave Wallet is very convenient for managing blockchain networks, with hundreds of EVM protocols available. GetBlock almost certainly has a node endpoint for active and popular ones.

    If you genuinely believe that a network is unfairly missing, you may and suggest it.

    1

    Search the network ID in Brave settings

    Return to the Wallet Networks menu. Instead of selecting existing networks, click on the Add button. Start typing “polygon zkevm” to locate the network quickly.

    After clicking on it, Brave fills all required fields automatically.

    2

    Get a network’s RPC URL at GetBlock

    It’s recommended to assign a custom account name, such as “Polygon zkEVM GetBlock,” to distinguish the dedicated account.

    Then, return to the wallet and locate a new Polygon zkEVM account with the ETH native token and a custom name.

    As with GetBlock’s Ethereum node, track the compute units usage at the GetBlock dashboard.

    Team accounts setup

    Set up your team account on GetBlock, invite and onboard team members with this step-by-step guide.

    A team account is a shared workspace where multiple users can collaborate. This setup is ideal for companies and teams using GetBlock services.

    Key benefits:

    • Organized collaboration: Work together on company resources.

    • Enhanced security:

    Dedicated nodes: Manage & extend subscriptions

    Track and extend your dedicated node subscriptions on GetBlock.

    This page explains how to manage your dedicated node subscriptions, including checking their status and extending the service duration—all from your user account.


    hashtag
    Tracking subscription status

    You can monitor the status of your dedicated node subscriptions in three different ways.

    What Are Token Extensions

    Solana Token Extensions: guide to types, use cases & why they matter for SPL tokens

    The Solana Program Library (SPL) Token program defines a standard for creating, minting, transferring, and burning both fungible and non-fungible tokens, similar to the ERC-20 and ERC-721 standards in Ethereum. This program has a restricted definition, hence requiring developers to build custom code to add functionality beyond what is originally provided. This is time-consuming and difficult to achieve adoption across the ecosystem.

    Solana's programming model requires that programs be included in transactions alongside accounts, making it complicated to craft transactions involving multiple token programs. Additionally, each forked version introduces unaudited code, raising security concerns.

    Then comes the Token Extension (Token-2022). This is a more advanced token program that maintains the original functionalities while expanding its capacity beyond the fundamentals (e.g., token transfers, minting, etc.). The difference lies in the optional extensions you can enable to add new capabilities natively.

    eth_accounts - Arbitrum

    Example code for the eth_accounts JSON RPC method. Сomplete guide on how to use eth_accounts JSON RPC in GetBlock Web3 documentation.

    This method gets a list of addresses owned by the client.

    hashtag
    Parameters

    • None

    eth_blockNumber - Arbitrum

    Example code for the eth_blockNumber JSON RPC method. Сomplete guide on how to use eth_blockNumber JSON RPC in GetBlock Web3 documentation.

    This method gets the number of the most recent block.

    hashtag
    Parameters

    • None

    EU (Frankfurt):   https://go.getblock.io/<ACCESS_TOKEN>/
    US (New York):    https://go.getblock.us/<ACCESS_TOKEN>/
    Asia (Singapore): https://go.getblock.asia/<ACCESS_TOKEN>/
    https://go.getblock.io/
    curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/info'
    {
      "block_height": "58851650",
      "chain_id": 1,
      "epoch": "2796",
      "git_hash": "6568c5ee6a58b4f96c0780d4f66d7e573e61c418",
      "ledger_timestamp": "1685696086534090",
      "ledger_version": "152087593",
      "node_role": "full_node",
      "oldest_block_height": "1101178",
      "oldest_ledger_version": "2287593"
    }
    import axios from 'axios'
    
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/info',
      headers: {}
    };
    
    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });
    https://go.getblock.io/<ACCESS_TOKEN>
    curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/estimate_gas_price'
    {
        "deprioritized_gas_estimate": 100,
        "gas_estimate": 100,
        "prioritized_gas_estimate": 150
    }
    
    const axios = require('axios');
    
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/estimate_gas_price',
    };
    
    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });
    
    
    import requests
    
    url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/estimate_gas_price"
    response = requests.request("GET", url, headers=headers, data=payload)
    
    print(response.text)

    Error messages (if failed)

  • Fee paid (lamports)

  • Compute units used

  • List of program invocations

  • Accounts array (all accounts involved)

  • Nested/inner instructions

  • Timestamp

  • Owner program (pre and post)

  • Data changes (what was modified)

  • Rent epoch information

  • ledger_version

    string

    The latest version of the ledger

    oldest_ledger_version

    string

    The earliest version of the ledger

    ledger_timestamp

    string

    Timestamp of the latest ledger version in microseconds

    node_role

    string

    Role of this node in the network

    oldest_block_height

    string

    Lowest block height available

    block_height

    string

    Current block height

    git_hash

    string

    Git hash of the node build

    prioritized_gas_estimate

    String

    Higher gas price estimate — ensures faster transaction processing.

    How to create a node endpoint for blockchain API access
    GetBlock RPC endpoint setup interface

    Rich filtering: Subscribe only to relevant updates using account keys, owner programs, or commitment levels

  • Protobuf encoding: Receive parsed, typed messages instead of raw base64 data

  • Bidirectional streaming: Maintain long-lived connections with built-in keep-alives

  • Block Meta

    Block metadata with transaction counts and execution status

    DEX monitors and price feeds
  • DeFi strategy engines

  • Alerting and notification systems

  • NFT marketplace trackers

  • Wallet activity monitors

  • Custom solutions for enterprise needs

    Accounts

    Real-time account updates including lamports, owner, and data

    Transactions

    Full transaction data with metadata and instruction details

    Blocks

    Block metadata including slot, parent slot, and timestamp

    Slots

    getblock.ioarrow-up-right
    Dedicated Solana Nodearrow-up-right
    Yellowstone gRPC GitHub Repositoryarrow-up-right
    GetBlock Solana Nodesarrow-up-right
    GetBlock Supportarrow-up-right
    GetBlock dashboardarrow-up-right
    support pagearrow-up-right

    Overview

    Learn how Yellowstone gRPC works and why it's essential for real-time Solana applications

    Quickstart Guide

    Enable the add-on and start streaming data with code examples in TypeScript, Python, Go, and Rust

    Slot notifications as they're processed by the leader

  • Code example

  • Integration

  • in your
    package.json
    .
  • Add the following code to the file (index.js):

    Replace <ACCESS_TOKEN> with your actual access token from GetBlock.

  • Run the script:

    The sequence number and authentication key log in your console like this:

  • and insert the following code:

    Replace <ACCESS_TOKEN> with your actual access token from GetBlock.

  • Run the script:

  • /v1/accounts/{account_hash}
  • /v1/accounts/{account_hash}/resources

  • /v1/accounts/{account_hash}/resource/{resource_type}

  • /v1/accounts/{account_hash}/modules

  • /v1/accounts/{account_hash}/module/{module_name}

  • /v1/accounts/{account_hash}/transactions

  • Events

    • /v1/accounts/{account_hash}/events/{creation_number}

    • /v1/accounts/{account_hash}/events/{event_handle}/{field_name}

  • Blocks

    • /v1/blocks/by_height/{block_height}

    • /v1/blocks/by_version/{version}

  • Transactions

    • /v1/transactions

    • /v1/transactions/by_hash/{transaction_hash}

    • /v1/transactions/by_version/{version}

  • Additional Utility

    • /v1/estimate_gas_price

  • npmarrow-up-right
    yarnarrow-up-right
    main.pyarrow-up-right
    import Client, {
      SubscribeRequest,
      CommitmentLevel
    } from "@triton-one/yellowstone-grpc";
    
    const client = new Client("https://go.getblock.io/", "YOUR_ACCESS_TOKEN");
    const stream = await client.subscribe();
    
    stream.write({
      accounts: ["YourWalletPubkeyHere"],
      commitment: CommitmentLevel.PROCESSED,
    } as SubscribeRequest);
    
    stream.on("data", (msg) => {
      if (msg.accountChange) {
        console.log(`Account updated: ${msg.accountChange.pubkey}`);
      }
    });
    import axios from 'axios'
    
    let account = {
      method: 'get',
      url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f',
    };
     
    axios.request(account)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });
    node index.js
    {
      "Sequence_number": "219241",
      "Authentication_key": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f"
    }
    python main.py
    mkdir aptos-api-quickstart
    cd aptos-api-quickstart
    npm init --yes
    mkdir aptos-api-quickstart
    cd aptos-api-quickstart
    yarn init --yes
    npm install axios
    yarn add axios
    mkdir aptos-api-quickstart
    cd aptos-api-quickstart
    python -m venv venv
    source venv/bin/activate  
    # On Windows, use venv\Scripts\activate
    pip install requests
    import requests
    
    url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f"
    
    response = requests.get(url)
    
    print(response.text)
    GetBlock-operated infrastructure with validator peering
  • Leased SWQoS Connections

    1. Higher priority than unstaked RPC traffic, ensuring transactions cut ahead during congestion

    2. Reserve priority bandwidth specifically for LandFirst traffic

  • Jito Block Engine Integration

    1. MEV-aware auction mechanism for guaranteed inclusion

    2. Bundle support for atomic multi-transaction operations

    3. Priority placement through competitive tipping

  • Geographic Location: network topology that defines the lowest-path latency to the current leader.

    Fails or delays

    Adaptive routing

    Bundle support

    No

    Yes (via Jito)

    MEV protection

    No

    Yes (via Jito)

    Landing probability

    60-90% (varies)

    95%+ (measured)

    Aspect

    Standard RPC

    LandFirst

    Routing paths

    Single path

    Three paths (SWQoS + Jito)

    Validator priority

    None (unstaked)

    High (stake-weighted)

    GetBlock support teamarrow-up-right

    Congestion handling

    Click Get, and the endpoint is ready.

    If the network of interest is already present, such as with Ethereum, click on the three-dot options () button right of Ethereum and then select Edit to open the account settings.

    Look at the RPC URLs settings fro Ethereum: usually, a default Brave Wallet endpoint is present here. As every wallet user connects to it by default, it’s overloaded and insecure. That’s why a custom RPC URL is essential for Web3 activities.

    3

    Add a custom API URL to the network

    Go to the GetBlock dashboard and copy the newly obtained Ethereum RPC access token. Add it under RPC URLs as shown below.

    Return to the GetBlock dashboard, click Get again, and select Polygon zkEVM mainnet this time. Currently, only the Frankfurt region is available for zkEVM nodes.

    Voila—the free and highly secure Polygon zkEVM node endpoint is ready.

    3

    Add a custom API URL to the new network

    Copy the access token and go to the Brave settings. Add the new RPC URLs field and paste the access token.

    official websitearrow-up-right
    compute unit
    contact usarrow-up-right
    Downloading Brave browser with integrated wallet
    How to start using a Brave browser wallet
    Creating Ethereum access token in GetBlock
    Getting an ETH RPC URL for Brave wallet
    Adding Polygon to Brave
    New Polygon zkEVM account with GetBlock endpoint
    three-dot menu
    Role-based access limits each member to only the features they need.
  • Efficient management: Easily switch between personal and team accounts.

  • A team account user is a regular GetBlock user. When invited to a team, they can work on company resources, manage service plans or team settings, provided the corresponding permissions are granted.


    hashtag
    Creating a team account on GetBlock

    This part covers a step-by-step guide to setting up your team workspace.

    1. Sign in to your GetBlock account. If you don’t have a user account yet, create one following this guide.

    2. Click on the profile icon in the bottom-left corner of the sidebar. Select "Create new team" from the dropdown menu.

    1. A popup window will appear. Assign a team name and click the "Create team" button.

    1. Once the space is created, navigate to Account Settings > Team to manage team settings or add teammates.


    hashtag
    Adding teammates

    The creator of the team account controls who gets invited and manages user roles.

    circle-exclamation

    Limits on GetBlock team accounts:

    • Each user can create up to 3 teams.

    • A user can be invited to an unlimited number of teams.

    • One team can have a maximum of 30 users.

    You can invite team members to join your team account using either their email address or GetBlock User ID.

    • If the teammate has a GetBlock account: You can invite them using their ID. Since they are already registered, they just need to accept the invitation.

    • If the teammate is not registered on GetBlock: Invite them via email so they can first create an account before joining the team.

    1. Go to Account Settings > Team.

    2. Click "Add team member" in the top-right corner.

    3. Request the User ID from the teammate (they can find it under Account Settings > General).

    4. Enter the name, User ID, and send the invite.

    The user gets a notification and can accept the invite.

    1. Go to Account Settings > My Team.

    2. Click "Add team member" in the top-right corner.

    3. Enter the teammate's name and email address.

    A team member is marked as when they have successfully accepted the invitation and joined the team.

    If the invitation has been sent but not yet accepted, their status remains .


    hashtag
    Managing roles & permissions

    Once the user has joined, the team owner or an admin can update their permissions:

    1. Go to My Team in Account Settings.

    2. Click the three-dot menu (⋮) next to a team member.

    3. Select "Edit access level".

    4. Assign permissions:

      • Endpoints: Create and manage node endpoints, access tokens, and view statistics.

      • Subscriptions & payments: Handle payments and plans.

      • Admin: Includes all the above permissions, plus the access to manage team settings and member roles.

    5. Save changes.

    circle-exclamation

    If a Member has no permissions assigned, they will have View-Only access by default.

    hashtag
    Roles-based permissions

    This table provides a breakdown of actions team account users can perform based on their role.

    Action
    Owner
    Admin
    Member

    Create & manage access tokens

    ✅

    ✅

    🔓

    Manage subscriptions & payments

    ✅

    circle-check

    If you need someone to help manage other team members, be sure to give them Admin status.


    hashtag
    Revoking team access

    To remove a user from your team account:

    1. Navigate to Team in the Account Settings.

    2. Click the three-dot menu (⋮) next to the team member name.

    3. Select "Remove" from the dropdown menu.

    circle-check

    When removed from a team, users lose access to that team workspace but keep their personal account.


    hashtag
    How to join a team account

    If you’ve been invited to a team on GetBlock, follow these steps to accept the invitation and join the team.

    When you have a pending team invitation, a notification badge appears on your account icon .

    1. Click your account icon to view an invitation.

    2. Click "Accept" if you're ready to join.

    1. After accepting the invitation, you are given access to your team’s workspace. Your will be determined by the team owner or admin.

    When someone who is not yet registered on GetBlock receives a team invitation, they must first sign up for an account:

    1. Check your inbox for an email invitation from GetBlock.

    2. Clicking the invitation link redirects you to the sign-up page.

    3. Create a


    hashtag
    Switching between personal & team accounts

    circle-check

    A team user does not lose access to their personal account. They can still use and manage their own endpoints and subscriptions.

    To switch between your personal account and any team accounts you are part of:

    • Click the account icon in the left panel.

    • A dropdown will show all teams & personal accounts.

    • Switch between them as needed.

    The teams list is sorted by recent activity, with the most recently accessed accounts at the top.


    hashtag
    Best practices for team security

    • Regularly review and audit permissions. Revoke access for users who are no longer active.

    • Grant admin privileges only to trusted team members.

    • Give Members only the necessary permissions (e.g., endpoints access or subscriptions management).

    • Never share login credentials—use team accounts instead.


    hashtag
    Need help?

    If you run into any issues or have questions, please check out our FAQarrow-up-right or visit our Contact Centerarrow-up-right. You can also use the Help button within your GetBlock dashboard to access support or submit a request.

    hashtag
    1. Dashboard

    The widget on your dashboard alerts you when your subscription is about to expire or is in a grace period. Click the widget to open a pop-up that lists all nodes that require renewal.

    hashtag
    2. Plan manager

    The Manage Plans section can be found by navigating to the “Pricing” option in the left-side menu. You'll see three tabs: click on “Manage Plans” to view all your subscriptions in one place.

    hashtag
    3. "Endpoints" list

    Each endpoint in “My endpoints” list shows its current subscription status.


    hashtag
    Subscription status breakdown

    Status
    Dashboard View
    Manage Plans View

    Active

    (Recurring Payment)

    Active

    (One-Time Payment)


    hashtag
    Changing the subscription period

    You can modify your subscription period at any time if you’re on a one-time payment plan paid with:

    • Cryptocurrency;

    • Credit card.

    circle-exclamation

    Note on Recurring Payments

    Users cannot manually extend a plan when using recurring payments. These subscriptions renew automatically at the end of a billing cycle.

    However, if a payment fails (e.g., due to an expired card or insufficient funds), your subscription will enter a 3-day grace period. During this time, your node remains active, allowing you to update your payment details and retry the renewal before the service is interrupted.

    hashtag
    Available options

    You can extend your subscription to one of the following periods:

    • 1 month

    • 6 months

    • 12 months


    hashtag
    How to extend your Dedicated Node plan

    There are three ways to extend your subscription.

    hashtag
    Option 1: The Dedicated Nodes dashboard

    1. Go to Dedicated Nodes tab from your dashboard. Look for the subscription alert widget.

    1. Click the widget to see a list of nodes needing renewal and choose one. A pop-up will show extension options (1, 6, or 12 months).

    1. Choose a new period and review details. Proceed to checkout.

    2. Complete the payment by following the instructions provided.

    3. Check the "Payment History" under the Pricing tab to track the progress.

    hashtag
    Video guide

    For fiat (credit card) payments:

    • Payments are processed via Paddle.

    • VAT may apply depending on the user's location.

    • The extension is applied instantly once the payment is completed.

    For crypto payments:

    • Payments are processed via NOWPayments.

    • Make sure to account for network fees to avoid payment issues.

    • The extension is applied

    hashtag
    Option 2: From “Endpoints” list

    1. Navigate to your main dashboard and switch to the Dedicated Nodes tab.

    2. Choose a node to extend. Expand the node’s details and click "Extend" to begin the process.

    3. Follow the pop-up instructions to select the new subscription period and finalize the process.

    hashtag
    Option 3: Via the "Manage Plans" menu

    1. Navigate to Pricing > Manage Plans.

    2. Review all subscriptions. Subscriptions nearing expiration are listed at the top.

    3. Follow the same steps: Select your node, choose a new period, and confirm your payment.


    hashtag
    How to keep your Dedicated Node running smoothly

    If you face any issues with renewal or extensions, feel free to reach out to GetBlock support—we’re happy to assist.

    hashtag
    Why Token Extensions Matter

    Token Extensions address a growing need: permissioned tokens on a permissionless network. This makes Solana viable for:

    • Institutional adoption – Banks, asset managers, and regulated entities (e.g., Paxos with USDP) can issue compliant tokens with built-in controls like clawback capabilities and KYC-gated transfers

    • Real-World Asset (RWA) tokenization – Securities, bonds, and other regulated assets require features like transfer restrictions and mandatory compliance checks

    • Creator economies – NFT royalties, transfer taxes, and holder rewards can be enforced at the protocol level rather than relying on marketplace cooperation

    hashtag
    Available Extensions

    Token Extensions are divided into two categories:

    hashtag
    Mint Extensions (Applied to Token Mints)

    Extension
    Description
    Potential Use Cases
    Real-World Example

    Confidential Transfers

    Protects the confidentiality of user balances within a transfer, as well as hiding transaction amounts

    Onchain payroll, B2B payments, treasury management

    Transfer Fees

    The ability to charge fees at the protocol level; fees are withheld from recipient

    hashtag
    Account Extensions (Applied to Token Accounts)

    Extension
    Description
    Potential Use Cases

    Memo Transfer

    Requires a memo instruction before all incoming transfers

    Payment attribution, compliance records, invoice tracking

    Immutable Owner

    Prevents the token account owner from being changed

    Security, preventing account hijacking

    circle-exclamation

    hashtag
    Extension Compatibility

    Not all extensions can be combined. Some conflicts include:

    • Non-Transferable + Transfer Hooks: If tokens can't transfer, a hook has no work to do

    • Non-Transferable + Transfer Fees: No transfers means no fees to collect

    • Confidential Transfers + Transfer Hooks: Hooks need to read transfer amounts, but confidential transfers encrypt them

    hashtag
    Next Steps

    • Learn about how to create and Mint token with Token-2022 and GetBlock Solana RPC

    hashtag
    Request
    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header '
    
    import axios from 'axios'
    let 
    

    hashtag
    Response

    hashtag
    Response Parameter Definition

    Field
    Data Type
    Definition

    result

    string

    An array of addresses owned by the client.

    If the accounts doesn't have any address, it returns empty array.

    hashtag
    Use case

    This method is generally used to:

    • Retrieve the list of locally unlocked accounts on a full node.

    • Identify which account a node can use for signing transactions.

    • Pre–Web3 wallet integrations where the node itself managed keys.

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    403

    Missing or invalid ACCESS_TOKEN.

    hashtag
    Integration with Web3

    The eth_accounts can help developers to:

    • Identify available signing accounts

    • Auto-select a default wallet in development

    • Validate that a local signer exists

    • Simplify onboarding in testing environments

    hashtag
    Request
    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header '
    
    import axios from 'axios'
    let 
    

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Data Type
    Definition

    result

    string

    The block number of the most recently mined block as a hexadecimal string.

    hashtag
    Use case

    eth_blockNumber is used to:

    • Track the latest block height

    • Monitor chain progress or finality

    • Trigger event-based updates when the block number increases

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    hashtag
    Integration with Web3

    The eth_blockNumber can help developers to:

    • Polling the chain every few seconds

    • Syncing contract state

    • Updating dashboards (TVL, gas metrics, transactions)

    State Transitions

    Account and contract state

    Fresher data for decisions

    Transaction

    Submiting Trsanction

    Submit single transactions or bundles with optimized propagation paths

    /v1/accounts/{account_hash}/resources - Aptos

    Example code for the /v1/accounts/{account_hash}/resources JSON-RPC method. Сomplete guide on how to use /v1/accounts/{account_hash}/resources json-rpc in GetBlock.io Web3 documentation.

    This endpoint retrieves all resources linked to a specific account at the latest ledger version. These resources include on-chain data such as the authentication key, sequence number, GUIDs, smart contract states, and tokens.

    hashtag
    Supported Networks

    • Mainnet

    hashtag
    Parameters

    Parameter
    Data type
    Description
    Required
    In

    hashtag
    Request Example

    URL

    Example

    hashtag
    Response

    hashtag
    Response Definition

    Value
    Data type
    Description

    hashtag
    Use Cases

    This method can be used for:

    • Checking on-chain state of tokens or smart contracts.

    • Tracking smart contract event counters for deposits/withdrawals.

    • Powering portfolio trackers or explorers that display account assets.

    hashtag
    Code Examples

    hashtag
    Python (requests)

    hashtag
    Node.js (Axios)

    Replace <ACCESS_TOKEN> with your actual access token from GetBlock.

    hashtag
    Error Handling

    • Missing or invalid account hash → Empty or malformed response.

    • 403 → Access token is missing or invalid.

    hashtag
    Integration with Web3

    By integrating /v1/accounts/{account_hash}/resources, developers can:

    • Read smart contract resources tied to an account (for DeFi, staking, etc.).

    • Power explorers or portfolio trackers to show account assets.

    • Support reliable transaction pipelines and conditional dApp logic.

    /v1/accounts/{account_hash}/events/{event_handle}/{field_name} - Aptos

    Example code for the /v1/accounts/{account_hash}/events/{event_handle}/{field_name} JSON-RPC method. Сomplete guide on how to use /v1/accounts/{account_hash}/events/{event_handle}/{field_name} json-rp

    This endpoint retrieves events for a given account using an event handle struct and a field name within that struct. It allows more precise event queries compared to using only the creation number.

    hashtag
    Supported Network

    hashtag
    Parameters

    Parameter
    Data type
    Description
    Required
    In

    hashtag
    Request Example

    Base URL

    Example (cURL)

    hashtag
    Response Example

    hashtag
    Response Parameters

    Field
    Type
    Description

    hashtag
    Use Cases

    This endpoint can be used to:

    • Query specific event handles such as deposit_events or withdraw_events.

    • Display transaction logs tied to particular smart contracts or account resources.

    • Track contract-specific activity within dApps for analytics or notifications.

    hashtag
    Code Examples

    hashtag
    Python (requests)

    hashtag
    Node.js (Axios)

    Replace <ACCESS_TOKEN> with your actual GetBlock API token.

    hashtag
    Error Handling

    Status Code
    Error Message
    Cause

    hashtag
    Integration with Web3

    By integrating /v1/accounts/{account_hash}/events/{event_handle}/{field_name}, developers can:

    • Track token-specific events like deposits, withdrawals, mints, or burns.

    • Enable in-wallet notifications (e.g., “You received 250 APT”).

    • Monitor DeFi or NFT protocol activity by subscribing to contract events.

    CU and rate limits

    GetBlock provides access to over 100 blockchains. CU and rate limits depend on the selected plan.

    This guide explains how limits work across all available plans, helping you understand what’s included and how to choose the option that best fits your current workload and future growth.

    circle-check
    • Shared Nodes operate on a system of limits defined by Compute Units (CUs) and Requests Per Second (RPS). Each plan also determines how many access tokens you can generate.

    • With Dedicated Nodes, you’re not limited by CUs or RPS.


    hashtag
    Shared node limits

    GetBlock’s shared node service is subject to several usage limits. These are the key limits that directly affect costs and performance:

    • : Measures the computational effort required to process requests. Different shared node plans include a varying number of CUs that you can use in a month.

    • RPS (Requests Per Second): Each plan enforces a maximum number of requests you can send every second. While you’re not billed per request, staying within this limit is critical to maintaining optimal service quality.

    • : Access tokens are unique identifiers used to authenticate your connection to GetBlock’s node infrastructure, generated when you create an endpoint. The limitation on your plan determines how many of these access tokens (and therefore endpoints) you can create.

    Plan
    Free
    Starter
    Advanced
    Pro
    Enterprise

    To see the full comparison table, navigate to .

    circle-info

    Your balance of CUs for Shared Nodes is distributed on all endpoints added under the ‘Shared nodes’ tab.

    The plan is ideal if you’re just starting out and do not have complex calls or large request volumes.

    • CU: 50,000/day

    • Throughput: 20 requests per second (RPS)


    hashtag
    Managing unused & extra CUs

    If you don’t use all your allocated CUs within a month, the unused amount will carry over to the next month as long as your subscription is active and renewed. If your subscription expires or is not renewed on time, the remaining CUs will be lost.

    circle-check

    If your demand exceeds the included limits, you can purchase extra CU packages. This means that even within a given plan, there’s room for scaling without an immediate need to move to a higher tier.


    hashtag
    Dedicated node limits

    Our Dedicated Node service is perfect for teams and projects that demand absolute freedom from rate limits and CU monitoring.

    • CU: Unlimited

    • Rate: Unlimited


    If you’re unsure which plan best fits your needs, our team is ready to help! or visit our page for more information.\

    Overview

    GetBlock API docs: RPC endpoints, SDK guides, and developer tools. Everything you need to connect and build on 100+ blockchain networks

    hashtag
    Getting Started with GetBlock

    To get started, follow these steps:

    1. Sign up: Create an account to access your Access Token.

    2. Generate access token: Navigate to the dashboard, and generate your first access token for API authentication.

    3. Choose the blockchain name and type: Select the blockchain network you want to interact with, set up testnet/mainnet, and choose the interface you’re going to use.

    4. Send your first request:

    hashtag
    Key Features of GetBlock

    GetBlock is offering one of the most comprehensive APIs toolkits in the segment supporting hundreds of dApps with fast and reliable connection to blockchain nodes.

    hashtag
    100+ blockchains in store

    • Seamless connection to full and archive nodes

    • Shared and dedicated nodes: Tailored for your dApp’s needs.

    • Programmable and non-programmable blockchains

    See full list: All mainstream RPC interfaces

    • WebSockets

    • JSON RPC

    • GraphQL

    • REST API

    Add them in Lego-like manner:

    hashtag
    Industry-leading suite of add-ons and ready-made APIs

    • DAS API

    • Firehose

    • Blockbook

    • Yellowstone Geyser

    Need more? Don’t hesitate to contact sales:

    hashtag
    Examples for Console REST API Requests

    hashtag
    cURL

    Most *nix-based systems come with cURL pre-installed. cURL is a command-line tool and library for transferring data with URLs. To check if cURL is installed, run the following command:

    Example of requesting the latest block number using the GetBlock API and cURL:

    hashtag
    Python

    To run Python examples, ensure Python is installed along with the requests package. You can install the package using the following command:

    Example:

    hashtag
    JavaScript

    For JavaScript examples, you'll need Node.js version 18 or later. Follow the official documentation to install the latest stable version globally. Verify your installation by running:

    hashtag
    Ruby

    To execute Ruby examples, install Ruby on your machine. Refer to the official installation guide for details. Confirm installation by running:

    hashtag
    Supported networks

    We provide APIs for a wide range of networks, including:

    eth_getBlockTransactionCountByNumber - Arbitrum

    Example code for the eth_getBlockTransactionCountByNumber JSON RPC method. Сomplete guide on how to use eth_getBlockTransactionCountByNumber JSON RPC in GetBlock Web3 documentation.

    This method returns the number of transactions in a block identified by its block number.

    hashtag
    Parameters

    Parameter
    Type
    Required
    Description

    hashtag
    Request

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Type
    Description

    hashtag
    Use case

    The eth_getBlockTransactionCountByNumber is used to:

    • Calculating chain throughput by measuring transactions per block

    • Building analytics dashboards that monitor block activity in real time

    • Lightweight block scanning without fetching full block data

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    hashtag
    Integration with Web3

    The eth_getBlockTransactionCountByNumber can help developers:

    • Track live activity on the chain

    • Build explorers and dashboards without fetching heavy block objects

    • Detect transaction spikes for alerts and monitoring

    eth_getBalance - Arbitrum

    Example code for the eth_getBalance JSON RPC method. Сomplete guide on how to use eth_getBalance JSON RPC in GetBlock Web3 documentation.

    This method retrieves the account balance of a given address. The balance is returned in wei, the smallest unit of Ether.

    hashtag
    Parameters

    Parameter
    Type
    Required
    Description

    hashtag
    Request

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Type
    Description

    hashtag
    Use case

    eth_getBalance is used to:

    • Display a user's wallet balance in dApps and wallets

    • Check on-chain balances for dashboards or explorers

    • Validate whether an account can pay gas fees

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    hashtag
    Integration with Web3

    The eth_getBalance can help developers:

    • Fetch balances dynamically without requiring a transaction

    • Power trustless dashboards and explorers

    • Validate user accounts before executing transactions

    Arbitrum (ARB)

    Arbitrum Network API Reference for efficient interaction with ARB nodes, enabling fast, low-cost Layer 2 scaling solutions for Ethereum with high throughput and secure smart contracts.

    hashtag
    Overview

    Arbitrum is a suite of Ethereum Layer 2 scaling technologies built on the Arbitrum Nitro tech stack that includes Arbitrum One (a live implementation of the Arbitrum Rollup Protocol) and Arbitrum Nova (a live implementation of the Arbitrum AnyTrust Protocol).

    Arbitrum chains are EVM-compatible blockchains that use an underlying EVM chain (e.g., Ethereum) for settlement and succinct fraud proofs (as needed). You can use Arbitrum chains to do everything you do on Ethereum—use Web3 apps, deploy smart contracts, etc., but your transactions will be cheaper and faster.

    hashtag
    Key Features

    1. High Throughput & Low Fees: Arbitrum offers faster transaction speeds and significantly lower fees than the Ethereum mainnet, while maintaining EVM support, making it ideal for high-volume applications like DeFi or gaming.

    2. EVM Compatibility: Arbitrum chains are Ethereum-compatible and allow you to deploy Solidity smart contracts, as well as Vyper and other languages that compile to EVM bytecode.

    3. Extended Language Support (Stylus): The latest version of the Arbitrum tech stack, called , maintains Nitro's Ethereum compatibility while enabling the development of highly performant smart contracts in programming languages such as Rust, C++, and C.

    circle-info

    TECHNICAL DISCLAIMER: AUTHORITATIVE JSON-RPC API SPECIFICATION.

    GetBlock's RPC API reference documentation is provided exclusively for informational purposes and to optimize the developer experience. The canonical and normative specification for Ethereum Virtual Machine (EVM) JSON-RPC methods is solely maintained and published through the official Ethereum Foundation documentation portal at . This resource constitutes the sole authoritative reference implementation of the JSON-RPC 2.0 protocol interface across EVM-compatible execution clients.

    hashtag
    Supported Network

    Network
    Chain ID
    JSON
    WSS

    hashtag
    Base URL

    hashtag
    Quickstart

    In this section, you will learn how to make your first call with either:

    • Axios

    • Python

    hashtag
    Quickstart with Axios

    Before you begin, you must have already installed npm or yarn on your local machine. If not, check out or .

    1. Set up your project using this command:

    circle-info

    This creates a project directory named aptos-api-quickstart and initialises a Node.js project within it.

    1. Install Axios using this command:

    1. Create a new file and name it index.js. This is where you will make your first call.

    2. Set the ES module "type": "module" in your package.json.

    3. Add the following code to the file (

    hashtag
    Quickstart with Python and Requests

    Before you begin, you must have installed Python and Pip on your local machine.

    1. Set up your project using this command:

    2. Set up a virtual environment to isolate dependencies:

    3. Install the requests library:

    4. Create a new file called

    eth_gasPrice - Arbitrum

    Example code for the eth_gasPrice JSON RPC method. Сomplete guide on how to use eth_gasPrice JSON RPC in GetBlock Web3 documentation.

    This method gets the current average gas price on the Arbitrum network. This value is derived from recent transactions and can be used as a baseline for setting transaction fees.

    hashtag
    Parameters

    • None

    hashtag
    Request

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Type
    Description

    hashtag
    Use case

    eth_gasPrice is used to:

    • Determines the baseline cost for sending transactions

    • Allows wallets to calculate estimated fees

    • Helps dApps display up-to-date network fees

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    hashtag
    Integration with Web3

    The eth_gasPrice can help developers:

    • Display real-time gas prices in interfaces

    • Adjust transaction fees automatically

    • Improve user experience during times of congestion

    /v1/accounts/{account_hash}/module/{module_name} - Aptos

    Example code for the /v1/accounts/{account_hash}/module/{module_name} JSON-RPC method. Сomplete guide on how to use /v1/accounts/{account_hash}/module/{module_name}json-rpc in GetBlock.io Web3 documen

    This endpoint fetches detailed information about a single smart contract (module) deployed under a specific Aptos account. The response contains the module's bytecode and ABI, providing a complete description of its functions, structs, and on-chain logic.


    hashtag
    Supported Network

    /v1/transactions - Aptos

    Example code for the /v1/transactions json-rpc method. Сomplete guide on how to use /v1/transactions json-rpc in GetBlock.io Web3 documentation.

    This endpoint gets the list of recent transactions from the Aptos blockchain.

    hashtag
    Supported Network

    • Mainnet

    /v1/blocks/by_height/{block_height} - Aptos

    Example code for the /v1/blocks/by_height/{block_height} json-rpc method. Сomplete guide on how to use /v1/blocks/by_height/{block_height} json-rpc in GetBlock.io Web3 documentation.

    This endpoint gets a specific block's information from the Aptos blockchain network, given its height.

    hashtag
    Supported Networks

    • Mainnet

    /v1/transactions/by_version/{version} - Aptos

    Example code for the /v1/transactions/by_version/{version} json-rpc method. Сomplete guide on how to use /v1/transactions/by_version/{version} json-rpc in GetBlock.io Web3 documentation.

    This endpoint gets a transaction by its ledger version number from Aptos blockchain.

    hashtag
    supported Network

    • Mainnet

    /v1/accounts/{account_hash}/resource/{resource_type} - Aptos

    Example code for the /v1/accounts/{account_hash}/resource/{resource_type} JSON-RPC method. Сomplete guide on how to use /v1/accounts/{account_hash}/resource/{resource_type} json-rpc in GetBlock.io Web

    This endpoint gets an individual resource from a given account and at a specific ledger version. This is more specific than /resources since it targets one resource type directly.

    hashtag
    Supported Networks

    /v1/accounts/{account_hash}/events/{creation_number} - Aptos

    Example code for the /v1/accounts/{account_hash}/events/{creation_number} JSON-RPC method. Сomplete guide on how to use /v1/accounts/{account_hash}/events/{creation_number} json-rpc in GetBlock.io Web

    This endpoint retrieves events for a given account based on the creation number of the event handle. Events are emitted during transactions and serve as logs of on-chain actions such as token transfers, deposits, or contract interactions.

    hashtag
    Supported Network

    eth_call - Arbitrum

    Example code for the eth_call JSON RPC method. Сomplete guide on how to use eth_call JSON RPC in GetBlock Web3 documentation.

    This method executes a read-only smart contract call on the Arbitrum blockchain without creating a transaction.

    circle-exclamation

    This method does not modify the blockchain state. It only simulates the call and returns the output.

    eth_getCode - Arbitrum

    Example code for the eth_getCode JSON RPC method. Сomplete guide on how to use eth_getCode JSON RPC in GetBlock Web3 documentation.

    This method returns the bytecode stored at a specific address. If the address has no smart contract deployed, the result will be 0x.

    hashtag
    Parameters

    Parameter
    Type

    eth_getBlockTransactionCountByHash - Arbitrum

    Example code for the eth_getBlockTransactionCountByHash JSON RPC method. Сomplete guide on how to use eth_getBlockTransactionCountByHash JSON RPC in GetBlock Web3 documentation.

    This method returns the number of transactions contained in a block identified by its block hash.

    hashtag
    Parameters

    Parameter
    Type
    Required
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
      "jsonrpc": "2.0",
      "method": "eth_accounts",
      "params": [],
      "id": "getblock.io"
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
        "jsonrpc": "2.0",
         "method": "eth_accounts",
        "params": [],
        "id": "getblock.io"
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    const { ethers } = require('ethers');
    
    // Initialize Ethers provider with GetBlock
    const provider = new ethers.JsonRpcProvider(
        'https://go.getblock.us/<ACCESS-TOKEN>/'
    );
    
    // Using the method through Ethers
    async function useEthersMethod() {
        try {
            // Method-specific Ethers implementation
            const result = await provider.send('eth_accounts', []);
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Ethers Error:', error);
            throw error;
        }
    }
    {
      "jsonrpc": "2.0",
      "id": "1",
      "result": [
        "0xd1f5279be4b4dd94133a23dee1b23f5bfe436tf3r"
      ]
    }
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
      "jsonrpc": "2.0",
      "method": "eth_blockNumber",
      "params": [],
      "id": "getblock.io"
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
        "jsonrpc": "2.0",
         "method": "eth_blockNumber",
        "params": [],
        "id": "getblock.io"
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function fetchBlockNumberFromProvider() {
      try {
        // Call the method — this will resolve to a number (promise resolves to number)
         const result = await provider.send("eth_blockNumber", []);
        console.log("Block number result:", result);
        return result;
      } catch (error) {
        console.error("Ethers Error fetching block number:", error);
        throw error;
      }
    }
    import { createPublicClient, http } from 'viem';
    import { arbitrum } from 'viem/chains';
    
    // Create Viem client with GetBlock
    const client = createPublicClient({
      chain: arbitrum,
      transport: http("https://go.getblock.us/<ACCESS_TOKEN>"),
    });
    
    // Using the method through Viem
    async function fetchAccountViem() {
        try {
            // Method-specific Viem implementation
            const result = await client.request({
                method: 'eth_blockNumber',
            });
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Viem Error:', error);
            throw error;
        }
    }
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": "0x183037af"
    }
    - Mainnet
    Content-Type: application/json
    '
    \
    --data '{
    "jsonrpc": "2.0",
    "method": "eth_blockNumber",
    "params": [],
    "id": "getblock.io"
    }'
    data
    =
    JSON
    .
    stringify
    (
    {
    jsonrpc: "2.0",
    method: "eth_blockNumber",
    params: [],
    id: "getblock.io",
    });
    let config = {
    method: "post",
    maxBodyLength: Infinity,
    url: "https://go.getblock.us/<ACCESS_TOKEN>",
    headers: {
    "Content-Type": "application/json",
    },
    data: data,
    };
    axios
    .request(config)
    .then((response) => {
    console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
    console.log(error);
    });

    Permanent royalties, publisher fees, transaction fees

    BERNarrow-up-right (6.9% transfer fee)

    Transfer Hooks

    Gives the token issuer control over which wallets can interact with their token and how tokens and users interact

    KYC verification, token-gated access, royalty enforcement

    WEN (WNS)arrow-up-right

    Metadata & Metadata Pointer

    Establishes verifiable links between tokens and metadata directly on mint accounts

    Token verification, accounts receivable attribution

    WEN (WNS)arrow-up-right

    Interest-Bearing Tokens

    Adjusts displayed token amounts over time (cosmetic, not actual minting)

    Yield-bearing stablecoins, bonds, savings products

    Non-Transferable Tokens

    Makes it impossible to reassign the owner of a token, except by issuer

    Managing an external database, non-transferable mints of NFTs, soul-bound credentials

    Permanent Delegate

    Allows a program to have irrevocable authority over a token

    Automatic subscription services, updating real world assets, stablecoin regulatory compliance with freeze & seize orders

    Paxos USDParrow-up-right

    Default Account State

    Configure and enforce token account permissions (frozen by default)

    KYC verification, compliance gating

    Close Mint

    Allows closing mint accounts when supply reaches 0

    Temporary tokens, limited editions

    Token Groups and Members

    Enables grouping tokens together

    NFT collections, token families

    WEN (WNS)arrow-up-right

    Pausable Mint

    Allows pausing all token operations globally

    Emergency stops, maintenance windows

    CPI Guard

    Protects against certain cross-program invocation attacks

    Security for high-value accounts

    Paxos USDParrow-up-right
    Exploring Brave Wallet network accounts
    Adding GetBlock Ethereum endpoint to Brave Wallet
    Creating zkEVM access token in GetBlock
    Adding GetBlock zkEVM endpoint to Brave Wallet’
    spinner
    spinner
    spinner

    string

    The ledger version to get the account state

    No

    Query

    start

    string

    The starting point for retrieving resources

    No

    Query

    limit

    integer

    The maximum number of resources per request

    No

    Query

    string

    The authentication key used to verify the identity of the account owner.

    coin_register_events

    object

    Events associated with coin registration for the account.

    counter

    string

    The counter value associated with a particular operation.

    guid

    object

    Unique identifier (GUID) of the resource.

    id

    object

    The resource identifier.

    addr

    string

    The address associated with the resource.

    creation_num

    string

    The creation number of the resource.

    sequence_number

    string

    Tracks the order of transactions initiated by the account.

    Supporting conditional logic in dApps (e.g., only allow staking if a required resource exists).

    account_hash

    string

    Aptos account address

    Yes

    Path

    type

    string

    The type format of the account resource.

    data

    object

    The additional data or information related to the account resource.

    ledger_version

    authentication_key

    string

    Struct type name that contains the event handle.

    Yes

    Path

    field_name

    string

    Field name within the struct that holds the event handle.

    Yes

    Path

    start

    string

    Starting point or offset for retrieving events. Defaults to latest if not provided.

    No

    Query

    limit

    integer

    Maximum number of events to retrieve per request. Defaults to standard page size if unspecified.

    No

    Query

    string

    Number of transactions submitted and committed on-chain by the account.

    type

    string

    Type of event emitted.

    Internal server error

    Node or network issue — retry the request later.

    Enhance analytics dashboards by focusing on targeted on-chain event streams.

    account_hash

    string

    Aptos account address

    Yes

    Path

    guid.creation_number

    string

    Unique identifier for this event stream under the given account.

    guid.account_address

    string

    Account address that owns this event handle.

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    404

    Resource not found

    Invalid event_handle or field_name.

    event_handle

    sequence_number

    500

    L1 and L2 protocols
  • EVM and non-EVM networks

  • And more

    https://getblock.io/nodes/arrow-up-right
    https://account.getblock.io/arrow-up-right
    https://getblock.io/contact/arrow-up-right
    Aptos (APT)arrow-up-right
    Arbitrum (ARB)arrow-up-right
    Avalanche (AVAX)arrow-up-right
    Bitcoin Cash (BCH)arrow-up-right
    BNB Smart Chain (BSC)arrow-up-right
    Bitcoin-SV (BSV)arrow-up-right
    Bitcoin (BTC)arrow-up-right
    Bitcoin Gold (BTG)arrow-up-right
    Cronos (CRO)arrow-up-right
    Dash (DASH)arrow-up-right
    DigiByte (DGB)arrow-up-right
    Dogeсoin (DOGE)arrow-up-right
    Polkadot (DOT)arrow-up-right
    Ethereum Classic (ETC)arrow-up-right
    Ethereum (ETH)arrow-up-right
    Fantom (FTM)arrow-up-right
    Fuse.io (FUSE)arrow-up-right
    Moonbeam (GLMR)arrow-up-right
    Gnosis Chain (GNO)arrow-up-right
    Huobi ECO Chain (HECO)arrow-up-right
    KuCoin Community Chain (KCC)arrow-up-right
    Kusama (KSM)arrow-up-right
    Polygon (MATIC)arrow-up-right
    Moonriver (MOVR)arrow-up-right
    Near Protocol (NEAR)arrow-up-right
    Harmony (ONE)arrow-up-right
    Ontology (ONT)arrow-up-right
    Optimism (OP)arrow-up-right
    Rootstock (RSK)arrow-up-right
    Solana (SOL)arrow-up-right
    Theta (THETA)arrow-up-right
    TON (TON)arrow-up-right
    Tron (TRX)arrow-up-right
    NEM (XEM)arrow-up-right
    Monero (XMR)arrow-up-right
    ZCash (ZEC)arrow-up-right
    Detecting unusually busy or empty blocks
  • Supporting explorers and monitoring tools that show activity patterns

  • Estimate network load to optimize dapp behavior
  • Streamline backend indexing by filtering blocks based on transaction count

  • block_number

    string

    yes

    Block number in hex format, or a keyword such as latest, earliest, or pending.

    result

    string (hex)

    Number of transactions in the specified block. Returns null if the block does not exist.

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    -32602

    Invalid argument

    The block hash isn't accurate or incomplete or keyword missing

    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data '{
       "jsonrpc": "2.0",
        "method": "eth_getBlockTransactionCountByNumber ",
        "params": [
            "latest"
        ],
        "id": "getblock.io"
    }'
    import axios from 'axios'
    let data = JSON.stringify({
        "jsonrpc": "2.0",
       "method": "eth_getBlockTransactionCountByNumber",
        "params": [
            "latest"
        ],
        "id": "getblock.io"
    };
    
    let config = {
      method: "post",
      maxBodyLength: Infinity,
      url: "https://go.getblock.us/<ACCESS_TOKEN>",
      headers: {
        "Content-Type": "application/json",
      },
      data: data,
    };
    
    axios
      .request(config)
      .then((response) => {
        console.log(JSON.stringify(response.data));
      })
      .catch((error) => {
        console.log(error);
      });
    
    Automated scripts can monitor whale wallets or treasury wallets
  • DeFi apps check collateral levels or borrowing capacity

  • Track portfolio values in real time
  • Access historical balances using specific block numbers

  • address

    string

    yes

    The account address to query (0x-prefixed).

    block

    string

    yes

    Block number or tag. Can be: "latest", "earliest", "pending" or a hex-encoded block number.

    result

    string (hex)

    Account balance in wei

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    -32602

    Invalid argument

    Wallet address isn't accurate or incomplete

    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data '{
      "jsonrpc": "2.0",
      "method": "eth_getBalance",
      "id": "getblock.io",
      "params": [
            "0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
            "latest"
        ]
    }'
    import axios from 'axios'
    let data = JSON.stringify({
      "jsonrpc": "2.0",
      "method": "eth_getBalance",
      "id": "getblock.io",
      "params": [
            "0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
            "latest"
        ],
    };
    
    let config = {
      method: "post",
      maxBodyLength: Infinity,
      url: "https://go.getblock.us/<ACCESS_TOKEN>",
      headers: {
        "Content-Type": "application/json",
      },
      data: data,
    };
    
    axios
      .request(config)
      .then((response) => {
        console.log(JSON.stringify(response.data));
      })
      .catch((error) => {
        console.log(error);
      });
    
    Useful for automated bots adjusting to network congestion
  • Let's developers optimize cost-sensitive interactions such as bridging, swapping, or minting

  • Support trustless fee estimation without relying on third-party APIs

    result

    string (hex)

    Current average gas price in wei

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data '{
      "jsonrpc": "2.0",
      "method": "eth_gasPrice",
      "id": "getblock.io",
      "params": [],
    }'
    import axios from 'axios'
    let data = JSON.stringify({
      "jsonrpc": "2.0",
      "method": "eth_gasPrice",
      "id": "getblock.io",
      "params": [],
    };
    
    let config = {
      method: "post",
      maxBodyLength: Infinity,
      url: "https://go.getblock.us/<ACCESS_TOKEN>",
      headers: {
        "Content-Type": "application/json",
      },
      data: data,
    };
    
    axios
      .request(config)
      .then((response) => {
        console.log(JSON.stringify(response.data));
      })
      .catch((error) => {
        console.log(error);
      });
    
    Content-Type: application/json
    '
    \
    --data '{
    "jsonrpc": "2.0",
    "method": "eth_accounts",
    "params": [],
    "id": "getblock.io"
    }'
    data
    =
    JSON
    .
    stringify
    (
    {
    jsonrpc: "2.0",
    method: "eth_accounts",
    params: [],
    id: "getblock.io",
    });
    let config = {
    method: "post",
    maxBodyLength: Infinity,
    url: "https://go.getblock.us/<ACCESS_TOKEN>",
    headers: {
    "Content-Type": "application/json",
    },
    data: data,
    };
    axios
    .request(config)
    .then((response) => {
    console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
    console.log(error);
    });

    Fraud-Proof Security: The Arbitrum Rollup Protocol is a trustless, permissionless protocol that uses its underlying base layer for data availability and inherits its security.

  • Cross-Chain Interactions: Every Arbitrum chain includes a bridge to/from its parent chain. Arbitrum enables easy cross-chain interactions, asset transfers, and data exchange with Ethereum and other EVM-compatible networks, fostering a connected ecosystem for multi-chain dApps.

  • ✔

    Nova

    42170

    ✔

    ✔

    index.js
    ):

    Replace <ACCESS_TOKEN> with your actual access token from GetBlock.

  • Run the script:

    The sequence number and authentication key log in your console like this:

  • and insert the following code:

    Replace <ACCESS_TOKEN> with your actual access token from GetBlock.

  • Run the script:

  • Mainnet

    42161

    ✔

    ✔

    Sepolia

    421614

    Stylusarrow-up-right
    ethereum.orgarrow-up-right
    npmarrow-up-right
    yarnarrow-up-right

    ✔

    main.pyarrow-up-right
    https://go.getblock.io//
    
    curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/resources?ledger_version=3357308041&limit=10'
    [
      {
        "type": "0x1::account::Account",
        "data": {
          "authentication_key": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
          "coin_register_events": {
            "counter": "0",
            "guid": {
              "id": {
                "addr": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
                "creation_num": "0"
              }
            }
          },
          "guid_creation_num": "2",
          "key_rotation_events": {
            "counter": "0",
            "guid": {
              "id": {
                "addr": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
                "creation_num": "1"
              }
            }
          },
          "rotation_capability_offer": {
            "for": { "vec": [] }
          },
          "sequence_number": "234285",
          "signer_capability_offer": {
            "for": { "vec": [] }
          }
        }
      }
    ]
    import requests
    
    url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/resources?ledger_version=3357308041&limit=10"
    
    response = requests.get(url)
    
    print(response.text)
    import axios from 'axios';
    
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/resources?ledger_version=3357308041&limit=10',
      headers: {}
    };
    
    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });
    https://go.getblock.io/<ACCESS\_TOKEN>/
    curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/events/0x1::account::Account/coin_register_events'
        [
          {
            "version": "2304959",
            "guid": {
              "creation_number": "0",
              "account_address": "0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12"
            },
            "sequence_number": "0",
            "type": "0x1::account::CoinRegisterEvent",
            "data": {
              "type_info": {
                "account_address": "0x1",
                "module_name": "0x6170746f735f636f696e",
                "struct_name": "0x4170746f73436f696e"
              }
            }
          },
          {
            "version": "2665347733",
            "guid": {
              "creation_number": "0",
              "account_address": "0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12"
            },
            "sequence_number": "1",
            "type": "0x1::account::CoinRegisterEvent",
            "data": {
              "type_info": {
                "account_address": "0xec42a352cc65eca17a9fa85d0fc602295897ed6b8b8af6a6c79ef490eb8f9eba",
                "module_name": "0x616d6d5f73776170",
                "struct_name": "0x506f6f6c4c6971756964697479436f696e3c3078313a3a6170746f735f636f696e3a3a4170746f73436f696e2c203078663232626564653233376130376531323162353664393161343931656237626364666431663539303739323661396535383333386639363461303162313766613a3a61737365743a3a555344543e"
              }
            }
          }
        ]
        import requests
        
        url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/events/0x1::account::Account/coin_register_events"
        
        response = requests.get(url)
        
        print(response.text)
        import axios from 'axios';
        
        let config = {
          method: 'get',
          maxBodyLength: Infinity,
          url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/events/0x1::account::Account/coin_register_events'
        };
        
        axios.request(config)
        .then((response) => {
          console.log(JSON.stringify(response.data));
        })
        .catch((error) => {
          console.log(error);
        });
        
    import requests
    url = "https://go.getblock.io/<ACCESS-TOKEN>/"
    headers = { "Content-Type": "application/json" }
    payload = { "jsonrpc": "2.0", "method": "eth_blockNumber", "params": [], "id": "getblock.io" }
    response = requests.post(url, headers=headers, json=payload)
    print(response.json())
    curl -h
    curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "jsonrpc": "2.0",
        "method": "eth_blockNumber",
        "params": [],
        "id": "getblock.io"
    }'
    python -m pip install requests
    import requests
    url = "https://go.getblock.io/<ACCESS-TOKEN>/"
    headers = { "Content-Type": "application/json" }
    payload = { "jsonrpc": "2.0", "method": "eth_blockNumber", "params": [], "id": "getblock.io" }
    response = requests.post(url, headers=headers, json=payload)
    print(response.json())
    node -v
    ruby -v
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
       "jsonrpc": "2.0",
        "method": "eth_getBlockTransactionCountByNumber",
        "params": [
            "latest"
        ],
        "id": "getblock.io"
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
       "jsonrpc": "2.0",
       "method": "eth_getBlockTransactionCountByNumber",
        "params": [
            "latest"
        ],
        "id": "getblock.io"
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": "0x8"
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function Call() {
      try {
         const result = await provider.send("eth_getBlockTransactionCountByNumber",
    ["latest"]);    
    console.log("The result:", result);
        return result;
      } catch (error) {
        console.error("The error:", error);
        throw error;
      }
    }
    import { createPublicClient, http } from 'viem';
    import { arbitrum } from 'viem/chains';
    
    // Create Viem client with GetBlock
    const client = createPublicClient({
      chain: arbitrum,
      transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
    });
    
    // Using the method through Viem
    async function Call() {
        try {
            // Method-specific Viem implementation
            const result = await client.request({
               method:   "eth_getBlockTransactionCountByNumber",
               params:   ["latest"]
            });
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Viem Error:', error);
            throw error;
        }
    }
    
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
      "jsonrpc": "2.0",
      "method": "eth_getBalance",
      "id": "getblock.io",
      "params": [
            "0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
            "latest"
        ],
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
      "jsonrpc": "2.0",
      "method": "eth_getBalance",
      "id": "getblock.io",
      "params": [
            "0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
            "latest"
        ],
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": "0x20a2c3a842980"
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function Call() {
      try {
         const result = await provider.send("eth_getBalance", ["0xb8b2522480f850eb198ada5c3f31ac528538d2f5", "latest"]);
        console.log("The result:", result);
        return result;
      } catch (error) {
        console.error("The error:", error);
        throw error;
      }
    }
    import { createPublicClient, http } from 'viem';
    import { arbitrum } from 'viem/chains';
    
    // Create Viem client with GetBlock
    const client = createPublicClient({
      chain: arbitrum,
      transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
    });
    
    // Using the method through Viem
    async function Call() {
        try {
            // Method-specific Viem implementation
            const result = await client.request({
                method: 'eth_getBalance',
                params: ["0xb8b2522480f850eb198ada5c3f31ac528538d2f5", "latest"],
            });
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Viem Error:', error);
            throw error;
        }
    }
    
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
      "jsonrpc": "2.0",
      "method": "eth_gasPrice",
      "id": "getblock.io",
      "params": [],
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
      "jsonrpc": "2.0",
      "method": "eth_gasPrice",
      "id": "getblock.io",
      "params": [],
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": "0x989680"
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function Call() {
      try {
         const result = await provider.send("eth_gasPrice", []);
        console.log("The result:", result);
        return result;
      } catch (error) {
        console.error("The error:", error);
        throw error;
      }
    }
    import { createPublicClient, http } from 'viem';
    import { arbitrum } from 'viem/chains';
    
    // Create Viem client with GetBlock
    const client = createPublicClient({
      chain: arbitrum,
      transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
    });
    
    // Using the method through Viem
    async function Call() {
        try {
            // Method-specific Viem implementation
            const result = await client.request({
                method: 'eth_gasPrice',
            });
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Viem Error:', error);
            throw error;
        }
    }
    
    RBAC: access denied
    node index.js
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": "0x183037af"
    }
    python main.py
    https://go.getblock.us/
    https://go.getblock.io
    mkdir arbitrum-api-quickstart
    cd arbitrum-api-quickstart
    npm init --yes
    mkdir arbitrum-api-quickstart
    cd arbitrum-api-quickstart
    yarn init --yes
    npm install axios
    yarn add axios
    mkdir arbitrum-api-quickstart
    cd arbitrum-api-quickstart
    python -m venv venv
    source venv/bin/activate  
    # On Windows, use venv\Scripts\activate
    pip install requests
    import axios from 'axios'
    let data = JSON.stringify({
      jsonrpc: "2.0",
      method: "eth_blockNumber",
      params: [],
      id: "getblock.io",
    });
    
    let config = {
      method: "post",
      maxBodyLength: Infinity,
      url: "https://go.getblock.us/<ACCESS_TOKEN>",
      headers: {
        "Content-Type": "application/json",
      },
      data: data,
    };
    
    axios
      .request(config)
      .then((response) => {
        console.log(JSON.stringify(response.data));
      })
      .catch((error) => {
        console.log(error);
      });
    
    import requests
    import json
    
    url = "https://go.getblock.us/<ACCESS_TOKEN>"
    
    payload = json.dumps({
      "jsonrpc": "2.0",
      "method": "eth_blockNumber",
      "params": [],
      "id": "getblock.io"
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    

    Send the invite.

    circle-exclamation

    The invite link is valid for 30 minutes. If it expires, please resend an invitation.

    The user will receive an invitation email with a link to sign up and join the team.

    secure password
    for your new account.
  • Check the boxes to agree to the Terms of Service and Privacy Policy and complete the registration.

  • circle-exclamation

    The invite link is valid for 30 minutes. If it expires, ask the team owner or admin to send a new invitation.

    Once registered, you’ll have your personal GetBlock account. Additionally, you gain access to the team’s dashboard and resources based on permissions given by the team owner or admin.

    circle-info

    Next steps: Explore GetBlock

    Now that you’ve joined a team, here are a few useful resources to help you get started:

    • Getting Started – Learn more about GetBlock.

    • – How to create and manage node endpoints.

    • – Understanding plans and payments.

    ✅

    🔓

    Add & remove team members

    ✅

    ✅

    ❌

    Edit access levels

    ✅

    ✅

    ❌

    Promote to Admin

    ✅

    ❌

    ❌

    role and permissions
    Adding users to the team account on GetBlock
    Viewing permissions for team account users
    Active
    Pending
    How to create a team account on GetBlock
    Creating an enterprise account with RPC node provider GetBlock
    Collaboration feature for GetBlock enterprise users
    Managing team account user permissions and roles
    Instructions to remove a team user from the GetBlock team account
    How to join a team account on GetBlock
    Using GetBlock's personal and team accounts
    after blockchain confirmation
    , which may take a few minutes.

    Expiring Soon

    (One-Time Payment)

    In Grace Period

    (Recurring /One-Time)

    tracking the status of dedicated blockchain node subscriptions from GetBlock account
    How to manage dedicated node plans and subsciriptions from GetBlock's user account
    Checking the status of dedicated node subscriptions from the main GetBlock user dashboard
    How to manage node subscriptions from the GetBlock dashboard
    How to extend dedicated node plan using GetBlock
    Managing RPC node subscriptions from the main dashboard's endpoints list
    Flexible dedicated RPC node plan subscription

    CU Allocation

    50k/day

    50M/month

    220M/month

    600M/month

    Custom

    RPS Limit

    20 RPS

    100 RPS

    300 RPS

    500 RPS

    Custom

    Access Tokens

    2

    10

    25

    50

    Custom

    Extra CU Purchase

    ❌

    ✅

    ✅

    ✅

    ✅

    Access Tokens: 2
    circle-exclamation

    Compute Units are renewed daily, but unused CUs cannot be transferred to the next day.

    Clients who want to increase their usage limits can choose between the higher-tier options.

    This is a monthly subscription designed for use cases that are growing beyond the free tier. It offers a significant increase in CU compared to the Free plan.

    • CU: 50M per month (~1.6M/day)

    • Throughput: 100 requests per second (RPS)

    • Access Tokens: 10

    • Additional CU packages can be purchased as needed.

    The Advanced Plan is a mid-to-upper tier, production-ready plan, suitable for moderate-to-high traffic applications.

    • CU: 220M per month (~7.2M/day)

    • Throughput: 300 requests per second (RPS)

    • Access Tokens: 25

    • Add extra compute units (CU) to your account balance when needed without switching plans

    The Pro Plan is built for applications that need significantly higher throughput and increased resource availability compared to lower tier plans.

    • CU: 600M per month (~20M/day)

    • Throughput: 500 requests per second (RPS)

    • Access Tokens: 50

    • Purchase additional CU packages when required

    The Enterprise plan is fully customizable with tailored CU allocations, rate limits, and access tokens to meet exceptionally high call volumes and performance requirements.

    • CU: Custom monthly allocation based on your demands

    • Throughput: Custom

    • Access Tokens: Custom

    • Additional CU packages can be purchased on demand

    Price/month

    $0

    $49

    $199

    $499

    CU (Compute Units)
    Access Tokens
    https://getblock.io/pricing/arrow-up-right
    Top up CUs and boost limits
    Contact our support teamarrow-up-right
    Choosing your plan
    GetBlock's free RPC node plan limits
    Dedicated node for scalable and unlimited RPC node access

    from $999

    Mainnet

    hashtag
    Parameters

    Parameter
    Data type
    Description
    Required
    In

    account_hash

    string

    Aptos account address.

    Yes

    Path


    hashtag
    Request

    Base URL

    Example (cURL)

    hashtag
    Response


    hashtag
    Response Parameter Definition

    Field
    Type
    Description

    bytecode

    string

    Hex-encoded bytecode of the deployed module.

    abi

    object

    ABI (Application Binary Interface) containing metadata for module interaction.


    hashtag
    Use Cases

    This endpoint can be used to:

    • Retrieve module ABIs for building smart contract interaction interfaces.

    • Fetch module bytecode for on-chain security analysis and verification.

    • Display contract details in analytics dashboards or blockchain explorers.

    • Enable dApps to validate if a specific module exists before user interaction.

    hashtag
    Code Examples

    Python (requests)

    Node(Axios)


    hashtag
    Error Handling

    Status Code
    Error Message
    Cause

    403

    Forbidden

    Missing or invalid <ACCESS_TOKEN>.

    404

    Resource not found

    The specified module does not exist.


    hashtag
    Integration with Web3

    By integrating /v1/accounts/{account_hash}/module/{module_name}, developers can:

    • Retrieve module ABIs to construct transactions for smart contracts dynamically.

    • Validate wallet or dApp interactions by confirming module existence.

    • Fetch module bytecode for security inspection or automated audits.

    • Allow services or other contracts to interpret available structs and functions dynamically.

    hashtag
    Parameter

    Parameter

    Type

    In

    Required

    Description

    start

    Integer

    Query

    No

    Starting transaction version for pagination.

    hashtag
    Request

    Base URL

    Example(cURL)

    hashtag
    Response Example

    hashtag
    Response Parameter Definition

    Field

    Type

    Description

    version

    String

    Global transaction version (unique ID in Aptos ledger).

    hash

    String

    Transaction hash.

    hashtag
    Use Cases

    This method is used for:

    • Display a feed of recent blockchain activity.

    • Monitor all user-submitted transactions in real time.

    • Build analytics dashboards for transaction patterns.

    hashtag
    Code Example

    Node(Axios)

    Python(Request)

    hashtag
    Error handling

    Status Code

    Error Message

    Cause

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    500

    Internal server error

    Node or network issue; retry later.

    hashtag
    Integration with Web3

    By integrating /v1/transactions, developers can:

    • Stream blockchain activity into wallets and dApps.

    • Enable dashboards showing the latest transfers, mints, or contract calls.

    • Support DeFi/NFT protocols by tracking relevant transactions.

    • Provide analytics & insights on transaction frequency, volume, and patterns.

    hashtag
    Parameter

    Parameter

    Type

    In

    Required

    Description

    block_height

    Integer

    Path

    Yes

    Height (number) of the block to fetch.

    hashtag
    Request

    Base URL

    Example(cURL)

    hashtag
    Response Example

    hashtag
    Response Parameter Definition

    Field

    Description

    block_height

    The height of the block

    block_hash

    The hash of the block at the specified height

    block_timestamp

    The time at which the block was created/added to the chain

    first_version

    hashtag
    Use Cases

    This method can be used for:

    • Get a specific block by its height.

    • Explore transactions inside a given block.

    • Build block explorers or monitoring dashboards.

    hashtag
    Code Example

    Python(Request)

    Node(Axios)

    hashtag
    Error Handling

    Status Code

    Error Message

    Cause

    403

    Forbidden

    Invalid or missing ACCESS_TOKEN.

    410

    Block has been pruned

    No block exists for the specified height or pruned.

    hashtag
    Integration with Web3

    By integrating /v1/blocks/by_height/{block_height}, developers can:

    • Synchronise chain data by fetching blocks sequentially.

    • Monitor on-chain activity at the block level.

    • Enable dApps to verify inclusion of transactions at a given height.

    hashtag
    Parameter

    Parameter

    Data type

    Description

    Required

    In

    version

    integer

    The ledger version

    Yes

    Path

    hashtag
    Request

    Base URL

    Example(cURL)

    hashtag
    Response Example

    hashtag
    Response Parameter Definition

    Field

    Type

    Description

    version

    String

    Global transaction version number.

    hash

    String

    Hash of the transaction.

    hashtag
    Use cases

    This method is used for:

    • Retrieve details of a specific transaction by its version.

    • Debug failed transactions by checking vm_status.

    • Build explorers that let users search transactions by version.

    • Track system-level transactions like block epilogues.

    hashtag
    Code Example

    Node(axios)

    Python(Request)

    hashtag
    Error handling

    Status Code

    Error Message

    Cause

    403

    forbidden

    Missing or invalid <ACCESS_TOKEN>.

    410

    Ledger version has been pruned

    Incorrect version number or being pruned

    hashtag
    Integration with Web3

    By integrating /v1/transactions/by_version/{version}, developers can:

    • Trace exact transactions for auditing or compliance.

    • Debug dApps by fetching execution results and state changes.

    • Enable explorers to link transactions with block details. Monitor validators/system txns like block prologues and epilogues.

    Mainnet

    hashtag
    Parameters

    Parameter

    Data type

    Description

    Required

    In

    account_hash

    string

    Aptos account address

    Yes

    Path

    hashtag
    Request Example

    Base URL

    Example(cURL)

    hashtag
    Response

    hashtag
    Response Parameter Definition

    Value
    Data type
    Description

    type

    string

    The type format of the account address

    data

    object

    The additional data or information related to the account resource

    hashtag
    Use Cases

    This method can be used to:

    • Fetch a specific token balance without retrieving all account resources.

    • Query a single resource type (like a staking pool or NFT ownership).

    • Used in wallets and DeFi apps where targeted resource data is required.

    hashtag
    Code Examples

    Python (Requests)

    Node(Axios)

    hashtag
    Error handling

    The possible error you may experience includes the following:

    Status Code

    Error Message

    Cause

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    404

    Resource not found

    The given resource type does not exist for this account.

    hashtag
    Integration with Web3

    By integrating /v1/accounts/{account_hash}/resource/{resource_type, developers can:

    • Query a single CoinStore to show token balances in wallets.

    • Validate a user’s participation in staking, liquidity pools, or governance.

    • Reduce bandwidth by fetching only the resource you need, instead of all resources.

    • Pull targeted NFT or token data for user profiles or marketplaces.

    Mainnet

    hashtag
    Parameters

    Parameter
    Data type
    Description
    Required
    In

    account_hash

    string

    Aptos account address.

    Yes

    Path


    hashtag
    Request

    Base URL

    Request Example (cURL)

    hashtag
    Response


    hashtag
    Response Parameter Definition

    Field
    Type
    Description

    version

    string

    Ledger version number at which the event was recorded.

    guid

    object

    Globally unique identifier (GUID) for the event.

    hashtag
    Use Cases

    This method can be used for:

    • Tracking account-level activity logs such as deposits, withdrawals, and transfers.

    • Building blockchain explorers that display historical event data.

    • Monitoring DeFi or NFT protocols that emit custom contract events.

    • Triggering real-time alerts when specific on-chain events occur.


    hashtag
    Code Examples

    hashtag
    Node.js (Axios)

    hashtag
    Python (Request)

    Replace <ACCESS_TOKEN> with your actual GetBlock access token.


    hashtag
    Error Handling

    Status Code
    Error Message
    Cause

    400

    Invalid account address

    The provided account_hash is invalid.

    401

    Unauthorized

    Missing or invalid <ACCESS_TOKEN>.


    hashtag
    Integration with Web3

    By integrating /v1/accounts/{account_hash}/events/{creation_number}, developers can:

    • Optimise event tracking for NFT, DeFi, and gaming applications.

    • Build real-time activity feeds from on-chain actions.

    • Map blockchain transactions into user-friendly notifications.

    • Support advanced analytics for blockchain event visualisation.

    hashtag
    Parameters
    Field
    Type
    Required
    Description

    transaction

    object

    yes

    Main transaction object containing the call data

    from

    string

    hashtag
    Request

    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header '
    
    import axios from 'axios'
    let 
    

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Data Type
    Definition

    result

    string

    The return value of the executed contract function, encoded as a hexadecimal string.

    hashtag
    Use case

    eth_call is used to:

    • Track the latest block height

    • Monitor chain progress or finality

    • Trigger event-based updates when the block number increases

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    hashtag
    Integration with Web3

    The eth_call can help developers to:

    • Enables trustless frontends

    • Reads live contract state without gas

    • Supports dashboards, DeFi analytics, wallets, NFT explorers

    • Let's developers simulate transactions before execution

    Required
    Description

    address

    string

    yes

    The target address to inspect. Must be a valid 20 byte Ethereum-style address.

    block_number

    string

    yes

    The block number or state override reference such as latest, earliest, or pending.

    hashtag
    Request

    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header '
    
    import axios from 'axios'
    let 
    

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Type
    Description

    result

    string (hex)

    Contract bytecode at the given address. Returns 0x if the address is not a contract.

    hashtag
    Use case

    The eth_getCode is used to:

    • Checking if an address is a contract or an externally owned account

    • Verifying onchain deployments for security audits

    • Allowing frontends to detect contract upgrades by comparing bytecode

    • Supporting explorers that display contract metadata

    • Identifying proxy contracts by checking for minimal bytecode patterns

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    -32602

    Invalid argument

    • The Address not 20 bytes or missing prefix

    • block hash isn't accurate or incomplete

    • keyword missing

    hashtag
    Integration with Web3

    The eth_getCode method helps developers to:

    • Detect whether a user is interacting with a contract or a wallet

    • Validate deployed bytecode for audit and debugging purposes

    • Build tools that identify proxies, multicall contracts, routers, and libraries

    • Support trustless dapps that rely on on-chain introspection

    • Ensure safe interactions by verifying contract code before sending transactions

    Description

    block_hash

    string

    yes

    Hash of the block whose transaction count is being requested. Must be a valid 32-byte hex string with 0x prefix.

    hashtag
    Request

    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header '
    
    import axios from 'axios'
    let 
    

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Type
    Description

    result

    string (hex)

    Transaction count of the block. Returns null if the block is not found.

    hashtag
    Use case

    The eth_getBlockTransactionCountByHash is used to:

    • Counting total transactions in a given block

    • Building block explorers or analytics dashboards

    • Monitoring throughput or spikes in chain activity

    • Identifying empty or low-activity blocks

    • Pre-processing blocks before downloading the full transaction list

    • Reducing bandwidth when only counts are needed instead of full block data

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    -32602

    Invalid argument

    The block hash isn't accurate or incomplete

    hashtag
    Integration with Web3

    The eth_getBlockTransactionCountByHash can help developers:

    • Power block explorers that show transaction counts without loading full blocks

    • Measure chain activity for dashboards and metrics

    • Build fast monitoring tools that track throughput

    • Reduce bandwidth usage by avoiding heavy block queries

    • Support systems that decide whether to fetch full block data based on count

    eth_getStorageAt - Arbitrum

    Example code for the eth_getStorageAt JSON RPC method. Сomplete guide on how to use eth_getStorageAt JSON RPC in GetBlock Web3 documentation.

    This method returns the value stored at a specific storage slot of a contract. Every smart contract stores its data in 32-byte slots, and this method provides direct low-level access to them.

    hashtag
    Parameters

    Parameter
    Type
    Required
    Description

    hashtag
    Request

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Type
    Description

    hashtag
    Use case

    The eth_getStorageAt is used to:

    • Reading contract variables without calling a function

    • Inspecting mappings, arrays, and structs by computing their storage slots

    • Powering dashboards and analytics tools that pull historical state data

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    hashtag
    Integration with Web3

    The eth_getStorageAt method helps developers to:

    • Build trustless analytics dashboards

    • Inspect contract internals without a function call

    • Recover lost data values during debugging

    eth_getTransactionCount - Arbitrum

    Example code for the eth_getTransactionCount JSON RPC method. Сomplete guide on how to use eth_getTransactionCount JSON RPC in GetBlock Web3 documentation.

    This method returns the number of transactions sent from an address. This value is also known as the nonce. It is required when creating new transactions because each transaction from the same sender must have a unique nonce.

    hashtag
    Parameters

    Parameter
    Type
    Required
    Description

    hashtag
    Request

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Type
    Description

    hashtag
    Use case

    The eth_getTransactionCount :

    • Determining the correct nonce before sending a new transaction

    • Replaying transaction history for analytics or dashboards

    • Monitoring the activity of accounts in explorers

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    hashtag
    Integration with Web3

    The eth_getTransactionCount method helps developers to:

    • Manage nonces automatically when sending transactions

    • Prevent duplicate transactions by checking the latest nonce

    • Build reliable wallet transaction pipelines

    What counts as a CU

    Learn what Compute Units (CUs) are and how GetBlock calculates them to track and price API calls

    In our Shared Node plans, we use CU-based pricing. CUs, Compute Units, is a way to measure the computational resources that each API request consumes.

    circle-info

    hashtag
    Request vs CU

    How to Use Multicall3

    Multicall3 batches multiple operations into a single transaction with atomic execution.

    Multicall3 batches multiple operations into a single transaction with atomic execution using bsc_private_tx to get MEV protection with internal fee payment.

    This is very good for most use cases, e.g., DEX swaps, token purchases, etc but consumes a lot of gas. If any part fails, the entire transaction reverts.

    hashtag
    How it works

    This is how Multicall3 works:

    /v1/blocks/by_version/{version} - Aptos

    Example code for the /v1/blocks/by_version/{version} JSON-RPC method. Сomplete guide on how to use /v1/blocks/by_version/{version} json-rpc in GetBlock.io Web3 documentation.

    This endpoint gets a transaction by its ledger version number from Aptos blockchain.

    hashtag
    Supported Network

    • Mainnet

    eth_estimateGas - Arbitrum

    Example code for the eth_estimateGas JSON RPC method. Сomplete guide on how to use eth_estimateGas JSON RPC in GetBlock Web3 documentation.

    This method estimates the gas required to execute a transaction on Arbitrum without broadcasting it. This simulates execution and returns the minimal gas needed.

    hashtag
    Parameters

    Field
    Type
    Required
    https://go.getblock.io/<ACCESS_TOKEN>/
    curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/module/curves'
    {
      "bytecode": "0xa11ceb0b050000000b01000402040c03101e042e0c053a0f07497e08c701400687020a109102300ac1020a0ccb023e00000101000200000003000001090700000400000100000500010100000600010100000700010100010a000301000302040204040405020201020001010109000108020108000108010663757276657309747970655f696e666f06537461626c650c556e636f7272656c61746564126173736572745f76616c69645f63757276650969735f737461626c650f69735f756e636f7272656c617465640e69735f76616c69645f63757276650b64756d6d795f6669656c640854797065496e666f07747970655f6f66190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12000000000000000000000000000000000000000000000000000000000000000103081127000000000000126170746f733a3a6d657461646174615f76301c011127000000000000114552525f494e56414c49445f43555256450000020108010102010801000100000005380003040700270201010000000438013802210202010000000438013803210203010000010a380403030506080c00050838050c000b000200",
      "abi": {
        "address": "0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12",
        "name": "curves",
        "friends": [],
        "exposed_functions": [
          {
            "name": "assert_valid_curve",
            "visibility": "public",
            "is_entry": false,
            "is_view": false,
            "generic_type_params": [{ "constraints": [] }],
            "params": [],
            "return": []
          },
          {
            "name": "is_stable",
            "visibility": "public",
            "is_entry": false,
            "is_view": false,
            "generic_type_params": [{ "constraints": [] }],
            "params": [],
            "return": ["bool"]
          },
          {
            "name": "is_uncorrelated",
            "visibility": "public",
            "is_entry": false,
            "is_view": false,
            "generic_type_params": [{ "constraints": [] }],
            "params": [],
            "return": ["bool"]
          },
          {
            "name": "is_valid_curve",
            "visibility": "public",
            "is_entry": false,
            "is_view": false,
            "generic_type_params": [{ "constraints": [] }],
            "params": [],
            "return": ["bool"]
          }
        ],
        "structs": [
          {
            "name": "Stable",
            "is_native": false,
            "is_event": false,
            "abilities": [],
            "generic_type_params": [],
            "fields": [{ "name": "dummy_field", "type": "bool" }]
          },
          {
            "name": "Uncorrelated",
            "is_native": false,
            "is_event": false,
            "abilities": [],
            "generic_type_params": [],
            "fields": [{ "name": "dummy_field", "type": "bool" }]
          }
        ]
      }
    }
    import requests
    
    url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/module/curves"
    
    response = requests.get(url)
    
    print(response.text)
    import axios from 'axios';
    
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/module/curves'
    };
    
    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });
    https://go.getblock.io/<ACCESS_TOKEN>
    curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions?limit=1'
    [
        {
            "version": "3556744764",
            "hash": "0x1cd28f386d48edfaf30c822117bd0b971e349c59f5fdd08f284558b33ac1715f",
            "state_change_hash": "0xafb6e14fe47d850fd0a7395bcfb997ffacf4715e0f895cc162c218e4a7564bc6",
            "event_root_hash": "0x414343554d554c41544f525f504c414345484f4c4445525f4841534800000000",
            "state_checkpoint_hash": "0xe8daf9e9f3986dc69e0247b5638af4f55a6e5912da8a2c71e1fa537009a59964",
            "gas_used": "0",
            "success": true,
            "vm_status": "Executed successfully",
            "accumulator_root_hash": "0x6a006a1a2d4d22b7fdf4ca27a31aac610c3911429d8e5f925e31016738b225e2",
            "changes": [],
            "timestamp": "1760341338522220",
            "block_end_info": {
                "block_gas_limit_reached": false,
                "block_output_limit_reached": false,
                "block_effective_block_gas_units": 71,
                "block_approx_output_size": 7846
            },
            "type": "block_epilogue_transaction"
        }
    ]
    
    const axios = require('axios');
    
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions?limit=1',
    };
    
    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });
    
    
    import requests
    
    url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions?limit=1"
    
    response = requests.request("GET", url, headers=headers, data=payload)
    
    print(response.text)
    
    
    https://go.getblock.io/<ACCESS_TOKEN>
    curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/blocks/by_height/425737645?with_transactions=false'
    
    {
        "block_height": "445814139",
        "block_hash": "0x0ac6b36f89b6a3fc9b7c2cabcb1f29cc624e609ed0978dd2a757b048196cb3bc",
        "block_timestamp": "1759349325550593",
        "first_version": "3492983944",
        "last_version": "3492983948",
        "transactions": null
    }
    import requests
    
    url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/blocks/by_height/425737645?with_transactions=false"
    response = requests.request("GET", url, headers=headers, data=payload)
    
    print(response.text)
    import axios from ‘axios’
    
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: "https://go.getblock.io/<ACCESS_TOKEN>/v1/blocks/by_height/425737645?with_transactions=false"
    };
    
    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });
    https://go.getblock.io/<ACCESS_TOKEN>
    curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_version/3363904007'
    {
        "version": "3363904007",
        "hash": "0xd797b944ed8657406a1b09a5928048093399fc0a2f576d3e57c0f9cedbf95c4a",
        "state_change_hash": "0xafb6e14fe47d850fd0a7395bcfb997ffacf4715e0f895cc162c218e4a7564bc6",
        "event_root_hash": "0x414343554d554c41544f525f504c414345484f4c4445525f4841534800000000",
        "state_checkpoint_hash": "0xbf257d934f991d1e7d74079cc9060d3ac005aaa208d93a1fd4928dfc224bba53",
        "gas_used": "0",
        "success": true,
        "vm_status": "Executed successfully",
        "accumulator_root_hash": "0xc985314d5c118899c649b772c237178c63f328e7d286aceea01a30373d491d95",
        "changes": [],
        "timestamp": "1757261767411156",
        "block_end_info": {
            "block_gas_limit_reached": false,
            "block_output_limit_reached": false,
            "block_effective_block_gas_units": 500,
            "block_approx_output_size": 21541
        },
        "type": "block_epilogue_transaction"
    }
    
    const axios = require('axios');
    
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_version/3541136893',
    };
    
    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });
    import requests
    
    url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_version/3541136893"
    
    response = requests.request("GET", url, headers=headers, data=payload)
    
    print(response.text)
    https://go.getblock.io/<ACCESS-TOKEN>/
    curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/resource/0x1::account::Account'
    {
        "type": "0x1::account::Account",
        "data": {
            "authentication_key": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
            "coin_register_events": {
                "counter": "0",
                "guid": {
                    "id": {
                        "addr": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
                        "creation_num": "0"
                    }
                }
            },
            "guid_creation_num": "2",
            "key_rotation_events": {
                "counter": "0",
                "guid": {
                    "id": {
                        "addr": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
                        "creation_num": "1"
                    }
                }
            },
            "rotation_capability_offer": {
                "for": {
                    "vec": []
                }
            },
            "sequence_number": "250163",
            "signer_capability_offer": {
                "for": {
                    "vec": []
                }
            }
        }
    }
    
    import requests
    
    url = "https://go.getblock.io/b293629b1b3a4e188efb3c4e94d133b6/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/resource/0x1::account::Account"
    response = requests.request("GET", url, headers=headers, data=payload)
    
    print(response.text)
    
    import axios from 'axios'
    
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: 'https://go.getblock.io/b293629b1b3a4e188efb3c4e94d133b6/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/resource/0x1::account::Account',
    };
    
    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });
    
    
    https://go.getblock.io/
    <ACCESS_TOKEN>
    curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/events/0'
    [
      {
        "version": "2665347733",
        "guid": {
          "creation_number": "0",
          "account_address": "0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12"
        },
        "sequence_number": "1",
        "type": "0x1::account::CoinRegisterEvent",
        "data": {
          "type_info": {
            "account_address": "0xec42a352cc65eca17a9fa85d0fc602295897ed6b8b8af6a6c79ef490eb8f9eba",
            "module_name": "0x616d6d5f73776170",
            "struct_name": "0x506f6f6c4c6971756964697479436f696e3c3078313a3a6170746f735f636f696e3a3a4170746f73436f696e2c203078663232626564653233376130376531323162353664393161343931656237626364666431663539303739323661396535383333386639363461303162313766613a3a61737365743a3a555344543e"
          }
        }
      }
    ]
    
    import axios from 'axios';
    
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xc32f662cd9718f02d8a8e5628f8f642fa27cd9b5f457b406ed734901a4939e34/events/0?limit=1&start=1'
    };
    
    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });
    import requests
    
    url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xc32f662cd9718f02d8a8e5628f8f642fa27cd9b5f457b406ed734901a4939e34/events/0?limit=1&start=1"
    
    response = requests.get(url)
    
    print(response.text)
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
      "jsonrpc": "2.0",
      "method": "eth_call",
      "id": "getblock.io",
      "params": [
        {
          "to": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
          "data": "0x8da5cb5b"
        },
        "latest"
      ]
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{{
      "jsonrpc": "2.0",
      "method": "eth_call",
      "id": "getblock.io",
      "params": [
        {
          "to": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
          "data": "0x8da5cb5b"
        },
        "latest"
      ]
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/24915a36b17143a891d3b10447615258";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function Call() {
      try {
        // Call the method — this will resolve to a number (promise resolves to number)
         const result = await provider.send("eth_call", [
           {
             to: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
             data: "0x8da5cb5b",
           },
           "latest",
         ]);
        console.log("The result:", result);
        return result;
      } catch (error) {
        console.error("Ethers Error fetching block number:", error);
        throw error;
      }
    }
    
    
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": "0x0000000000000000000000002bad8182c09f50c8318d769245bea52c32be46cd"
    }
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
       "jsonrpc": "2.0",
        "method": "eth_getCode",
        "params": [
            "0x9b956e3d318625be2686ae7268d81777c462d41f",
            "latest"
        ],
        "id": "getblock.io"
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
       "jsonrpc": "2.0",
       "method": "eth_getCode",
        "params": [
            "0x9b956e3d318625be2686ae7268d81777c462d41f",
            "latest"
        ],
        "id": "getblock.io"
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function Call() {
      try {
         const result = await provider.send("eth_getCode",
      [
            "0x9b956e3d318625be2686ae7268d81777c462d41f",
            "latest"
        ],);    
    console.log("The result:", result);
        return result;
      } catch (error) {
        console.error("The error:", error);
        throw error;
      }
    }
    import { createPublicClient, http } from 'viem';
    import { arbitrum } from 'viem/chains';
    
    // Create Viem client with GetBlock
    const client = createPublicClient({
      chain: arbitrum,
      transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
    });
    
    // Using the method through Viem
    async function Call() {
        try {
            // Method-specific Viem implementation
            const result = await client.request({
              "method": "eth_getCode",
        "params": [
            "0x9b956e3d318625be2686ae7268d81777c462d41f",
            "latest"
        ]
            });
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Viem Error:', error);
            throw error;
        }
    }
    
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": "0x"
    }
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
       "jsonrpc": "2.0",
        "method": "eth_getBlockTransactionCountByHash",
        "params": [
            "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a"
        ],
        "id": "getblock.io"
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
       "jsonrpc": "2.0",
       "method": "eth_getBlockTransactionCountByHash",
        "params": [
            "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a"
        ],
        "id": "getblock.io"
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function Call() {
      try {
         const result = await provider.send("eth_getBlockTransactionCountByHash",
    ["0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a"]);    
    console.log("The result:", result);
        return result;
      } catch (error) {
        console.error("The error:", error);
        throw error;
      }
    }
    import { createPublicClient, http } from 'viem';
    import { arbitrum } from 'viem/chains';
    
    // Create Viem client with GetBlock
    const client = createPublicClient({
      chain: arbitrum,
      transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
    });
    
    // Using the method through Viem
    async function Call() {
        try {
            // Method-specific Viem implementation
            const result = await client.request({
               method:   "eth_getBlockTransactionCountByHash",
               params:   ["0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a"]
            });
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Viem Error:', error);
            throw error;
        }
    }
    
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": "0x5"
    }
    Content-Type: application/json
    '
    \
    --data '{
    "jsonrpc": "2.0",
    "method": "eth_getCode",
    "params": [
    "0x9b956e3d318625be2686ae7268d81777c462d41f",
    "latest"
    ],
    "id": "getblock.io"
    }'
    data
    =
    JSON
    .
    stringify
    (
    {
    "jsonrpc": "2.0",
    "method": "eth_getCode",
    "params": [
    "0x9b956e3d318625be2686ae7268d81777c462d41f",
    "latest"
    ],
    "id": "getblock.io"
    };
    let config = {
    method: "post",
    maxBodyLength: Infinity,
    url: "https://go.getblock.us/<ACCESS_TOKEN>",
    headers: {
    "Content-Type": "application/json",
    },
    data: data,
    };
    axios
    .request(config)
    .then((response) => {
    console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
    console.log(error);
    });
    Content-Type: application/json
    '
    \
    --data '{
    "jsonrpc": "2.0",
    "method": "eth_getBlockTransactionCountByHash",
    "params": [
    "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a"
    ],
    "id": "getblock.io"
    }'
    data
    =
    JSON
    .
    stringify
    (
    {
    "jsonrpc": "2.0",
    "method": "eth_getBlockTransactionCountByHash",
    "params": [
    "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a"
    ],
    "id": "getblock.io"
    };
    let config = {
    method: "post",
    maxBodyLength: Infinity,
    url: "https://go.getblock.us/<ACCESS_TOKEN>",
    headers: {
    "Content-Type": "application/json",
    },
    data: data,
    };
    axios
    .request(config)
    .then((response) => {
    console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
    console.log(error);
    });

    module_name

    string

    The name of the smart contract module.

    Yes

    Path

    ledger_version

    string

    The ledger version to retrieve the module state. Optional parameter.

    No

    Query

    abi.address

    string

    Account address where the module is deployed.

    abi.name

    string

    Name of the module.

    abi.exposed_functions

    array

    List of public functions, including parameters, return types, and visibility.

    abi.structs

    array

    Struct definitions with fields and type information.

    500

    Internal server error

    Node or network issue. Retry the request later.

    limit

    Integer

    Query

    No

    Number of transactions to return. Default: 25. Maximum: 100.

    state_change_hash

    String

    Hash of all state changes caused by this transaction.

    event_root_hash

    String

    Merkle root hash of all events emitted.

    state_checkpoint_hash

    String

    Hash of the state checkpoint for this transaction.

    gas_used

    String

    Amount of gas consumed (0 here, since it’s a system txn).

    success

    Boolean

    Whether the transaction executed successfully.

    vm_status

    String

    VM execution result.

    accumulator_root_hash

    String

    Ledger’s global accumulator root after applying this transaction.

    changes

    Array

    State changes caused (empty here).

    timestamp

    String

    Unix timestamp in microseconds.

    block_end_info

    Object

    Metadata about block execution limits.

    block_end_info.block_gas_limit_reached

    Boolean

    Whether the block’s gas limit was hit.

    block_end_info.block_output_limit_reached

    Boolean

    Whether block output size was exceeded.

    block_end_info.block_effective_block_gas_units

    Interger

    Total effective gas used in the block.

    block_end_info.block_approx_output_size

    Integer

    Approximate output size of the block in bytes.

    type

    String

    Transaction type → here it’s block_epilogue_transaction (special system txn marking block end).

    with_transactions

    Boolean

    Query

    No

    If true, returns full transactions inside the block. Default: false.

    The version number of the first transaction in the block

    last_version

    The version number of the last transaction in the block

    transactions

    An array containing the details of the transactions included in the block

    type (transaction)

    The type of the change

    hash

    The hash of the transaction

    sender

    The account from which the transaction was sent

    sequence_number

    The sequence of a transaction sent by the specific sender

    max_gas_amount

    The maximum amount of gas allocated for the execution of a transaction

    gas_unit_price

    The cost per unit of gas (determines the transaction fee)

    expiration_timestamp_secs

    The timestamp until which the transaction can be included in a block

    payload

    The data carried by a transaction

    type (payload)

    The type of payload indicates the purpose of the data contained

    function

    The function associated with the payload

    type_arguments

    An array specifying the types of arguments provided to the function

    arguments

    An array containing the actual arguments passed to the function

    signature

    An array with signature details

    type (signature)

    The type of signature used to verify authenticity

    public_key

    The public key of the account that generated the signature

    signature (value)

    The actual signature generated with the private key

    500

    Internal server error

    Node or network issue; retry later.

    state_change_hash

    String

    Hash of all state changes from this txn.

    event_root_hash

    String

    Merkle root hash of all events.

    state_checkpoint_hash

    String

    Hash of the state checkpoint.

    gas_used

    String

    Amount of gas consumed.

    success

    Boolean

    Whether transaction executed successfully.

    vm_status

    String

    Result status from Aptos VM.

    accumulator_root_hash

    String

    Global accumulator root hash.

    changes

    Array

    State changes applied (empty for system txns).

    timestamp

    String

    Unix timestamp in microseconds.

    block_end_info

    Object

    Metadata about block execution.

    block_end_info.block_gas_limit_reached

    Booleab

    Block’s gas limit was reached.

    block_end_info.block_output_limit_reached

    Boolean

    Block’s output size limit was hit.

    block_end_info.block_effective_block_gas_units

    Integer

    Effective gas used in this block.

    block_end_info.block_approx_output_size

    Interger

    Approximate output size of block in bytes.

    type

    String

    Transaction type (e.g., user_transaction, block_epilogue_transaction).

    500

    Internal server error

    Node or network issue; retry later.

    resource_type

    string

    The type format of the account address to retrieve

    Yes

    path

    ledger_version

    string

    The ledger version to get the account state

    No

    query

    authentication_key

    string

    The authentication key associated with the account to verify the identity of account owner

    coin_register_events

    object

    The events associated with coin registration for the specified response

    counter

    string

    The counter value associated with a particular operation

    guid

    object

    the unique identifier (GUID) of the resource

    id

    objecct

    The resource identifier

    addr

    string

    The address associated with the resource

    creation_num

    string

    The creation number of the resource

    sequence_number

    string

    The sequence number tracks the order of transactions initiated by the account

    500

    Internal server error

    Node or network issue. Retry later.

    creation_number

    integer

    The creation number of the event handle to be retrieved.

    Yes

    Path

    start

    string

    Starting point or offset for retrieving events. Defaults to showing the latest transactions if omitted.

    No

    Query

    limit

    integer

    Maximum number of events to retrieve per request. Defaults to the standard page size if not provided.

    No

    Query

    guid.creation_number

    string

    Creation number assigned to this event stream within the account.

    guid.account_address

    string

    Address of the account that owns this event handle.

    sequence_number

    string

    Sequential index of this event in the event stream.

    type

    string

    Fully qualified event type (e.g., 0x1::account::WithdrawEvent).

    data

    object

    Additional data payload associated with the event (depends on event type).

    404

    Event stream not found

    No event stream exists for the given creation_number.

    422

    Invalid creation number

    Malformed or unsupported creation number format.

    500

    Internal server error

    Node or network failure while retrieving events.

    Content-Type: application/json
    '
    \
    --data '{
    "jsonrpc": "2.0",
    "method": "eth_call",
    "id": "getblock.io",
    "params": [
    {
    "to": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
    "data": "0x8da5cb5b"
    },
    "latest"
    ]
    }'
    data
    =
    JSON
    .
    stringify
    (
    {
    "jsonrpc": "2.0",
    "method": "eth_call",
    "id": "getblock.io",
    "params": [
    {
    "to": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
    "data": "0x8da5cb5b"
    },
    "latest"
    ]
    };
    let config = {
    method: "post",
    maxBodyLength: Infinity,
    url: "https://go.getblock.us/<ACCESS_TOKEN>",
    headers: {
    "Content-Type": "application/json",
    },
    data: data,
    };
    axios
    .request(config)
    .then((response) => {
    console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
    console.log(error);
    });

    optional

    Caller address used for the simulation. Included inside the transaction object

    to

    string

    yes

    Smart contract address to call

    gas

    string (hex)

    optional

    Gas limit for the simulated call

    gasPrice

    string (hex)

    optional

    Ignored for simulations but allowed for compatibility

    value

    string (hex)

    optional

    Amount of ETH to send with the call (usually zero)

    data

    string

    yes

    Encoded function selector plus parameters

    block tag

    string or hex

    optional

    Block context for the simulation. Default is latest

    Managing Endpoints
    Plans & Limits
    Inviting teammates to GetBlock's team account
    GetBlock sign-up page
    Starter plan limits for Shared RPC nodes by GetBlock
    RPC node with higher-limit access
    GetBlock's Enterprise plan with custom usage limit settings
    Helping wallets validate allowance, balances, or approvals stored on-chain
  • Supporting audits by letting developers inspect raw contract storage

  • Read live smart contract state with zero gas
  • Simulate contract reads on historical blocks

  • Validate approvals or configurations stored in private mappings

  • address

    string

    yes

    The target contract address. Must be a valid Ethereum-style address.

    position

    string (hex)

    yes

    The storage slot index. Must be a 32-byte hex value (e.g. "0x0", "0x1", "0xabc...").

    block_number

    string

    yes

    result

    string (hex)

    32-byte hex value stored at the given slot. Empty slots return "0x000...000".

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    -32602

    Invalid argument

    • The Address not 20 bytes or missing prefix

    • Slot value not valid hex

    • Block number incorrect or out of range

    • keyword missing

    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data '{
       "jsonrpc": "2.0",
           "method": "eth_getStorageAt",
        "params": [
            "0x80d40e32FAD8bE8da5C6A42B8aF1E181984D137c",
            "0x0",
            "latest"
        ],
        "id": "getblock.io"
    }'
    import axios from 'axios'
    let data = JSON.stringify({
        "jsonrpc": "2.0",
           "method": "eth_getStorageAt",
        "params": [
            "0x80d40e32FAD8bE8da5C6A42B8aF1E181984D137c",
            "0x0",
            "latest"
        ],
        "id": "getblock.io"
    };
    
    let config = {
      method: "post",
      maxBodyLength: Infinity,
      url: "https://go.getblock.us/<ACCESS_TOKEN>",
      headers: {
        "Content-Type": "application/json",
      },
      data: data,
    };
    
    axios
      .request(config)
      .then((response) => {
        console.log(JSON.stringify(response.data));
      })
      .catch((error) => {
        console.log(error);
      });
    

    Block identifier such as "latest", "earliest", "pending", or a hex-encoded block number.

    Validating whether a wallet has pending transactions
  • Preventing double-spending by ensuring nonces are sequential

  • Track account activity in explorers and dashboards
  • Detect pending transactions by comparing pending vs latest values

  • Support batch transaction systems that depend on precise nonce control

  • address

    string

    yes

    The address for which to retrieve the transaction count. Must be a hex string with 0x prefix.

    block

    string

    yes

    Block context for the query. Accepted values include latest, earliest, pending, or a block number in hex.

    result

    string (hex)

    Number of transactions sent from this address. Equivalent to the account nonce.

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    -32602

    Invalid argument

    • Invalid address

    • Block parameter not recognized

    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data '{
       "jsonrpc": "2.0",
       "method": "eth_getTransactionCount",
        "params": [
            "0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
            "latest"
        ],
        "id": "getblock.io"
    }'
    import axios from 'axios'
    let data = JSON.stringify({
        "jsonrpc": "2.0",
         "method": "eth_getTransactionCount",
        "params": [
            "0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
            "latest"
        ],
        "id": "getblock.io"
    };
    
    let config = {
      method: "post",
      maxBodyLength: Infinity,
      url: "https://go.getblock.us/<ACCESS_TOKEN>",
      headers: {
        "Content-Type": "application/json",
      },
      data: data,
    };
    
    axios
      .request(config)
      .then((response) => {
        console.log(JSON.stringify(response.data));
      })
      .catch((error) => {
        console.log(error);
      });
    
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
       "jsonrpc": "2.0",
            "method": "eth_getStorageAt",
        "params": [
            "0x80d40e32FAD8bE8da5C6A42B8aF1E181984D137c",
            "0x0",
            "latest"
        ],
        "id": "getblock.io"
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
       "jsonrpc": "2.0",
        "method": "eth_getStorageAt",
        "params": [
            "0x80d40e32FAD8bE8da5C6A42B8aF1E181984D137c",
            "0x0",
            "latest"
        ],
        "id": "getblock.io"
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": "0x000000000000000000000000aadc76c6e4abeeb52d764443357f6e75db28f0e1"
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function Call() {
      try {
         const result = await provider.send("eth_getStorageAt",
        [
            "0x80d40e32FAD8bE8da5C6A42B8aF1E181984D137c",
            "0x0",
            "latest"
        ],);    
    console.log("The result:", result);
        return result;
      } catch (error) {
        console.error("The error:", error);
        throw error;
      }
    }
    import { createPublicClient, http } from 'viem';
    import { arbitrum } from 'viem/chains';
    
    // Create Viem client with GetBlock
    const client = createPublicClient({
      chain: arbitrum,
      transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
    });
    
    // Using the method through Viem
    async function Call() {
        try {
            // Method-specific Viem implementation
            const result = await client.request({
            method: "eth_getStorageAt",
            params: [
            "0x80d40e32FAD8bE8da5C6A42B8aF1E181984D137c",
            "0x0",
            "latest"
        ]
            });
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Viem Error:', error);
            throw error;
        }
    }
    
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
       "jsonrpc": "2.0",
        "method": "eth_getTransactionCount",
        "params": [
            "0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
            "latest"
        ],
        "id": "getblock.io"
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
       "jsonrpc": "2.0",
       "method": "eth_getTransactionCount",
        "params": [
            "0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
            "latest"
        ],
        "id": "getblock.io"
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": "0x50"
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function Call() {
      try {
         const result = await provider.send("eth_getTransactionByHash",
        [
            "0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181"
        ]);    
    console.log("The result:", result);
        return result;
      } catch (error) {
        console.error("The error:", error);
        throw error;
      }
    }
    import { createPublicClient, http } from 'viem';
    import { arbitrum } from 'viem/chains';
    
    // Create Viem client with GetBlock
    const client = createPublicClient({
      chain: arbitrum,
      transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
    });
    
    // Using the method through Viem
    async function Call() {
        try {
            // Method-specific Viem implementation
            const result = await client.request({
             method: "eth_getTransactionCount",
          params: ["0xb8b2522480f850eb198ada5c3f31ac528538d2f5", "latest"]});
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Viem Error:', error);
            throw error;
        }
    }
    
    Requests are the raw number of calls (e.g., an RPC method call) you make to the node, while Compute Units show how much computing power each call uses.

    Instead of charging a fixed fee for every call, GetBlock calculates the “cost” of processing a request based on the actual computational work involved – such as CPU & memory usage, and disk I/O.

    Here's how it works:

    • Different shared node plans include different allocations of Compute Units (CUs)

    • Each API call deducts an amount based on the resources it consumes

    • Users can track their remaining CUs in real time on the dashboard

    This model ensures costs are aligned with actual infrastructure usage.

    circle-info

    Learn More

    • CU and rate limits — Check how many CUs are included in each plan.


    hashtag
    How CUs are calculated

    Every API call "spends" a number of Compute Units. The total value is determined by three main factors:

    1. Base CU cost (chain multiplier) reflecting the network's resource intensity

    2. Method-specific multiplier which varies by API method

    3. Archive Modifier applied when a request is served by an archive node

    The total Compute Units for an API call are calculated using the following formula:

    Where:

    • Archive Modifier = 1 for standard full-node requests

    • Archive Modifier = 2 for requests served by archive endpoint


    hashtag
    1. Chain-based multipliers

    Not all blockchains are built or operate the same way. GetBlock accounts for inherent differences between networks by assigning chain multipliers based on factors such as:

    • Protocol complexity and the size of the blockchain data

    • Node infrastructure costs

    • Operational overhead

    Here’s how blockchains are grouped based on their average resource intensity:

    Chains
    Multiplier
    Explanation

    Algorand, Bitcoin, Bitcoin Cash, Dash, Dogecoin, Ethereum Classic, Kusama, Litecoin, Near, OKB, Polkadot, Rootstock, Scroll, Shiba Inu, Sonic, Syscoin, Telos, Zcash, others

    10

    Low per-request resource cost and write/read complexity

    Aptos, Arbitrum, Arbitrum Nova, Avalanche, BNB Smart Chain, Base, Blast, Cardano, Cosmos, Cronos, Ethereum, Filecoin, Flow, Gnosis, Harmony, Kaia, Linea, Moonbeam, OKT, Optimism, Polygon, Polygon zkEVM, StarkNet, Tezos, Tron, XRP, opBNB, zkSync

    20

    Moderate resource intensity


    hashtag
    2. Method-specific multipliers

    Different API methods put different loads on backend nodes. For example:

    • eth_blockNumber is lightweight since it just returns the latest block number.

    • trace_replayBlockTransactions executes a full replay of all txs in a block and can be extremely heavy.

    Therefore, individual blockchain methods have their own multipliers, depending on how computationally demanding each particular operation is.

    The example table below shows some Ethereum blockchain methods with their associated multipliers and total CU calculated for the full node queries.

    Ethereum RPC Method
    Method Multiplier
    Base Chain Multiplier
    Total CU

    eth_blockNumber

    1

    20

    20

    eth_getTransactionByHash

    1

    Calculation example for debug_traceTransaction: 20 (Ethereum base multiplier)×2 (method multiplier)=40 CU20\ (\text{Ethereum base multiplier}) \times 2\ (\text{method multiplier}) = \mathbf{40\ CU}20 (Ethereum base multiplier)×2 (method multiplier)=40 CU

    For full details on all methods - including exact multipliers and total CU values for each protocol - please refer to our Compute Units pagearrow-up-right.


    hashtag
    3. Archive modifier

    GetBlock Shared Node endpoints can be configured in Archive Mode to provide historical state access from managed archive nodes.

    To reflect the heavier load on node infrastructure, requests to these endpoints use an Archive Modifier of 2 applied on top of an existing method multiplier.

    Example: Ethereum (chain multiplier = 20), debug_traceTransaction (method multiplier = 2):

    • Regular full-node request: 20 × 2 × 1 = 40 CU

    • Archive-mode request: 20 × 2 × 2 = 80 CU (archive modifier applied)

    The table below shows CU costs for some Ethereum RPC methods when requests are sent to an archive-enabled endpoint (Archive Modifier = 2).

    Ethereum RPC Method
    Method Multiplier
    Base Chain Multiplier
    Archive Modifier
    Total CU (Archive Endpoint)

    eth_blockNumber

    1

    20

    2

    40

    circle-info

    hashtag
    The Archive Modifier is applied to all requests sent to an archive-enabled endpoint.

    If a request is routed to an archive endpoint, the Archive Modifier = 2 — even if the specific method does not require historical state.

    Requests sent to full node endpoints use Archive Modifier = 1.

    The tables above includes selected RPC methods for illustration purposes. The complete list of all CU costs is maintained on the Compute Units pagearrow-up-right.


    hashtag
    Why we use the CU system at GetBlock?

    hashtag
    🛡️ It helps keep infrastructure stable

    Tracking and pricing requests based on how “heavy” they are:

    • Discourages abuse (like hammering archive calls) and protects node performance & uptime.

    • Makes it easier for GetBlock to scale and optimize resources behind the scenes.

    hashtag
    💰 Compute Units provide a fair, usage-based billing model

    A simple per-request pricing model would charge the same for all methods, which isn’t scalable or logical. The CU model fixes this imbalance.

    hashtag
    ⚙️ To help developers build smarter

    Because each API call has a clear CU cost, you can spot inefficiencies quickly (e.g. which parts of your dApp consume the most), making it easier to fine-tune performance.

    Total CU=Chain Multiplier×Method Multiplier×Archive Modifier\text{Total CU} = \text{Chain Multiplier} \times \text{Method Multiplier} \times \text{Archive Modifier} Total CU=Chain Multiplier×Method Multiplier×Archive Modifier

    hashtag
    Prerequisites

    You must have the following:

    • Node.js v18 or later installed

    • A funded BSC wallet with sufficient BNB for transactions and gas

    • GetBlock's BSC Accelerated Dedication Node

    hashtag
    Reference Addresses

    Address
    Purpose

    0xcA11bde05977b3631167028862bE2a173976CA11

    Multicall3 contract

    0x6374Ca2da5646C73Eb444aB99780495d61035f9b

    Gateway fee recipient

    hashtag
    Example

    1

    Set up the project

    mkdir multicall3-example
    cd multicall3-example
    npm init
    
    mkdir multicall3-example
    cd multicall3-example
    yarn init
    
    2

    Create a new file named index.js. This is where you will make your first call.

    3

    Set the ES module "type": "module" in your package.json.

    4

    Create .env file and add the following:

    5

    Add the following code to index.js:

    The following example demonstrates a simple BNB transfer with a priority fee:

    6

    Run the code using this command:

    7

    Sample response

    hashtag
    Extension sample

    You can extend this code for a DEX swap by encoding the router call and including it as the second Multicall3 call:

    hashtag
    Troubleshooting

    Problem
    Solution

    "Multicall3: call failed"

    • Check you have enough BNB for all calls + gas

    • Increase gas limit to 200000

    • Verify target addresses are correct

    TX not included

    • Increase tip amount

    • Check if you're rate limited

    • Verify TX is valid (simulate first)

    Low priority despite tip

    • Increase tip amount

    • Check builder status

    • Try different builders: mev_builders: ["48club", "bloxroute"]

    hashtag
    Conclusion

    This is the simplest method for adding tips to private transactions: batch multiple operations into a single transaction with atomic execution. This is very good and highly recommended for day-to-day activities like sending transactions or DEX swaps.

    hashtag
    Parameter

    Parameter

    Data type

    Description

    Required

    In

    version

    integer

    The ledger version

    Yes

    Path

    hashtag
    Request

    Base URL

    Example(cURL)

    hashtag
    Response Example

    hashtag
    Response Parameter Definition

    Field
    Type
    Description

    block_height

    string

    Height of the block in the blockchain.

    block_hash

    string

    Unique hash identifying the block.

    hashtag
    Use cases

    This method is used for:

    • Retrieve details of a specific transaction by its version.

    • Debug failed transactions by checking vm_status.

    • Build explorers that let users search transactions by version.

    • Track system-level transactions like block epilogues.

    hashtag
    Code Example

    Node(Axios)

    Python(Request)

    hashtag
    Error handling

    Status Code

    Error Message

    Cause

    403

    forbidden

    Missing or invalid <ACCESS_TOKEN>.

    410

    Ledger version has been pruned

    Incorrect version number or being pruned

    hashtag
    Integration with Web3

    By integrating /v1/transactions/by_version/{version}, developers can:

    • Trace exact transactions for auditing or compliance.

    • Debug dApps by fetching execution results and state changes.

    • Enable explorers to link transactions with block details. Monitor validators/system txns like block prologues and epilogues.

    Description

    transaction

    object

    yes

    Main transaction object used for estimation

    from

    string

    optional

    Sender address. Required for some contract calls

    to

    string

    optional

    hashtag
    Request

    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header '
    
    import axios from 'axios'
    let 
    

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Type
    Description

    result

    string (hex)

    Estimated gas required for the transaction

    hashtag
    Use case

    eth_estimateGas is used to:

    • Estimating gas before sending an on-chain transaction

    • Setting safe gas limits for dApps and wallets

    • Contract deployments

    • Approvals, swaps, mints, transfers

    • Estimating costs for batch calls

    • Preventing out-of-gas failures

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    hashtag
    Integration with Web3

    The eth_estimateGas can help developers:

    • Allows dApps to simulate actions safely

    • Helps builders understand live contract state without spending gas

    • Useful for DeFi dashboards, explorers, and analytics tools

    • Enables wallets to preview costs before sending a transaction

    • Supports trustless frontends because the estimation is done by the blockchain directly

    • Test interactions like swaps, mints, or transfers without actual execution

    How to extend your node subscription with a card payment

    eth_getTransactionByBlockHashAndIndex - Arbitrum

    Example code for the eth_getTransactionByBlockHashAndIndex JSON RPC method. Сomplete guide on how to use eth_getTransactionByBlockHashAndIndex JSON RPC in GetBlock Web3 documentation.

    This method returns information about a transaction at a given index within a block, identified by its block hash. This method helps developers inspect specific transactions without having to scan the entire block.

    hashtag
    Parameters

    Parameter
    Type
    Required
    Description

    hashtag
    Request

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Type
    Description

    hashtag
    Use case

    The eth_getTransactionByBlockHashAndIndex is used to:

    • Fetch transactions in the exact order they appear in a block

    • Supports debugging by locating problematic transactions in a specific block

    • Helps indexers reconstruct historical transaction sequences

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    hashtag
    Integration with Web3

    The eth_getTransactionByBlockHashAndIndex method helps developers to:

    • Build richer block explorers that display ordered transaction lists

    • Generate analytics around transaction distribution inside blocks

    • Debug transactions by locating their exact place in the block

    eth_getTransactionByHash - Arbitrum

    Example code for the eth_getTransactionByHash JSON RPC method. Сomplete guide on how to use eth_getTransactionByHash JSON RPC in GetBlock Web3 documentation.

    This method retrieves the full details of a transaction using its transaction hash. This endpoint is one of the most frequently used methods when tracking transaction progress, debugging smart contracts, or building explorers.

    hashtag
    Parameters

    Parameter
    Type
    Required
    Description

    hashtag
    Request

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Type
    Description

    hashtag
    Use case

    The eth_getTransactionByHash :

    • Track a transaction using only its hash

    • Build user dashboards showing live transaction updates

    • Debug smart contract interactions using transaction input data

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    hashtag
    Integration with Web3

    The eth_getTransactionByHash method helps developers to:

    • Build trustless frontends that check transaction status directly

    • Track pending, failed, or confirmed transactions in real time

    • Support dashboards, DeFi interfaces, wallets, and explorers

    eth_getTransactionByBlockNumberAndIndex - Arbitrum

    Example code for the eth_getTransactionByBlockNumberAndIndex JSON RPC method. Сomplete guide on how to use eth_getTransactionByBlockNumberAndIndex JSON RPC in GetBlock Web3 documentation.

    This method retrieves a transaction from a block, using the block number and the transaction index within it. This method is essential for inspecting the precise ordering of transactions and analyzing how blocks are structured.

    hashtag
    Parameters

    Parameter
    Type
    Required
    Description

    hashtag
    Request

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Type
    Description

    hashtag
    Use case

    The eth_getTransactionByBlockNumberAndIndex :

    • Show block transaction lists sorted by index

    • Helps indexers and analytics platforms reconstruct transaction sequencing

    • Useful for debugging or tracking transaction ordering effects like MEV

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    hashtag
    Integration with Web3

    The eth_getTransactionByBlockNumberAndIndex method helps developers:

    • Build trustless UIs that load transaction lists directly from RPC

    • Power dashboards analyzing block activity and congestion

    • Support exchanges, wallets, and bridges that track transaction placement

    How to Create Tokens With Metadata On Solana Using Token-2022

    Create Solana SPL tokens with metadata using Token-2022 program — developer guide

    Now that you have learnt about , in this guide, you will be learning how to create a simple token with metadata extension

    hashtag
    Prerequistics

    Before you begin, ensure you have the following:

    How to Build a Solana AI Agent

    Learn how to build an AI agent that swap token, checks balance and transfers on Solana

    AI agents are autonomous systems that perform operations or tasks without human intervention. These agents act independently, as set up by users. For example, if you set up your agent to send a reminder or a report to your friend, this agent will perform the task on your behalf without your friend knowing that the action was performed by itself.

    In the blockchain context, AI agents can:

    • Execute token swaps when prices hit targets

    /v1/accounts/{account_hash}/transactions - Aptos

    Example code for the /v1/accounts/{account_hash}/transactions json-rpc method. Сomplete guide on how to use /v1/accounts/{account_hash}/transactions json-rpc in GetBlock.io Web3 documentation.

    This endpoint gets the on-chain committed transactions associated with a specific account. This includes submitted, executed, or pending transactions where the account is the sender.

    hashtag
    Supported Network

    • Mainnet

    const PANCAKE_ROUTER = '0x10ED43C718714eb63d5aA57B78B54704E256024E';
    const WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
    const TOKEN_ADDRESS = '0xYOUR_TOKEN_ADDRESS';
    
    // Build the swap calldata
    const routerABI = [
      'function swapExactETHForTokens(uint256 amountOutMin, address[] path, address to, uint256 deadline)'
    ];
    const router = new ethers.Contract(PANCAKE_ROUTER, routerABI, wallet);
    
    const deadline = Math.floor(Date.now() / 1000) + 300;  // 5 minutes from now
    const swapData = router.interface.encodeFunctionData('swapExactETHForTokens', [
      minAmountOut,
      [WBNB, TOKEN_ADDRESS],
      wallet.address,
      deadline
    ]);
    
    // Construct the Multicall3 calls
    const calls = [
      {
        target: BLOXROUTE_FEE,
        allowFailure: false,
        value: ethers.parseEther('0.0005'),  // Priority fee
        callData: '0x'
      },
      {
        target: PANCAKE_ROUTER,
        allowFailure: false,
        value: ethers.parseEther('1.0'),  // Swap amount
        callData: swapData
      }
    ];
    https://go.getblock.io/<ACCESS_TOKEN>
    curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_version/3556737308?with_transactions=false'
    {
        "block_height": "456015808",
        "block_hash": "0xdbe2cbd48ec3b897fa5f6b1ff51bd8eef280e300e12b6ff153b3959a7440a268",
        "block_timestamp": "1760341227055115",
        "first_version": "3556737303",
        "last_version": "3556737309",
        "transactions": null
    }
    
    const axios = require('axios');
    
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_version/3363904007',
    };
    
    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });
    import requests
    
    url = 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_version/3363904007'
    
    response = requests.request("GET", url, headers=headers, data=payload)
    
    print(response.text)
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
      "jsonrpc": "2.0",
      "method": "eth_estimateGas",
      "id": "getblock.io",
      "params": [
        {
          "from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
          "to": "0x44aa93095d6749a706051658b970b941c72c1d53",
          "value": "0x1"
        }
      ],
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
      "jsonrpc": "2.0",
      "method": "eth_estimateGas",
      "id": "getblock.io",
      "params": [
        {
          "from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
          "to": "0x44aa93095d6749a706051658b970b941c72c1d53",
          "value": "0x1"
        }
      ],
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function Call() {
      try {
         const result = await provider.send("eth_estimateGas", [
           {
             from: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
             to: "0x44aa93095d6749a706051658b970b941c72c1d53",
             value: "0x1",
           },
         ]);
        console.log("The result:", result);
        return result;
      } catch (error) {
        console.error("The error:", error);
        throw error;
      }
    }
    import { createPublicClient, http } from 'viem';
    import { arbitrum } from 'viem/chains';
    
    // Create Viem client with GetBlock
    const client = createPublicClient({
      chain: arbitrum,
      transport: http("https://go.getblock.us/<ACCESS_TOKEN>");
    
    // Using the method through Viem
    async function Call() {
        try {
            // Method-specific Viem implementation
            const result = await client.request({
              method: "eth_estimateGas",
              params: [
                {
                  from: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
                  to: "0x44aa93095d6749a706051658b970b941c72c1d53",
                  value: "0x1",
                },
              ]
            });
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Viem Error:', error);
            throw error;
        }
    }
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": "0x5208"
    }

    with_transactions

    boolean

    To contain transactions' details or not

    no

    Query

    block_timestamp

    string

    Timestamp (in microseconds) when the block was created.

    first_version

    string

    First transaction version included in this block.

    last_version

    string

    Last transaction version included in this block.

    transactions

    objects

    List of transactions contained in this block.

    transactions.type

    string

    Type of the transaction (e.g., user_transaction, block_metadata_transaction).

    transactions.hash

    string

    Unique hash identifying the transaction.

    transactions.sender

    string

    Account address that initiated the transaction.

    transactions.sequence_number

    string

    The sender’s sequence number for this transaction.

    transactions.max_gas_amount

    string

    Maximum gas units the sender is willing to spend.

    transactions.gas_unit_price

    string

    Gas price per unit.

    transactions.expiration_timestamp_secs

    string

    Expiration timestamp (in seconds) after which the transaction becomes invalid.

    transactions.payload

    object

    Payload object describing the action being executed.

    transactions.payload.type

    string

    Type of payload (e.g., entry_function_payload).

    transactions.payload.function

    string

    Function name being called (e.g., 0x1::coin::transfer).

    transactions.payload.type_arguments

    array

    Type arguments for the function (e.g., token types).

    transactions.payload.arguments

    array

    Arguments passed to the function (e.g., recipient address, amount).

    transactions.signature

    object

    Signature object verifying the transaction.

    transactions.signature.type

    string

    Type of cryptographic signature (e.g., ed25519_signature).

    transactions.signature.public_key

    string

    Public key of the sender.

    transactions.signature.signature

    string

    Cryptographic signature validating the transaction.

    500

    Internal server error

    Node or network issue; retry later.

    Content-Type: application/json
    '
    \
    --data '{
    "jsonrpc": "2.0",
    "method": "eth_estimateGas",
    "id": "getblock.io",
    "params": [
    {
    "from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    "to": "0x44aa93095d6749a706051658b970b941c72c1d53",
    "value": "0x1"
    }
    ],
    }'
    data
    =
    JSON
    .
    stringify
    (
    {
    "jsonrpc": "2.0",
    "method": "eth_estimateGas",
    "id": "getblock.io",
    "params": [
    {
    "from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    "to": "0x44aa93095d6749a706051658b970b941c72c1d53",
    "value": "0x1"
    }
    ],
    };
    let config = {
    method: "post",
    maxBodyLength: Infinity,
    url: "https://go.getblock.us/<ACCESS_TOKEN>",
    headers: {
    "Content-Type": "application/json",
    },
    data: data,
    };
    axios
    .request(config)
    .then((response) => {
    console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
    console.log(error);
    });

    Recipient or contract address. Omit when deploying a contract

    gas

    string (hex)

    optional

    Gas limit upper bound; node adjusts actual estimation

    gasPrice

    string (hex)

    optional

    Optional gas price included for compatibility

    value

    string (hex)

    optional

    Amount of ETH sent with the transaction

    data

    string

    optional

    Encoded function call or contract bytecode

    block tag

    string or hex

    optional

    Block context for the estimation, default is latest

    Allora, Avail, Bahamut, Chiliz, Ronin, Stellar, Zilliqa, Xphere

    30

    Moderate–high resource intensity

    Solana, Sui, TON, 0g, Akash, Atleta, B3, Berachain, Bitlayer, Botanix, Celo, Core, Corn, Cronos zkEVM, Electroneum, Etherlink, Flare, Goat, Gravity, IOTA, IOTA EVM, Immutable zkEVM, Incentiv, Ink, Lens, Matchain, Metis, Midnight, Monad, Movement, Nervos, Oasis, Rollux, SEI, Siacoin, Somnia, Soneium, Stacks, Swellchain, TAC, Taiko, Tenet, Unichain, XDC, Xai, Zora

    50

    High resource intensity: high throughput, large state or complex execution environments

    20

    20

    debug_traceTransaction

    2

    20

    40

    debug_traceBlock

    2

    20

    40

    trace_call

    2

    20

    40

    trace_transaction

    2

    20

    40

    txpool_status

    2

    20

    40

    trace_replayTransaction

    4

    20

    80

    eth_getTransactionByHash

    1

    20

    2

    40

    debug_traceTransaction

    2

    20

    2

    80

    debug_traceBlock

    2

    20

    2

    80

    trace_call

    2

    20

    2

    80

    trace_transaction

    2

    20

    2

    80

    txpool_status

    2

    20

    2

    80

    trace_replayTransaction

    4

    20

    2

    160

    How to check your CU balance in GetBlock accounts

    string (hex)

    Block number

    from

    string

    Address that initiated the transaction

    to

    string or null

    Recipient address or null for contract creation

    value

    string (hex)

    Amount transferred in wei

    nonce

    string (hex)

    Number of transactions sent by the sender

    gas

    string (hex)

    Gas limit

    gasPrice

    string (hex)

    Gas price in wei

    input

    string (hex)

    Transaction calldata

    transactionIndex

    string (hex)

    Index of this transaction in the block

    v, r, s

    string

    Signature fields

    Used by wallets to verify whether their transaction was included and at what position
  • Supports analytics tools that measure block activity density

  • Power DeFi dashboards and monitoring tools that react to specific activity
  • Build trustless frontends that fetch live block data without running a node

  • block_hash

    string

    yes

    The block hash used to locate the block containing the transaction.

    index

    string (hex)

    yes

    The transaction index position within the block, encoded as a hex integer (e.g. "0x0", "0x2").

    hash

    string

    Transaction hash

    blockHash

    string

    Hash of the block this transaction belongs to

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    -32602

    Invalid argument

    • The block hash does not exist

    • Index is not a proper hex integer

    • Block does have transaction at that index

    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data '{
       "jsonrpc": "2.0",
           "method": "eth_getTransactionByBlockHashAndIndex",
     "params": [
    "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
    "0x0"
        ],
        "id": "getblock.io"
    }'
    import axios from 'axios'
    let data = JSON.stringify({
        "jsonrpc": "2.0",
        "method": "eth_getTransactionByBlockHashAndIndex",
     "params": [
    "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
    "0x0"
        ],
        "id": "getblock.io"
    };
    
    let config = {
      method: "post",
      maxBodyLength: Infinity,
      url: "https://go.getblock.us/<ACCESS_TOKEN>",
      headers: {
        "Content-Type": "application/json",
      },
      data: data,
    };
    
    axios
      .request(config)
      .then((response) => {
        console.log(JSON.stringify(response.data));
      })
      .catch((error) => {
        console.log(error);
      });
    

    blockNumber

    string or null

    Block number in hex. Null if pending

    transactionIndex

    string or null

    Index of this transaction in the block

    from

    string

    Sender address

    to

    string or null

    Receiver address. Null for contract creation

    value

    string (hex)

    Amount sent in wei

    nonce

    string (hex)

    Counter of transactions sent by the sender

    gas

    string (hex)

    Gas limit for the transaction

    gasPrice

    string (hex)

    Gas price in wei

    input

    string (hex)

    Calldata or contract code

    v, r, s

    string

    Transaction signature components

    Power explorers that index and display transaction details
  • Determine whether a transaction has been mined or is still pending

  • Analyze gas usage patterns and sender behavior

  • Read transaction calldata for analytics and debugging
  • Improve UX by notifying users instantly when their transaction is included

  • Verify transaction ordering for MEV, priority fees, and gas bidding strategies

  • tx_hash

    string

    yes

    The hash of the transaction to retrieve. Must be a 32-byte hex encoded string prefixed with 0x.

    hash

    string

    Hash of the transaction

    blockHash

    string or null

    Hash of the block that contains this transaction. Null if pending

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    -32602

    Invalid argument

    • Transaction hash is invalid

    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data '{
       "jsonrpc": "2.0",
       "method": "eth_getTransactionByHash",
        "params": [
            "0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181"
        ],
        "id": "getblock.io"
    }'
    import axios from 'axios'
    let data = JSON.stringify({
        "jsonrpc": "2.0",
         "method": "eth_getTransactionByHash",
        "params": [
            "0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181"
        ],
        "id": "getblock.io"
    };
    
    let config = {
      method: "post",
      maxBodyLength: Infinity,
      url: "https://go.getblock.us/<ACCESS_TOKEN>",
      headers: {
        "Content-Type": "application/json",
      },
      data: data,
    };
    
    axios
      .request(config)
      .then((response) => {
        console.log(JSON.stringify(response.data));
      })
      .catch((error) => {
        console.log(error);
      });
    

    blockNumber

    string (hex)

    Block number

    from

    string

    Sender address

    to

    string or null

    Receiver address or null for contract creation

    value

    string (hex)

    Value transferred in wei

    nonce

    string (hex)

    Number of transactions previously sent by the sender

    gas

    string (hex)

    Gas limit

    gasPrice

    string (hex)

    Gas price in wei

    input

    string (hex)

    Transaction calldata

    transactionIndex

    string (hex)

    Index of the transaction inside the block

    v, r, s

    string

    ECDSA signature values

    Wallets can verify whether a transaction was placed at the expected block position
  • Helps monitoring systems detect anomalies such as missing or reordered transactions

  • Generate block-level historical analytics
  • Verify transaction ordering for MEV, priority fees, and gas bidding strategies

  • block_number

    string

    yes

    The block number encoded as a hex string. Special values: "latest", "earliest", "pending".

    index

    string (hex)

    yes

    The position of the transaction in the block, encoded as a hex integer (for example "0x0" or "0x5").

    hash

    string

    Hash of the transaction

    blockHash

    string

    Hash of the block this transaction belongs to

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    -32602

    Invalid argument

    • The block number does not exist or is beyond the chain height

    • Index is not a valid hex integer

    • Block does have transaction at that index

    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data '{
       "jsonrpc": "2.0",
       "method": "eth_getTransactionByBlockNumberAndIndex",
     "params": ["latest", "0x0"],
        "id": "getblock.io"
    }'
    import axios from 'axios'
    let data = JSON.stringify({
        "jsonrpc": "2.0",
           "method": "eth_getTransactionByBlockNumberAndIndex",
     "params": ["latest", "0x0"],
        "id": "getblock.io"
    };
    
    let config = {
      method: "post",
      maxBodyLength: Infinity,
      url: "https://go.getblock.us/<ACCESS_TOKEN>",
      headers: {
        "Content-Type": "application/json",
      },
      data: data,
    };
    
    axios
      .request(config)
      .then((response) => {
        console.log(JSON.stringify(response.data));
      })
      .catch((error) => {
        console.log(error);
      });
    

    blockNumber

    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
       "jsonrpc": "2.0",
        "method": "eth_getTransactionByBlockHashAndIndex",
     "params": [
    "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
    "0x0"
        ],
        "id": "getblock.io"
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
       "jsonrpc": "2.0",
           "method": "eth_getTransactionByBlockHashAndIndex",
     "params": [
    "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
    "0x0"
        ],
        "id": "getblock.io"
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": {
            "blockHash": "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
            "blockNumber": "0x5206d53",
            "from": "0x00000000000000000000000000000000000a4b05",
            "gas": "0x0",
            "gasPrice": "0x0",
            "hash": "0xaf256a9ce8839489dcaa4f9a2740bcd5865b3db34a15434cce29e6bdcf043bc7",
            "input": "0x6bf6a42d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105e0460000000000000000000000000000000000000000000000000000000005206d530000000000000000000000000000000000000000000000000000000000000000",
            "nonce": "0x0",
            "to": "0x00000000000000000000000000000000000a4b05",
            "transactionIndex": "0x0",
            "value": "0x0",
            "type": "0x6a",
            "chainId": "0xa4b1",
            "v": "0x0",
            "r": "0x0",
            "s": "0x0"
        }
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function Call() {
      try {
         const result = await provider.send("eth_getTransactionByBlockHashAndIndex",
         [
    "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
    "0x0"
        ]);    
    console.log("The result:", result);
        return result;
      } catch (error) {
        console.error("The error:", error);
        throw error;
      }
    }
    import { createPublicClient, http } from 'viem';
    import { arbitrum } from 'viem/chains';
    
    // Create Viem client with GetBlock
    const client = createPublicClient({
      chain: arbitrum,
      transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
    });
    
    // Using the method through Viem
    async function Call() {
        try {
            // Method-specific Viem implementation
            const result = await client.request({
            method: "eth_getTransactionByBlockHashAndIndex",
     params: [
    "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
    "0x0"
        ]
            });
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Viem Error:', error);
            throw error;
        }
    }
    
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
       "jsonrpc": "2.0",
        "method": "eth_getTransactionByHash",
        "params": [
            "0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181"
        ],
        "id": "getblock.io"
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
       "jsonrpc": "2.0",
       "method": "eth_getTransactionByHash",
        "params": [
            "0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181"
        ],
        "id": "getblock.io"
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": {
            "blockHash": "0xd8fe755134d44967f0c919084d3e0ec9b875c476c924f37bff17e5ef37d10d47",
            "blockNumber": "0x5911313",
            "from": "0xe911f7f98ac57cf0c1cc71519d3ba720089381c4",
            "gas": "0x1a02b0",
            "gasPrice": "0x1dcd6500",
            "hash": "0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181",
            "input": "0x1801fbe5d5843b1d8c7345812c7ba7257e927b0c5e000000a6ca46b71aa1cdb6545660ad000000004f62e6aa5433274e333035ca261c12397df9febee0782f42749b8e0b",
            "nonce": "0x3c",
            "to": "0xae56c981f9bb8b07e380b209fcd1498c5876fd4c",
            "transactionIndex": "0x1",
            "value": "0x0",
            "type": "0x0",
            "chainId": "0xa4b1",
            "v": "0x14986",
            "r": "0x87ac24f33be39a0bd27fe84a8934aa957610872606e5dbc46d296843a57930df",
            "s": "0x6ad9aba71382c20a528f3310c369b095e15991b352aea3261e2683c2b1288964"
        }
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function Call() {
      try {
         const result = await provider.send("eth_getTransactionByHash",
        [
            "0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181"
        ]);    
    console.log("The result:", result);
        return result;
      } catch (error) {
        console.error("The error:", error);
        throw error;
      }
    }
    import { createPublicClient, http } from 'viem';
    import { arbitrum } from 'viem/chains';
    
    // Create Viem client with GetBlock
    const client = createPublicClient({
      chain: arbitrum,
      transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
    });
    
    // Using the method through Viem
    async function Call() {
        try {
            // Method-specific Viem implementation
            const result = await client.request({
             method: "eth_getTransactionByHash",
             params: [
            "0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181"
        ],
            });
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Viem Error:', error);
            throw error;
        }
    }
    
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
       "jsonrpc": "2.0",
          "method": "eth_getTransactionByBlockNumberAndIndex",
     "params": ["latest", "0x0"],
        "id": "getblock.io"
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
       "jsonrpc": "2.0",
      "method": "eth_getTransactionByBlockNumberAndIndex",
     "params": ["latest", "0x0"],
        "id": "getblock.io"
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": {
            "blockHash": "0xbb465c64e929a4700a6c5cfc3355e651e0f558134e09e06b4c65657f24499cec",
            "blockNumber": "0x185f29e6",
            "from": "0x00000000000000000000000000000000000a4b05",
            "gas": "0x0",
            "gasPrice": "0x0",
            "hash": "0x61d48ab94f7fccf48f4baa3903781053f932feb466474c037736e910d7ca2afe",
            "input": "0x6bf6a42d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016ddb2700000000000000000000000000000000000000000000000000000000185f29e60000000000000000000000000000000000000000000000000000000000000000",
            "nonce": "0x0",
            "to": "0x00000000000000000000000000000000000a4b05",
            "transactionIndex": "0x0",
            "value": "0x0",
            "type": "0x6a",
            "chainId": "0xa4b1",
            "v": "0x0",
            "r": "0x0",
            "s": "0x0"
        }
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function Call() {
      try {
         const result = await provider.send( "eth_getTransactionByBlockNumberAndIndex",
     ["latest", "0x0"]);    
    console.log("The result:", result);
        return result;
      } catch (error) {
        console.error("The error:", error);
        throw error;
      }
    }
    import { createPublicClient, http } from 'viem';
    import { arbitrum } from 'viem/chains';
    
    // Create Viem client with GetBlock
    const client = createPublicClient({
      chain: arbitrum,
      transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
    });
    
    // Using the method through Viem
    async function Call() {
        try {
            // Method-specific Viem implementation
            const result = await client.request({
             method: "eth_getTransactionByBlockNumberAndIndex",
             params: ["latest", "0x0"]
            });
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Viem Error:', error);
            throw error;
        }
    }
    
    -y
    npm install ws ethers dotenv
    -y
    yarn ws ethers
    Node installed on your PC, preferably v20+
  • A package manager such as npm or yarn

  • Solana Wallet, e.g., Phantomarrow-up-right, Solfarearrow-up-right, or Metamaskarrow-up-right

  • Solana Access token from GetBlockarrow-up-right

  • Basic knowledge of JavaScript and Typescript

  • Basic understanding of Solana (wallets, transactions, lamports)

  • hashtag
    Set up your environment

    1

    Create a new project directory:

    2

    Install required dependencies:

    3

    Create a .env file and add the following:

    hashtag
    Configuration File

    Create config.js file and add the following:

    hashtag
    Create a Token with Metadata Extension

    1

    Create a new file index.js . This will serve as your working file

    2

    Import all the dependencies:

    3

    Generate an account for the mint address

    4

    Define the token metadata:

    5

    Calculate the metadata space and rent needed for the mint account:

    This ensures our token mint account has sufficient space for the extensions you use or else the metadata initialization would fail with an insufficient lamports error.

    6

    Define the structure of the transaction:

    This creates the mint address, initializes the mint, metadata, points to the mint itself as the metadata account, and sends the transaction.

    chevron-rightComplete codehashtag
    7

    Run the code using this command:

    8

    Result:

    Verify on the :

    hashtag
    Conclusion

    In this guide, you have learnt how to create a token with metadata extension. This guide also walks you through generating a Mint account for your token.

    circle-info

    This guide uses Solana Devnet. If you want to make use of Mainnet, go to your account dashboard arrow-up-rightand get a Solana mainnet access token.

    hashtag
    Additional Resources

    1. Token Metadata Interfacearrow-up-right

    2. Solana Tokenarrow-up-right

    3. What are Token Extensions

    token extension
    Rebalance portfolios across DeFi protocols
  • Monitor wallets and automate transfers

  • Mint NFTs based on social media triggers

  • hashtag
    Core Stack of AI Agents

    Just like every area of development has its own stack for building applications, AI agent development has its own stack, typically consisting of three layers:

    1. Large Language Models (LLMs): The reasoning brain of every AI agent. LMs handle natural language understanding, interpret user requests, process blockchain data, and decide which actions to take.

    2. Agent Frameworks: These define the agent's structure, personality, and interactions with external platforms. Examples include ElizaOS, LangChain, Rig, and AgentiPy.

    3. Blockchain Toolkits: SDKs that enable agents to interact with networks like Solana. Examples include the Solana Agent Kit and GOAT Toolkit.

    hashtag
    Why Are AI Agents Important in Blockchain?

    1. Simplification of Complex Tasks: AI agents can handle complex DeFi tasks, such as finding the best yield, rebalancing portfolios, or executing arbitrage trades faster than humans.

    2. Enhanced Security: They provide continuous monitoring of vulnerabilities in smart contracts and wallets and detect fraudulent activity in real time.

    3. Simplified User Experience (Web3 Adoption): AI agents act as intermediaries, translating natural-language requests into complex on-chain actions, reducing technical barriers for users.

    4. Decentralized Autonomous Interactions: Agents can hold funds, sign transactions, and interact with dApps autonomously, creating new, self-sustaining, AI-driven economic ecosystems.

    5. Intelligent Data Processing: They provide an insightful report on vast, immutable datasets on the blockchain to support better decision-making.

    Now that you've learnt about AI agents, their core stack, and its importance. In this guide, you will be learning how to build an AI agent on Solana, a fast and growing blockchain network. This agent will be able to transfer SOL to USDC and check your account balance as seen below:

    hashtag
    Prerequisites

    You must have the following:

    1. Node.js v23+arrow-up-right is installed on your laptop

    2. Solana Wallet, e.g., Phantomarrow-up-right, Solflarearrow-up-right, MetaMaskarrow-up-right, etc

    3. API keys such as OpenAIarrow-up-right (for the LLM) and Solana Devnet RPC URL (Optional: GetBlock Solana RPC URLarrow-up-right)

    4. Package manager installed on your laptop(Preferrably )

    circle-info

    Devnet RPC URL is used for this guide. If you want to interact with Mainnet, then make use of GetBlock Solana RPC URLarrow-up-right

    hashtag
    Project Setup

    1

    Create a new project directory

    2

    Install the dependencies:

    chevron-rightPackages Descriptionhashtag
    3

    Create a .env file and add the following details:

    4

    Create agent.ts file, this is where you will be building your AI agent

    5

    Import your dependencies:

    6

    Initialize your Agent

    This:

    • Connect the AI agent to Solana Devnet and access your wallet to perform actions

    • Empower the agent with tools for swapping(jupiter()

    7

    Create Interface for interaction:

    This defines an interactive CLI chat loop between you and the AI agent and also logs any errors.

    8

    Run the agent using this command

    You can make any request in any language, as seen below:

    You can see that it interprets your natural language, uses the tools plugin to get the right response for it

    hashtag
    Extend AI Agent capacity

    Improve the capacity of your agent by adding more tools:

    1. Mint NFT:

    hashtag
    Best Practice

    1. Store private keys in .env only — never commit this file.

    2. Use a dedicated burner wallet with minimal funds for testing

    3. On mainnet, double-check all transactions before confirming.

    hashtag
    Conclusion

    In this guide, you have learn what AI agents are, their core stack, and how to build one for yourself to send, swap, launch a token, and check your account balance.

    hashtag
    Additional Resources

    1. GOAT Docsarrow-up-right

    2. Langchain Docsarrow-up-right

    3. OpenAI Platformarrow-up-right

    hashtag
    Parameters

    Parameter

    Data type

    Description

    Required

    In

    account_hash

    string

    Aptos account address

    Yes

    Path

    hashtag
    Request

    Base URL

    Example(cURl)

    hashtag
    Response

    hashtag
    Response Parameter Definition

    Field

    Type

    Description

    version

    String

    The transaction version (ledger sequence number).

    hash

    String

    Unique hash of the transaction.

    hashtag
    Use Cases

    This method can be used for:

    • Get an account’s transaction history.

    • Build wallet activity feeds (incoming/outgoing transfers).

    • Build block explorers that show user-specific transactions.

    • Track failed vs successful transactions.

    hashtag
    Code Example

    Python Request

    Node(axios)

    hashtag
    Error handling

    Status Code

    Error Message

    Cause

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    404

    Resource not found

    The given resource type does not exist for this account.

    hashtag
    Integration with Web3

    By integrating /v1/accounts/{account_hash}/transactions into developers can:

    • Build transaction history dashboards to show a user’s past on-chain actions.

    • Track when a user’s transaction is confirmed or fails.

    • dApps can fetch all transactions from an account for financial or legal reporting.

    • analyse user behaviour, token transfers, and contract interactions for dApps.

    eth_getBlockByHash - Arbitrum

    Example code for the eth_getBlockByHash JSON RPC method. Сomplete guide on how to use eth_getBlockByHash JSON RPC in GetBlock Web3 documentation.

    This method retrieves a full block using its block hash. Optionally includes full transaction objects or just the transaction hashes.

    hashtag
    Parameters

    Parameter
    Type
    Required
    Description

    hashtag
    Request

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Type
    Description

    hashtag
    Use case

    The eth_getBlockHash is used to:

    • Fetching block details for explorers and dashboards

    • Tracking new blocks in real time

    • Verifying a transaction’s block inclusion

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    hashtag
    Integration with Web3

    The eth_getBlockByHash can help developers:

    • Observing full historical block data

    • Powering explorers with detailed transaction info

    • Displaying block metadata in analytics dashboards

    eth_getBlockByNumber - Arbitrum

    Example code for the eth_getBlockByNumber JSON RPC method. Сomplete guide on how to use eth_getBlockByNumber JSON RPC in GetBlock Web3 documentation.

    This method retrieves a full block by its block number. Supports returning either full transaction objects or only transaction hashes.

    hashtag
    Parameters

    Parameter
    Type
    Required
    Description

    hashtag
    Request

    hashtag
    Response

    hashtag
    Reponse Parameter Definition

    Field
    Type
    Description

    hashtag
    Use case

    The eth_getBlockByNumber is used to:

    • Real-time monitoring of blockchain activity

    • Fetching the latest block information for dashboards

    • Analyzing block-level gas usage and activity patterns

    hashtag
    Error handling

    Status Code
    Error Message
    Cause

    hashtag
    Integration with Web3

    The eth_getBlockByNumber can help developers:

    • Stream blocks in real time for analytics

    • Power live dashboards with block updates

    • Confirm block finality before executing contracts

    How to Submit Transaction to Private Mempool

    Learn how to submit transaction to private mempool directly to block builders, protecting you from MEV extraction until it's included in a block.

    When you submit a transaction to the public mempool, it's visible to everyone. MEV bots can:

    • Sandwich your trade: Place orders before and after yours to extract value

    • Front-run you: Copy your trade and execute it first

    How to Submit Transactions to Public Mempool

    Learn how to submit transactions to the BNB Chain public mempool through GetBlock's BDN fast path.

    This process involves submitting transactions to the BNB Chain public mempool via GetBlock's BDN fast path. Your transaction propagates to validators significantly faster than through standard P2P gossip, increasing the probability of earlier block inclusion.

    hashtag
    When to Use Public Mempool

    Use public mempool submission when:

    ACCESS_TOKEN=your-accelerated-node-endpoint
    RPC_URL=your-normal-bsc-node-endppoint //e.g https
    PRIVATE_KEY=your-wallet-private-key
    import WebSocket from "ws"; 
    import { ethers } from "ethers";
    import "dotenv/config";
    const PRIVATE_KEY = process.env.PRIVATE_KEY
    const RPC_URL = process.env.RPC_URL;
    
    // Constants
    const MULTICALL3 = "0xcA11bde05977b3631167028862bE2a173976CA11";
    const BLOXROUTE_FEE = "0x6374Ca2da5646C73Eb444aB99780495d61035f9b";
    
    const MULTICALL_ABI = [
      "function aggregate3Value(tuple(address target, bool allowFailure, uint256 value, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[])",
    ];
    
    async function sendPrivateTxWithTip() {
      const provider = new ethers.JsonRpcProvider(RPC_URL);
      const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
    
      console.log("Wallet:", wallet.address);
    
      // Define amounts
      const tipAmount = ethers.parseEther("0.0001"); // 0.0001 BNB tip
      const transferAmount = ethers.parseEther("0.001"); // Your actual transfer
      const totalValue = tipAmount + transferAmount;
    
      // Build Multicall3 calls
      const calls = [
        {
          target: BLOXROUTE_FEE, // Tip payment FIRST
          allowFailure: false,
          value: tipAmount,
          callData: "0x", // Empty = simple transfer
        },
        {
          target: process.env.TO_ADDRESS, // Your actual transaction
          allowFailure: false,
          value: transferAmount,
          callData: "0x", // Or your contract calldata
        },
      ];
      // Encode Multicall3 call
      const multicall = new ethers.Contract(MULTICALL3, MULTICALL_ABI, wallet);
      const data = multicall.interface.encodeFunctionData("aggregate3Value", [
        calls,
      ]);
      // Get nonce
      const nonce = await provider.getTransactionCount(wallet.address);
      // Sign transaction
      const signedTx = await wallet.signTransaction({
        nonce: nonce,
        to: MULTICALL3,
        value: totalValue,
        data: data,
        gasPrice: ethers.parseUnits("3", "gwei"),
        gasLimit: 150000, // Higher for Multicall3
        chainId: 56,
      });
      const signedTxNoPrefix = signedTx.startsWith("0x")
      ? signedTx.slice(2)
      : signedTx;
    
      console.log("Transaction built:");
      console.log("  Tip:", ethers.formatEther(tipAmount), "BNB");
      console.log("  Transfer:", ethers.formatEther(transferAmount), "BNB");
      console.log("  Total:", ethers.formatEther(totalValue), "BNB");
    
      // Send via bsc_private_tx
      const ws = new WebSocket(process.env.ACCESS_TOKEN);
    
      ws.on("open", () => {
        const request = {
          jsonrpc: "2.0",
          id: 1,
          method: "bsc_private_tx",
          params: {
            transaction: signedTxNoPrefix,
            mev_builders: ["all"],
          },
        };
    
        console.log("\nSending private TX with tip...");
        ws.send(JSON.stringify(request));
      });
    
      ws.on("message", (data) => {
        const response = JSON.parse(data);
    
        if (response.result) {
          console.log("\n✅ Transaction submitted!");
          console.log("TX Hash:", response.result.txHash);
          console.log(
            "BSCScan:",
            `https://bscscan.com/tx/${response.result.txHash}`,
          );
        } else {
          console.error("\n❌ Error:", response.error);
        }
    
        ws.close();
      });
    }
    sendPrivateTxWithTip().catch(console.error);
    
    node index.js
    Wallet: 0xD1AF2dAc.....
    Transaction built:
      Tip: 0.0001 BNB
      Transfer: 0.001 BNB
      Total: 0.0011 BNB
    Sending private TX with tip...
    ✅ Transaction submitted!
    TX Hash: 61bd625be986bb45e9fb495a5dba7bf39e00fd6871176971663436465311c970
    BSCScan: https://bscscan.com/tx/61bd625be986bb45e9fb495a5dba7bf39e00fd6871176971663436465311c970
    mkdir token-2022-tutorial
    cd token-2022-tutorial
    npm init -y
    npm install @solana/web3.js @solana/spl-token @solana/spl-token-metadata dotenv
    import { 
    Keypair, 
    SystemProgram, 
    Transaction, 
    sendAndConfirmTransaction } 
    from "@solana/web3.js";
    
    import { TOKEN_2022_PROGRAM_ID, 
    ExtensionType, 
    createInitializeMintInstruction, 
    createInitializeMetadataPointerInstruction, 
    getMintLen, 
    TYPE_SIZE, 
    LENGTH_SIZE } 
    from "@solana/spl-token";
    
    import { createInitializeInstruction, pack } from "@solana/spl-token-metadata";
    import { connection, payer } from "./config.js";
    config.js
    import { Connection, Keypair } from "@solana/web3.js";
    import bs58 from "bs58";
    
    import 'dotenv/config'
    
    // Replace with your GetBlock endpoint
    const GETBLOCK_RPC_URL = process.env.RPC_URL;
    
    // Create connection to Solana via GetBlock
    const connection = new Connection(GETBLOCK_RPC_URL, "confirmed");
    
    // Load keypair from private key in .env 
    const payer = Keypair.fromSecretKey(bs58.decode(process.env.PRIVATE_KEY));
    
    export { connection, payer};
    mkdir solana-ai-agent
    cd solana-ai-agent
    pnpm add @goat-sdk/adapter-langchain @goat-sdk/core @goat-sdk/plugin-jupiter @goat-sdk/plugin-pumpfun @goat-sdk/plugin-spl-token @goat-sdk/wallet-solana @langchain/core @langchain/langgraph @langchain/activitylanareal timebs58 dotenv
    import { crossmint } from "@goat-sdk/crossmint";
    import { Connection, Keypair } from "@solana/web3.js";
    import { solana } from "@goat-sdk/wallet-solana";
    import { jupiter } from "@goat-sdk/plugin-jupiter";
    import { splToken } from "@goat-sdk/plugin-spl-token";
    import { getOnChainTools } from "@goat-sdk/adapter-langchain";
    import { ChatOpenAI } from "@langchain/openai";
    import { pumpfun } from "@goat-sdk/plugin-pumpfun";
    import { createReactAgent } from "@langchain/langgraph/prebuilt";
    import { MemorySaver } from "@langchain/langgraph";
    import * as dotenv from "dotenv";
    import bs58 from "bs58";
    import * as readline from "readline";
    
    async function initializeAgent() { .....
    
    // continuation
    const tools = await getOnChainTools({
        wallet: solana({
          keypair,
          connection,
        }),
        plugins: [
          splToken(),  
          pumpfun(),
          jupiter(),
          crossmint()
        ],
      });
    }
    /// rest of code (readline interface and agent.invoke loop)
    
    https://go.getblock.io/<ACCESS_TOKEN>
    curl -X GET "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f
    /transactions?limit=5"
    [
        {
            "version": "3574927316",
            "hash": "0x01ef3543f79823b3a9fbc8acac9fba4bb25c7c1abb65f533caff2d9bcc0678f6",
            "state_change_hash": "0x5cfb448ecb226172f3f5279d02658a645afdacf88a1ce308bf5b0717eca0c99e",
            "event_root_hash": "0x63937d2f2e996f5c9e6cd669e518fdf7e474af4902a11501ec15dbb8d53e5ce9",
            "state_checkpoint_hash": null,
            "gas_used": "82",
            "success": true,
            "vm_status": "Executed successfully",
            "accumulator_root_hash": "0x3d25cf24e802a777497da7f76fdeb05a472b30586f2171b82fbb72e1e3504609",
            "changes": [
                {
                    "address": "0xa",
                    "state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
                    "data": {
                        "type": "0x1::coin::PairedCoinType",
                        "data": {
                            "type": {
                                "account_address": "0x1",
                                "module_name": "0x6170746f735f636f696e",
                                "struct_name": "0x4170746f73436f696e"
                            }
                        }
                    },
                    "type": "write_resource"
                }
    
            ],
            "sender": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
            "sequence_number": "871700",
            "max_gas_amount": "200000",
            "gas_unit_price": "100",
            "expiration_timestamp_secs": "1760643271",
            "payload": {
                "function": "0x487e905f899ccb6d46fdaec56ba1e0c4cf119862a16c409904b8c78fab1f5e8a::router::swap",
                "type_arguments": [],
                "arguments": [
                    "0x82e0b52f95ae57b35220726a32c3415919389aa5b8baa33a058d7125797535cc01000000000000000000000000000000683e030100000000000000000000000000000000000000000000000000000000d093f60000000000000000000000000000000000000000000000000000000000"
                ],
                "type": "entry_function_payload"
            },
            "signature": {
                "public_key": "0x7df17b23676ef29e040847e64ae2a8351819d4bfaf64f3bfe2124d92156c1c02",
                "signature": "0x8001b27ddb488c1ad5f4f6ed7fe4886b42528b0646a05685469b524b67cc6298192fa42d9af5ff2df1791c88f2f16dfdc22c8c1d5060795c68161a25ef335d01",
                "type": "ed25519_signature"
            },
            "replay_protection_nonce": null,
            "events": [
                {
                    "guid": {
                        "creation_number": "0",
                        "account_address": "0x0"
                    },
                    "sequence_number": "0",
                    "type": "0xa611a8ba7261ed1f4d3afe4ac2166fc9f3180103e3296772d593a1e2720c7405::stable::IncentiveSynced",
                    "data": {
                        "accumulated_rewards_per_share": "33902212381193",
                        "campaign_idx": "15",
                        "last_accumulation_time": "1760643255",
                        "last_total_shares": "4992836695498717952869616",
                        "pool_addr": "0x82e0b52f95ae57b35220726a32c3415919389aa5b8baa33a058d7125797535cc",
                        "total_distributed": "25151305402",
                        "ts": "1760643255618178"
                    }
                },
                {
                    "guid": {
                        "creation_number": "0",
                        "account_address": "0x0"
                    },
                    "sequence_number": "0",
                    "type": "0xa611a8ba7261ed1f4d3afe4ac2166fc9f3180103e3296772d593a1e2720c7405::stable::Swapped",
                    "data": {
                        "bought_id": "0",
                        "buyer": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
                        "pool_addr": "0x82e0b52f95ae57b35220726a32c3415919389aa5b8baa33a058d7125797535cc",
                        "sold_id": "1",
                        "stored_balances": [
                            "1990058935750",
                            "3042379974793"
                        ],
                        "tokens_bought": "16980317",
                        "tokens_sold": "16989240",
                        "ts": "1760643255618178"
                    }
                },
            "timestamp": "1760643255618178",
            "type": "user_transaction"
        }
    ]
    import requests
    
    url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xc20ea5a196c81d8d7aff814aa37f8a5823acffbc4193efd3b2aafc9ef2803255/transactions"
    
    response = requests.request("GET", url, headers=headers, data=payload)
    
    print(response.text)
    
    
    import axios from 'axios';
    
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xc20ea5a196c81d8d7aff814aa37f8a5823acffbc4193efd3b2aafc9ef2803255/transactions',
      headers: { }
    };
    
    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });
    

    start

    string

    The starting point or offset for retrieving resources. If not provided, defaults to showing the latest transactions

    No

    query

    limit

    integer

    The maximum number of resources to retrieve per request. If not provided, defaults to default page size

    No

    query

    state_change_hash

    String

    Hash of all state changes caused by this transaction.

    event_root_hash

    String

    Merkle root of events emitted in this transaction.

    gas_used

    String

    Amount of gas consumed by the transaction.

    success

    Boolean

    Whether the transaction executed successfully.

    vm_status

    String

    Execution status from the Aptos VM.

    accumulator_root_hash

    String

    Root hash of the transaction accumulator after applying this txn.

    changes

    Array

    List of state changes caused by the transaction.

    changes.address

    String

    Address whose resource was modified.

    changes.state_key_hash

    String

    State key hash for the modified resource.

    changes.type

    String

    Type of state change (e.g., write_resource).

    changes.data

    Object

    Modified resource data.

    changes.data.type

    String

    Type of resource (e.g., CoinStore<AptosCoin>).

    changes.data.data

    Object

    Full contents of the updated resource (balance, events, frozen state, etc).

    500

    Internal server error

    Node or network issue. Retry later.

    spinner
    Solscanarrow-up-right
    Solana programarrow-up-right
    GetBlock Account Dashboardarrow-up-right
    Create Token With Metadata Repoarrow-up-right
    Solscan verification

    string

    Previous block hash

    nonce

    string

    64-bit hash used for PoW (Arbitrum always 0)

    sha3Uncles

    string

    Keccak hash of uncles

    logsBloom

    string

    Bloom filter for logs

    transactionsRoot

    string

    Root of transaction trie

    stateRoot

    string

    Root of state trie

    miner

    string

    Validator / proposer address

    difficulty

    string (hex)

    Arbitrum always zero

    totalDifficulty

    string (hex)

    Always zero

    size

    string (hex)

    Size of the block in bytes

    gasLimit

    string (hex)

    Gas limit for the block

    gasUsed

    string (hex)

    Gas consumed

    timestamp

    string (hex)

    Unix timestamp

    transactions

    array

    Either full objects or transaction hashes

    uncles

    array

    Always empty for Arbitrum

    Monitoring gas usage per block
  • Analyzing contract activity in a specific block

  • Auditing validator performance through block metadata

  • Reconstructing block timelines for auditing and security tools
  • Connecting validator/rollup behavior to specific blocks

  • block_hash

    string

    yes

    The 32-byte block hash to query (0x-prefixed).

    full_transactions

    boolean

    yes

    If true, returns full transaction objects. If false, returns only transaction hashes.

    number

    string (hex)

    Block number

    hash

    string

    Block hash

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    -32602

    Invalid argument

    The block hash isn't accurate or incomplete or full_transaction boolean is missing

    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data '{
       "jsonrpc": "2.0",
        "method": "eth_getBlockByHash",
        "params": [
            "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
            false
        ],
        "id": "getblock.io"
    }'
    import axios from 'axios'
    let data = JSON.stringify({
        "jsonrpc": "2.0",
        "method": "eth_getBlockByHash",
        "params": [
            "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
            false
        ],
        "id": "getblock.io"
    };
    
    let config = {
      method: "post",
      maxBodyLength: Infinity,
      url: "https://go.getblock.us/<ACCESS_TOKEN>",
      headers: {
        "Content-Type": "application/json",
      },
      data: data,
    };
    
    axios
      .request(config)
      .then((response) => {
        console.log(JSON.stringify(response.data));
      })
      .catch((error) => {
        console.log(error);
      });
    

    parentHash

    string

    Previous block hash

    nonce

    string

    Always 0 on Arbitrum

    sha3Uncles

    string

    Keccak hash of uncles

    logsBloom

    string

    Bloom filter for logs

    transactionsRoot

    string

    Root of transactions trie

    stateRoot

    string

    Root of state trie

    miner

    string

    Address that proposed the block

    difficulty

    string

    Always zero on Arbitrum

    totalDifficulty

    string

    Always zero

    size

    string

    Block size in bytes

    gasLimit

    string

    Block gas limit

    gasUsed

    string

    Total gas consumed

    timestamp

    string

    Unix timestamp

    transactions

    array

    List of transaction hashes or objects

    uncles

    array

    Always empty

    Validating the inclusion of transactions within a specific block
  • Supporting DeFi applications that depend on accurate state timing

  • Powering NFT explorers and block visualizers

  • Inspect transaction activity between specific blocks
  • Support trustless frontends that monitor chain state

  • block_number

    string

    yes

    Block number as a hex string (for example "0x10fb78") or special tags: "latest", "earliest", "pending".

    full_transactions

    boolean

    yes

    If true, returns full transaction objects. If false, returns only transaction hashes.

    number

    string (hex)

    Block number

    hash

    string

    Block hash

    403

    Forbidden

    Missing or invalid ACCESS_TOKEN.

    -32602

    Invalid argument

    The block hash isn't accurate or incomplete or full_transaction boolean is missing

    curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data '{
       "jsonrpc": "2.0",
        "method": "eth_getBlockByNumber",
        "params": [
            "latest",
            false
        ],
        "id": "getblock.io"
    }'
    import axios from 'axios'
    let data = JSON.stringify({
        "jsonrpc": "2.0",
        "method": "eth_getBlockByNumber",
        "params": [
            "latest",
            false
        ],
        "id": "getblock.io"
    };
    
    let config = {
      method: "post",
      maxBodyLength: Infinity,
      url: "https://go.getblock.us/<ACCESS_TOKEN>",
      headers: {
        "Content-Type": "application/json",
      },
      data: data,
    };
    
    axios
      .request(config)
      .then((response) => {
        console.log(JSON.stringify(response.data));
      })
      .catch((error) => {
        console.log(error);
      });
    

    parentHash

    .env
    RPC_URL=https://api.devnet.solana.com //or mainnet URL
    PRIVATE_KEY=your-wallet-private-key
    async function createTokenWithMetadata() {
      console.log("=== Creating Token with Metadata Extension ===\n");
      console.log("Payer address:", payer.publicKey.toBase58());
      const mintKeypair = Keypair.generate();
      const mint = mintKeypair.publicKey;
      console.log("\nMint address:", mint.toBase58());
     const metadata = {
       updateAuthority: payer.publicKey,
       mint: mint,
       name: "GetBlock Tutorial Token",
       symbol: "GBT",
       uri: "https://getblock.io/",
       additionalMetadata: [["description", "A test token created with GetBlock"]],
     };
    const decimals = 9;
    const mintLen = getMintLen([ExtensionType.MetadataPointer]);
    const metadataLen =
      TYPE_SIZE + // 2 bytes for type
      LENGTH_SIZE + // 2 bytes for length
      pack(metadata).length; // Actual metadata size
    const lamports = await connection.getMinimumBalanceForRentExemp
      mintLen + metadataLen,
    );
    const transaction = new Transaction().add(
      SystemProgram.createAccount({
        fromPubkey: payer.publicKey,
        newAccountPubkey: mint,
        space: mintLen, // ← Just the mint size
        lamports: lamports, // ← But funded for full size
        programId: TOKEN_2022_PROGRAM_ID,
      }),
      createInitializeMetadataPointerInstruction(
        mint, // mint
        payer.publicKey, // authority
        mint, // metadata address (pointing to itself)
        TOKEN_2022_PROGRAM_ID,
      ),
      createInitializeMintInstruction(
        mint, // mint
        decimals, // decimals
        payer.publicKey, // mint authority
        null, // freeze authority (optional)
        TOKEN_2022_PROGRAM_ID,
      ),
      createInitializeInstruction({
        programId: TOKEN_2022_PROGRAM_ID,
        mint: mint,
        metadata: mint,
        name: metadata.name,
        symbol: metadata.symbol,
        uri: metadata.uri,
        mintAuthority: payer.publicKey,
        updateAuthority: payer.publicKey,
      }),
    );
    console.log("\nSending transaction...");
    const signature = await sendAndConfirmTransaction(
      connection,
      transaction,
      [payer, mintKeypair], // Signers
      { commitment: "confirmed" },
    );
    console.log("\Token created successfully!");
    console.log("Transaction signature:", signature);
    console.log("Mint address:", mint.toBase58());
    console.log("\nToken details:");
    console.log("  Name:", metadata.name);
    console.log("  Symbol:", metadata.symbol);
    console.log("  Decimals:", decimals);
    console.log("  URI:", metadata.uri);
    return mint;
    }
    ceateTokenWithMetadata()
    .then(() => process.exit(0))
    .catch((error) => {
      console.error("Error:", error);
      process.exit(1);
    });
    index.js
    import { Keypair, SystemProgram, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
    import { TOKEN_2022_PROGRAM_ID, ExtensionType, createInitializeMintInstruction, createInitializeMetadataPointerInstruction, getMintLen, TYPE_SIZE, LENGTH_SIZE } from "@solana/spl-token";
    import { createInitializeInstruction, pack } from "@solana/spl-token-metadata";
    import { connection, payer } from "./config.js";
    async function createTokenWithMetadata() {
      console.log("=== Creating Token with Metadata Extension ===\n");
      console.log("Payer address:", payer.publicKey.toBase58());
      const mintKeypair = Keypair.generate();
      const mint = mintKeypair.publicKey;
      console.log("\nMint address:", mint.toBase58());
      const metadata = {
        updateAuthority: payer.publicKey,
        mint: mint,
        name: "GetBlock Tutorial Token",
        symbol: "GBT",
        uri: "https://getblock.io/",
        additionalMetadata: [["description", "A test token created with GetBlock"]],
      };
      const decimals = 9;
      const mintLen = getMintLen([ExtensionType.MetadataPointer]);
      const metadataLen =
        TYPE_SIZE + // 2 bytes for type
        LENGTH_SIZE + // 2 bytes for length
        pack(metadata).length; // Actual metadata size
      const lamports = await connection.getMinimumBalanceForRentExemption(
        mintLen + metadataLen,
      );
      const transaction = new Transaction().add(
        SystemProgram.createAccount({
          fromPubkey: payer.publicKey,
          newAccountPubkey: mint,
          space: mintLen, // ← Just the mint size
          lamports: lamports, // ← But funded for full size
          programId: TOKEN_2022_PROGRAM_ID,
        }),
        createInitializeMetadataPointerInstruction(
          mint, // mint
          payer.publicKey, // authority
          mint, // metadata address (pointing to itself)
          TOKEN_2022_PROGRAM_ID,
        ),
        createInitializeMintInstruction(
          mint, // mint
          decimals, // decimals
          payer.publicKey, // mint authority
          null, // freeze authority (optional)
          TOKEN_2022_PROGRAM_ID,
        ),
        createInitializeInstruction({
          programId: TOKEN_2022_PROGRAM_ID,
          mint: mint,
          metadata: mint,
          name: metadata.name,
          symbol: metadata.symbol,
          uri: metadata.uri,
          mintAuthority: payer.publicKey,
          updateAuthority: payer.publicKey,
        }),
      );
      console.log("\nSending transaction...");
      const signature = await sendAndConfirmTransaction(
        connection,
        transaction,
        [payer, mintKeypair], // Signers
        { commitment: "confirmed" },
      );
    
      console.log("\Token created successfully!");
      console.log("Transaction signature:", signature);
      console.log("Mint address:", mint.toBase58());
      console.log("\nToken details:");
      console.log("  Name:", metadata.name);
      console.log("  Symbol:", metadata.symbol);
      console.log("  Decimals:", decimals);
      console.log("  URI:", metadata.uri);
    
      return mint;
    }
    createTokenWithMetadata()
      .then(() => process.exit(0))
      .catch((error) => {
        console.error("Error:", error);
        process.exit(1);
      });
    
    node index.js
    === Creating Token with Metadata Extension ===
    
    Payer address: 5C7dUe5ZDWBCYQ5eqtGPRyz7CQYk2aK4FhZTDYQeji7r
    
    Mint address: BVwyGVpUNUL7eYVqbMtzgbinTiUgd3tNXsgxfxoAQaWe
    
    Sending transaction...
    
    Token created successfully!
    Transaction signature: N9DHUYdNRUc9RC2H6LMtiSPpY2UW1aVmFZsK7b8KG3xpTUWiVDrj79EkxHTh74T5QmbMR3CbprYif3jNveAnQBJ
    Mint address: BVwyGVpUNUL7eYVqbMtzgbinTiUgd3tNXsgxfxoAQaWe
    
    Token details:
      Name: GetBlock Tutorial Token
      Symbol: GBT
      Decimals: 9
      URI: https://getblock.io/
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
       "jsonrpc": "2.0",
        "method": "eth_getBlockByHash",
        "params": [
            "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
            false
        ],
        "id": "getblock.io"
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
       "jsonrpc": "2.0",
        "method": "eth_getBlockByHash",
        "params": [
            "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
            false
        ],
        "id": "getblock.io"
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": {
            "baseFeePerGas": "0x5f5e100",
            "difficulty": "0x1",
            "extraData": "0xe31298ca6df96cb00d355ca9554878c19d39292b6a26eb9fc54b5df482851ef7",
            "gasLimit": "0x4000000000000",
            "gasUsed": "0x229dd8",
            "hash": "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
            "l1BlockNumber": "0x105e046",
            "logsBloom": "0x00000100000000020000100000000000080000000000000000000000001000001000000000000000000000000101000000000000000000000001010000000000000010000000000000001008000120000100000000001000800100008000000000000000000000000000000000000000021000200000400000000010000000001000000000000000000000000008000000000001000000000008000000000010000000000000000000000000000000000000000000000000000000000000000000008002000048000000000000000000200800000000000010000000000000000000000040000000000000008000000010000000004010400000000000000040",
            "miner": "0xa4b000000000000000000073657175656e636572",
            "mixHash": "0x0000000000012069000000000105e046000000000000000a0000000000000000",
            "nonce": "0x00000000000c7662",
            "number": "0x5206d53",
            "parentHash": "0xb458d44871af788992e51a89661eb28a6539cf9f33c0e9a30d0aab5f2e50e974",
            "receiptsRoot": "0x184ea05480454e4c4fcf6406106a4cb13477af97d45752a126ee84de88695c7c",
            "sendCount": "0x12069",
            "sendRoot": "0xe31298ca6df96cb00d355ca9554878c19d39292b6a26eb9fc54b5df482851ef7",
            "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
            "size": "0x579",
            "stateRoot": "0xea41be04084dc613cfbf8d1fef75d9a097fad2b222373669e42e2aa173175649",
            "timestamp": "0x644f0242",
            "transactions": [
                "0xaf256a9ce8839489dcaa4f9a2740bcd5865b3db34a15434cce29e6bdcf043bc7",
                "0xfd7e27e19777598be2536bc6e4a5e89cc8a386eca46374333b1fba22641ed255",
                "0x98b2f04b2eb747e685c7db6f97ef2aaca236e146afb310ed039d56ab8599eb0e",
                "0x23c566cf1c2f208a74ef2e585b5bfe7fcffab6445027f06b4207ec43968cf71e",
                "0x9febdfb50d48f1891b6660379dcea3d0060808538a102d589e7ea3b7aa6d787d"
            ],
            "transactionsRoot": "0x22ef4159c9394a555af55a3ae5719bf15c1ff296838dd920f1566eeecb15aa1f",
            "uncles": []
        }
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function Call() {
      try {
         const result = await provider.send("eth_getBlockByHash", [
      "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
      false,
    ]);    console.log("The result:", result);
        return result;
      } catch (error) {
        console.error("The error:", error);
        throw error;
      }
    }
    import { createPublicClient, http } from 'viem';
    import { arbitrum } from 'viem/chains';
    
    // Create Viem client with GetBlock
    const client = createPublicClient({
      chain: arbitrum,
      transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
    });
    
    // Using the method through Viem
    async function Call() {
        try {
            // Method-specific Viem implementation
            const result = await client.request({
                method: 'eth_getBlockByHash',
                params: [ "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
     false],
            });
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Viem Error:', error);
            throw error;
        }
    }
    
    import requests
    import json
    
    url = "https://go.getblock.us/<ACESS_TOKEN>"
    
    payload = json.dumps({
       "jsonrpc": "2.0",
        "method": "eth_getBlockByNumber",
        "params": [
            "latest",
            false
        ],
        "id": "getblock.io"
    })
    headers = {
      'Content-Type': 'application/json'
    }
    
    response = requests.request("POST", url, headers=headers, data=payload)
    
    print(response.text)
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .build()?;
    
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Content-Type", "application/json".parse()?);
    
        let data = r#"{
       "jsonrpc": "2.0",
        "method": "eth_getBlockByNumber",
        "params": [
            "latest",
            false
        ],
        "id": "getblock.io"
    }"#;
    
        let json: serde_json::Value = serde_json::from_str(&data)?;
    
        let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
            .headers(headers)
            .json(&json);
    
        let response = request.send().await?;
        let body = response.text().await?;
    
        println!("{}", body);
    
        Ok(())
    }
    {
        "jsonrpc": "2.0",
        "id": "getblock.io",
        "result": {
            "baseFeePerGas": "0x7cf30f8",
            "difficulty": "0x1",
            "extraData": "0x539464419cc7e1235fba3837a56b348ecb8ae3a3ed2f1c8839012038bbb59e32",
            "gasLimit": "0x4000000000000",
            "gasUsed": "0x1560d7",
            "hash": "0x1d77c0b85c1d0a75c19c94dc05868c936dc6d6b537c1846613e97110c90b3f48",
            "l1BlockNumber": "0x16dd9f1",
            "logsBloom": "0x000100c2000c0008800000044000200000000000000000180000010401000800000408020108000800800000000000000100400108082210006000000028000000000001000200080014040800002004000000040280000008004020000020412000000c0002040000001824000000000000040000000000004000100008000a0020800080004010000001000000000800000000000001000080000000000000020000200001000000000020800000000000080000000000000000080000001000402002000000200000000000010008040082001000882042200200008000080210040000200000000020000000200000000000080040000000000000400400",
            "miner": "0xa4b000000000000000000073657175656e636572",
            "mixHash": "0x0000000000025f6000000000016dd9f100000000000000280000000000000000",
            "nonce": "0x0000000000221739",
            "number": "0x185eef3d",
            "parentHash": "0x9c39e9f3fbc4b716cc974f5bec6766c95d23caf0dd89c97da33bc39656643437",
            "receiptsRoot": "0xb51b31ab3fccbb7423ae394c8d5e2039b55476d9df233e8031bf1c7d5620e489",
            "sendCount": "0x25f60",
            "sendRoot": "0x539464419cc7e1235fba3837a56b348ecb8ae3a3ed2f1c8839012038bbb59e32",
            "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
            "size": "0xed9",
            "stateRoot": "0x764448b4dcde129e0630c8f010e8a7c6ebcc446ec4cb2c2bea87d8f3ff8d86d8",
            "timestamp": "0x69384f78",
            "transactions": [
                "0xd31a43fdc91c3aaa6b00537d8788b06b28833ea14d237488ac35d5993ed8634c",
                "0xdf1df3a844340e0ae82485f78754818d8d628ac7236b6bcdbe3946c219301a45",
                "0x4c02aa4e537ff54dbfda1b3ef528bd611cfe88225d071fda4fa57a12801a2c88",
                "0x5c4f37fdf581342bb1e0eed9522feb69e988b5270945ce6128d55914b0a76c8f",
                "0x795fdc0ab98a9ec4f651779dfc055677f7a35596dda5292ab966b4c35c935231",
                "0x93e9d4fd77c2a9f34f80b328cbbe0613d943d376277a3758c0023c9e349becaf",
                "0xe05ee8bbc3a0db68529271b76ddcca2e5ac3c52263d57268293c09606d1bcaa6",
                "0x5f9fe747df5850d935f769be1a3e91102cd5ab73750b14b82f7e0afbba7cb30f",
                "0x7ee97b9dfa06eeec0bfac8bdcfb320888092a735174b5b7b15f0d066b6b85ecf",
                "0x8357a5f4721cec2e7d27caa0c0ae909e4db26f0e001888651f6213430e3489fe",
                "0xbc740ac9a94989b232c9445e475eb1cc94c3ed858a869ce0c43029cb9ed9d836",
                "0x89203f417d97ae57eaa1f73f1e08a11a9ffd73936744233555152d37d38cdb6e"
            ],
            "transactionsRoot": "0xacd0886f4df73a6d36dcbe36a854a162d25d2e2b81d6362b174d01582aeae562",
            "uncles": []
        }
    }
    import { ethers } from "ethers";
    const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    async function Call() {
      try {
         const result = await provider.send("eth_getBlockByNumber", ["latest", false],);    console.log("The result:", result);
        return result;
      } catch (error) {
        console.error("The error:", error);
        throw error;
      }
    }
    import { createPublicClient, http } from 'viem';
    import { arbitrum } from 'viem/chains';
    
    // Create Viem client with GetBlock
    const client = createPublicClient({
      chain: arbitrum,
      transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
    });
    
    // Using the method through Viem
    async function Call() {
        try {
            // Method-specific Viem implementation
            const result = await client.request({
                method: 'eth_getBlockByNumber',
                params: ["latest", false],
            });
            console.log('Result:', result);
            return result;
        } catch (error) {
            console.error('Viem Error:', error);
            throw error;
        }
    }
    

    @goat-sdk/plugin-pumpfun

    Lets the agent buy and sell tokens on Pump.fun

    @goat-sdk/adapter-langchain

    Converts GOAT tools into a format LangChain agents can call

    @langchain/core

    Core building blocks for the LangChain AI framework

    @langchain/langgraph

    Runs the agent loop — handles thinking, tool calling, and replying

    @langchain/openai

    Connects LangChain to OpenAI so GPT-4o can power the reasoning

    @solana/web3.js

    Standard library for talking to the Solana blockchain and RPCs

    bs58

    Decodes base58 private keys into a format the code can use

    dotenv

    Loads your .env file so secrets are not hardcoded in the source

    ), launch token(
    pumpfun()
    ) and send and receive SPL token(
    splToken()
    )
  • Specify the language model to use

  • Create short-term memory so it remembers previous messages within the same chat session.

  • Package

    What it does

    @goat-sdk/core

    The brain of GOAT — connects your wallet to AI-usable tools

    @goat-sdk/wallet-solana

    Lets GOAT read and control your Solana wallet

    @goat-sdk/plugin-jupiter

    Allows the agent to swap tokens using Jupiter DEX aggregator

    @goat-sdk/plugin-spl-token

    pnpmarrow-up-right
    GetBlock Account Dashboardarrow-up-right
    Solana Agent Guide Repoarrow-up-right

    Lets the agent send, receive, and check balances of SPL tokens (USDC, BONK)

    Back-run you: Profit from the price impact you create

    Meanwhile, Private transactions eliminate this exposure by hiding your transactions until they are included.

    hashtag
    Private TX vs Public Mempool

    Aspect
    Public Mempool
    Private TX

    Visibility

    Everyone sees it

    Only builders see it

    MEV exposure

    Vulnerable

    Protected

    hashtag
    When to Use Private Transactions

    Use private transactions when:

    • Executing large swaps that could be sandwiched

    • Trading tokens with low liquidity

    • Running strategies you don't want copied

    • Protecting any transaction from front-running

    hashtag
    Request Sample

    Parameter
    Type
    Required
    Description

    transaction

    string

    Yes

    Signed raw transaction hex

    hashtag
    How to Submit Transaction to Private Mempool

    1

    Set up the project

    2

    Set the ES module "type": "module" in your package.json.

    3

    Create a file and name it index.js

    4

    Create .env file and add the following:

    5

    Import the dependencies

    6

    Create and Sign Your Transaction

    7

    Submit Privately

    8

    Response

    chevron-rightComplete Example: Private BNB Transferhashtag
    chevron-rightComplete Example: MEV-Protected PancakeSwap Tradehashtag

    hashtag
    Selecting Specific Builders

    There are list of builders who should receive the transaction without delay. There are:

    • bloxroute: bloXroute internal builder(default)

    • all: all builders

    • Other options: 48club, blockrazor, jetbldr, nodereal

    hashtag
    Troubleshooting

    Problem
    Solution

    Transaction not included

    Without a priority tip, private transactions compete based on gas fees alone. If your transaction isn't being included:

    • Increase gas price — Higher gas = higher priority for builders

    • Add a priority tip — See

    "Invalid transaction"

    • Verify your transaction is properly signed

    • Check the chain ID is 56 (BSC Mainnet)

    • Ensure the nonce is correct

    Connection issues

    • Verify your API key is valid

    • Check network connectivity

    • Try reconnecting after a few seconds

    hashtag
    Next Steps

    To increase the priority for inclusion in your private transactions, see Private Transactions with Tips.

    You want faster propagation without hiding your transaction

  • MEV exposure is acceptable for your use case

  • You're competing on speed rather than privacy

  • You need broad validator visibility quickly

  • For MEV-sensitive transactions, see Private Transactions instead.

    hashtag
    Sample Request

    wss://go.getblock.io/<ACCESS_TOKEN>
    blxr_tx
    Parameter
    Type
    Required
    Description

    nonce

    int

    Yes

    Transaction count for your address

    hashtag
    How to Submit a Transaction to Public Mempool

    1

    Set up the project

    mkdir transaction-public-mempool
    cd transaction-public-mempool
    npm init
    
    mkdir transaction-public-mempool
    cd transaction-public-mempool
    yarn init
    
    2

    Create a new file named index.js. This is where you will make your first call.

    3

    Set the ES module "type": "module" in your package.json.

    4

    Create .env file and add the following:

    5

    Add the following code to index.js:

    6
    7

    Create and Sign Your Transaction

    8

    Submit via WebSocket

    9

    Response

    chevron-rightComplete Example: BNB Transferhashtag
    import WebSocket from "ws";
    import
    
    chevron-rightComplete Example: Token Swap on PancakeSwaphashtag

    hashtag
    Gas Price Recommendations

    Priority
    Gas Price
    Use Case

    Standard

    3 gwei

    Regular transfers

    Fast

    5 gwei

    Time-sensitive trades

    circle-info

    Note: Higher gas prices increase inclusion priority but also increase transaction cost.

    hashtag
    Troubleshooting

    1. "nonce too low"

    Your nonce is behind the network state. Fetch the latest:

    1. "insufficient funds"

    Ensure you have enough BNB for both the transaction value and gas:

    1. "replacement transaction underpriced"

    If replacing a pending transaction, increase the gas price by at least 10%:

    1. Transaction not included

    • Increase gas price for higher priority

    • Check that the transaction is valid

    • Verify sufficient balance

    hashtag
    Next Steps

    For transactions that need MEV protection, see:

    • Private Transactions — Hidden from public mempool

    • Private Transactions with Tips — Prioritized private submission

    How to use Bundle

    This guide explains how to submit transaction bundles on BNB Smart Chain using GetBlock's MEV endpoint.

    A bundle is a group of transactions submitted together with a guarantee that either all transactions execute in sequence or none are included. This atomic execution model supports several advanced use cases:

    • Arbitrage: Execute a buy on one DEX and a sell on another within the same block, ensuring both trades complete, or neither does

    • Liquidations: Check a position's health and liquidate it atomically, preventing front-running

    • Complex strategies: Coordinate multi-step transactions with guaranteed execution order

    hashtag
    Prerequisites

    Before submitting bundles, ensure you have:

    • A GetBlock API key with MEV endpoint access

    • Node.js v16 or later

    • A funded BSC wallet with sufficient BNB for all transactions and gas

    hashtag
    Sample Request

    Connect to the MEV WebSocket endpoint with your API key:

    Parameter
    Type
    Required
    Description

    hashtag
    Example

    1

    Set up the project

    2

    Create a new file named index.js. This is where you will make your first call.

    3

    hashtag
    Example: DEX Arbitrage

    chevron-rightThis example demonstrates a complete arbitrage strategy: buying a token on PancakeSwap V2 and selling on PancakeSwap V3 within the same block, with an optional priority fee.hashtag

    hashtag
    Reference Addresses

    Address

    hashtag
    Comparing Bundles and Private Transactions

    Choose the appropriate method based on your use case:

    hashtag
    Best Practices

    1. Use Sequential Nonces

    All transactions in a bundle must have consecutive nonces starting from your wallet's current nonce:

    2. Include a Priority Fee

    Adding a fee payment as the final transaction increases the likelihood of bundle inclusion:

    hashtag
    Choose an Appropriate blocks_count Value

    The blocks_count parameter determines how long your bundle remains valid. Shorter validity periods signal higher urgency to builders:

    Use Case
    Recommended blocks_count

    hashtag
    Simulate Before Submitting

    Test your transaction logic before submitting a bundle by simulating each transaction:

    hashtag
    Troubleshooting

    Problem
    Solution

    /v1/accounts/{account_hash}/modules - Aptos

    Example code for the /v1/accounts/{account_hash}/modules JSON-RPC method. Сomplete guide on how to use /v1/accounts/{account_hash}/modules json-rpc in GetBlock.io Web3 documentation.

    This endpoint gets all modules(known as smart contracts)’ bytecode deployed under a specific account at a specific ledger version. These modules define smart contract logic and can include structs, resources, and functions.


    hashtag
    Supported Network

    • Mainnet

    hashtag
    Parameters

    Parameter
    Data Type
    Description
    Required
    In

    hashtag
    Request Example

    Base URL

    Example(cURL)


    hashtag
    Response

    hashtag
    Response Parameter Definition

    Field
    Description

    hashtag
    Use Cases

    This endpoint can be used to:

    • Verify what functions and structs are exposed to dApps.

    • Assist in smart contract audits by fetching bytecode and ABIs.

    • Identify available functions, structs, and bytecode before interacting with a contract.


    hashtag
    Code Examples

    Python (Requests)

    Node(Axios)


    hashtag
    Error handling

    Some of the errors you may face are:

    • 403, which means your access token is incorrect or does not exist. To resolve this, you need to get a new access token or recheck your access token.

    • 500, which means a Node or network issue. Retry later

    • 404


    hashtag
    Integration with Web3

    By integrating /v1/accounts/{account_hash}/modules, developers can:

    • Build contract explorers that Show deployed modules, their functions, and structs on user-friendly dashboards.

    • Enable smart contract interactions

    • Integrate module inspection for debugging, auditing, and testing workflows.

    How To Optimize Solana Transactions with Priority Fees

    Learn how to land your Solana transaction faster using priority fee and GetBlock

    Solana processes thousands of transactions per second, but during periods of high network activity, your transactions may compete for block space. Priority fees let you bid for faster inclusion in the validator's queue, ensuring your time-sensitive transactions reach the network quickly.

    In this guide, you'll learn about priority fees, when you should use them, how to calculate compute uint(CU), and how to create one for yourself.

    hashtag
    What Are Priority Fees?

    Quickstart guide

    Follow these steps to activate the Solana Yellowstone gRPC add-on on GetBlock

    GetBlock offers with the Solana Geyser gRPC plugin, so you can start using it immediately, without any node setup and maintenance — simply enable the add-on and point your gRPC client at our endpoints.

    hashtag
    Prerequisites

    • A GetBlock account with a Dedicated Solana Node subscription

    RPC_URL=https://api.devnet.solana.com
    PRIVATE_KEY=your_wallet_private_key
    OPENAI_API_KEY=your_openai_secret_key
    import { Connection, Keypair } from "@solana/web3.js";
    import { solana } from "@goat-sdk/wallet-solana";
    import { jupiter } from "@goat-sdk/plugin-jupiter";
    import { splToken } from "@goat-sdk/plugin-spl-token";
    import { getOnChainTools } from "@goat-sdk/adapter-langchain";
    import { ChatOpenAI } from "@langchain/openai";
    import { pumpfun } from "@goat-sdk/plugin-pumpfun";
    import { createReactAgent } from "@langchain/langgraph/prebuilt";
    import { MemorySaver } from "@langchain/langgraph";
    import * as dotenv from "dotenv";
    import bs58 from "bs58";
    import * as readline from "readline";
    
    
    dotenv.config();
    async function initializeAgent() {
      const connection = new Connection(process.env.RPC_URL!, "confirmed");
      const privateKey = process.env.SOLANA_PRIVATE_KEY!;
      const keypair = Keypair.fromSecretKey(bs58.decode(privateKey));
      const tools = await getOnChainTools({
        wallet: solana({
          keypair,
          connection,
        }),
        plugins: [
          splToken(),  
          pumpfun(),
          jupiter(),
        ],
      });
      const llm = new ChatOpenAI({
        modelName: "gpt-4o",
        temperature: 0, // Lower temperature is better for tool calling
      });
      const memory = new MemorySaver();
      return createReactAgent({
        llm,
        tools,
        checkpointSaver: memory,
      });
    }
    async function run() {
      const agent = await initializeAgent();
      const config = { configurable: { thread_id: "goat-session-1" } };
      const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
      const ask = (prompt: string) => new Promise<string>((resolve) => rl.question(prompt, resolve)
      console.log('Solana AI Agent ready. Type "exit" to quit.\n');
      while (true) {
        const input = await ask("You: ");
        if (input.trim().toLowerCase() === "exit") {
          rl.close();
          break;
        }
        const response = await agent.invoke(
          { messages: [{ role: "user", content: input }] },
          config,
        );
        const lastMessage = response.messages[response.messages.length - 1];
        console.log("Agent:", lastMessage.content, "\n");
      }
    }
    run().catch(console.error);
    npx tsx agent.ts
    You: What is my wallet address and how much sol do i have left
    Agent: Your wallet address is `5C7dUe5ZDWBCYQ5eqtGPRyz7CQYk2aK4FhZTDYQeji7r`, and you have approximately 7.94991 SOL left in your wallet. 
    
    You: Send 0.05 sol to 3xk5f92EhRfDSD29W9ZWKmX2x7DXkc6TpMW8TpX5eFU8
    Agent: The transaction to send 0.05 SOL to the address `3xk5f92EhRfDSD29W9ZWKmX2x7DXkc6TpMW8TpX5eFU8` has been successfully completed. You can view the transaction details with the hash: [2ZK5U6pJ7i6j8nDRvdidgEyPnRPivzyBddUrJGebnefApFFXcvmomYNGZVC85XNjnAG5PTnuUyCwFYtjp55HNfLX](https://explorer.solana.com/tx/2ZK5U6pJ7i6j8nDRvdidgEyPnRPivzyBddUrJGebnefApFFXcvmomYNGZVC85XNjnAG5PTnuUyCwFYtjp55HNfLX). 
    
    You: Если вы обращаетесь в поддержку, можно сказать: "Подскажите, пожалуйста, мой адрес кошелька и баланс SOL"
    Agent: Ваш адрес кошелька: `5C7dUe5ZDWBCYQ5eqtGPRyz7CQYk2aK4FhZTDYQeji7r`.
    
    К сожалению, возникла ошибка при попытке получить баланс SOL. Пожалуйста, проверьте правильность адреса кошелька и попробуйте снова. 
    
    wss://go.getblock.io/<ACCESS_TOKEN>
    bsc_private_tx
    mkdir transaction-private-mempool
    cd transaction-private-mempool
    npm init -y
    npm install ws ethers dotenv
    mkdir transaction-private-mempool
    cd transaction-private-mempool
    yarn init -y
    yarn ws ethers
    import WebSocket from "ws";
    import { ethers } from "ethers";
    import "dotenv/config";
    
    const PRIVATE_KEY = process.env.PRIVATE_KEY;
    const RPC_URL = process.env.RPC_URL;
    
    async function sendPrivateTransaction(recipient, amountBNB) {
      const provider = new ethers.JsonRpcProvider(RPC_URL);
      const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
    
      console.log("Wallet:", wallet.address);
      console.log("Recipient:", recipient);
      console.log("Amount:", amountBNB, "BNB");
      console.log("Mode: Private (MEV Protected)");
    
      // Get nonce
      const nonce = await provider.getTransactionCount(wallet.address);
    
      // Build transaction
      const signedTx = await wallet.signTransaction({
        nonce: nonce,
        to: recipient,
        value: ethers.parseEther(amountBNB),
        gasPrice: ethers.parseUnits("3", "gwei"),
        gasLimit: 21000,
        chainId: 56,
      });
    const signedTxNoPrefix = signedTx.startsWith("0x")
      ? signedTx.slice(2)
      : signedTx;
    
    
      // Submit privately
      const ws = new WebSocket(process.env.ACCESS_TOKEN);
    
      return new Promise((resolve, reject) => {
        ws.on("open", () => {
          console.log("\nSubmitting private transaction...");
    
          ws.send(
            JSON.stringify({
              jsonrpc: "2.0",
              id: 1,
              method: "bsc_private_tx",
              params: {
                transaction: signedTxNoPrefix,
                mev_builders: ["all"],
              },
            }),
          );
        });
    
        ws.on("message", (data) => {
          const response = JSON.parse(data);
          ws.close();
    
          if (response.result) {
            console.log("\n✅ Private transaction submitted!");
            console.log("TX Hash:", response.result.txHash);
            console.log(
              "BSCScan:",
              `https://bscscan.com/tx/${response.result.txHash}`,
            );
            resolve(response.result.txHash);
          } else {
            console.error("\n❌ Error:", response.error);
            reject(response.error);
          }
        });
    
        ws.on("error", reject);
      });
    }
    
    // Usage
    sendPrivateTransaction(process.env.TO_ADDRESS, "0.001").catch(console.error);
    
    import  WebSocket from 'ws';
    import { ethers } from 'ethers';
    import 'dotenv/config';
    
    const PRIVATE_KEY = process.env.PRIVATE_KEY;
    const RPC_URL = process.env.RPC_URL;
    const PANCAKE_ROUTER = '0x10ED43C718714eb63d5aA57B78B54704E256024E';
    const WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
    
    async function privateSwap(tokenAddress, amountBNB, minAmountOut) {
      const provider = new ethers.JsonRpcProvider(RPC_URL);
      const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
      
      // Router ABI
      const routerABI = [
        'function swapExactETHForTokens(uint256 amountOutMin, address[] path, address to, uint256 deadline) payable'
      ];
      const router = new ethers.Contract(PANCAKE_ROUTER, routerABI, wallet);
      
      // Build swap calldata
      const deadline = Math.floor(Date.now() / 1000) + 300;
      const swapData = router.interface.encodeFunctionData('swapExactETHForTokens', [
        minAmountOut,
        [WBNB, tokenAddress],
        wallet.address,
        deadline
      ]);
      
      // Get nonce
      const nonce = await provider.getTransactionCount(wallet.address);
      
      // Sign transaction
      const signedTx = await wallet.signTransaction({
        nonce: nonce,
        to: PANCAKE_ROUTER,
        value: ethers.parseEther(amountBNB),
        data: swapData,
        gasPrice: ethers.parseUnits('3', 'gwei'),
        gasLimit: 300000,
        chainId: 56
      });
      
      console.log('Swap details:');
      console.log('  Amount:', amountBNB, 'BNB');
      console.log('  Token:', tokenAddress);
      console.log('  Min out:', ethers.formatEther(minAmountOut));
      console.log('  Mode: Private (MEV Protected)');
      
      // Submit privately
      const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
      
      return new Promise((resolve, reject) => {
        ws.on('open', () => {
          ws.send(JSON.stringify({
            jsonrpc: '2.0',
            id: 1,
            method: 'bsc_private_tx',
            params: {
              transaction: signedTx,
              mev_builders: ['all']
            }
          }));
        });
        
        ws.on('message', (data) => {
          const response = JSON.parse(data);
          ws.close();
          
          if (response.result) {
            console.log('\n✅ Private swap submitted!');
            console.log('TX Hash:', response.result.txHash);
            console.log('BSCScan:', `https://bscscan.com/tx/${response.result.txHash}`);
            resolve(response.result.txHash);
          } else {
            console.error('\n❌ Error:', response.error);
            reject(response.error);
          }
        });
      });
    }
    
    // Usage: Swap 1 BNB for BUSD (MEV protected)
    privateSwap(
      '0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56',  // BUSD
      '1.0',                                          // 1 BNB
      ethers.parseEther('200')                        // Min 200 BUSD
    ).catch(console.error);
    params: {
      transaction: signedTx,
      mev_builders: ['48club', 'bloxroute']  // Specific builders only
    }
    import WebSocket from 'ws';
    import { ethers } from 'ethers';
    import 'dotenv/config';
    
    const PRIVATE_KEY = process.env.PRIVATE_KEY;
    const RPC_URL = process.env.RPC_URL;
    
    const PANCAKE_ROUTER = '0x10ED43C718714eb63d5aA57B78B54704E256024E';
    const WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
    
    async function swapBNBForToken(tokenAddress, amountBNB, minAmountOut) {
      const provider = new ethers.JsonRpcProvider(RPC_URL);
      const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
      
      // Router ABI
      const routerABI = [
        'function swapExactETHForTokens(uint256 amountOutMin, address[] path, address to, uint256 deadline) payable'
      ];
      const router = new ethers.Contract(PANCAKE_ROUTER, routerABI, wallet);
      
      // Build swap calldata
      const deadline = Math.floor(Date.now() / 1000) + 300;  // 5 minutes
      const swapData = router.interface.encodeFunctionData('swapExactETHForTokens', [
        minAmountOut,
        [WBNB, tokenAddress],
        wallet.address,
        deadline
      ]);
      
      // Get nonce
      const nonce = await provider.getTransactionCount(wallet.address);
      
      // Build transaction
      const tx = {
        nonce: nonce,
        to: PANCAKE_ROUTER,
        value: ethers.parseEther(amountBNB),
        data: swapData,
        gasPrice: ethers.parseUnits('3', 'gwei'),
        gasLimit: 300000,  // Higher gas limit for swaps
        chainId: 56
      };
      
      // Sign transaction
      const signedTx = await wallet.signTransaction(tx);
      const signedTxNoPrefix = signedTx.startsWith("0x")
     ? signedTx.slice(2)
     : signedTx;
      
      console.log('Swap details:');
      console.log('  Amount:', amountBNB, 'BNB');
      console.log('  Token:', tokenAddress);
      console.log('  Min out:', ethers.formatEther(minAmountOut));
      
      // Submit via BDN
     const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
      
      return new Promise((resolve, reject) => {
        ws.on('open', () => {
          ws.send(JSON.stringify({
            jsonrpc: '2.0',
            id: 1,
            method: "blxr_tx",
            params: {"transaction": signedTxNoPrefix},
          }));
        });
        
        ws.on('message', (data) => {
          const response = JSON.parse(data);
          ws.close();
          
          if (response.result) {
            console.log('\n✅ Swap submitted!');
            console.log('TX Hash:', response.result);
            resolve(response.result);
          } else {
            console.error('\n❌ Error:', response.error);
            reject(response.error);
          }
        });
      });
    }
    
    // Usage: Swap 0.001 BNB for BUSD
    swapBNBForToken(
      '0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56',  // BUSD
      '0.001',                                          // 0.001 BNB
      ethers.parseEther('50')                         // Min 50 BUSD
    ).catch(console.error);
    const nonce = await provider.getTransactionCount(wallet.address, 'pending');
    Required = value + (gasPrice × gasLimit)
    const newGasPrice = existingGasPrice * 110n / 100n;
    https://youtu.be/2AQzYFHsZY0?si=xSn4FlRHOrXjua-Gyoutu.bechevron-right
    Try specific builders — Some builders may be more responsive

    Inclusion speed

    Gas price dependent

    Builder dependent

    Best for

    Speed-competitive scenarios

    Value-sensitive trades

    mev_builders

    array

    No

    Builders to send to. Default: ["all"]

    Private Transactions with Tips
    -y
    npm install ws ethers dotenv
    -y
    yarn ws ethers dotenv
    {
    ethers
    }
    from
    "
    ethers
    "
    ;
    import "dotenv/config";
    const PRIVATE_KEY = process.env.PRIVATE_KEY;
    const RPC_URL = process.env.RPC_URL;
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
    // Get current nonce
    const nonce = await provider.getTransactionCount(wallet.address);
    // Build transaction
    const tx = {
    nonce: nonce,
    to: "0xd26ea0f03100358b2Ebd4c9638f042aAda9a1BcF",
    value: ethers.parseEther("0.001"),
    gasPrice: ethers.parseUnits("3", "gwei"), // Minimum 3 gwei for BSC
    gasLimit: 21000,
    chainId: 56, // BSC Mainnet
    };
    // Sign transaction
    const signedTx = await wallet.signTransaction(tx); // e.g. "0xabcdef..."
    const signedTxNoPrefix = signedTx.startsWith("0x")
    ? signedTx.slice(2)
    : signedTx;
    console.log(signedTxNoPrefix);
    const ws = new WebSocket(process.env.ACCESS_TOKEN);
    ws.on("open", () => {
    ws.send(
    JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "blxr_tx",
    params: {"transaction": signedTxNoPrefix},
    }),
    );
    });
    ws.on("message", (data) => {
    const response = JSON.parse(data);
    if (response.result?.txHash) {
    const hash = response.result.txHash;
    console.log("TX Hash:", hash);
    console.log(`https://bscscan.com/tx/${hash}`);
    } else if (response.error) {
    console.error("❌ Error:", response.error.message);
    }
    ws.close();
    });

    to

    string

    Yes

    Recipient address

    value

    BigInt

    Yes

    Amount in wei

    gasPrice

    BigInt

    Yes

    Gas price (minimum 3 gwei)

    gasLimit

    int

    Yes

    Gas limit for execution

    data

    string

    No

    Calldata for contract calls

    chainId

    int

    Yes

    56 for BSC Mainnet

    Urgent

    10+ gwei

    Competitive scenarios

    {
      "jsonrpc": "2.0",
      "id": 1,
      "method": "blxr_tx",
      "params": ["0x<signed_transaction_hex>"]
    }
    {
      "jsonrpc": "2.0",
      "id": 1,
      "result": "0x<transaction_hash>"
    }

    string

    The ledger version to get the account state

    No

    Query

    start

    string

    The starting point for getting the resources

    No

    Query

    friends

    The module friends

    exposed_functions

    The public functions of the module

    name (function)

    The function name

    visibility

    The visibility of the function (public, private, or friend)

    is_entry

    Indicates if the function is an entry function

    is_view

    Indicates if the function is a view function

    generic_type_params

    The generic type parameters associated with the Move function

    constraints

    Any constraints associated with the function

    params

    The parameters associated with the Move function

    return

    The return type of the function

    structs

    The list of structs defined within the module

    name (struct)

    The struct name

    is_native

    Indicates if the module is native (implemented outside Move)

    abilities

    The list of abilities or capabilities provided by the module

    fields

    The list of fields defined within the struct

    type

    The field type

    , which means the resources were not found. To resolve this, use the right account_hash, or it is not a smart contract address.
    dApps can query other on-chain modules to understand what functions are available for reuse.

    account_hash

    string

    Aptos account address

    Yes

    Path

    bytecode

    The bytecode representation of the module

    abi

    The Application Binary Interface (ABI) of the Move module

    address

    The address of the Aptos account

    name

    ledger_version

    The name of the smart contract

    {
      "jsonrpc": "2.0",
      "id": 1,
      "method": "bsc_private_tx",
      "params": {
        "transaction": "0xf86c...",
        "mev_builders": ["all"]
      }
    }
    {
      "jsonrpc": "2.0",
      "id": 1,
      "result": {
        "txHash": "0x..."
      }
    }
    ACCESS_TOKEN=your-accelerated-node-endpoint
    RPC_URL=your-normal-bsc-node-endppoint //e.g https
    PRIVATE_KEY=your-wallet-private-key
    import WebSocket from 'ws';
    import { ethers } from 'ethers';
    import 'dotenv/config';
    
    const PRIVATE_KEY = process.env.PRIVATE_KEY;
    const RPC_URL = process.env.RPC_URL
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
    
    // Get current nonce
    const nonce = await provider.getTransactionCount(wallet.address);
    
    // Build transaction
    const tx = {
      nonce: nonce,
      to: '0xRECIPIENT_ADDRESS',
      value: ethers.parseEther('0.1'),
      gasPrice: ethers.parseUnits('3', 'gwei'),
      gasLimit: 21000,
      chainId: 56
    };
    
    // Sign transaction
    const signedTx = await wallet.signTransaction(tx);
    const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
    
    ws.on('open', () => {
      ws.send(JSON.stringify({
        jsonrpc: '2.0',
        id: 1,
        method: 'bsc_private_tx',
        params: {
          transaction: signedTx,
          mev_builders: ['all']
        }
      }));
    });
    
    ws.on('message', (data) => {
      const response = JSON.parse(data);
      
      if (response.result) {
        console.log('✅ Private TX submitted!');
        console.log('TX Hash:', response.result.txHash);
      } else {
        console.error('❌ Error:', response.error);
      }
      
      ws.close();
    });
    Wallet: 0xD1AF2dAc4e0a....
    Recipient: 0xd26ea.....
    Amount: 0.001 BNB
    Mode: Private (MEV Protected)
    
    Submitting private transaction...
    
    ✅ Private transaction submitted!
    TX Hash: 14223ac9adf33b77e4b52e8612dd351517b1bbc5b771567089994a6183f46df2
    BSCScan: https://bscscan.com/tx/14223ac9adf33b77e4b52e8612dd351517b1bbc5b771567089994a6183f46df2
    ACCESS_TOKEN=your-accelerated-node-endpoint
    RPC_URL=your-normal-bsc-node-endppoint //e.g https
    PRIVATE_KEY=your-wallet-private-key
    TO_ADDRESS=the-receiver-address
    import WebSocket from "ws";
    import { ethers } from "ethers";
    import "dotenv/config";
    const PRIVATE_KEY = process.env.PRIVATE_KEY;
    const RPC_URL = process.env.RPC_URL;
    const provider = new ethers.JsonRpcProvider(RPC_URL);
    const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
    
    // Get current nonce
    const nonce = await provider.getTransactionCount(wallet.address);
    // Build transaction
    const tx = {
      nonce: nonce,
      to: process.env.TO_ADDRESS,
      value: ethers.parseEther("0.001"),
      gasPrice: ethers.parseUnits("3", "gwei"), // Minimum 3 gwei for BSC
      gasLimit: 21000,
      chainId: 56, // BSC Mainnet
    };
    // Sign transaction
    const signedTx = await wallet.signTransaction(tx); 
    const signedTxNoPrefix = signedTx.startsWith("0x")
      ? signedTx.slice(2)
      : signedTx;
    const ws = new WebSocket(process.env.ACCESS_TOKEN);
    ws.on("open", () => {
      ws.send(
        JSON.stringify({
          jsonrpc: "2.0",
          id: 1,
          method: "blxr_tx",
          params: {"transaction": signedTxNoPrefix},
        }),
      );
    });
    ws.on("message", (data) => {
      const response = JSON.parse(data);
      if (response.result?.txHash) {
      const hash = response.result.txHash;
      console.log("TX Hash:", hash);
      console.log(`https://bscscan.com/tx/${hash}`);
    } else if (response.error) {
        console.error("❌ Error:", response.error.message);
      }
      ws.close();
    });
    01f86c380384b2d05e0082520894d26ea0f03100358b2ebd4c9638f042aada9a1bcf87038d7ea4c6800080c001a04647f98754480337ae409bcc225f2d62b706b47f31385221421cea20e41080b0a03ae32f07bb7110c4153c2ab121c152db7d3030d54cc0c5341f0b75b20e3d439d
    TX Hash: 00d4fe2db5c667ce549318cf621913af1bcb130022ec51020cbb6cae2b7eedce
    https://bscscan.com/tx/00d4fe2db5c667ce549318cf621913af1bcb130022ec51020cbb6cae2b7eedce
    https://go.getblock.io/<ACCESS-TOKEN>/
    curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/modules?ledger_version=3362752463&limit=2'
    [
        {
            "bytecode": "0xa11ceb0b050000000801000203022305251d0742470889012006a9012e10d7014f0ca602c703000000010001000002020100000303010000040004000005050400000606010000070401000203030103030303030304040401040204040102000202030403030404046d617468076d696e5f753634076d756c5f6469760c6d756c5f6469765f753132380b6d756c5f746f5f753132380c6f766572666c6f775f61646406706f775f31300473717274190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e120308d0070000000000000410ffffffffffffffffffffffffffffffff0410ffffffffffffffff0000000000000000126170746f733a3a6d657461646174615f76303b01d007000000000000124552525f4449564944455f42595f5a45524f1e5768656e20747279696e6720746f20646976696465206279207a65726f2e00010000010c0a000a0123030505080b000c02050a0b010c020b02020101000004120a020600000000000000002203060700270b00350b0135180b02351a0c030b03340202010000040f0a0232000000000000000000000000000000002203060700270b000b01180b021a0c030b0334020301000007060b00350b0135180204010000042207010a01170c020a020a00230309050f0b000b02173201000000000000000000000000000000170207010a00170c020a020a01230318051e0b010b0217320100000000000000000000000000000017020b000b0116020501000008150601000000000000000c0231000c01280a010a0023030a05130b02060a00000000000000180c020b013101160c0105040b020206010000092f0a00320400000000000000000000000000000023030505120b00320000000000000000000000000000000021030a050d0600000000000000000c01050f0601000000000000000c010b010c02052d0a000c040a0032020000000000000000000000000000001a3201000000000000000000000000000000160c030a030a0423031f052a0a030c040a000a031a0b031632020000000000000000000000000000001a0c03051a0b04340c020b020200",
            "abi": {
                "address": "0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12",
                "name": "math",
                "friends": [],
                "exposed_functions": [
                    {
                        "name": "min_u64",
                        "visibility": "public",
                        "is_entry": false,
                        "is_view": false,
                        "generic_type_params": [],
                        "params": [
                            "u64",
                            "u64"
                        ],
                        "return": [
                            "u64"
                        ]
                    },
                    {
                        "name": "mul_div",
                        "visibility": "public",
                        "is_entry": false,
                        "is_view": false,
                        "generic_type_params": [],
                        "params": [
                            "u64",
                            "u64",
                            "u64"
                        ],
                        "return": [
                            "u64"
                        ]
                    },
                    {
                        "name": "mul_div_u128",
                        "visibility": "public",
                        "is_entry": false,
                        "is_view": false,
                        "generic_type_params": [],
                        "params": [
                            "u128",
                            "u128",
                            "u128"
                        ],
                        "return": [
                            "u64"
                        ]
                    },
                    {
                        "name": "mul_to_u128",
                        "visibility": "public",
                        "is_entry": false,
                        "is_view": false,
                        "generic_type_params": [],
                        "params": [
                            "u64",
                            "u64"
                        ],
                        "return": [
                            "u128"
                        ]
                    },
                    {
                        "name": "overflow_add",
                        "visibility": "public",
                        "is_entry": false,
                        "is_view": false,
                        "generic_type_params": [],
                        "params": [
                            "u128",
                            "u128"
                        ],
                        "return": [
                            "u128"
                        ]
                    },
                    {
                        "name": "pow_10",
                        "visibility": "public",
                        "is_entry": false,
                        "is_view": false,
                        "generic_type_params": [],
                        "params": [
                            "u8"
                        ],
                        "return": [
                            "u64"
                        ]
                    },
                    {
                        "name": "sqrt",
                        "visibility": "public",
                        "is_entry": false,
                        "is_view": false,
                        "generic_type_params": [],
                        "params": [
                            "u128"
                        ],
                        "return": [
                            "u64"
                        ]
                    }
                ],
                "structs": []
            }
        },
        {
            "bytecode": "0xa11ceb0b050000000b01000402040c03101e042e0c053a0f07497e08c701400687020a109102300ac1020a0ccb023e00000101000200000003000001090700000400000100000500010100000600010100000700010100010a000301000302040204040405020201020001010109000108020108000108010663757276657309747970655f696e666f06537461626c650c556e636f7272656c61746564126173736572745f76616c69645f63757276650969735f737461626c650f69735f756e636f7272656c617465640e69735f76616c69645f63757276650b64756d6d795f6669656c640854797065496e666f07747970655f6f66190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12000000000000000000000000000000000000000000000000000000000000000103081127000000000000126170746f733a3a6d657461646174615f76301c011127000000000000114552525f494e56414c49445f43555256450000020108010102010801000100000005380003040700270201010000000438013802210202010000000438013803210203010000010a380403030506080c00050838050c000b000200",
            "abi": {
                "address": "0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12",
                "name": "curves",
                "friends": [],
                "exposed_functions": [
                    {
                        "name": "assert_valid_curve",
                        "visibility": "public",
                        "is_entry": false,
                        "is_view": false,
                        "generic_type_params": [
                            {
                                "constraints": []
                            }
                        ],
                        "params": [],
                        "return": []
                    },
                    {
                        "name": "is_stable",
                        "visibility": "public",
                        "is_entry": false,
                        "is_view": false,
                        "generic_type_params": [
                            {
                                "constraints": []
                            }
                        ],
                        "params": [],
                        "return": [
                            "bool"
                        ]
                    },
                    {
                        "name": "is_uncorrelated",
                        "visibility": "public",
                        "is_entry": false,
                        "is_view": false,
                        "generic_type_params": [
                            {
                                "constraints": []
                            }
                        ],
                        "params": [],
                        "return": [
                            "bool"
                        ]
                    },
                    {
                        "name": "is_valid_curve",
                        "visibility": "public",
                        "is_entry": false,
                        "is_view": false,
                        "generic_type_params": [
                            {
                                "constraints": []
                            }
                        ],
                        "params": [],
                        "return": [
                            "bool"
                        ]
                    }
                ],
                "structs": [
                    {
                        "name": "Stable",
                        "is_native": false,
                        "is_event": false,
                        "abilities": [],
                        "generic_type_params": [],
                        "fields": [
                            {
                                "name": "dummy_field",
                                "type": "bool"
                            }
                        ]
                    },
                    {
                        "name": "Uncorrelated",
                        "is_native": false,
                        "is_event": false,
                        "abilities": [],
                        "generic_type_params": [],
                        "fields": [
                            {
                                "name": "dummy_field",
                                "type": "bool"
                            }
                        ]
                    }
                ]
            }
        }
    ]
    import requests
    
    url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/modules?ledger_version=3362752463&limit=2"
    response = requests.request("GET", url, headers=headers, data=payload)
    
    print(response.text)
    import axios from ‘axios’;
    
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/modules?ledger_version=3362752463&limit=2',
    };
    
    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });

    mev_builders

    object

    No

    Target builders. Use {"all": ""} for all builders, or specify individual builders

    blocks_count

    integer

    No

    Number of blocks the bundle remains valid. Default: 5, Maximum: 20

    Submit bundles using the mev_sendBundle method:

    {
      "jsonrpc": "2.0",
    

    A successful submission returns a bundle hash:

    {
      "jsonrpc": "2.0",
    

    Set the ES module "type": "module" in your package.json.

    4

    Create .env file and add the following:

    5

    Add the following code to index.js:

    The following example demonstrates a simple BNB transfer with a priority fee:

    6

    Run the code using this command:

    7

    Sample response

    Purpose

    0x10ED43C718714eb63d5aA57B78B54704E256024E

    PancakeSwap V2 Router

    0x13f4EA83D0bd40E75C8222255bc855a974568Dd4

    PancakeSwap V3 Router

    0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c

    WBNB

    0x6374Ca2da5646C73Eb444aB99780495d61035f9b

    Priority fee recipient

    hashtag
    Code Example

    Simple transfers, individual swaps

    Arbitrage, multi-step operations

    Adding priority fees

    Via Multicall3

    Separate transaction in bundle

    mev_builders format

    Array: ["all"]

    Object: {"all": ""}

    transactions

    array

    Yes

    Aspect

    bsc_privateTx

    mev_sendBundle

    Transaction count

    Single

    Multiple

    Atomicity

    Not applicable

    All-or-nothing execution

    Time-sensitive arbitrage

    2–3

    Standard bundles

    5

    Less urgent operations

    10–20

    Bundle Not Included

    If your bundle is not included after the specified block count:

    • Increase the priority fee — Add a higher fee payment transaction

    • Verify nonce sequence — Nonces must be strictly consecutive with no gaps

    • Reduce blocks_count — Shorter validity signals higher priority to builders

    • Validate each transaction — Ensure every transaction in the bundle is valid independently

    "Invalid bundle" Error

    This error indicates a formatting or validation issue:

    • Check parameter format — The transactions parameter must be an array; mev_builders must be an object

    • Verify signatures — All transactions must be properly signed

    • Confirm chain ID — Use chain ID 56 for BSC Mainnet

    Partial Execution

    Bundles execute atomically, so partial execution should not occur. If you observe partial execution:

    • Contact support — This indicates a potential builder issue

    • Verify using the bundle hash — Check the bundle status on a block explorer

    wss://go.getblock.io/<ACCESS_TOKEN>
    mkdir bundle-example
    cd bundle-example
    npm init -y
    npm install ws ethers dotenv
    mkdir bundle-example
    cd bundle-example
    yarn init -y
    yarn ws ethers dotenv

    Array of signed raw transactions (hex-encoded)

    Use cases

    Priority fees are optional fees you add to a Solana transaction to increase its scheduling priority. Think of them as a tip to validators—transactions with higher priority fees get processed before those with lower fees or no fees at all.

    The formula is simple:

    Where:

    • Compute Units (CU) measure the computational resources your transaction consumes

    • Compute Unit Price is how much you're willing to pay per CU, measured in microLamports

    Quick conversion:

    • 1 SOL = 1,000,000,000 lamports

    • 1 lamport = 1,000,000 microLamports

    • Therefore: 1 microLamport = 0.000000000001 SOL

    hashtag
    When Should You Use Priority Fees?

    Priority fees aren't always necessary. Here's when they make sense:

    Scenario
    Recommendation

    Simple wallet transfers during normal activity

    Skip or use minimal fees

    DeFi swaps and trades

    Medium priority recommended

    NFT mints during launch

    High to urgent priority

    Arbitrage opportunities

    circle-info

    During normal network conditions, transactions land fine without priority fees. Only add them when speed matters or when the network is congested.

    hashtag
    Understanding Compute Units

    Every Solana transaction consumes compute units. The more complex your transaction, the more CUs it uses.

    Typical CU usage:

    • Simple SOL transfer: ~450 CU

    • Token transfer (SPL): ~20,000-30,000 CU

    • DEX swap: ~100,000-200,000 CU

    • Complex DeFi operations: ~200,000-400,000 CU

    circle-info

    You're charged based on the compute unit limit you set, not what you actually use. If you set a limit of 200,000 CU but only use 50,000, you still pay for 200,000. This is why simulation matters.

    Default behavior:

    • Without SetComputeUnitLimit: Solana defaults to 200,000 CU per instruction

    • Without SetComputeUnitPrice: No priority fee is charged (only base fee)

    hashtag
    Prerequisites

    You must have the following:

    1. Node.js v23+arrow-up-right is installed on your laptop

    2. Solana Wallet, e.g., Phantomarrow-up-right, Solflarearrow-up-right, MetaMaskarrow-up-right, etc

    3. Solana Devnet RPC URL (Optional: GetBlock Solana RPC URLarrow-up-right)

    4. A package manager installed on your laptop(Preferrably npm)

    circle-info

    Devnet RPC URL is used for this guide. If you want to interact with the Mainnet, then make use of GetBlock Solana RPC URLarrow-up-right

    hashtag
    Project Setup

    1

    Create a new project directory

    2

    Install the dependencies:

    chevron-rightPackage Descriptionhashtag
    Package
    Description
    3

    Create a .env file and add the following details:

    4

    Create index.ts file, this is where you will be writing your script

    5

    Import your dependencies and load the .env variables:

    6

    Build the Transfer Instruction

    This creates the instruction to move SOL. LAMPORTS_PER_SOL (1,000,000,000) converts from SOL to the smallest unit (lamports).

    7

    Simulate to Estimate Compute Units

    This:

    • Wraps the transfer instruction in a versioned transaction (the modern Solana format) for simulation.

    • Gets a recent blockhash — required to build a valid transaction even for simulation.

    8

    Get a Dynamic Priority Fee and calculate the total cost

    This helps gain insight into what was recently paid for priority fees and calculate what you paid, rather than guessing, which can prevent wastage or setting the fee too low.

    9

    Build the final transaction

    This:

    • Assembles 3 instructions: CU limit → priority fee → SOL transfer, then attaches blockhash and fee payer.

    • Signs with the private key, submits, waits for confirmation, and returns the signature.

    10

    Run the code using this command

    11

    Result

    You will get a response like this: This should show the estimated CU, the total priority fee used, and the transaction hash

    hashtag
    Best Practices

    1. Never hardcode compute unit limits. Simulation catches errors before they cost you fees:

    1. Network conditions change. Fetch recent fees instead of using static values:

    hashtag
    Conclusion

    Priority fees are a powerful tool for ensuring your Solana transactions reach their destination quickly during network congestion. The key steps are:

    1. Build your instructions - Create the core transaction logic

    2. Simulate - Get actual compute unit requirements

    3. Fetch network fees - Understand current market rates

    4. Add compute budget - Set limit and price (in that order, before main instructions)

    5. Send - Sign and submit with appropriate commitment level

    hashtag
    Additional Resources

    • Solana Core Feesarrow-up-right

    • GetBlock Dashboardarrow-up-right

    • Solana Devnet Explorerarrow-up-right

    Your gRPC endpoint URL with access token (found in GetBlock dashboard)

    hashtag
    Enabling the Solana gRPC add-on on GetBlock

    The Yellowstone gRPC add-on to Solana currently requires a Dedicated Nodearrow-up-right subscription on GetBlock. Here’s how to set it up with gRPC API:

    1. Sign up / log in: Create an account at GetBlock.io or log in to your existing account.

    2. Deploy a dedicated Solana node:

      1. Go to your user dashboard, switch the tab to “Dedicated nodes”, and scroll down to “My endpoints”

      2. Choose Solana under “Protocol”, set the network to mainnet.

      3. Click on Get.

    1. Enable the gRPC add-on: In Step 3 (Select API and Add‑ons) of your node setup, check Yellowstone gRPC under Add‑ons.

    circle-check

    All Dedicated Node plan subscribers receive the Yellowstone gRPC API at no extra cost together with their Solana node.

    Once your node is live, you’ll be able to create gRPC endpoints to begin using the add-on.

    hashtag
    Get your gRPC endpoint

    Return to My endpoints in your Dedicated node dashboard and generate a gRPC Access Tokenarrow-up-right.

    The dashboard will generate your new HTTPS‐style gRPC endpoint URL.

    hashtag
    Endpoint & authentication

    The endpoint URL will be used by your gRPC client to authenticate and interact with the Solana network. Regional domain determines which data center you’re talking to (Europe, US, or Asia).

    circle-info

    Your node’s region is locked in when you deploy it, during the setup flow. Once the node is provisioned in that region, all your endpoint URLs will correspond to the location you selected.

    Example endpoint URLs:

    When establishing your gRPC channel, the authentication is handled via an access token:

    circle-info

    GetBlock provides a single TLS endpoint – you don’t need to open or configure a different port for gRPC access.


    hashtag
    Subscribing to Data Streams: Code examples

    Dragon’s Mouth uses gRPC over HTTP/2 for all communication. Its message schemas are defined in Protocol Buffer (.proto) files, included in the Yellowstone repositoryarrow-up-right, which specify all the RPC methods and data types.

    The power of Yellowstone is real‑time streaming: open a single bi‑directional stream, send a SubscribeRequest with your filters, and get back a sequence of SubscribeUpdate messages.

    Here are the main subscription targets:

    Stream Field
    Proto Name
    What You Get

    slots

    slots: SlotsFilter

    Slot numbers as they’re processed by leader

    blocks

    blocks: BlocksFilter

    Block metadata (slot, parent slot, timestamp)

    circle-info

    All filters can be combined in the same request.

    Developers can integrate Yellowstone streams using standard gRPC client libraries. Triton’s Yellowstone repository includes example clientsarrow-up-right in Rust, Python, Go, and TypeScript.

    The part below will show common ways to initialize your connection to the GetBlock gRPC endpoint and open a bidirectional subscription stream (Subscribe) with filters.


    hashtag
    1. CLI (using grpcurl)

    A generic tool like grpcurl is perfect to just poke at the API and explore method calls:


    hashtag
    2. Using a high‑level SDK (Node.js / TypeScript)

    The triton-one/yellowstone-grpc repository is the official client toolkit for Solana’s Yellowstone (Geyser) gRPC API.

    It wraps the raw gRPC calls in friendly methods, handles reconnects, back‑pressure, and includes TypeScript types out of the box – easiest to get started with minimal boilerplate.

    Install the SDK:

    Connect to the gRPC endpoint and subscribe to the stream:


    hashtag
    3. Python, Rust, and Go streaming examples

    Below are minimal examples using Triton's Yellowstone helper libraries to stream real-time data from Solana via gRPC.

    Setup & run:

    Make sure the following dependencies are installed:

    Go Example (go-client/main.go):

    Make sure you clone the Yellowstone repo (for the examples.grpc module):

    Python Example (python-client/stream.py):

    Setup:

    Ensure your Cargo.toml includes:

    Rust Example (rust-client/src/main.rs):


    hashtag
    Unary RPC methods

    In addition to streaming subscriptions, the same gRPC interface also provides unary RPCs for quick, one-off queries:

    • getSlot: Returns the current slot number.

    • getBlockHeight: Retrieves the current block height.

    • getLatestBlockhash: Fetches the most recent blockhash.

    • isBlockhashValid: Checks whether a given blockhash is still valid.

    • getVersion: Returns version info for both the gRPC plugin and the connected Solana node

    You can call these methods directly on the gRPC client without opening a streaming connection.


    hashtag
    Yellowstone gRPC best practices

    Before you start streaming data with the Yellowstone Geyser plugin, consider these recommendations:

    • Filtering is crucial: Always narrow your subscription to only the accounts or programs you need. Excessive or empty filters can overwhelm clients and hit rate limits.

    • Combine with JSON‑RPC: Use gRPC for real‑time streaming. Continue to use GetBlock’s JSON‑RPC Solana endpoints for on‑demand calls like getBlock, sendTransaction, or historical queries.

    • Keeping your stream alive: gRPC streams may time out if idle. The Yellowstone plugin can handle keep-alive pings. In your SubscribeRequest, you can set ping: true to respond to server pings (or send a minimal ping message periodically) to keep the stream alive.

    • Selecting the right commitment levels: Choose processed, confirmed, or finalized in your SubscribeRequest to balance between lowest latency (processed) and highest certainty (finalized). For most real‑time use cases (dashboards, bots), use processed to see intra‑slot updates.

    circle-info

    hashtag
    About commitment levels

    In Solana’s commitment hierarchy, you have processed, confirmed, and finalized:

    • Finalized: After full consensus & finalized in the ledger.

    • Confirmed: Once a supermajority of validators have voted.

    • Processed: Means the validator has received and executed the transaction, but it may not yet have enough votes to be considered confirmed/finalized – (“intra-slot”).

    Streaming at “processed” gives you every transaction and account write the moment the leader executes it, well before it appears in a confirmed block.


    With these examples and notes, you should be able to jump right into using GetBlock’s Yellowstone gRPC API in the language of your choice.

    hashtag
    💬 Need help?

    Check out the Yellowstone gRPC docsarrow-up-right or reach out via GetBlock supportarrow-up-right.

    SOL nodesarrow-up-right

    /v1/transactions/by_hash/{transaction_hash} - Aptos

    Example code for the /v1/transactions/by_hash/{transaction_hash} json-rpc method. Сomplete guide on how to use /v1/transactions/by_hash/{transaction_hash} json-rpc in GetBlock.io Web3 documentation.

    This endpoint gets a transaction from the Aptos blockchain by its transaction hash. Every transaction has a unique hash that can be used to retrieve full details.

    hashtag
    Supported network

    ACCESS_TOKEN=your-accelerated-node-endpoint
    RPC_URL=your-normal-bsc-node-endppoint //e.g https
    PRIVATE_KEY=your-wallet-private-key
    import WebSocket from "ws";
    import { ethers } from "ethers";
    import "dotenv/config";
    const PRIVATE_KEY = process.env.PRIVATE_KEY;
    const RPC_URL = process.env.RPC_URL;
    async function submitBundle() {
      const provider = new ethers.JsonRpcProvider(RPC_URL);
      const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
      // Get the current nonce for your wallet
      const nonce = await provider.getTransactionCount(wallet.address);
      // Transaction 1: First operation
      const tx1 = await wallet.signTransaction({
        nonce: nonce,
        to: DEX_A,
        value: ethers.parseEther("0.001"),
        data: buyCalldata,
        gasPrice: ethers.parseUnits("3", "gwei"),
        gasLimit: 300000,
        chainId: 56,
      });
      // Transaction 2: Second operation (must use nonce + 1)
      const tx2 = await wallet.signTransaction({
        nonce: nonce + 1,
        to: DEX_B,
        value: 0,
        data: sellCalldata,
        gasPrice: ethers.parseUnits("3", "gwei"),
        gasLimit: 300000,
        chainId: 56,
      });
      // Connect to the MEV endpoint
      const ws = new WebSocket(process.env.ACCESS_TOKEN);
    
      ws.on("open", () => {
        ws.send(
          JSON.stringify({
            jsonrpc: "2.0",
            id: 1,
            method: "mev_sendBundle",
            params: {
              transactions: [tx1.slice(2), tx2.slice(2)],
              mev_builders: { all: "" },
              blocks_count: 5,
            },
          }),
        );
      });
      ws.on("message", (data) => {
        const response = JSON.parse(data);
    
        if (response.result) {
          console.log("Bundle submitted successfully");
          console.log("Bundle Hash:", response.result.bundleHash);
        } else {
          console.error("Submission failed:", response.error);
        }
    
        ws.close();
      });
    }
    submitBundle();
    node index.js
    const nonce = await provider.getTransactionCount(wallet.address);
    
    // Transaction 1: nonce
    // Transaction 2: nonce + 1
    // Transaction 3: nonce + 2
    const feeTx = await wallet.signTransaction({
      nonce: lastNonce,
      to: '0x6374Ca2da5646C73Eb444aB99780495d61035f9b',
      value: ethers.parseEther('0.001'),
      gasPrice: ethers.parseUnits('3', 'gwei'),
      gasLimit: 21000,
      chainId: 56
    });
    await provider.call({
      to: tx1.to,
      data: tx1.data,
      value: tx1.value
    });
    const WebSocket = require('ws');
    const { ethers } = require('ethers');
    import 'dotenv/config';
    
    const PRIVATE_KEY = process.env.PRIVATE_KEY;
    const RPC_URL= process.env.RPC_URL
    
    // Contract addresses
    const PANCAKE_V2_ROUTER = '0x10ED43C718714eb63d5aA57B78B54704E256024E';
    const PANCAKE_V3_ROUTER = '0x13f4EA83D0bd40E75C8222255bc855a974568Dd4';
    const FEE_ADDRESS = '0x6374Ca2da5646C73Eb444aB99780495d61035f9b';
    const WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
    const TOKEN = '0xYOUR_TOKEN';
    
    async function arbitrage() {
      const provider = new ethers.JsonRpcProvider(RPC_URL);
      const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
      
      const nonce = await provider.getTransactionCount(wallet.address);
      const deadline = Math.floor(Date.now() / 1000) + 300;
      
      // Encode the V2 swap
      const v2ABI = [
        'function swapExactETHForTokens(uint256 amountOutMin, address[] path, address to, uint256 deadline) payable'
      ];
      const v2Router = new ethers.Contract(PANCAKE_V2_ROUTER, v2ABI, wallet);
      
      const buyData = v2Router.interface.encodeFunctionData('swapExactETHForTokens', [
        0,  // amountOutMin (set appropriately in production)
        [WBNB, TOKEN],
        wallet.address,
        deadline
      ]);
      
      // Transaction 1: Buy on PancakeSwap V2
      const tx1 = await wallet.signTransaction({
        nonce: nonce,
        to: PANCAKE_V2_ROUTER,
        value: ethers.parseEther('1.0'),
        data: buyData,
        gasPrice: ethers.parseUnits('3', 'gwei'),
        gasLimit: 300000,
        chainId: 56
      });
      
      // Transaction 2: Sell on PancakeSwap V3
      // Note: V3 uses a different interface; replace with your actual V3 swap calldata
      const tx2 = await wallet.signTransaction({
        nonce: nonce + 1,
        to: PANCAKE_V3_ROUTER,
        value: 0,
        data: '0x...',  // Your V3 swap calldata
        gasPrice: ethers.parseUnits('3', 'gwei'),
        gasLimit: 300000,
        chainId: 56
      });
      
      // Transaction 3: Priority fee (optional but recommended)
      const tx3 = await wallet.signTransaction({
        nonce: nonce + 2,
        to: FEE_ADDRESS,
        value: ethers.parseEther('0.001'),
        gasPrice: ethers.parseUnits('3', 'gwei'),
        gasLimit: 21000,
        chainId: 56
      });
      
      // Submit the bundle
      const ws = new WebSocket(process.env.ACCESS_TOKEN);
      
      return new Promise((resolve, reject) => {
        ws.on('open', () => {
          ws.send(JSON.stringify({
            jsonrpc: '2.0',
            id: 1,
            method: 'mev_sendBundle',
            params: {
              transactions: [tx1, tx2, tx3],
              mev_builders: { all: '' },
              blocks_count: 3  // Short validity for time-sensitive arbitrage
            }
          }));
        });
        
        ws.on('message', (data) => {
          const response = JSON.parse(data);
          ws.close();
          
          if (response.result) {
            console.log('Bundle submitted successfully');
            console.log('Bundle Hash:', response.result.bundleHash);
            resolve(response.result.bundleHash);
          } else {
            console.error('Submission failed:', response.error);
            reject(response.error);
          }
        });
      });
    }
    
    arbitrage();
    mkdir priority-fees
    cd priority-fees
    npm install @solana/web3.js dotenv base58
    Priority Fee = Compute Units × Compute Unit Price
    // Good: Simulate and use actual consumption + buffer
    const simulation = await connection.simulateTransaction(tx);
    const estimatedCU = Math.ceil(simulation.value.unitsConsumed * 1.1);
    
    // Bad: Hardcoded value wastes money or fails
    const estimatedCU = 1_400_000; // Don't do this
    // Good: Adapt to current network conditions
    const fees = await connection.getRecentPrioritizationFees();
    const dynamicFee = calculatePercentile(fees, 75);
    
    // Bad: Static fee may be too low or waste money
    const staticFee = 50_000; // Don't do this
    cd go-client
    go mod tidy
    go run main.go
    go get github.com/rpcpool/yellowstone-grpc/examples/golang@latest
    go get google.golang.org/grpc@latest
    import (
       "context"
       "fmt"
       "log"
       "time"
    
       ygrpc "github.com/rpcpool/yellowstone-grpc/examples/golang/pkg/grpc"
       pb "github.com/rpcpool/yellowstone-grpc/examples/golang/pkg/proto"
       "google.golang.org/grpc/metadata"
    )
    
    func main() {
       endpoint := "go.getblock.io:443"
       token := "YOUR_GETBLOCK_TOKEN"
    
       client, err := ygrpc.NewGrpcConnection(context.Background(), endpoint)
       if err != nil {
           log.Fatalf("Connection error: %v", err)
       }
       defer client.Close()
    
       ctx := metadata.AppendToOutgoingContext(context.Background(), "x-token", token)
       stream, err := client.Subscribe(ctx)
       if err != nil {
           log.Fatalf("Subscription error: %v", err)
       }
    
    
       req := &pb.SubscribeRequest{
           Accounts: map[string]*pb.SubscribeRequestFilterAccounts{
               "example": {
                   Account: []string{"YOUR_WATCHED_ACCOUNT"},
               },
           },
           Commitment: pb.CommitmentLevel_CONFIRMED,
       }
    
    
       if err := stream.Send(req); err != nil {
           log.Fatalf("Send error: %v", err)
       }
    
    
       fmt.Println("Streaming...")
       for {
           res, err := stream.Recv()
           if err != nil {
               log.Printf("Stream error: %v", err)
               time.Sleep(time.Second)
               continue
           }
           fmt.Printf("Update at slot %d for %s\n", res.GetSlot(), res.GetAccount().GetAccount().GetPubkey())
       }
    }
    git clone https://github.com/rpcpool/yellowstone-grpc
    export PYTHONPATH=$PYTHONPATH:$(pwd)/yellowstone-grpc/examples/python
    from examples.grpc import new_client
    import time
    from google.protobuf.json_format import MessageToDict
    
    endpoint = "go.getblock.io:443"
    token = "YOUR_GETBLOCK_TOKEN"
    
    channel, client = new_client(endpoint, token)
    
    req = {
       "accounts": {
           "example": {
               "account": ["YOUR_WATCHED_ACCOUNT"]
           }
       },
       "commitment": "CONFIRMED"
    }
    
    stream = client.Subscribe(iter([req]))
    
    for update in stream:
       print("Update:", MessageToDict(update))
       time.sleep(0.5)
    // Europe (Frankfurt)
    https://go.getblock.io/<YOUR_ACCESS_TOKEN>/
    
    // USA (New York)
    https://go.getblock.us/<YOUR_ACCESS_TOKEN>/
    
    // Asia (Singapore)
    https://go.getblock.asia/<YOUR_ACCESS_TOKEN>/
    
    ENDPOINT = 'https://go.getblock.io';
    TOKEN = 'YOUR_GETBLOCK_ACCESS_TOKEN';
    # 1) List services and methods 
    grpcurl \
      -insecure \
      -authority go.getblock.io \
      -H "x-access-token: YOUR_ACCESS_TOKEN" \
      go.getblock.io:443 \
      list
    
    # 2) Subscribe to slots
    grpcurl \
      -insecure \
      -authority go.getblock.io \
      -H "x-access-token: YOUR_ACCESS_TOKEN" \
      go.getblock.io:443 \
      geyser.Geyser/Subscribe \
      -d '{ "slots": { "slots": []{} } }'
    
    npm install @triton-one/yellowstone-grpc
    # or
    yarn add @triton-one/yellowstone-grpc
    import Client, {
     SubscribeRequest,
     CommitmentLevel,
     SubscribeResponse,
    } from "@triton-one/yellowstone-grpc";
    
    
    async function main() {
     // Initialize
     const ENDPOINT = "https://go.getblock.io/";
     const TOKEN    = "<YOUR_ACCESS_TOKEN>";
     const client   = new Client(ENDPOINT, TOKEN);
    
    
      // Open a bidirectional stream
     const stream = await client.subscribe();
    
    
     // send a request to start all streams
     stream.write({
       accounts:   ["YourWalletPubkeyHere"],
       programs:   [],
       commitment: CommitmentLevel.PROCESSED,
     } as SubscribeRequest);
    
     stream.on("data", (msg: SubscribeResponse) => {
       if (msg.accountChange) {
         console.log(
           `▶ Account ${msg.accountChange.pubkey} = ${msg.accountChange.lamports}`
         );
       }
     });
    
    
     // End the stream
     stream.end();
     await client.close();
    }
    
    
    main().catch(console.error);
    
    "id": 1,
    "method": "mev_sendBundle",
    "params": {
    "transactions": ["0xf86c...", "0xf86c..."],
    "mev_builders": { "all": "" },
    "blocks_count": 5
    }
    }
    "id": 1,
    "result": {
    "bundleHash": "0x..."
    }
    }

    Dry-runs the transaction against the network without actually submitting it. Returns how many compute units it would use.

  • Takes the simulated CU count, adds a 10% buffer, then adds 600 extra to account for the two ComputeBudget instructions that will be in the final transaction but weren't in the simulation. Falls back to 200,000 if the simulation returned nothing.

  • Decodes private key, creates wallet keypair, parses recipient address, calls function with 0.001 SOL.

    chevron-rightComplete Working Examplehashtag

    Here's a full example that puts everything together:

    Extreme priority

    Network congestion detected

    Increase from baseline

    Time-sensitive operations

    High priority minimum

    @solana/web3.js

    Standard library for talking to the Solana blockchain and RPCs

    dotenv

    Loads your .env file so secrets are not hardcoded in the source

    base58

    Decodes base58 private keys into a format the code can use

    Priority fee Full Code repositoryarrow-up-right
    Solana Compute Budgetarrow-up-right

    blocksMeta

    blocksMeta: BlocksFilter

    Block metadata + transaction counts + status

    accounts

    accounts: AccountsFilter

    Account lamports, owner, executable flag, rent epoch

    accountsDataSlice

    accountsDataSlice: AccountsDataSliceFilter

    Partial account data blobs

    transactions

    transactions: TransactionsFilter

    Full transaction data + meta

    Deploying a private Solana node with GetBlock RPC provider
    Configuring a dedicated SOL node on GetBlock
    index.ts
    import {
      Connection,
      Keypair,
      Transaction,
      TransactionMessage,
      VersionedTransaction,
      SystemProgram,
      PublicKey,
      ComputeBudgetProgram,
      sendAndConfirmTransaction,
      LAMPORTS_PER_SOL,
      TransactionInstruction,
    } from "@solana/web3.js";
    import "dotenv/config";
    import bs58 from "bs58";
    
    const SOLANA_RPC = process.env.GETBLOCK_API_KEY;
    const PRIVATE_KEY = process.env.PRIVATE_KEY;
    const RECIPIENT_WALLET = process.env.RECIPIENT_WALLET;
    
    if (!SOLANA_RPC || !PRIVATE_KEY || !RECIPIENT_WALLET) {
      throw new Error("Missing required environment variables: GETBLOCK_API_KEY, PRIVATE_KEY, or RECIPIENT_WALLET");
    }
    
    async function sendWithPriorityFee(
      wallet: Keypair,
      recipient: PublicKey,
      amountSol: number,
    ): Promise<string> {
      const connection = new Connection(SOLANA_RPC!);
    
      // 1. Create the transfer instruction
      const transferIx = SystemProgram.transfer({
        fromPubkey: wallet.publicKey,
        toPubkey: recipient,
        lamports: amountSol * LAMPORTS_PER_SOL,
      });
    
      // 2. Simulate to estimate compute units
      const { blockhash: simBlockhash } = await connection.getLatestBlockhash();
      const simMessage = new TransactionMessage({
        payerKey: wallet.publicKey,
        recentBlockhash: simBlockhash,
        instructions: [transferIx],
      }).compileToV0Message();
      const simTx = new VersionedTransaction(simMessage);
    
      const simulation = await connection.simulateTransaction(simTx);
      // Add 600 CU overhead to account for the two ComputeBudget instructions
      // (each ~150 CU), which are not included in the simulation
      const estimatedCU = Math.max(
        Math.ceil((simulation.value.unitsConsumed || 200_000) * 1.1) + 600,
        600,
      );
    
      console.log(`Estimated CU: ${estimatedCU}`);
    
      // 3. Get dynamic priority fee from network
      const recentFees = await connection.getRecentPrioritizationFees();
      const sortedFees = recentFees
        .map((f) => f.prioritizationFee)
        .filter((f) => f > 0)
        .sort((a, b) => a - b);
    
      const dynamicFee =
        sortedFees.length > 0
          ? sortedFees[Math.floor(sortedFees.length * 0.75)]
          : 10_000;
    
      console.log(`Priority fee: ${dynamicFee} microLamports/CU`);
    
      // 4. Calculate total cost
      const totalPriorityFee = Math.ceil((estimatedCU * dynamicFee) / 1_000_000);
      console.log(
        `Total priority fee: ${totalPriorityFee} lamports (${totalPriorityFee / LAMPORTS_PER_SOL} SOL)`,
      );
    
      // 5. Build final transaction
      const { blockhash } = await connection.getLatestBlockhash("confirmed");
    
      const finalTx = new Transaction();
      finalTx.add(ComputeBudgetProgram.setComputeUnitLimit({ units: estimatedCU }));
      finalTx.add(
        ComputeBudgetProgram.setComputeUnitPrice({ microLamports: dynamicFee }),
      );
      finalTx.add(transferIx);
      finalTx.recentBlockhash = blockhash;
      finalTx.feePayer = wallet.publicKey;
    
      // 6. Sign and send
      finalTx.sign(wallet);
    
      const signature = await sendAndConfirmTransaction(
        connection,
        finalTx,
        [wallet],
        { skipPreflight: false, preflightCommitment: "confirmed" },
      );
    
      console.log(
        `Transaction confirmed: https://solscan.io/tx/${signature}?cluster=devnet`,
      );
      return signature;
    }
    
    // Main entry point
    const privateKeyBytes = bs58.decode(PRIVATE_KEY!);
    const wallet = Keypair.fromSecretKey(privateKeyBytes);
    const recipient = new PublicKey(RECIPIENT_WALLET!);
    const amountSol = 0.001; // Amount in SOL to send
    
    sendWithPriorityFee(wallet, recipient, amountSol).catch(console.error);
    
    RPC_URL=https://api.devnet.solana.com //GETBLOCK_API_KEY=your_getblock_api
    PRIVATE_KEY=your_wallet_private_key
    RECIPIENT_WALLET=the_receiver_wallet
    import {
      Connection,
      Keypair,
      Transaction,
      TransactionMessage,
      VersionedTransaction,
      SystemProgram,
      PublicKey,
      ComputeBudgetProgram,
      sendAndConfirmTransact
      LAMPORTS_PER_SOL,
      TransactionInstruction
    } from "@solana/web3.js"
    import "dotenv/config";
    import bs58 from "bs58";
    
    const SOLANA_RPC = process.env.RPC_URL; //replace with GETBLOCK_API_KEY if you are interacting with Mainnet
    const PRIVATE_KEY = process.env.PRIVATE_KEY;
    const RECIPIENT_WALLET = process.env.RECIPIENT_WALLET;
    async function sendWithPriorityFee(
      wallet: Keypair,
      recipient: PublicKey,
      amountSol: number,
    ): Promise<string> {
      const connection = new Connection(SOLANA_RPC!);
    
      // 1. Create the transfer instruction
      const transferIx = SystemProgram.transfer({
        fromPubkey: wallet.publicKey,
        toPubkey: recipient,
        lamports: amountSol * LAMPORTS_PER_SOL,
      });
     const { blockhash: simBlockhash } = await connection.getLatestBlockhash();
     const simMessage = new TransactionMessage({
       payerKey: wallet.publicKey,
       recentBlockhash: simBlockhash,
       instructions: [transferIx],
     }).compileToV0Message();
     const simTx = new VersionedTransaction(simMessage);
     const simulation = await connection.simulateTransaction(simTx);
     // Add 600 CU overhead to account for the two ComputeBudget instructions
     // (each ~150 CU), which are not included in the simulation
     const estimatedCU = Math.max(
       Math.ceil((simulation.value.unitsConsumed || 200_000) * 1.1) + 600,
       600,
     );
    const recentFees = await connection.getRecentPrioritizationFees();
    const sortedFees = recentFees
      .map((f) => f.prioritizationFee)
      .filter((f) => f > 0)
      .sort((a, b) => a - b);
    const dynamicFee =
      sortedFees.length > 0
        ? sortedFees[Math.floor(sortedFees.length * 0.75)]
        : 10_000;
    console.log(`Priority fee: ${dynamicFee} microLamports/CU`);
    
    const totalPriorityFee = Math.ceil((estimatedCU * dynamicFee) / 1_000_000);
    console.log(
      `Total priority fee: ${totalPriorityFee} lamports (${totalPriorityFee / LAMPORTS_PER_SOL} SOL)`,
    );
      const { blockhash } = await connection.getLatestBlockhash("confirmed");
      const finalTx = new Transaction();
      finalTx.add(ComputeBudgetProgram.setComputeUnitLimit({ units: estimatedCU }));
      finalTx.add(
        ComputeBudgetProgram.setComputeUnitPrice({ microLamports: dynamicFee }),
      );
      finalTx.add(transferIx);
      finalTx.recentBlockhash = blockhash;
      finalTx.feePayer = wallet.publicKey;
    
      finalTx.sign(wallet);
      const signature = await sendAndConfirmTransaction(
        connection,
        finalTx,
        [wallet],
        { skipPreflight: false, preflightCommitment: "confirmed" },
      );
      console.log(
        `Transaction confirmed: https://solscan.io/tx/${signature}?cluster=devnet`,
      );
      return signature;
    }
    
    const privateKeyBytes = bs58.decode(PRIVATE_KEY!);
    const wallet = Keypair.fromSecretKey(privateKeyBytes);
    const recipient = new PublicKey(RECIPIENT_WALLET!);
    const amountSol = 0.001; // Amount in SOL to send
    sendWithPriorityFee(wallet, recipient, amountSol).catch(console.error);
    npx ts-node index.ts
    Estimated CU: 765
    Priority fee: 10000 microLamports/CU
    Total priority fee: 8 lamports (8e-9 SOL)
    Transaction confirmed: https://solscan.io/tx/2xaGFBomVphZWDBwiT4KeyqwHrDkgsoLdhFawbXotAam43yziCwUdSqQCGiXtoHF2h8gAAEnZ4GjNi3tQ8QX3RSp?cluster=devnet
    cd rust-client
    cargo build
    cargo run
    [dependencies]
    yellowstone-grpc = { git = "https://github.com/rpcpool/yellowstone-grpc", branch = "main" }
    tonic = "0.9"
    tokio = { version = "1", features = ["full"] }
    use tonic::metadata::MetadataValue;
    use yellowstone_grpc::client::{subscribe_with_token, SubscribeRequest};
    
    #[tokio::main]
    async fn main() {
       let endpoint = "https://go.getblock.io";
       let token = "YOUR_GETBLOCK_TOKEN";
    
       let mut stream = subscribe_with_token(endpoint, token, SubscribeRequest {
           accounts: Some({
               let mut m = std::collections::HashMap::new();
               m.insert("example".to_string(), vec!["YOUR_WATCHED_ACCOUNT".to_string()]);
               m
           }),
           commitment: Some("confirmed".into()),
           ..Default::default()
       }).await.expect("stream failed");
    
       println!("Streaming...");
       while let Some(Ok(update)) = stream.message().await {
           println!("Update: {:?}", update);
       }
    }
    Mainnet

    hashtag
    Parameter

    Parameter

    Type

    In

    Required

    Description

    transaction_hash

    String

    Path

    Yes

    Hash of the transaction

    hashtag
    Request

    Base URL

    Example(cURL)

    hashtag
    Response Example

    hashtag
    Response parameter Definition

    Field

    Type

    Description

    version

    String

    Global transaction version number.

    hash

    String

    Transaction hash used for lookup.

    hashtag
    Use cases

    This method can be used for:

    • Retrieve any transaction directly by hash (common for explorers and wallets).

    • Debug and verify contract execution results.

    • Cross-reference hash → version → block for indexing.

    • Track system and user transactions separately.

    hashtag
    Code example

    Node(axios)

    Python(Request)

    hashtag
    Error handling

    Status Code

    Error Message

    Cause

    400

    Invalid transaction hash

    Hash format is invalid (not hex or malformed).

    403

    Forbidden

    Missing or invalid <ACCESS_TOKEN>.

    hashtag
    Integration with Web3

    By integrating /v1/transactions/by_hash/{txn_hash}, developers can:

    • Fetch transactions directly from wallet or explorer UIs.

    • Debug dApps by verifying hash results against VM status.

    • Enable search bars in explorers where users paste transaction hashes.

    • Support analytics pipelines that track txns by hash across modules.

    How to Subscribe to Stream

    Learn how to direct real-time access to transaction and block streams sourced from the BDN, bypassing RPC node-level execution and processing entirely.

    Stream subscription provides you with direct access to blockchain data as it propagates through the BDN network. This is very good for users e.g traders who want to get data earlier e.g new released token With a stream subscription, you enjoy:

    • Faster blocks: Receive new blocks before standard RPC propagation

    • Mempool access: See pending transactions before they're mined

    • Lower latency: Edge infrastructure minimizes network hops

    hashtag
    Code Sample

    Here, you will be checking if you are connected to streams

    hashtag
    How to Subscribe to Streams

    To subscribe to streams, there are four parameters you can make use of as seen below:

    Stream
    Description
    Use Case

    hashtag
    1. Block Streams (bdnBlocks)

    Subscribe to new blocks as they're produced.

    Include Options

    Field
    Description

    Example: Subscribe to Blocks

    hashtag
    2. Transaction Streams (newTxs / pendingTxs)

    Subscribe to mempool transactions as they propagate through the network.

    Include Options

    Field
    Description

    Filters

    Reduce bandwidth by filtering server-side:

    Filter
    Type
    Description

    Example: Monitor PancakeSwap Transactions

    hashtag
    3. Transaction Receipts (txReceipts)

    Subscribe to transaction confirmations.

    Include Options

    Field
    Description

    Example:

    hashtag
    Unsubscribing

    To stop receiving notifications, unsubscribe using the subscription ID:

    hashtag
    Best Practices

    1. Request Only What You Need

    1. Use Server-Side Filters

    1. Handle Reconnection

    1. Process Messages Asynchronously

    hashtag
    Rate Limits

    Tier
    Concurrent Subscriptions
    Message Rate

    Contact to upgrade your tier.

    hashtag
    Troubleshooting

    Problem
    Solution

    hashtag
    Next Step

    1. with accelerated propagation

    2. Using private transactions for or

    https://go.getblock.io/<ACCESS_TOKEN>
    curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_hash/0xd797b944ed8657406a1b09a5928048093399fc0a2f576d3e57c0f9cedbf95c4a'
    {
        "version": "3556737308",
        "hash": "0x4c3248d4c2f3a5ca1617e43e69332c66586478871ee44634cdb4554fe537dff6",
        "state_change_hash": "0x50148eff819eeb093efbe1cb56936ba02b3169db3343f5df0cb47aba016ea227",
        "event_root_hash": "0x1c432ce28a587287ef8abf14f025b78f5e288e886f16f217919cd2e35274f5f3",
        "state_checkpoint_hash": null,
        "gas_used": "195",
        "success": false,
        "vm_status": "Move abort in 0x31deb490728ae8e1a89675ee4c1877af8e5849c526d2c9a64238c49d8ece08a0::fa: E_NO_PROFIT(0x385): ",
        "accumulator_root_hash": "0xdc354eb8f4a96e9267bab2727240965becd154e35a21fede212af96f56333955",
        "changes": [
            {
                "address": "0xa",
                "state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
                "data": {
                    "type": "0x1::coin::PairedCoinType",
                    "data": {
                        "type": {
                            "account_address": "0x1",
                            "module_name": "0x6170746f735f636f696e",
                            "struct_name": "0x4170746f73436f696e"
                        }
                    }
                },
                "type": "write_resource"
            },
            {
                "address": "0xa",
                "state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
                "data": {
                    "type": "0x1::coin::PairedFungibleAssetRefs",
                    "data": {
                        "burn_ref_opt": {
                            "vec": [
                                {
                                    "metadata": {
                                        "inner": "0xa"
                                    }
                                }
                            ]
                        },
                        "mint_ref_opt": {
                            "vec": [
                                {
                                    "metadata": {
                                        "inner": "0xa"
                                    }
                                }
                            ]
                        },
                        "transfer_ref_opt": {
                            "vec": [
                                {
                                    "metadata": {
                                        "inner": "0xa"
                                    }
                                }
                            ]
                        }
                    }
                },
                "type": "write_resource"
            },
            {
                "address": "0xa",
                "state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
                "data": {
                    "type": "0x1::fungible_asset::ConcurrentSupply",
                    "data": {
                        "current": {
                            "max_value": "340282366920938463463374607431768211455",
                            "value": "25726501655234340"
                        }
                    }
                },
                "type": "write_resource"
            },
            {
                "address": "0xa",
                "state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
                "data": {
                    "type": "0x1::fungible_asset::Metadata",
                    "data": {
                        "decimals": 8,
                        "icon_uri": "",
                        "name": "Aptos Coin",
                        "project_uri": "",
                        "symbol": "APT"
                    }
                },
                "type": "write_resource"
            },
            {
                "address": "0xa",
                "state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
                "data": {
                    "type": "0x1::object::ObjectCore",
                    "data": {
                        "allow_ungated_transfer": true,
                        "guid_creation_num": "1125899906842625",
                        "owner": "0x1",
                        "transfer_events": {
                            "counter": "0",
                            "guid": {
                                "id": {
                                    "addr": "0xa",
                                    "creation_num": "1125899906842624"
                                }
                            }
                        }
                    }
                },
                "type": "write_resource"
            },
            {
                "address": "0xa",
                "state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
                "data": {
                    "type": "0x1::primary_fungible_store::DeriveRefPod",
                    "data": {
                        "metadata_derive_ref": {
                            "self": "0xa"
                        }
                    }
                },
                "type": "write_resource"
            },
            {
                "address": "0x60d8ef2e962b1d1b4f602c72e23eed6fbba86eefb41853a7688073fc918d912",
                "state_key_hash": "0x222b15ff81f90d75937ef6012807f0de0e0d488ccb5a229e55a954bc7870c75d",
                "data": {
                    "type": "0x1::fungible_asset::FungibleStore",
                    "data": {
                        "balance": "566263899",
                        "frozen": false,
                        "metadata": {
                            "inner": "0xa"
                        }
                    }
                },
                "type": "write_resource"
            },
            {
                "address": "0x60d8ef2e962b1d1b4f602c72e23eed6fbba86eefb41853a7688073fc918d912",
                "state_key_hash": "0x222b15ff81f90d75937ef6012807f0de0e0d488ccb5a229e55a954bc7870c75d",
                "data": {
                    "type": "0x1::object::ObjectCore",
                    "data": {
                        "allow_ungated_transfer": false,
                        "guid_creation_num": "1125899906842625",
                        "owner": "0x31deb490728ae8e1a89675ee4c1877af8e5849c526d2c9a64238c49d8ece08a0",
                        "transfer_events": {
                            "counter": "0",
                            "guid": {
                                "id": {
                                    "addr": "0x60d8ef2e962b1d1b4f602c72e23eed6fbba86eefb41853a7688073fc918d912",
                                    "creation_num": "1125899906842624"
                                }
                            }
                        }
                    }
                },
                "type": "write_resource"
            },
            {
                "address": "0x95a0fd88b11286d4790c253b39c6678b798c54b54b63bfd2bfe042411ee2e3e8",
                "state_key_hash": "0xf389cd5138744eb2c2c40a6b708ff717cb7a04bec7c9c1b9b8847857eaf617cd",
                "data": {
                    "type": "0x1::account::Account",
                    "data": {
                        "authentication_key": "0x95a0fd88b11286d4790c253b39c6678b798c54b54b63bfd2bfe042411ee2e3e8",
                        "coin_register_events": {
                            "counter": "0",
                            "guid": {
                                "id": {
                                    "addr": "0x95a0fd88b11286d4790c253b39c6678b798c54b54b63bfd2bfe042411ee2e3e8",
                                    "creation_num": "0"
                                }
                            }
                        },
                        "guid_creation_num": "2",
                        "key_rotation_events": {
                            "counter": "0",
                            "guid": {
                                "id": {
                                    "addr": "0x95a0fd88b11286d4790c253b39c6678b798c54b54b63bfd2bfe042411ee2e3e8",
                                    "creation_num": "1"
                                }
                            }
                        },
                        "rotation_capability_offer": {
                            "for": {
                                "vec": []
                            }
                        },
                        "sequence_number": "1680",
                        "signer_capability_offer": {
                            "for": {
                                "vec": []
                            }
                        }
                    }
                },
                "type": "write_resource"
            }
        ],
        "sender": "0x95a0fd88b11286d4790c253b39c6678b798c54b54b63bfd2bfe042411ee2e3e8",
        "sequence_number": "1679",
        "max_gas_amount": "5000",
        "gas_unit_price": "100",
        "expiration_timestamp_secs": "1760341246",
        "payload": {
            "function": "0x31deb490728ae8e1a89675ee4c1877af8e5849c526d2c9a64238c49d8ece08a0::lesserafim_3::crazy",
            "type_arguments": [
                "0x1::aptos_coin::AptosCoin",
                "0x111ae3e5bc816a5e63c2da97d0aa3886519e0cd5e4b046659fa35796bd11542a::stapt_token::StakedApt",
                "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDC",
                "0x159df6b7689437016108a019fd5bef736bac692b6d4a1f10c941f6fbb9a74ca6::oft::CakeOFT",
                "0x8d87a65ba30e09357fa2edea2c80dbac296e5dec2b18287113500b902942929d::celer_coin_manager::UsdcCoin",
                "0x1::aptos_coin::AptosCoin",
                "u64",
                "u64",
                "u64",
                "u64",
                "u64"
            ],
            "arguments": [
                "0x010f0a0101",
                "0x01010101010000",
                [
                    "25",
                    "10",
                    "30",
                    "25",
                    "25"
                ],
                [
                    {
                        "inner": "0xa"
                    },
                    {
                        "inner": "0xa"
                    },
                    {
                        "inner": "0xa"
                    },
                    {
                        "inner": "0xa"
                    },
                    {
                        "inner": "0xa"
                    },
                    {
                        "inner": "0xa"
                    }
                ],
                [
                    "0x1",
                    "0x5669f388059383ab806e0dfce92196304205059874fd845944137d96bbdfc8de",
                    "0x1",
                    "0x1",
                    "0x1"
                ],
                [
                    false,
                    true,
                    false,
                    true,
                    false
                ],
                "28452012"
            ],
            "type": "entry_function_payload"
        },
        "signature": {
            "sender": {
                "public_key": "0x1e9d94603ebd6b4a1d38e760be2b0523f09fb1f59e1e43c657f0ab3ef6205427",
                "signature": "0x05f71501658fdc40b6f42f71d6c298a378434a5825af5bc0efcc15aba2aa38625064612139299f43ae40e710bad18ce0b9935dee00b705285a8f73318f06a301",
                "type": "ed25519_signature"
            },
            "secondary_signer_addresses": [],
            "secondary_signers": [],
            "fee_payer_address": "0x31deb490728ae8e1a89675ee4c1877af8e5849c526d2c9a64238c49d8ece08a0",
            "fee_payer_signer": {
                "public_key": "0x17dfb6544cf49621c75af067528755a38061bdd210342f8bdf565bcdf561f056",
                "signature": "0x7866a52d642e7442671d0614cf7b201a29bdbd8b709ea59462d32917c368f596d771ab6592d1659952970cb277a35d536d0966a754c2cd610858f8c04eb93e08",
                "type": "ed25519_signature"
            },
            "type": "fee_payer_signature"
        },
        "replay_protection_nonce": null,
        "events": [
            {
                "guid": {
                    "creation_number": "0",
                    "account_address": "0x0"
                },
                "sequence_number": "0",
                "type": "0x1::transaction_fee::FeeStatement",
                "data": {
                    "execution_gas_units": "130",
                    "io_gas_units": "65",
                    "storage_fee_octas": "0",
                    "storage_fee_refund_octas": "0",
                    "total_charge_gas_units": "195"
                }
            }
        ],
        "timestamp": "1760341227055115",
        "type": "user_transaction"
    }
    
    const axios = require('axios');
    
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_hash/0xd797b944ed8657406a1b09a5928048093399fc0a2f576d3e57c0f9cedbf95c4a',
    };
    
    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error);
    });
    
    
    import requests
    
    url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_hash/0xd797b944ed8657406a1b09a5928048093399fc0a2f576d3e57c0f9cedbf95c4a"
    response = requests.request("GET", url, headers=headers, data=payload)
    
    print(response.text)

    state_change_hash

    String

    Hash of all state changes from this transaction.

    event_root_hash

    String

    Merkle root hash of emitted events.

    state_checkpoint_hash

    String

    State checkpoint hash for this transaction.

    gas_used

    String

    Amount of gas consumed.

    success

    Boolean

    Whether execution succeeded.

    vm_status

    String

    Aptos VM execution result.

    accumulator_root_hash

    String

    Ledger accumulator root hash.

    changes

    Array

    State changes caused (may be empty).

    timestamp

    String

    Unix timestamp in microseconds.

    block_end_info

    Object

    Block execution metadata.

    type

    String

    Transaction type (e.g., user_transaction, block_epilogue_transaction).

    500

    Internal server error

    Node or network issue; retry later.

    Pending transactions

    Front-running protection

    txReceipts

    Transaction receipts after confirmation

    Trade confirmation

    gas_price

    Gas price (hex)

    input

    Transaction calldata

    array

    Function selectors (first 4 bytes of calldata)

    Unlimited

    Unlimited

    bdnBlocks

    New blocks with headers and transactions

    Block monitoring, analytics

    newTxs

    New transactions entering mempool

    MEV detection, copy trading

    header

    Block header (number, hash, timestamp, gasUsed, gasLimit)

    transactions

    Full transaction list

    hash

    Block hash only

    tx_hash

    Transaction hash

    from

    Sender address

    to

    Recipient address

    value

    to

    array

    Transaction recipient addresses

    from

    array

    Transaction sender addresses

    receipt

    Full transaction receipt

    logs

    Event logs emitted

    Standard

    5

    1,000/sec

    Pro

    20

    10,000/sec

    No messages received

    • Check subscription response—did you receive a subscription ID?

    • Verify filters aren't too restrictive

    • Confirm your API key is valid and active

    High latency

    • Reduce the number of include fields

    • Add filters to reduce message volume

    • Check your network connection

    Missed messages

    • Process messages asynchronously

    • Increase your message queue buffer

    • Consider multiple connections for different streams

    Connection Drop

    supportenvelope
    Submitting transactions to public mempool
    MEV protection
    without MEV Protection
    wss://go.getblock.io/<ACCESS_TOKEN>
    index.js
    //npm install ws dotenv
    import WebSocket from "ws";
    import "dotenv/config";
    
    const ws = new WebSocket(
      `wss://go.getblock.io/${process.env.ACCESS_TOKEN}`,
    );
    
    ws.on("open", () => {
      console.log("Connected to BSC streams");
    });
    
    ws.on("error", (err) => {
      console.error("WebSocket error:", err.message);
    });
    > [email protected] start
    > node index.js
    
    Connected to BSC streams

    pendingTxs

    Transaction value (hex)

    method_id

    Enterprise

    • Implement automatic reconnection (see example above)

    • Re-subscribe after each reconnect—subscriptions don't persist

    • Check your network stability

    subscribe-blocks.js
    import WebSocket from "ws";
    import "dotenv/config";
    
    const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
    
    ws.on("open", () => {
      console.log("Connected");
    
      // Subscribe to new blocks
      ws.send(
        JSON.stringify({
          jsonrpc: "2.0",
          id: 1,
          method: "subscribe",
          params: ["bdnBlocks", { include: ["header", "transactions", "hash"] }],
        }),
      );
    });
    
    ws.on("message", (data) => {
      const message = JSON.parse(data);
    
      // Subscription confirmation
      if (message.id === 1 && message.result) {
        console.log("Subscribed! ID:", parseInt(message.result));
        return;
      }
    
      // Block notification
      if (message.params?.result) {
        const block = message.params.result;
        console.log("New block:", {
          number: parseInt(block.header.number, 16),
          hash: block.header.hash,
          txCount: block.transactions?.length || 0,
        });
      }
    });
    
    Connected
    Subscribed! ID: 9
    New block: { number: 84411561, hash: undefined, txCount: 86 }
    New block: { number: 84411562, hash: undefined, txCount: 105 }
    New block: { number: 84411563, hash: undefined, txCount: 66 }
    New block: { number: 84411564, hash: undefined, txCount: 66 }
    New block: { number: 84411565, hash: undefined, txCount: 78 }
    New block: { number: 84411566, hash: undefined, txCount: 93 }
    New block: { number: 84411567, hash: undefined, txCount: 63 }
    monitor-pancakeswap.js
    import WebSocket from "ws";
    import { ethers } from "ethers";
    import "dotenv/config";
    
    const PANCAKE_ROUTER = "0x10ED43C718714eb63d5aA57B78B54704E256024E";
    
    const SWAP_METHODS = {
      "0x38ed1739": "swapExactTokensForTokens",
      "0x7ff36ab5": "swapExactETHForTokens",
      "0x18cbafe5": "swapExactTokensForETH",
      "0xfb3bdb41": "swapETHForExactTokens",
      "0x5c11d795": "swapExactTokensForTokensSupportingFeeOnTransferTokens",
      "0xb6f9de95": "swapExactETHForTokensSupportingFeeOnTransferTokens",
    };
    
    function monitorPancakeSwap() {
      const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
    
      ws.on("open", () => {
        console.log("🔌 Connected to BSC stream");
        console.log("📊 Monitoring PancakeSwap...\n");
    
        ws.send(
          JSON.stringify({
            jsonrpc: "2.0",
            id: 1,
            method: "subscribe",
            params: [
              "pendingTxs",
              {
                include: ["tx_hash", "from", "to", "value", "input", "gas_price"],
                filters: {
                  to: [PANCAKE_ROUTER],
                },
              },
            ],
          }),
        );
      });
    
      ws.on("message", (data) => {
        const msg = JSON.parse(data);
    
        // Subscription confirmed
        if (msg.id === 1) {
          console.log("✅ Subscribed to PancakeSwap transactions\n");
          return;
        }
    
        // New transaction
        if (msg.params?.result) {
          const tx = msg.params.result;
          const methodId = tx.input?.slice(0, 10);
          const methodName = SWAP_METHODS[methodId] || "unknown";
    
          if (SWAP_METHODS[methodId]) {
            const value = ethers.formatEther(tx.value || "0");
            const gasPrice = ethers.formatUnits(tx.gas_price || "0", "gwei");
    
            console.log("🔄 Swap detected:");
            console.log(`   Hash: ${tx.tx_hash.slice(0, 18)}...`);
            console.log(`   Method: ${methodName}`);
            console.log(`   From: ${tx.from.slice(0, 10)}...`);
            console.log(`   Value: ${value} BNB`);
            console.log(`   Gas: ${gasPrice} gwei`);
            console.log("");
          }
        }
      });
    
      ws.on("close", () => {
        console.log("Disconnected, reconnecting in 5s...");
        setTimeout(monitorPancakeSwap, 5000);
      });
    
      ws.on("error", (err) => {
        console.error("WebSocket error:", err.message);
      });
    }
    
    monitorPancakeSwap();
    
    {
      "tx_hash": "0xdef456...",
      "from": "0xabc...",
      "to": "0x10ED43C718714eb63d5aA57B78B54704E256024E",
      "value": "0x16345785d8a0000",
      "gas_price": "0xb2d05e00",
      "input": "0x38ed1739..."
    }
    import WebSocket from 'ws';
    import 'dotenv/config';
    
    const PANCAKE_ROUTER = '0x10ED43C718714eb63d5aA57B78B54704E256024E';
    
    const SWAP_METHODS = {
      '0x38ed1739': 'swapExactTokensForTokens',
      '0x7ff36ab5': 'swapExactETHForTokens',
      '0x18cbafe5': 'swapExactTokensForETH',
      '0xfb3bdb41': 'swapETHForExactTokens',
    };
    
    function monitorNewTxs() {
      const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
    
      ws.on('open', () => {
        console.log('Connected to BSC stream');
        console.log('Monitoring confirmed PancakeSwap swaps...\n');
    
        ws.send(JSON.stringify({
          jsonrpc: '2.0',
          id: 1,
          method: 'subscribe',
          params: ['newTxs', {
            include: ['tx_hash', 'from', 'to', 'value', 'input'],
            filters: {
              to: [PANCAKE_ROUTER],
              method_id: Object.keys(SWAP_METHODS)
            }
          }]
        }));
      });
    
      ws.on('message', (data) => {
        const msg = JSON.parse(data);
    
        if (msg.id === 1) {
          console.log('Subscribed to confirmed PancakeSwap transactions\n');
          return;
        }
    
        if (msg.params?.result) {
          const tx = msg.params.result;
          const methodId = tx.input?.slice(0, 10);
          const methodName = SWAP_METHODS[methodId] || 'unknown';
    
          console.log('Confirmed swap:');
          console.log(`  Hash:   ${tx.tx_hash}`);
          console.log(`  Method: ${methodName}`);
          console.log(`  From:   ${tx.from}`);
          console.log(`  To:     ${tx.to}`);
          console.log(`  Value:  ${tx.value}`);
          console.log('');
        }
      });
    
      ws.on('close', () => {
        console.log('Disconnected, reconnecting in 5s...');
        setTimeout(monitorNewTxs, 5000);
      });
    
      ws.on('error', (err) => {
        console.error('WebSocket error:', err.message);
      });
    }
    
    monitorNewTxs();
    
    {
        "jsonrpc":"2.0",
        "id":1,
        "result":"0x11"
    }
    import WebSocket from 'ws';
    import 'dotenv/config';
    
    const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
    
    ws.on("open", () => {
      console.log("Connected");
    
      // Subscribe to new blocks
      ws.send(JSON.stringify({
        jsonrpc: '2.0',
        id: 1,
        method: 'subscribe',
        params: ['txReceipts', {
          include: ['receipt', 'logs']
        }]
      }));
    });
    
    ws.on("message", (data) => {
      const message = JSON.parse(data);
      console.log(message)})
    { 
      jsonrpc: '2.0', 
      id: 1, 
      result: '0x10' 
    }
    unsubscribe.js
    import WebSocket from "ws";
    import "dotenv/config";
    const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
    ws.on("open", () => {
      console.log("Connected");
    
    ws.send(
      JSON.stringify({
        jsonrpc: "2.0",
        id: 10,
        method: "unsubscribe",
        params: ["23"], // Subscription ID
      }),
    );})
    
    ws.on("message", (data) => {
      const message = JSON.parse(data);
      console.log(JSON.stringify(message, null, 2));
    });
    { 
        jsonrpc: '2.0', 
        id: 10, 
        result: true 
    }
    // ❌ Bad: Request everything
    include: ['tx_contents']  // Large payloads, high bandwidth
    // ✅ Good: Request specific fields
    include: ['tx_hash', 'from', 'to', 'value']  // Small payloads
    // ❌ Bad: Filter client-side
    params: ['newTxs', { include: ['tx_contents'] }]
    // Then filter in your code... wasteful!
    // ✅ Good: Filter server-side
    params: ['newTxs', {
      include: ['tx_hash', 'to', 'input'],
      filters: { to: ['0xTargetContract'] }
    }]
    function createConnection() {
      const ws = new WebSocket(`wss://bsc.getblock.io/mev/ws?api_key=${API_KEY}`);
      
      ws.on('close', () => {
        console.log('Disconnected, reconnecting...');
        setTimeout(createConnection, 5000);
      });
      
      ws.on('open', () => {
        // Re-subscribe after reconnect
        subscribeToFeeds(ws);
      });
      
      return ws;
    }
    ws.on('message', async (data) => {
      // Don't block the message loop
      setImmediate(() => {
        processMessage(JSON.parse(data));
      });
    });

    How to Build Basic-level Model-Context Protocol with GetBlock API Endpoints

    A step-by-step guide on how to build MCP with GetBlock API

    The Model-Context Protocol (MCP) is an open standard created by Anthropicarrow-up-right that provides a universal way for AI assistants to connect to external data sources and tools.

    With MCP, AI applications can connect to various data sources (e.g., local files, databases), tools (e.g., search engines, calculators), and workflows (e.g., specialized prompts)—enabling them to access key information and perform tasks effectively.

    You can picture MCP as a "USB-C for AI":

    • Before USB-C: Every device had different charging ports

    • After USB-C: One universal port works with everything

    Similarly, MCP creates a universal "port" for AI assistants to connect to data.

    In short, MCP helps AI applications access the right information at the right time, thereby reducing the likelihood of incorrect or misleading responses.

    In this guide, you will learn how to:

    • Get a GetBlock Access Token for Ethereum's API endpoint

    • A basic MCP server with three core capabilities:

      • Check ETH balance for any Ethereum address

    hashtag
    Prerequisites

    1. Basic understanding of JavaScript

    2. Must have installed and

    3. A GetBlock

    hashtag
    Technology Stack:

    • Node.js: JavaScript runtime environment that lets developers create servers, web apps, command line tools and scripts.

    • This allows applications to provide the context for LLMs in a standardized way.

    • : TypeScript-first validation library.

    hashtag
    Step 1: Project Initialization

    1. Set up your project directory using this command:

    1. Install Dependencies:

    • @modelcontextprotocol/sdk: Core MCP server functionality that provides McpServer class and transport mechanisms.

    • ethers: Js library for interacting with Blockchain e.g Ethereum.

    1. Configure Package.json

    • "type": "module" - Enables ES6 import/export syntax (required for MCP SDK)

    • "main": "server.js" - Specifies entry point of your application

    • "bin" - Allows running server as npx mcp-ethereum

    1. Get GetBlock's API Access Token

      1. Log in to your

      2. On your dashboard, scroll and click on Get Endpoint

    Create the following files to have a basic structure for your project:

    hashtag
    Step 2: Server File Setup

    hashtag
    1. Import dependencies

    circle-check

    Your script will be written inside server.js

    What this does:

    • Reads API token from environment variable

    • Creates Ethers provider pointing to GetBlock endpoint

    • All blockchain queries route through GetBlock's infrastructure

    hashtag
    3. Create MCP server instance

    Configuration:

    • name - Unique identifier for your server

    • version - Semantic version for tracking updates

    • console.error() - Logs to stderr (separate from data output)

    hashtag
    4. Implement Blockchain Query Tools

    Tool 1: Get ETH Balance

    This tool fetches the ETH balance for any Ethereum address:

    What this does:

    • Register the tool

    • Validates Ethereum address format

    • Queries Ethereum blockchain through GetBlock

    Tool 2: Get Gas Price

    This tool retrieves current Ethereum gas prices:

    What it does:

    • Register the tool

    • Fetch gas price

    • Converts the gas price from Wei to Gwei (1 Gwei = 10^9 Wei)

    Tool 3: Get Block Number

    This tool returns the latest Ethereum block number.

    What this does:

    • Get the latest block

    • Includes server timestamp for correlation

    hashtag
    5: Server Startup and Connection

    1. Create a Server connection with Claude desktop

    What this does:

    • const transport = new StdioServerTransport(): create communication channel between the client(Claude Desktop) and the server(script)

    • Links MCP server to transport mechanism

    • Registers all tools with MCP client

    1. Start the server and shut down:

    What this does:

    • SIGINT - Handles Ctrl+C interrupts

    • When the user runs npm run start , this will start the server.

    hashtag
    Step 3: Configuration and Deployment

    1. Open your Claude Desktop

    2. Click on Settings

    3. Scroll down and Click on Developer

    1. Add the following configuration:

    Config Location:

    Edit Configuration:

    Add the following configuration:

    Config Location:

    Add the following configuration:

    hashtag
    Step 4: Testing Your Server

    Test 1: Check ETH Balance

    circle-check

    Permit Claude to query the data

    Expected: Claude calls get_eth_balance tool and shows balance e.g

    The ETH balance for address 0xd1af2dac4e0a9d1f58b99e2f42bc0320ed74a7cd is 0.000104792219532 ETH (approximately 104,792,219,532,000 wei).

    Test 2: Gas Price

    Expected: Claude calls get_gas_price tool and shows price in Gwei e.g

    The current Ethereum gas price is 0.071638489 Gwei (or about 71.6 million wei).

    For EIP-1559 transactions:

    • Max Fee Per Gas: 0.143276976 Gwei

    • Max Priority Fee Per Gas: 0.000000002 Gwei

    This is relatively low gas pricing, which means it's a good time for transactions on the Ethereum network.

    Test 3: Block Number

    Expected: Claude calls get_block_number tool and shows block e.g

    The latest Ethereum block number is 23,811,857 on the Ethereum Mainnet, as of 2025-11-16 at 12:50:34 UTC.

    hashtag
    Step 4: Advanced Tests

    Test 4: Multiple Queries

    Expected: Claude calls both tools and provides analysis e.g

    Balance for 0xd1af2dac4e0a9d1f58b99e2f42bc0320ed74a7cd:

    • 0.000104792219532 ETH

    Current Gas Price Assessment: The current gas price of 0.063 Gwei is very low. This is excellent for making transactions!

    For context:

    Test 5: Natural Language

    Expected: Claude checks gas price and provides a recommendation e.g

    Yes, now is an excellent time to send an Ethereum transaction! Here's why:

    The current gas price of 0.060 Gwei is extremely low. To put this in perspective, a standard ETH transfer (21,000 gas units) would only cost about:

    0.060 Gwei × 21,000 = 0.00000126 ETH (roughly $0.004 USD)

    This is about as cheap as gas fees get on Ethereum. Gas prices can spike to 30-100+ Gwei during busy periods, which would make the same transaction 500-1600x more expensive.

    However, one thing to consider: The address you checked (0xd1af...a7cd) only has 0.0001048 ETH. While the gas is cheap right now, you'd still need to ensure you're leaving enough in the wallet to cover the gas fee for any transaction you want to make.

    If you're planning to send transactions from a different address with more funds, or if you're just doing something simple like a basic ETH transfer, this is definitely an opportune moment to take advantage of these low gas prices!

    hashtag
    Troubleshooting

    If you experience this error:

    This means that:

    1. Your GetBlock token is missing or incorrect

    2. The base URL is not correct.

    circle-exclamation

    Each location has a unique URL

    hashtag
    Conclusion

    In this guide, you've successfully functional MCP server that connects AI assistants to blockchain data using the GetBlock API. Now you know what MCP is, how to set up your project, get your GetBlock Token and get a response directly from your Claude.

    hashtag
    Additional Resources

    Get current gas prices
  • Retrieve the latest block number

  • Claude configuration and deployment

  • Claude Desktoparrow-up-right
    : A library for interacting with the Ethereum blockchain and its ecosystem.
    zod
    : a schema that validates user inputs before processing.
    command
  • "scripts" - Defines shortcuts like npm start

  • Select the Ethereum Mainnet network
  • Under API Interface, select JSON-RPC

  • Click on Create to get your endpoint

  • Your endpoint will look like:

    f. Save the token in .env file in this format:

    circle-exclamation

    Keep your endpoint safe, as it contains an access token

  • Project Structure

  • Returns balance in Wei (smallest unit)
  • Converts Wei to human-readable ETH e.g 1500000000000000000 → "1.5"

  • Return MCP content format

    • JSON stringified with 2-space indentation

    • Includes raw Wei value for precision

  • Starts listening for incoming requests
    Under Local MCP Server, click on Edit Config
    Config Location:

    Add the following configuration:

    Low gas: < 20 Gwei
  • Average gas: 20-50 Gwei

  • High gas: 50-100 Gwei

  • Very high gas: > 100 Gwei

  • At 0.063 Gwei, you're looking at extremely cheap transaction costs right now. This is a great time to interact with the Ethereum network if you're planning any transactions.

    Nodearrow-up-right
    npmarrow-up-right
    accountarrow-up-right
    Model Context Protocol SDK:arrow-up-right
    Zodarrow-up-right
    GetBlock accountarrow-up-right
    MCP docsarrow-up-right
    MCP SDK
    Basic Ethereum MCP repoarrow-up-right

    How to Track Pump.fun Token Mints with GetBlock’s Yellowstone gRPC

    A complete guide on how to track Pump.fun token launches on Solana in real-time using GetBlock’s Yellowstone gRPC service.

    hashtag
    Overview

    Traditional blockchain monitoring relies on polling RPC endpoints every few seconds, which introduces significant latency (2-5 seconds) and checking for updates that may not exist.

    GetBlock's Yellowstone gRPC service solves this by streaming data from Solana validators in real time.

    Here is a comparison:

    Traditional RPC Polling
    Websocket
    Yellowstone gRPC

    hashtag
    Why GetBlock’s Yellowstone gRPC?

    GetBlock provides access to Solana's Yellowstone Geyser gRPC plugin, delivering real-time blockchain data through a high-performance streaming protocol:

    • Ultra-Low Latency: Direct streaming from validators with ~400ms latency vs 2-5 seconds with traditional RPC polling

    • Efficient Filtering: Subscribe only to the specific programs and accounts you need, reducing bandwidth and processing overhead

    • Bidirectional Streaming: Single persistent connection handles both requests and data flow, eliminating polling waste

    In this guide, you will learn how to:

    1. Connects to GetBlock's Yellowstone gRPC service

    2. Subscribes to all transactions involving Pump.fun's program

    3. Filters for token creation instructions specifically

    hashtag
    Prerequisites

    Before you begin, ensure you have:

    • and npm installed

    • Basic knowledge of JavaScript

    • A

    hashtag
    Technology Stack:

    • Node.js

    • - Official Yellowstone gRPC client

    • - Base58 encoding for Solana addresses

    hashtag
    Step 1: Set Up Your GetBlock’s Yellowstone Endpoint

    hashtag
    Deploy Your Dedicated Solana Node

    First, you need to deploy a dedicated Solana node on GetBlock with the Yellowstone gRPC add-on enabled.

    1. Sign up or log in

    • Go to

    • Create an account or log in to your existing account

    2. Deploy your dedicated node

    • Navigate to your user Dashboard

    • Switch to the "Dedicated nodes" tab

    • Scroll down to "My endpoints"

    3. Enable the Yellowstone gRPC add-on

    • In Step 3 of your node setup (Select API and Add-ons)

    • Check the box for Yellowstone gRPC under Add-ons

    • Complete payout and finalise the setup

    hashtag
    Generate a Yellowstone gRPC Access Token

    Once your node is live, you'll create an access token to authenticate your gRPC connections.

    1. Return to your dashboard

    • Under your dedicated node dashboard, click on "My endpoints".

    • Select Yellowstone gRPC

    • Click on Add to generate an access token

    2. Your endpoint URL

    You'll receive an HTTPS-style gRPC endpoint URL based on your chosen region:

    circle-exclamation

    Ensure you securely store both the base endpoint and the access token. You'll need them in your code to authenticate with GetBlock's Yellowstone service.

    circle-info

    GetBlock provides a single TLS endpoint - you don't need to configure different ports or protocols. Everything works over standard HTTPS (port 443).

    hashtag
    Step 2: Set up Development Environment

    1. Create a directory for your project

    1. Install Dependencies:

    What these packages do:

    • - Official client for connecting to Yellowstone gRPC services (works with GetBlock)

    • - Encodes binary data to base58 format (Solana's address format). Version 5.0.0 supports vanilla js.

    circle-info

    [email protected] because version 6.x + uses ES modules only, which don't work with vanilla js - require() statements.

    hashtag
    Project Structure

    Create the following files to have a basic structure for your project:

    hashtag
    Step 3: Start Building Your Monitor

    1. Import dependencies into pumpfun-monitor.js :

    What this does:

    • yellowstone gRPC Client for connecting to GetBlock

    • CommitmentLevel Settings for choosing transaction confirmation speed

    • bs58 for converting binary data into human-readable Solana addresses.

    1. Add your GetBlock configuration:

    What this does:

    • Stores your GetBlock credentials.

    triangle-exclamation

    Replace YOUR_ACCESS_TOKEN with the actual token you generated in Step 1.

    If you chose a different region, use that endpoint instead (e.g., https://go.getblock.us/<ACCESS_TOKEN> or https://go.getblock.asia/<ACCESS_TOKEN>.

    1. Add Pump.fun constants:

    What this does:

    • PUMPFUN_PROGRAM - The unique program ID for Pump.fun on Solana

    • CREATE_DISCRIMINATOR - The 8-byte identifier that marks token creation instructions (derived from hashing "global:create")

    1. Add statistics tracker:

    • This creates an object to track how many tokens you've detected and when the last one appeared.

    hashtag
    Step 4: Build Data Parser Functions

    Now, you'll add a function to decode the binary data from Pump.fun's instruction format.

    1. Add string decoder:

    What this does:

    • Pump.fun stores strings as [4 bytes for length][UTF-8 string data]. This function reads that format and returns both the string value and how many bytes were consumed.

    1. Add Instruction Parser:

      What this does:

    • Reads the token's metadata from Pump.fun's instruction data format. The data is organized like this:

      • First 8 bytes: Discriminator (identifies this as a "create" instruction)

      • Token name (e.g., "Super Doge")

    circle-check

    The function starts at byte 8 (after the discriminator) and reads each string one by one using the decodeString helper function.

    hashtag
    Step 5: Add Account Address Extractor

    The next step is to create a function that extracts account addresses to identify newly created tokens' mint address, bonding curve pool address and creator's wallet address.

    What this does:

    • Extracts three key addresses from the instruction:

      • accounts[0] - The newly created token's mint address

      • accounts[2] - The bonding curve pool address

    circle-check

    These are defined by Pump.fun's program structure.

    hashtag
    Step 6: Add Instruction Verifier

    The next step is to verify the instruction:

    What this does:

    • Verifies two things:

      • The instruction calling Pump.fun's program

      • The first 8 bytes which match the create discriminator

    circle-check

    Only instructions passing both checks are token creations.

    hashtag
    Step 7: Add Display Function

    The next step is to add a function that displays the data in a readable format:

    What this does:

    • Formats and displays all token information in a readable format

    • Updates statistics

    • Includes Solscan link to the token, transaction hash and creator.

    hashtag
    Step 8: Build the Main Monitor Function

    Now you'll create the core function that connects to GetBlock and processes blockchain data.

    circle-exclamation

    This section is broken into smaller parts for clarity.

    hashtag
    Part A: Start the Function and Connect

    What this does:

    • Creates a client connection to GetBlock using your credentials and opens a bi-directional streaming connection.

    hashtag
    Part B: Configure Subscription

    What this does:

    • Tells GetBlock you only want transactions involving Pump.fun's program, with CONFIRMED commitment level (~2-3 seconds, balanced speed/reliability).

    hashtag
    Part C: Handle Incoming Data

    What this does:

    • Processes each message from GetBlock - responds to keep-alive pings and extracts transaction data.

    hashtag
    Part D: Process Instructions

    What this does:

    • For each instruction, it checks if it's a create, parses metadata, extracts addresses, and displays results.

    hashtag
    Part E: Handle Errors

    What this does:

    • It handles stream errors and connection closures.

    hashtag
    Part F: Send Request

    What this does:

    • Sends your subscription request to GetBlock and confirms the connection is active.

    circle-exclamation

    This completes the monitorPumpfunMints() function - everything above is part of this one function in your pumpfun-monitor.js file.

    hashtag
    Step 9: Add Execution Code

    Finally, add the code to run your monitor:

    What this does:

    • Runs your monitor and automatically restarts it if it crashes.

    What this does:

    • Handles Ctrl+C to show final statistics before shutdown.

    hashtag
    Step 10: Run Your Monitor

    Run the following command in your terminal to start the server:

    hashtag
    Expected Output

    You'll see:

    This means you're connected to GetBlock and monitoring is active.

    hashtag
    When a Token Appears

    When a new token appears, it displays like this:

    Congratulations 🎉, you've successfully created an application that tracks Pump.fun token minted.

    hashtag
    Troubleshooting

    1. Connection issues:

    This means there is a connection glitch:

    • Verify your ENDPOINT and TOKEN in pumpfun-monitor.js

    • Check your GetBlock dashboard to confirm if the node is active

    • Test your internet connection

    1. Tokens not showing:

    • Be patient - Pump.fun typically has 50-200 tokens per day

    • Visit to verify tokens are being created

    • Try CommitmentLevel.PROCESSED for faster updates

    1. Parser Errors:

    These warnings are normal. This means some transactions aren't structured.

    hashtag
    Security Best Practices

    This is highly recommended to use environment variables instead of hard-coding. Create an .env file and store your token like this:

    and reference it in your pumpfun-monitor.js like this:

    circle-exclamation

    Remember to add the .env file in your .gitignore file.

    hashtag
    Conclusion

    In this guide, you learn how to build a tracking application that monitors Pump.fun token minted using GetBlock Yellowstone gRPC. This guide explains the importance of using GetBlock Yellowstone gRPC, how to get your Yellowstone gRPC token, set up the application to get the expected result.

    It also explains how to troubleshoot some errors you may encounter and possible ways to enhance the security and maintainability of your applications.

    hashtag
    Additional Resources

    How to Listen to High-Value SOL Transactions via Yellowstone Geyser gRPC with GetBlock

    How to Build an App to Track Large Solana Transactions with GetBlock Yellowstone Geyer gRPC

    Monitoring high-value SOL transactions is essential for understanding the dynamics of the Solana network. By using tools like Yellowstone Geyser gRPC with GetBlock, developers can gain real-time insights into significant financial movements, enabling them to make informed decisions and capitalize on trends within the Solana ecosystem.

    In this tutorial, you'll build a monitoring app that detects high-value SOL transfers the moment they occur on the Solana blockchain.

    You'll learn how to:

    • Connect to GetBlock's Yellowstone gRPC service for ultra-low latency blockchain data streaming

    • Subscribe to Solana's System Program to capture all native SOL transfers

    • Parse transfer instruction data to extract amounts, sender addresses, and recipient addresses

    • Filter transactions based on transfer amount thresholds

    • Display real-time alerts with formatted output and explorer links

    • Track statistics, including total volume and largest transfers

    hashtag
    Technology Stack:

    • Node.js

    • - Official Yellowstone gRPC client

    • - Base58 encoding for Solana addresses

    hashtag
    Prerequisites

    Before you begin, ensure you have:

    • Node.js v18 or higher is installed on your system

    • Basic JavaScript knowledge

    • A GetBlock account - Free sign-up available at getblock.io

    hashtag
    Step 1: Set Up Your GetBlock Yellowstone Endpoint

    hashtag
    Deploy Your Dedicated Solana Node

    First, you need to deploy a dedicated Solana node on GetBlock with the Yellowstone gRPC add-on enabled.

    1. Sign up or log in

    • Go to GetBlock

    • Create an account or log in to your existing account

    2. Deploy your dedicated node

    • Navigate to your user Dashboard

    • Switch to the "Dedicated nodes" tab

    • Scroll down to "My endpoints."

    3. Enable the Yellowstone gRPC add-on

    • In Step 3 of your node setup (Select API and Add-ons)

    • Check the box for Yellowstone gRPC under Add-ons

    • Complete payout and finalize the setup

    hashtag
    Generate Your gRPC Access Token

    Once your node is live, you'll create an access token to authenticate your gRPC connections.

    1. Return to your dashboard

    • Go to "My endpoints" in your Dedicated node dashboard and generate a gRPC Access Token

    2. Your endpoint URL

    You'll receive an HTTPS-style gRPC endpoint URL based on your chosen region:

    circle-exclamation

    Save both pieces of information:

    • Base Endpoint: https://go.getblock.io (or your region)

    • Access Token: The alphanumeric token generated

    hashtag
    Step 2: Initialize Your Project

    1. Open your terminal and create a new directory:

    1. Initialize Node.js Project

    1. Install the required packages:

    1. Create a new file:

    1. Configure package.json:

    • "type": "module" - Enables ES6 import/export syntax (required for modern JavaScript)

    • "main": "sol-transfer-monitor.js" - Specifies the entry point of your application

    • "scripts" - Defines shortcuts like

    hashtag
    Project Structure

    1. Create the following files to have a basic structure for your project:

    1. Create a .gitignore file:

    hashtag
    Step 3: Start Building Your Monitor

    circle-info

    You'll build everything in a single file called sol-transfer-monitor.js.

    hashtag
    Import Dependencies

    What this does:

    • Client - The main class for establishing a connection to GetBlock's Yellowstone gRPC service

    • CommitmentLevel- Configuration options that determine how finalized transactions should be before you receive them (PROCESSED = fastest but can be rolled back, CONFIRMED = balanced, FINALIZED = slowest but guaranteed)

    • bs58

    hashtag
    Add Your GetBlock Configuration

    What this does: Stores your GetBlock credentials for authenticating your connection.

    circle-exclamation

    If you chose a different region during setup, use that base URL instead (e.g., https://go.getblock.us or https://go.getblock.asia).

    hashtag
    Add Solana System Program Constants

    What this does:

    • SYSTEM_PROGRAM - This is the unique identifier for Solana's built-in System Program, which is responsible for all native SOL transfers on the network. Every time someone sends SOL from one wallet to another, this program processes it.

    • MIN_TRANSFER_AMOUNT - Sets the threshold for what qualifies as a "high-value" transfer. Only transfers of 100 SOL or more will trigger an alert. You can adjust this to any amount (e.g., 50 SOL, 1000 SOL, etc.).

    hashtag
    Add Statistics Tracker

    What this does:

    • Creates an object to track key metrics about the transfers you're monitoring. It records:

      • When the monitor started

      • How many high-value transfers have been detected

    hashtag
    Step 4: Build Utility Functions

    Now you'll add helper functions to format data and display results.

    hashtag
    Add SOL Formatter

    What this does:

    • Converts lamports (Solana's smallest unit) to SOL for human-readable display. Solana stores all amounts in lamports, where 1 SOL equals 1 billion lamports (similar to how 1 Bitcoin = 100 million satoshis). This function divides by 1 billion and rounds to 4 decimal places, so 5,500,000,000 lamports becomes "5.5000 SOL".

    hashtag
    Add Display Function

    What this does:

    • Formats and displays all transfer information clearly. It first updates your running statistics (incrementing the transfer count, adding to total volume, and checking if this is the largest transfer seen).

    • Then it converts the amount from lamports to SOL and prints out all the details, including sender, recipient, transaction signature, and slot number.

    • Finally, it includes clickable Solscan explorer links so you can investigate the transaction, sender, and recipient in more detail.

    hashtag
    Step 5: Build the Transfer Parser

    Now you'll create the function that extracts transfer details from instruction data.

    hashtag
    Add Transfer Instruction Parser

    What this does:

    • Extracts the transfer amount and account addresses from a System Program instruction.

    circle-check

    If anything goes wrong during parsing (malformed data, missing accounts, etc.), it catches the error and returns null.

    hashtag
    Step 6: Build the Main Monitor Function

    Now you'll create the core function that connects to GetBlock and processes blockchain data.

    hashtag
    Part A: Start the Function and Connect

    What this does:

    • Initializes the monitor by displaying startup information and establishing a connection to GetBlock.

    • Creates a new Client instance using your endpoint and token, then opens a bidirectional streaming connection.

    • The subscribe() method returns a stream object that handles both sending requests to GetBlock and receiving blockchain data.

    hashtag
    Part B: Configure Subscription

    What this does:

    • Builds the subscription request that tells GetBlock exactly what blockchain data you want to receive.

      • It filters sol_transfers

      • Send transactions that interact with the system

    hashtag
    Part C: Handle Incoming Data

    What this does:

    • Sets up an event handler that processes every message GetBlock sends through the stream.

    hashtag
    Part D: Process Instructions

    What this does:

    • Loops through each instruction in the transaction to find and process SOL transfers.

    hashtag
    Part E: Handle Stream Events

    What this does:

    • Sets up handlers for stream connection issues.

    • If the stream encounters an error (network problem, authentication issue, etc.), it logs the error message and rejects the Promise, which will trigger the auto-restart logic in the main() function.

    • The "end" and "close" events indicate the stream has been terminated gracefully, so it resolves the Promise normally.

    hashtag
    Part F: Send Subscription Request

    What this does:

    • Send your subscription request to GetBlock to activate the stream.

    • Once the request is sent successfully, it confirms that monitoring is active.

    • The callback function checks if there was an error sending the request - if so, it rejects the Promise; otherwise, it displays a success message. This completes the monitorHighValueTransfers() function.

    hashtag
    Step 7: Add Execution Code

    Finally, add the code to run your monitor and handle shutdown.

    hashtag
    Add Main Execution Function

    What this does:

    • Wraps your monitor in an auto-restart loop. If the monitor crashes for any reason (network disconnection, API error, unexpected data format), it catches the error, displays an error message, waits 5 seconds, and then automatically restarts the monitor. This ensures your monitor keeps running even if temporary issues occur.

    hashtag
    Add Shutdown Handler

    What this does:

    • Handles shutdown when you press Ctrl+C or cmd+C. Instead of abruptly terminating, it displays a summary of your monitoring session, including total transfers detected, cumulative volume, the largest transfer amount with a link to view it, and how long the monitor was running. Then it cleanly exits the process.

    hashtag
    Start the Monitor

    What this does:

    • Run everything. This is the last line of your sol-transfer-monitor.js file and triggers the execution of your monitor.

    hashtag
    TestStep 8: Tets Your Monitor

    1. Start the Monitor

    1. Expected Output:

    hashtag
    Troubleshooting

    1. Permission denied:

    This means that your access token is missing or incomplete, or you are using the wrong Base URL.

    2. No Transfers Showing

    • High-value transfers (100+ SOL) are less common than you might expect

    • Try lowering MIN_TRANSFER_AMOUNT to 10 or 50 SOL to see more activity

    • Use CommitmentLevel.PROCESSED for faster updates (though some may be rolled back)

    hashtag
    Conclusion

    In this guide, you've learnt how to build a monitor app that tracks high-value SOL transactions on Solana networks. It shows you the steps involved, such as:

    • Connects to GetBlock's Yellowstone gRPC service

    • Streams blockchain data with ~400ms latency

    • Filters for System Program transactions

    hashtag
    Additional Resources

    How to Monitor Liquidity Pools on Solana DEXes with GetBlock's Yellowstone gRPC

    Step-by-step guide for building a Node.js app to track real-time swaps on Solana using GetBlock's Yellowstone gRPC

    Monitoring liquidity pools on Solana decentralised exchanges (DEXes) in real-time is crucial for traders and developers who want to stay updated with the latest market conditions and make informed decisions.

    GetBlock's Yellowstone gRPC service allows developers to fetch data directly from Solana validators easily with low latency - appropriately ~400ms latency.

    In this guide, you'll build a monitor that tracks every swap happening on a specific Solana DEX liquidity pool, regardless of which platform (Jupiter, Raydium, Phantom Wallet, etc.) the user is trading with.

    You'll learn how to:

    • Connect to GetBlock's Yellowstone gRPC service for ultra-low latency blockchain data streaming

    • Subscribe to transactions involving specific liquidity pool addresses

    • Filter out failed transactions to show only successful swaps

    • Identify which DEX or aggregator initiated each swap (Jupiter, Raydium, etc.)

    • Display real-time swap alerts with formatted output and explorer links

    • Track comprehensive statistics about trading activity

    hashtag
    Prerequisites

    Before you begin, ensure you have:

    • and npm installed

    • Basic knowledge of JavaScript

    • A

    hashtag
    Technology Stack:

    • Node.js

    • - Official Yellowstone gRPC client

    • - Base58 encoding for Solana addresses

    hashtag
    Step 1: Set Up Your GetBlock’s Yellowstone Endpoint

    hashtag
    Deploy Your Dedicated Solana Node

    First, you need to deploy a dedicated Solana node on GetBlock with the Yellowstone gRPC add-on enabled.

    1. Sign up or log in

    • Go to

    • Create an account or log in to your existing account

    2. Deploy your dedicated node

    • Navigate to your user Dashboard

    • Switch to the "Dedicated nodes" tab

    • Scroll down to "My endpoints"

    3. Enable the Yellowstone gRPC add-on

    In Step 3 of your node setup (Select API and Add-ons):

    • Check the box for Yellowstone gRPC under Add-ons

    • Complete payout and finalize the setup

    hashtag
    Generate a Yellowstone gRPC Access Token

    Once your node is live, you'll create an access token to authenticate your gRPC connections.

    1. Return to your dashboard

    • Under your dedicated node dashboard, click on "My endpoints".

    • Select Yellowstone gRPC

    • Click on Add to generate an access token

    2. Your endpoint URL

    You'll receive an HTTPS-style gRPC endpoint URL based on your chosen region:

    circle-exclamation

    Ensure you securely store both the base endpoint and the access token. You'll need them in your code to authenticate with GetBlock's Yellowstone service.

    hashtag
    Step 2: Set up Development Environment

    1. Create a directory for your project

    1. Install Dependencies:

    What these packages do:

    • - Official client for connecting to Yellowstone gRPC services (works with GetBlock)

    • - Encodes binary data to base58 format (Solana's address format). Version 5.0.0 supports vanilla js.

    circle-info

    [email protected] because version 6.x + uses ES modules only, which don't work with vanilla js - require() statements.

    1. Configure Package.json

    • "type": "module" - Enables ES6 import/export syntax

    • "scripts" - Defines shortcuts like npm start

    hashtag
    Project Structure

    Create the following files to have a basic structure for your project:

    hashtag
    Step 3: Start Building Your Monitor

    circle-check

    You'll build everything in a single file called pool-monitor.js. Let's start creating it piece by piece.

    hashtag
    Import Dependencies

    Create a new file pool-monitor.js and add:

    What this does:

    • Client- The main class you'll use to connect to GetBlock's Yellowstone gRPC service and create a streaming connection

    • CommitmentLevel - Solana has different levels of transaction finality (how "confirmed" a transaction is). You'll use this to choose how finalised you want transactions to be before receiving them

    • bs58

    hashtag
    Add Your GetBlock Configuration

    What this does:

    • Stores your GetBlock credentials that you created in Replace YOUR_ACCESS_TOKEN with the actual token you generated. If you chose a different region, use that endpoint instead (e.g., https://go.getblock.us or https://go.getblock.asia).

    hashtag
    Add Pool Configuration

    What this does:

    • TARGET_POOL - The unique address of the liquidity pool you're monitoring. This is the SOL/USDC Concentrated Liquidity pool on Raydium, one of the most active trading pools on Solana, with over 140,000 transactions per day

    • POOL_NAME - A human-readable name for display purposes

    hashtag
    Add DEX Program IDs

    What this does:

    • Stores the unique program IDs for major Solana DEX platforms. These are like addresses for the programs (smart contracts) themselves. When someone makes a swap, their transaction calls one of these programs. By checking which program was called, you can identify if the swap came from:

      • Raydium_AMM - Raydium's standard automated market maker

      • Raydium_CLMM

    hashtag
    Add Statistics Tracker

    What this does:

    • It creates a simple object to track two key pieces of information: when the monitor was started (startTime) and the total number of successful swaps detected (totalSwaps).

    • This allows you to view cumulative statistics when you stop the program.

    hashtag
    Step 4: Build the Swap Source Identifier

    Now you'll add a function to identify which platform initiated each swap.

    What this does:

    • This function examines all the instructions in a transaction to figure out where the swap came from.

    Understanding how this works:

    • Every Solana transaction contains one or more "instructions" - think of these as individual commands or steps

    • Each instruction calls a specific program (smart contract)

    • The programIdIndex points to which program being called

    circle-check

    Why this matters:

    • Users don't always trade directly on Raydium. They might use Jupiter (which finds the best price by checking multiple DEXes) or their wallet's built-in swap feature. This function shows you the actual entry point the user used, which is interesting for understanding trading patterns.

    hashtag
    Step 5: Add Display Function

    What this does:

    • Formats and displays each swap in a readable way to your terminal.

    Break down:

    • stats.totalSwaps++ - Increments the counter every time we display a swap

    • "=".repeat(80) - Creates a visual separator line (80 equal signs)

    • SOURCE - Shows which platform was used (Jupiter, Raydium, etc.)

    circle-check

    Why formatted output matters:

    • Raw blockchain data is hard to read. This function turns binary data and hex strings into useful information that helps you understand what's happening.

    hashtag
    Step 6: Build the Main Monitor Function

    Now you'll create the core function that connects to GetBlock and processes blockchain data.

    circle-exclamation

    This is broken into smaller parts for clarity.

    hashtag
    Part A: Start the Function and Connect

    What this does:

    • Prints a startup message so you know the monitor is launching

    • Creates a Promise so this function can run asynchronously and handle errors properly

    • new Client(ENDPOINT, TOKEN, undefined)- Creates a connection client using your GetBlock credentials.

    circle-check

    Unlike making individual API requests (like asking "what's new?" every few seconds), this creates a persistent stream. GetBlock will push data to you immediately as it happens on the blockchain.

    hashtag
    Part B: Configure Subscription

    What this does:

    • Tells GetBlock exactly what data you want to receive

    hashtag
    Part C: Handle Incoming Data

    What this does:

    • Sets up an event listener that processes each message GetBlock sends you.

    hashtag
    Part D: Process and Display Swaps

    What this does:

    • processes each transaction and:

      • Checks if the transaction failed - txMeta.err will be present if the transaction failed. We skip these because failed swaps aren't useful to track (they might be due to slippage, insufficient balance, etc.)

      • Identifies the source - Calls our identifySwapSource() function to determine if it came from Jupiter, Raydium, or elsewhere

    hashtag
    Part E: Handle Stream Events

    What this does:

    • Handles different connection states such as:

      • error - If something goes wrong with the connection (network issue, GetBlock problem, etc.), we log the error and reject the Promise. This will trigger our auto-reconnect logic later

      • end - The stream ended gracefully (normal shutdown)

    Both end and close resolve the Promise, which allows the program to shut down cleanly or restart if needed.

    hashtag
    Part F: Send Subscription Request

    What this does:

    • Sends your subscription configuration to GetBlock and confirms the connection is active.

    circle-info

    At this stage, your monitor is fully connected, subscribed, and waiting for swaps. Every time someone trades on the SOL/USDC pool through any platform, you'll receive the data within ~400ms and display it.

    hashtag
    Step 7: Add Auto-Restart Functionality

    Add the code to run your monitor with automatic restart on errors:

    What this does:

    • Provides resilience by automatically restarting if something goes wrong.

    circle-check

    This ensures your monitor keeps running even if there's a temporary problem. In production, you'd want to add limits (don't restart forever if there's a permanent issue), but this is great for getting started.

    hashtag
    Step 8: Add Shutdown

    Finally, add the code to handle Ctrl+C successfully:

    hashtag
    Step 9: Test Your Monitor

    1. Run the Monitor

    1. Expected output:

    You'll see:

    What you see:

    • SOURCE- This swap came through Jupiter's aggregator

    • TRADER - The wallet address that made the swap

    • SIGNATURE - Unique transaction ID (click the link to see full details on Solscan)

    The SOL/USDC pool typically has 140,000+ swaps per day, so you should see activity within seconds of starting the monitor.

    hashtag
    Troubleshooting

    1. Connection Issues:

    • Verify your ENDPOINT and TOKEN in pool-monitor.js

    • Check your GetBlock dashboard, confirm the node is active

    • Test your internet connection

    1. No Swaps Showing:

    If you don't see any swaps after a minute:

    • The SOL/USDC pool is extremely active, so this is unusual

    • Try visiting to verify it's active

    • Check that your subscription was successful (you should see "✅ Subscription active")

    1. Processing Errors:

    • These are normal. Occasionally, some transactions have non-standard formats

    • Your monitor will skip these and continue running

    • Failed transactions are automatically filtered out

    hashtag
    Conclusion

    In this guide, you've learn how to build a monitor that fetches liquidity pools on Solana DEXes with GetBlock's Yellowstone gRPC. This guide exposes you to the importance of using GetBlock's Yellowstone gRPC and how to set up the project effectively.

    hashtag
    Resources:

    # create project folder
    mkdir basic-ethereum-mcp
    # navigate through the folder
    cd basic-ethereum-mcp
    # initialise npm
    npm init -y
    npm install @modelcontextprotocol/sdk zod ethers
    {
      "name": "basic-ethereum-mcp",
      "version": "1.0.0",
      "type": "module",
      "description": "MCP server with GetBlock API integration",
      "main": "server.js",
      "bin": {
        "mcp-ethereum": "./server.js"
      },
      "scripts": {
        "start": "node server.js"
      },
      "keywords": ["mcp", "blockchain", "ethereum", "getblock"],
      "author": "Your Name",
      "license": "MIT",
      "dependencies": {
        "@modelcontextprotocol/sdk": "^1.22.0",
        "ethers": "^6.15.0",
        "zod": "^3.25.76"
      }
    }
    ├── server.js            // Main application
    └── .env                // Environment variables
    └── .gitignore          // Git ignore file
    import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
    import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
    import { ethers } from "ethers";
    import { z } from "zod";
    
    // Validate environment
    const GETBLOCK_TOKEN = process.env.GETBLOCK_TOKEN;
    
    // Initialise Ethers provider with GetBlock
    const provider = new ethers.JsonRpcProvider(
      `https://go.getblock.us/${GETBLOCK_TOKEN}/`
    );
    // Create MCP server with modern API
    const server = new McpServer({
      name: "ethereum-mcp-server",
      version: "1.0.0",
    });
    
    console.error("✅ Ethereum MCP Server initialized");
    server.tool(
      "get_eth_balance",
      {
        address: z
          .string()
          .regex(/^0x[a-fA-F0-9]{40}$/)
          .describe("Ethereum address (0x followed by 40 hex characters)"),
      },
      async ({ address }) => {
        try {
          // Fetch balance from blockchain
          const balanceWei = await provider.getBalance(address);
    
          // Convert Wei to ETH
          const balanceEth = ethers.formatEther(balanceWei);
    
          // Return structured response
          return {
            content: [
              {
                type: "text",
                text: JSON.stringify(
                  {
                    address: address,
                    balance: balanceEth,
                    unit: "ETH",
                    balanceWei: balanceWei.toString(),
                  },
                  null,
                  2
                ),
              },
            ],
          };
        } catch (error) {
          return {
            content: [
              {
                type: "text",
                text: JSON.stringify({
                  error: error.message,
                  address: address,
                }),
              },
            ],
            isError: true,
          };
        }
      }
    );
    server.tool("get_gas_price", {}, async () => {
      try {
        // Fetch current fee data
        const feeData = await provider.getFeeData();
    
        // Convert to Gwei
        const gasPriceGwei = ethers.formatUnits(feeData.gasPrice, "gwei");
    
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(
                {
                  gasPrice: gasPriceGwei,
                  unit: "Gwei",
                  gasPriceWei: feeData.gasPrice.toString(),
                  maxFeePerGas: feeData.maxFeePerGas
                    ? ethers.formatUnits(feeData.maxFeePerGas, "gwei")
                    : null,
                  maxPriorityFeePerGas: feeData.maxPriorityFeePerGas
                    ? ethers.formatUnits(feeData.maxPriorityFeePerGas, "gwei")
                    : null,
                },
                null,
                2
              ),
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify({ error: error.message }),
            },
          ],
          isError: true,
        };
      }
    });
    server.tool("get_block_number", {}, async () => {
      try {
        // Fetch latest block number
        const blockNumber = await provider.getBlockNumber();
    
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(
                {
                  blockNumber: blockNumber,
                  timestamp: new Date().toISOString(),
                  network: "Ethereum Mainnet",
                },
                null,
                2
              ),
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify({ error: error.message }),
            },
          ],
          isError: true,
        };
      }
    });
    async function main() {
      try {
        // Create stdio transport for Claude Desktop
        const transport = new StdioServerTransport();
    
        // Connect server to transport
        await server.connect(transport);
    
        console.error("🚀 Ethereum MCP Server is running!");
        console.error("📡 Connected via stdio transport");
        console.error("⏳ Waiting for tool calls...");
      } catch (error) {
        console.error("❌ Failed to start server:", error);
        process.exit(1);
      }
    }
    // Handle graceful shutdown
    process.on("SIGINT", () => {
      console.error("\n👋 Shutting down...");
      process.exit(0);
    });
    
    // Start the server
    main().catch((error) => {
      console.error("💥 Fatal error:", error);
      process.exit(1);
    });
    ~/Library/Application Support/Claude/claude_desktop_config.json
    code ~/Library/Application\ Support/Claude/claude_desktop_config.json
    {
      "mcpServers": {
        "ethereum": {
          "command": "node",
          "args": [
            "/Users/YOUR_USERNAME/basic-ethereum-mcp/server.js"
          ],
          "env": {
            "GETBLOCK_TOKEN": "your-actual-getblock-token-here"
          }
        }
      }
    }
    %APPDATA%\Claude\claude_desktop_config.json
    {
      "mcpServers": {
        "ethereum": {
          "command": "node",
          "args": [
            "C:\\Users\\YOUR_USERNAME\\basic-ethereum-mcp/\\server.js"
          ],
          "env": {
            "GETBLOCK_TOKEN": "your-actual-getblock-token-here"
          }
        }
      }
    }
    What's the ETH balance of 0xd1af2dac4e0a9d1f58b99e2f42bc0320ed74a7cd?
    What's the current Ethereum gas price?
    What's the latest Ethereum block number?
    Check the balance for 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 
    and tell me if the current gas price is high or low
    Is now a good time to send an Ethereum transaction?
    https://go.getblock.us/7hys368hus...
    https://go.getblock.asia/f782e8ec54....
    https://go.getblock.io/d4067b3cc......
    https://go.getblock.us/{YOUR-ACCESS-TOKEN}/
    GETBLOCK_TOKEN=your_token
    ~/.config/Claude/claude_desktop_config.json
    {
      "mcpServers": {
        "ethereum": {
          "command": "node",
          "args": [
            "/home/YOUR_USERNAME/basic-ethereum-mcp//server.js"
          ],
          "env": {
            "GETBLOCK_TOKEN": "your-actual-getblock-token-here"
          }
        }
      }
    }

    No Infrastructure Needed: GetBlock manages validators, updates, and monitoring across global data centers (Europe, USA, Asia)

  • Simple Integration: Standard HTTPS endpoint with token authentication, works with existing gRPC client libraries.

  • Parses instruction data to extract token metadata
  • Extracts account addresses (mint, creator, bonding curve)

  • Displays formatted output with Solscan explorer links

  • Tracks statistics and auto-reconnects on errors

  • A Dedicated Solana Node subscription on GetBlock - Required for Yellowstone gRPC access
    GetBlock’s Dedicated Solana Node with Yellowstone add-on
    Under "Protocol", select Solana
  • Set the network to Mainnet

  • Click Get

  • Token symbol (e.g., "SDOGE")

  • Metadata URI (link to token image and details)

  • accounts[7] - The creator's wallet address

    2-5 second delays, constant API requests, high resource usage

    1-3 second delays, server pushes updates when available

    ~400ms latency, bidirectional streaming, direct validator connection

    Node.js arrow-up-right
    GetBlock’s accountarrow-up-right
    @triton-one/yellowstone-grpcarrow-up-right
    bs58arrow-up-right
    GetBlockarrow-up-right
    @triton-one/yellowstone-grpcarrow-up-right
    [email protected] arrow-up-right
    pump.funarrow-up-right
    GetBlock Dashboardarrow-up-right
    GetBlock Yellowstone gRPC API
    Yellowstone gRPC GitHubarrow-up-right
    GetBlock's Dedicated Solana Node with Yellowstone add-on
    A Dedicated Solana Node subscription on GetBlock - Required for Yellowstone gRPC access
    Under "Protocol", select Solana
  • Set the network to Mainnet

  • Click Get

  • You'll use these in your code to authenticate with GetBlock's Yellowstone service.

    npm start
    - A library that converts Solana's binary address format into the human-readable base58 strings you see on blockchain explorers (like "9wFFyRfZBsuAha4YcuxcXLKwMxJR...")
  • config: This loads the .env file

  • the cumulative volume of all transfers
  • information about the largest transfer seen so far.

  • Only receive transactions that are CONFIRMED
    Parses SOL transfer amounts and addresses
  • Filters by minimum transfer threshold

  • Displays formatted results with links

  • Tracks cumulative statistics

  • Handles errors and auto-reconnects

  • @triton-one/yellowstone-grpcarrow-up-right
    bs58arrow-up-right
    SOL Transfer Monitor Repoarrow-up-right
    GetBlock Solana RPC Nodearrow-up-right
    GetBlock Yellowstone gRPC
    A Dedicated Solana Node subscription on GetBlock - Required for Yellowstone gRPC access
    GetBlock’s Dedicated Solana Node with Yellowstone gRPC add-on
    Under "Protocol", select Solana
  • Set the network to Mainnet

  • Click Get

  • - A library that converts Solana's binary address data (which is just bytes) into the readable base58 format you see on block explorers (like 8sLbNZ...)
  • config() - To load the .env variables.

  • - Raydium's concentrated liquidity pools (like Uniswap V3)
  • JUPITER_V6 - Jupiter's DEX aggregator (finds best prices across multiple DEXes)

  • We look up that program's address using accountKeys[programIdx] and convert it from binary to a readable format using bs58.encode()
  • Then we check if it matches any of our known DEX programs (Jupiter, Raydium CLMM, or Raydium AMM)

  • If none match, you label it as "Other" (could be another DEX or aggregator like Orca, Phantom Swap, etc.)

  • TRADER - The Solana wallet address that initiated the swap

  • SIGNATURE - A unique identifier for this transaction (like a transaction hash)

  • SLOT - Solana's equivalent of a block number - tells you exactly when this happened on the blockchain

  • TIME - The local time when you received this swap notification

  • EXPLORE section - Provides clickable links to:

    • View the full transaction details on Solscan (a Solana block explorer)

    • View the pool itself and all its activity

  • await client.subscribe() - Opens a bidirectional streaming connection to GetBlock's Yellowstone service. This is the "pipe" through which blockchain data will flow to your application

    Gets the trader - In Solana, the first account in accountKeys is always the signer (the person who initiated the transaction). We convert it from binary to a readable format

  • Display severything - Calls our displaySwap() function with all the collected information

  • close - The connection closed (either normally or due to an error)

  • SLOT - Happened at blockchain slot 376,205,017

  • TIME- Your local time when you received this notification

  • Try CommitmentLevel.PROCESSED for faster updates
    Node.js arrow-up-right
    GetBlock’s accountarrow-up-right
    @triton-one/yellowstone-grpcarrow-up-right
    bs58arrow-up-right
    GetBlockarrow-up-right
    @triton-one/yellowstone-grpcarrow-up-right
    [email protected] arrow-up-right
    Step 1.
    the pool on Solscanarrow-up-right
    Pool monitor repoarrow-up-right
    GetBlock Yellowstone gRPC
    https://go.getblock.io/YOUR_ACCESS_TOKEN/
    https://go.getblock.us/YOUR_ACCESS_TOKEN/
    https://go.getblock.asia/YOUR_ACCESS_TOKEN/
    mkdir pumpfun-monitor
    cd pumpfun-monitor
    npm init-y
    npm install @triton-one/yellowstone-grpc [email protected]
    ├── pumpfun-monitor.js          // Main apllication
    └── .env                // Environment variables
    └── .gitignore          // Git ignore file
    const Client = require("@triton-one/yellowstone-grpc").default;
    const { CommitmentLevel } = require("@triton-one/yellowstone-grpc");
    const bs58 = require("bs58");
    // GetBlock Configuration
    const ENDPOINT = "https://go.getblock.io";  // Your region's endpoint
    const TOKEN = "YOUR_ACCESS_TOKEN";           // Your generated token
    // Pump.fun Program Constants
    const PUMPFUN_PROGRAM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";
    const CREATE_DISCRIMINATOR = Buffer.from([24, 30, 200, 40, 5, 28, 7, 119]);
    // Statistics Tracking
    let stats = {
      startTime: Date.now(),
      totalMints: 0,
      lastMintTime: null
    };
    What this does: 
    function decodeString(buffer, offset) {
      const length = buffer.readUInt32LE(offset);
      const str = buffer.slice(offset + 4, offset + 4 + length).toString('utf8');
      return { value: str, bytesRead: 4 + length };
    }
    function parseCreateInstruction(data) {
      try {
        let offset = 8; // Skip the discriminator
        
        const name = decodeString(data, offset);
        offset += name.bytesRead;
        
        const symbol = decodeString(data, offset);
        offset += symbol.bytesRead;
        
        const uri = decodeString(data, offset);
        
        return {
          name: name.value,
          symbol: symbol.value,
          uri: uri.value
        };
      } catch (error) {
        return null;
      }
    }
    
    function extractAccounts(transaction, instructionIndex) {
      try {
        const message = transaction.transaction.message;
        const instruction = message.instructions[instructionIndex];
        const accountKeys = message.accountKeys;
        
        const accountIndices = Array.from(instruction.accounts);
        const accounts = accountIndices.map(idx => {
          const accountKey = accountKeys[idx];
          return bs58.encode(Buffer.from(accountKey));
        });
        
        return {
          mint: accounts[0],
          bondingCurve: accounts[2],
          creator: accounts[7]
        };
      } catch (error) {
        return null;
      }
    }
    function isCreateInstruction(instruction, accountKeys) {
      const programIdx = instruction.programIdIndex;
      const programId = bs58.encode(accountKeys[programIdx]);
      
      if (programId !== PUMPFUN_PROGRAM) return false;
      
      const data = Buffer.from(instruction.data);
      return data.slice(0, 8).equals(CREATE_DISCRIMINATOR);
    }
    function displayTokenMint(tokenData, signature, slot) {
      stats.totalMints++;
      stats.lastMintTime = new Date();
      
      console.log("\n" + "=".repeat(80));
      console.log(`🎉 NEW PUMP.FUN TOKEN MINT #${stats.totalMints}`);
      console.log("=".repeat(80));
      
      console.log(`\n📛 NAME:        ${tokenData.name}`);
      console.log(`🏷️  SYMBOL:      $${tokenData.symbol}`);
      console.log(`\n🪙 MINT:        ${tokenData.mint}`);
      console.log(`👤 CREATOR:     ${tokenData.creator}`);
      console.log(`📊 BONDING:     ${tokenData.bondingCurve}`);
      console.log(`\n🔗 METADATA:    ${tokenData.uri}`);
      console.log(`📜 SIGNATURE:   ${signature}`);
      console.log(`🎰 SLOT:        ${slot}`);
      
      console.log(`\n🔍 EXPLORE:`);
      console.log(`   Token:   https://solscan.io/token/${tokenData.mint}`);
      console.log(`   TX:      https://solscan.io/tx/${signature}`);
      console.log(`   Creator: https://solscan.io/account/${tokenData.creator}`);
      
      console.log("\n" + "=".repeat(80) + "\n");
    }
    async function monitorPumpfunMints() {
      console.log("🚀 Starting Pump.fun Token Mint Monitor");
      console.log(`🎯 Watching program: ${PUMPFUN_PROGRAM}\n`);
      console.log("Waiting for new token mints...\n");
      
      return new Promise(async (resolve, reject) => {
        try {
          const client = new Client(ENDPOINT, TOKEN, undefined);
          const stream = await client.subscribe();
     const request = {
            accounts: {},
            slots: {},
            transactions: {
              pumpfun: {
                accountInclude: [PUMPFUN_PROGRAM],
                accountExclude: [],
                accountRequired: []
              }
            },
            transactionsStatus: {},
            entry: {},
            blocks: {},
            blocksMeta: {},
            commitment: CommitmentLevel.CONFIRMED,
            accountsDataSlice: [],
            ping: undefined
          };
    
    stream.on("data", (message) => {
          try {
            if (message.pong) {
              stream.write({ ping: { id: message.pong.id } });
              return;
            }
            
            if (message.transaction && message.filters && 
                message.filters.includes('pumpfun')) {
              
              const tx = message.transaction.transaction;
              const signature = bs58.encode(tx.signature);
              const slot = message.transaction.slot.toString();
              
              const txMessage = tx.transaction.message;
              const accountKeys = txMessage.accountKeys;
              const instructions = txMessage.instructions;
    for (let i = 0; i < instructions.length; i++) {
                  const instruction = instructions[i];
                  
                  if (isCreateInstruction(instruction, accountKeys)) {
                    const instructionData = Buffer.from(instruction.data);
                    const tokenMetadata = parseCreateInstruction(instructionData);
                    
                    if (!tokenMetadata) continue;
                    
                    const accounts = extractAccounts(
                      { transaction: { message: txMessage } },
                      i
                    );
                    
                    if (!accounts) continue;
                    
                    displayTokenMint(
                      { ...tokenMetadata, ...accounts },
                      signature,
                      slot
                    );
                  }
                }
              }
            } catch (error) {
              console.error(`Error: ${error.message}`);
            }
          });
    
        stream.on("error", (error) => {
            console.error(`Stream error: ${error.message}`);
            reject(error);
          });
          
          stream.on("end", () => resolve());
          stream.on("close", () => resolve());
    stream.write(request, (err) => {
            if (err) {
              reject(err);
            } else {
              console.log("✅ Subscription active - monitoring blockchain...\n");
            }
          });
          
        } catch (error) {
          reject(error);
        }
      });
    }
    
    async function main() {
      try {
        await monitorPumpfunMints();
      } catch (error) {
        console.error("Monitor crashed:", error.message);
        console.log("Restarting in 5 seconds...");
        setTimeout(main, 5000);
      }
    }
    process.on('SIGINT', () => {
      console.log("\n\n🛑 Shutting down...");
      console.log(`\nTotal mints detected: ${stats.totalMints}`);
      const uptime = Math.floor((Date.now() - stats.startTime) / 1000);
      console.log(`Uptime: ${Math.floor(uptime / 60)}m ${uptime % 60}s\n`);
      process.exit(0);
    });
    
    main();
    node pumpfun-monitor.js
    🚀 Starting Pump.fun Token Mint Monitor
    🎯 Watching program: 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P
    Waiting for new token mints...
    ✅ Subscription active - monitoring blockchain...
    ================================================================================
    🎉 NEW PUMP.FUN TOKEN MINT #1
    ================================================================================
    
    📛 NAME:        Super Doge
    🏷️  SYMBOL:      $SDOGE
    
    🪙 MINT:        7xKXtG5CJYAuGZ3w8bXRGLynAmj4twABC123def456
    👤 CREATOR:     9wFFyRfZBsuAha4YcuxcXLKwMxJR43S7fPfQLusDBzvT
    📊 BONDING:     HMU77nPMBMZ9Wf9TpvvJtFHkjNLkNeGZ8xzBvakKpump
    
    🔗 METADATA:    https://ipfs.io/ipfs/QmYJZ9HGVgYiRGkF...
    📜 SIGNATURE:   5TYqzsc8kGY7vMGDZxEbBFWGnEUPTQQMpk9k...
    🎰 SLOT:        376205017
    
    🔍 EXPLORE:
       Token:   https://solscan.io/token/7xKXtG5...
       TX:      https://solscan.io/tx/5TYqzsc8kGY7v...
       Creator: https://solscan.io/account/9wFFyRfZ...
    
    ================================================================================
    
    Connection refused
    Failed to extract accounts
    GETBLOCK_TOKEN=your_token node pumpfun-monitor.js
    //use dotenv
    const TOKEN = process.env.GETBLOCK_TOKEN;
    https://go.getblock.asia/YOUR_ACCESS_TOKEN/
    https://go.getblock.us/YOUR_ACCESS_TOKEN/
    https://go.getblock.io/YOUR_ACCESS_TOKEN/
    mkdir sol-transfer-monitor
    cd sol-transfer-monitor
    npm init -y
    npm install @triton-one/yellowstone-grpc [email protected] dotenv
    touch sol-transfer-monitor.js
    {
      "name": "sol-transfer-monitor",
      "version": "1.0.0",
      "description": "A Listener that tracks high-value SOL transactions",
      "main": "sol-transfer-monitor.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start": "node sol-transfer-monitor.js"
      },
      "keywords": [
        "Solana",
        "Liquidity Monitor",
        "Onchain transfer"
      ],
      "author": "",
      "license": "ISC",
      "type": "module",
      "dependencies": {
        "@triton-one/yellowstone-grpc": "^4.0.2",
        "bs58": "^5.0.0",
        "dotenv": "^17.2.3"
      }
    }
    
    pumpfun-migrations-listener/
    ├── sol-transfer-monitor.js          # Main application logic
    ├── .env              # Environment variables (add to .gitignore)
    ├── .gitignore        # Git ignore file
    └── package.json      # Project configuration
    node_modules/
    .env
    *.log
    import Client from "@triton-one/yellowstone-grpc";
    import { CommitmentLevel } from "@triton-one/yellowstone-grpc";
    import bs58 from "bs58";
    import { config } from "dotenv";
    config();
    
    const ENDPOINT = "https://go.getblock.io";  // Your region's endpoint
    const TOKEN = process.env.GETBLOCK_TOKEN;           // Your generated token
    // System Program (handles all native SOL transfers)
    const SYSTEM_PROGRAM = "11111111111111111111111111111111";
    
    // Minimum transfer amount in SOL to alert on
    const MIN_TRANSFER_AMOUNT = 100; // 100 SOL threshold
    // Statistics Tracking
    let stats = {
      startTime: Date.now(),
      totalTransfers: 0,
      totalVolume: 0,
      largestTransfer: 0,
      largestTransferTx: null
    };
    function formatSOL(lamports) {
      return (lamports / 1_000_000_000).toFixed(4);
    }
    function displayTransfer(transferData) {
      stats.totalTransfers++;
      stats.totalVolume += transferData.amount;
      
      if (transferData.amount > stats.largestTransfer) {
        stats.largestTransfer = transferData.amount;
        stats.largestTransferTx = transferData.signature;
      }
      
      const solAmount = formatSOL(transferData.amount);
      
      console.log("\n" + "=".repeat(80));
      console.log(`HIGH VALUE TRANSFER #${stats.totalTransfers}`);
      console.log("=".repeat(80));
      
      console.log(`\nAMOUNT:      ${solAmount} SOL`);
      console.log(`FROM:        ${transferData.from}`);
      console.log(`TO:          ${transferData.to}`);
      console.log(`SIGNATURE:   ${transferData.signature}`);
      console.log(`SLOT:        ${transferData.slot}`);
      
      console.log(`\nEXPLORE:`);
      console.log(`   TX:     https://solscan.io/tx/${transferData.signature}`);
      console.log(`   From:   https://solscan.io/account/${transferData.from}`);
      console.log(`   To:     https://solscan.io/account/${transferData.to}`);
      
      console.log("\n" + "=".repeat(80) + "\n");
    }
    function parseTransferInstruction(instruction, accountKeys) {
      try {
        const data = Buffer.from(instruction.data);
        
        // System program transfer instruction has type 2
        // Data format: [4 bytes: instruction type (2)][8 bytes: lamports amount]
        if (data.length < 12) return null;
        
        const instructionType = data.readUInt32LE(0);
        if (instructionType !== 2) return null; // Not a transfer instruction
        
        const lamports = data.readBigUInt64LE(4);
        
        // Get from and to accounts
        const accountIndices = Array.from(instruction.accounts);
        if (accountIndices.length < 2) return null;
        
        const fromAccount = bs58.encode(Buffer.from(accountKeys[accountIndices[0]]));
        const toAccount = bs58.encode(Buffer.from(accountKeys[accountIndices[1]]));
        
        return {
          amount: Number(lamports),
          from: fromAccount,
          to: toAccount
        };
      } catch (error) {
        return null;
      }
    }
    async function monitorHighValueTransfers() {
      console.log("Starting High Value SOL Transfer Monitor");
      console.log(`Minimum amount: ${MIN_TRANSFER_AMOUNT} SOL`);
      console.log(`Watching: Native SOL transfers\n`);
      console.log("Waiting for high value transfers...\n");
      
      return new Promise(async (resolve, reject) => {
        try {
          const client = new Client(ENDPOINT, TOKEN, undefined);
          const stream = await client.subscribe();
     const request = {
            accounts: {},
            slots: {},
            transactions: {
              sol_transfers: {
                accountInclude: [SYSTEM_PROGRAM],
                accountExclude: [],
                accountRequired: []
              }
            },
            transactionsStatus: {},
            entry: {},
            blocks: {},
            blocksMeta: {},
            commitment: CommitmentLevel.CONFIRMED,
            accountsDataSlice: [],
            ping: undefined
          };
    
    stream.on("data", (message) => {
        try {
          if (message.pong) {
            stream.write({ ping: { id: message.pong.id } });
            return;
          }
          
          if (message.transaction && message.filters && 
              message.filters.includes('sol_transfers')) {
            
            const tx = message.transaction.transaction;
            const signature = bs58.encode(tx.signature);
            const slot = message.transaction.slot.toString();
            
            const txMessage = tx.transaction.message;
            const accountKeys = txMessage.accountKeys;
            const instructions = txMessage.instructions;
    
    // Process each instruction
        for (const instruction of instructions) {
          const programIdx = instruction.programIdIndex;
          const programId = bs58.encode(accountKeys[programIdx]);
          
          // Only process System Program instructions
          if (programId !== SYSTEM_PROGRAM) continue;
          
          const transferData = parseTransferInstruction(instruction, accountKeys);
          
          if (!transferData) continue;
          
          // Check if transfer meets minimum threshold
          const solAmount = transferData.amount / 1_000_000_000;
          if (solAmount >= MIN_TRANSFER_AMOUNT) {
            displayTransfer({
              ...transferData,
              signature: signature,
              slot: slot
            });
          }
        }
      }
    } catch (error) {
      console.error(`Error processing transaction: ${error.message}`);
    }
    });
    
    stream.on("error", (error) => {
            console.error(`Stream error: ${error.message}`);
            reject(error);
          });
          
          stream.on("end", () => resolve());
          stream.on("close", () => resolve());
    
    stream.write(request, (err) => {
            if (err) {
              reject(err);
            } else {
              console.log("Subscription active - monitoring blockchain...\n");
            }
          });
          
        } catch (error) {
          reject(error);
        }
      });
    }
    
    async function main() {
      try {
        await monitorHighValueTransfers();
      } catch (error) {
        console.error("Monitor crashed:", error.message);
        console.log("Restarting in 5 seconds...");
        setTimeout(main, 5000);
      }
    }
    process.on('SIGINT', () => {
      console.log("\n\nShutting down...");
      console.log(`\nTotal high value transfers: ${stats.totalTransfers}`);
      console.log(`Total volume: ${formatSOL(stats.totalVolume)} SOL`);
      console.log(`Largest transfer: ${formatSOL(stats.largestTransfer)} SOL`);
      if (stats.largestTransferTx) {
        console.log(`Largest TX: https://solscan.io/tx/${stats.largestTransferTx}`);
      }
      const uptime = Math.floor((Date.now() - stats.startTime) / 1000);
      console.log(`Uptime: ${Math.floor(uptime / 60)}m ${uptime % 60}s\n`);
      process.exit(0);
    });
    main();
    npm start
    > [email protected] start
    > node sol-transfer-monitor.js
    
    [[email protected]] injecting env (1) from .env -- tip: ⚙️  load multiple .env files with { path: ['.env.local', '.env'] }
    Starting High Value SOL Transfer Monitor
    Minimum amount: 100 SOL
    Watching: Native SOL transfers
    
    Waiting for high value transfers...
    
    Subscription active - monitoring blockchain...
    
    
    ================================================================================
    HIGH VALUE TRANSFER #1
    ================================================================================
    
    AMOUNT:      1990.0000 SOL
    FROM:        5tzFkiKscXHK5ZXCGbXZxdw7gTjjD1mBwuoFbhUvuAi9
    TO:          53AXjkQHZQEbHZvV55VHtcZtFzBzArLZZG5AF4ufkRhv
    SIGNATURE:   4uJgnfRohiq6c9CDWUtk3w94ouYGya5dGkx4LSS5tuFGDRypuXtN7cQLLy3eNj5V1b5PwEWccJqLak1Rnd9kRtTB
    SLOT:        382899112
    
    EXPLORE:
       TX:     https://solscan.io/tx/4uJgnfRohiq6c9CDWUtk3w94ouYGya5dGkx4LSS5tuFGDRypuXtN7cQLLy3eNj5V1b5PwEWccJqLak1Rnd9kRtTB
       From:   https://solscan.io/account/5tzFkiKscXHK5ZXCGbXZxdw7gTjjD1mBwuoFbhUvuAi9
       To:     https://solscan.io/account/53AXjkQHZQEbHZvV55VHtcZtFzBzArLZZG5AF4ufkRhv
    
    ================================================================================
    
    ^C
    
    Shutting down...
    
    Total high value transfers: 7
    Total volume: 5519.0244 SOL
    Largest transfer: 2272.0770 SOL
    Largest TX: https://solscan.io/tx/3p92tKFb4AGRUJKA87vJD4fYcb3Z9wKi5AuUskA6TAR5SYciZxL3qmSH88ubQP3g7xSJQjC5kEeMSr7Lhhn8Hkc4
    Uptime: 1m 50s
    Stream error: 7 PERMISSION_DENIED: RBAC: access denied
    Monitor crashed: 7 PERMISSION_DENIED: RBAC: access denied
    https://go.getblock.io/YOUR_ACCESS_TOKEN/
    https://go.getblock.us/YOUR_ACCESS_TOKEN/
    https://go.getblock.asia/YOUR_ACCESS_TOKEN/
    mkdir pool-monitor
    cd pool-monitor
    npm init-y
    npm install @triton-one/yellowstone-grpc [email protected]
    {
      "name": "pool-monitor",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start": "node pool-monitor.js"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "type": "module",
      "dependencies": {
        "@triton-one/yellowstone-grpc": "^4.0.2",
        "bs58": "^5.0.0",
        "dotenv": "^17.2.3"
      }
    }
    
    ├── pool-monitor.js.          // Main application
    └── .env                // Environment variables
    └── .gitignore          // Git ignore file
    import Client from "@triton-one/yellowstone-grpc";
    import { CommitmentLevel } from "@triton-one/yellowstone-grpc";
    import bs58 from "bs58";
    import { config } from "dotenv";
    
    // Load environment variables from .env
    config();
    // GetBlock Configuration
    const ENDPOINT = "https://go.getblock.io";  // Your region's endpoint
    const TOKEN = process.env.GETBLOCK_TOKEN; ;           // Your generated token
    // Pool Configuration
    const TARGET_POOL = "8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj"; // SOL/USDC CLMM
    const POOL_NAME = "SOL/USDC";
    // Common Solana DEX Program IDs
    const RAYDIUM_AMM = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8";
    const RAYDIUM_CLMM = "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK";
    const JUPITER_V6 = "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4";
    // Statistics
    let stats = {
      startTime: Date.now(),
      totalSwaps: 0
    };
    function identifySwapSource(instructions, accountKeys) {
      for (const instruction of instructions) {
        const programIdx = instruction.programIdIndex;
        const programId = bs58.encode(accountKeys[programIdx]);
        
        if (programId === JUPITER_V6) {
          return "Jupiter";
        } else if (programId === RAYDIUM_CLMM) {
          return "Raydium CLMM";
        } else if (programId === RAYDIUM_AMM) {
          return "Raydium AMM";
        }
      }
      
      return "Other";
    }
    function displaySwap(swapData) {
      stats.totalSwaps++;
      
      console.log("\n" + "=".repeat(80));
      console.log(`✅ SWAP #${stats.totalSwaps} on ${POOL_NAME}`);
      console.log("=".repeat(80));
      
      console.log(`\n🔀 SOURCE:      ${swapData.source}`);
      console.log(`👤 TRADER:      ${swapData.trader}`);
      console.log(`📜 SIGNATURE:   ${swapData.signature}`);
      console.log(`🎰 SLOT:        ${swapData.slot}`);
      console.log(`⏰ TIME:        ${swapData.time}`);
      
      console.log(`\n🔍 EXPLORE:`);
      console.log(`   TX:   https://solscan.io/tx/${swapData.signature}`);
      console.log(`   Pool: https://solscan.io/account/${TARGET_POOL}`);
      
      console.log("\n" + "=".repeat(80) + "\n");
    }
    async function monitorPoolSwaps() {
      console.log("🚀 Starting Liquidity Pool Swap Monitor");
      console.log(`🎯 Pool: ${POOL_NAME}`);
      console.log(`📍 Address: ${TARGET_POOL}\n`);
      console.log("Waiting for swaps...\n");
      
      return new Promise(async (resolve, reject) => {
        try {
          const client = new Client(ENDPOINT, TOKEN, undefined);
          const stream = await client.subscribe();
    const request = {
            accounts: {},
            slots: {},
            transactions: {
              pool_swaps: {
                accountInclude: [TARGET_POOL],
                accountExclude: [],
                accountRequired: []
              }
            },
            transactionsStatus: {},
            entry: {},
            blocks: {},
            blocksMeta: {},
            commitment: CommitmentLevel.CONFIRMED,
            accountsDataSlice: [],
            ping: undefined
          };
    stream.on("data", (message) => {
    try {
      if (message.pong) {
        stream.write({ ping: { id: message.pong.id } });
        return;
      }
      
      if (message.transaction && message.filters && 
          message.filters.includes('pool_swaps')) {
        
        const tx = message.transaction.transaction;
        const signature = bs58.encode(tx.signature);
        const slot = message.transaction.slot.toString();
        
        const txMessage = tx.transaction.message;
        const accountKeys = txMessage.accountKeys;
        const instructions = txMessage.instructions;
    // Skip failed transactions
        const txMeta = message.transaction.meta;
        if (txMeta && txMeta.err) return;
        
        // Identify swap source
        const source = identifySwapSource(instructions, accountKeys);
        
        // Get trader (signer)
        const trader = accountKeys.length > 0 
          ? bs58.encode(Buffer.from(accountKeys[0])) 
          : "Unknown";
        
        displaySwap({
          source: source,
          trader: trader,
          signature: signature,
          slot: slot,
          time: new Date().toLocaleTimeString()
        });
      }
    } catch (error) {
      console.error(`Error processing transaction: ${error.message}`);
    }
    });
    
    stream.on("error", (error) => {
      console.error(`Stream error: ${error.message}`);
      reject(error);
    });
    
    stream.on("end", () => resolve());
    stream.on("close", () => resolve());
    stream.write(request, (err) => {
            if (err) {
              reject(err);
            } else {
              console.log("✅ Subscription active - monitoring pool swaps...\n");
            }
          });
          
        } catch (error) {
          reject(error);
        }
      });
    }
    async function main() {
      try {
        await monitorPoolSwaps();
      } catch (error) {
        console.error("Monitor crashed:", error.message);
        console.log("Restarting in 5 seconds...");
        setTimeout(main, 5000);
      }
    }
    process.on('SIGINT', () => {
      console.log("\n\n🛑 Shutting down...");
      console.log(`Total swaps detected: ${stats.totalSwaps}\n`);
      process.exit(0);
    });
    
    
    main();
    node pool-monitor.js
    🚀 Starting Liquidity Pool Swap Monitor
    🎯 Pool: SOL/USDC
    📍 Address: 8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj
    
    Waiting for swaps...
    
    ✅ Subscription active - monitoring pool swaps...
    
    This means you're connected to GetBlock and monitoring is active!
    When a Swap Appears
    ================================================================================
    ✅ SWAP #1 on SOL/USDC
    ================================================================================
    🔀 SOURCE:      Jupiter
    👤 TRADER:      9wFFyRfZBsuAha4YcuxcXLKwMxJR43S7fPfQLusDBzvT
    📜 SIGNATURE:   5TYqzsc8kGY7vMGDZxEbBFWGnEUPTQQMpk9kRvx3H8p2
    🎰 SLOT:        376205017
    ⏰ TIME:        14:32:18
    🔍 EXPLORE:
       TX:   https://solscan.io/tx/5TYqzsc8kGY7vMGDZxEbBFWGnEUPTQQMpk9kRvx3H8p2
       Pool: https://solscan.io/account/8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj
    ================================================================================
    "Connection refused"
    Error processing transaction warnings
    Yellowstone gRPC GitHubarrow-up-right
    Pump.fun on Solscanarrow-up-right
    Ethersenvelope

    How to Build Pump.fun to PumpSwap and Raydium Migrations Listener with GetBlock

    A step-by-step guide on how to build a real-time listener for Pump.fun token migrations to both PumpSwap and Raydium using GetBlock API

    Pump.funarrow-up-right is a Solana-based memecoin launchpad that uses a bonding curve mechanismarrow-up-right to initiate token distribution. When a token reaches an approximate market cap of $69,000, it graduates from the bonding curve. At this point, $12,000 of liquidity is deposited to either Raydium DEX arrow-up-rightor PumpSwaparrow-up-right (Pump.fun's native DEX). This migration creates immediate trading opportunities for developers and traders who can detect these events in real-time.

    circle-info

    March 2025, Pump.fun introduced PumpSwaparrow-up-right, her own decentralized exchange. Since then, most tokens have migrated to PumpSwap instead of Raydium. This guide will show you how to track migrations to both destinations.

    hashtag
    How Pump.fun Migrations Work

    Tokens on Pump.fun start trading on a bonding curve mechanism. When the bonding curve reaches completion (approximately $69,000 market cap), the protocol executes a migration.

    hashtag
    Migration Flow:

    1. Bonding Curve Phase: Token trades on Pump.fun using bonding curve pricing

    2. Completion Trigger: Bonding curve reaches ~$69k market cap

    3. Migration Transaction: Pump.fun migration account executes the migration

    hashtag
    Key Addresses

    Program
    Address
    circle-info

    The Pump.fun migration account manages both types of migrations.

    • For PumpSwap migrations, it calls migrate instruction on the Pump.fun program.

    In this guide, you will learn how to:

    • Get a GetBlock Access Token for Solana's API endpoint

    • Build a WebSocket listener that detects Pump.fun migrations to both PumpSwap and Raydium

    • Process transaction logs to extract token and pool information

    hashtag
    Prerequisites

    • Basic understanding of JavaScript

    • A GetBlock

    • Node.js installed (v18 or higher)

    hashtag
    Technology Stack

    • Node.js: JavaScript runtime environment for building server applications

    • Official Solana JavaScript SDK for blockchain interactions

    • : WebSocket client library for real-time connections

    hashtag
    Step 1: Project Initialization

    1. Set up your project directory using this command:

    1. Install Dependencies:

    1. Configure package.json:

    • "type": "module" - Enables ES6 import/export syntax (required for modern JavaScript)

    • "main": "server.js" - Specifies entry point of your application

    • "scripts" - Defines shortcuts like

    hashtag
    Get GetBlock's API Access Token

    1. Log in to your

    2. On your dashboard, scroll and click on Get Endpoint

    3. Select the Solana Mainnet network

    Your WebSocket endpoint will look like:

    1. Also get the HTTP endpoint for transaction fetching:

      • Return to the dashboard

      • Select JSON-RPC (https://) under API Interface

    Your HTTP endpoint will look like:

    1. Save both endpoints in a .env file in your project root:

    circle-exclamation

    Keep your endpoints safe, as they contain your access token

    hashtag
    Project Structure

    1. Create the following files to have a basic structure for your project:

    1. Create a .gitignore file:

    hashtag
    Step 2: Server File Setup

    circle-check

    Your script will be written inside server.js

    hashtag
    1. Import Dependencies and Configuration

    What this does:

    • Imports necessary libraries for Solana interactions and WebSocket connections

    • Loads API endpoints securely from environment variables

    • Validates that the required configuration is present

    hashtag
    2. Create the Migration Listener Class

    Breaking down the constructor:

    The constructor initializes all the state we need to track. Let me explain each property:

    • this.ws - Will hold our WebSocket connection to GetBlock

    • this.connection - HTTP connection for fetching full transaction details

    • this.subscriptionId - The ID returned when we subscribe to logs

    hashtag
    3. Create an Interval check

    What this does:

    • The start() method kicks everything off. It checks if the Websocket is connected or not.

    • The checkRunning() method creates a timer that runs every 60 seconds (60000 milliseconds). This serves two purposes:

      1. It shows the listener is still running

    circle-check

    Migration isn't frequent and may not occur within an hour. This is good for debugging—if no logs appear, it's a sign there's an issue with the subscription. This ensures that monitoring is active.

    hashtag
    4. Create GetBlock Websocket Connection

    What this does:

    • The connect() method creates a new WebSocket connection to GetBlock. Then it sets up four event listeners:

      • open - Called when the connection is established

      • message

    hashtag
    5. Subscribe to Migration Events

    What this does:

    • Uses Solana's logsSubscribe method to monitor transactions

    • Filters for transactions mentioning the Pump.fun migration account

    • Uses confirmed commitment for faster notifications (1-2 seconds)

    hashtag
    6. Handle Incoming Messages

    What this does:

    • Parses incoming WebSocket messages

    • Handles subscription confirmation and stores subscription ID

    • Processes log notifications for migration detection

    hashtag
    7. Process Transaction Logs

    What this does:

    • Checks transaction logs for migration keywords like:

    • Skips failed transactions

    • Fetches full transaction details when migration is detected

    hashtag
    8. Fetch Full Transaction Details

    What this does:

    • Waits 1 second for the transaction to propagate

    • Fetches complete transaction from Solana via HTTP

    • Extracts and displays migration data

    hashtag
    9. Extract Migration Data

    What this does:

    • Handles both versioned and legacy Solana transactions

    • Detects Raydium migrations by checking for Raydium program ID

    • Detects PumpSwap migrations by checking for Pump.fun program ID

    hashtag
    10. Display Migration Results

    What this does:

    • Displays Raydium migrations with pool and LP mint info

    • Displays PumpSwap migrations with bonding curve info

    • Provides links to Solscan and trading platforms

    hashtag
    11. Handle Reconnections

    What this does:

    • Implements exponential backoff for reconnections (2s, 4s, 8s, etc.)

    • Caps reconnection delay at 30 seconds

    • Exits after 10 failed reconnection attempts

    hashtag
    12. Initialize and Run

    What this does:

    • Handles graceful shutdown on Ctrl+C

    • Catches uncaught errors

    hashtag
    Step 4: Testing Your Listener

    Start your migration listener:

    Expected Output:

    hashtag
    Test 1: Real-time PumpSwap Migration

    When a token migrates to PumpSwap:

    hashtag
    Test 2: Real-time Raydium Migration

    When a token migrates to Raydium (rare):

    hashtag
    Test 3: Check if alive

    Every minute:

    hashtag
    Troubleshooting

    1. Missing access token or Connection error

    This means that:

    • You haven't set up your environment variable as follows in this guide

    • Your Access token is incorrect or incomplete

    2. Only seeing PumpSwap migrations or no migration at all

    This is expected. Since March 2025, most tokens (95%+) have migrated to PumpSwap instead of Raydium. Also, migration doesn't happen frequently.

    1. Not receiving any logs

    Solution:

    • Verify subscription succeeded (you should see ✅ Subscribed with ID)

    • Check GetBlock dashboard for API usage limits

    • Verify transactions exist at

    hashtag
    Conclusion

    In this guide, you've built an app that listens to Pump.fun token migrations to both PumpSwap and Raydium using GetBlock's Solana infrastructure. You learn:

    • How to connect to GetBlock's WebSocket API for real-time blockchain data

    • How to subscribe to specific account activities on Solana

    • How to distinguish between PumpSwap and Raydium migrations

    hashtag
    Additional Resources

    Liquidity Deployment: $12,000 of liquidity is deposited into either:
    • PumpSwap (Pump.fun's DEX) - Most common since March 2025

    • Raydium AMM - Less common, but still happens

    For Raydium migrations, it calls the
    initialize2
    instruction on Raydium's Liquidity Pool V4 program.
    Distinguish between PumpSwap and Raydium migrations
  • Handle reconnections and error scenarios

  • Display migration data in a user-friendly format

  • dotenvarrow-up-right: Environment variable management for secure configuration
    npm start
    Under API Interface, select WebSocket (wss://)
  • Click on Create to get your endpoint

  • Click Create
    Defines the key addresses we'll monitor for migrations
    • MIGRATION_ACCOUNT - This is the Pump.fun account that executes all migrations

    • RAYDIUM_PROGRAM - The Raydium program ID to detect Raydium migrations.

    • PUMPFUN_PROGRAM - The Pump.fun program ID to detect PumpSwap migrations.

  • this.isConnected - Boolean flag to track connection status

  • this.reconnectAttempts - Counter for reconnection attempts (we limit it to 10)

  • this.raydiumMigrationCount & this.pumpswapMigrationCount - Separate counters for each migration type

  • this.migrations - Array to store all detected migrations

  • this.startTime - Timestamp when listener started (for runtime tracking)

  • this.totalLogsReceived - Counter for all logs received (helps with debugging)

  • It provides statistics: runtime, total logs received, and migrations detected by type

  • - Called whenever we receive data
  • error - Called if something goes wrong

  • close - Called when the connection drops

  • When the connection opens, handleOpen() runs. It sets isConnected to true, resets the reconnection counter (since you've successfully connected), and most importantly, subscribes to the logs you need.

  • Extracts relevant addresses (token, pool, LP mint)
    How to extract token addresses and pool information from transactions
  • How to handle versioned Solana transactions

  • How to implement robust reconnection logic

  • Pump.fun Program

    6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P

    Pump.fun Migration Account

    39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg

    Raydium Liquidity Pool V4

    675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8

    accountarrow-up-right
    @solana/web3.js:arrow-up-right
    wsarrow-up-right
    GetBlock accountarrow-up-right
    Solscanarrow-up-right
    Solana Web3.js Documentationarrow-up-right
    Raydium SDKarrow-up-right
    Pump.fun Platformarrow-up-right
    # Create project folder
    mkdir pumpfun-migrations-listener
    cd pumpfun-migrations-listener
    
    # Initialize npm
    npm init -y
    npm install @solana/web3.js ws dotenv
    {
      "name": "pumpfun-migrations-listener",
      "version": "1.0.0",
      "type": "module",
      "description": "Real-time listener for Pump.fun migrations to PumpSwap and Raydium",
      "main": "server.js",
      "scripts": {
        "start": "node server.js"
      },
      "keywords": ["pump.fun", "pumpswap", "raydium", "solana", "getblock"],
      "author": "GetBlock",
      "license": "MIT",
     "dependencies": {
      "@solana/web3.js": "^1.98.4",
      "dotenv": "^17.2.3",
      "ws": "^8.18.3"
    }
    }
    wss://go.getblock.us/<ACCESS_TOKEN>
    https://go.getblock.us/<ACCESS_TOKEN>
    GETBLOCK_WS_ENDPOINT=wss://go.getblock.us/<ACCESS_TOKEN>
    GETBLOCK_HTTP_ENDPOINT=https://go.getblock.us/<ACCESS_TOKEN>
    pumpfun-migrations-listener/
    ├── server.js          # Main application logic
    ├── .env              # Environment variables (add to .gitignore)
    ├── .gitignore        # Git ignore file
    └── package.json      # Project configuration
    node_modules/
    .env
    *.log
    import { Connection, PublicKey } from '@solana/web3.js';
    import WebSocket from 'ws';
    import dotenv from 'dotenv';
    
    // Load environment variables
    dotenv.config();
    
    // Configuration
    const WS_ENDPOINT = process.env.GETBLOCK_WS_ENDPOINT;
    const HTTP_ENDPOINT = process.env.GETBLOCK_HTTP_ENDPOINT;
    const MIGRATION_ACCOUNT = '39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg';
    const RAYDIUM_PROGRAM = '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8';
    const PUMPFUN_PROGRAM = '6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P';
    
    // Validate configuration
    if (!WS_ENDPOINT || !HTTP_ENDPOINT) {
      console.error('❌ Missing required environment variables');
      console.error('Please set GETBLOCK_WS_ENDPOINT and GETBLOCK_HTTP_ENDPOINT in .env file');
      process.exit(1);
    }
    
    console.log('✅ Configuration loaded successfully');
    class PumpFunMigrationListener {
      constructor() {
        this.ws = null;
        this.connection = new Connection(HTTP_ENDPOINT, 'confirmed');
        this.subscriptionId = null;
        this.isConnected = false;
        this.reconnectAttempts = 0;
        this.maxReconnectAttempts = 10;
        this.raydiumMigrationCount = 0;
        this.pumpswapMigrationCount = 0;
        this.migrations = [];
        this.startTime = Date.now();
        this.totalLogsReceived = 0;
      }
      start() {
        console.log('🚀 Starting Pump.fun Migration Listener...');
        console.log('📡 Monitoring account:', MIGRATION_ACCOUNT);
        console.log('🎯 Tracking: Raydium + PumpSwap migrations');
        console.log('');
        this.connect();
        this.checkRunning();
      }
    
      checkRunning() {
        setInterval(() => {
          const runtime = Math.floor((Date.now() - this.startTime) / 1000);
          const hours = Math.floor(runtime / 3600);
          const minutes = Math.floor((runtime % 3600) / 60);
          const seconds = runtime % 60;
          
          console.log(`💓 Alive | Runtime: ${hours}h ${minutes}m ${seconds}s | Logs: ${this.totalLogsReceived} | Raydium: ${this.raydiumMigrationCount} | PumpSwap: ${this.pumpswapMigrationCount}`);
        }, 60000);
      }
      connect() {
        console.log('🔌 Connecting to GetBlock WebSocket...');
        this.ws = new WebSocket(WS_ENDPOINT);
    
        this.ws.on('open', () => this.handleOpen());
        this.ws.on('message', (data) => this.handleMessage(data));
        this.ws.on('error', (error) => this.handleError(error));
        this.ws.on('close', () => this.handleClose());
      }
    
      handleOpen() {
        console.log('✅ Connected to GetBlock WebSocket');
        this.isConnected = true;
        this.reconnectAttempts = 0;
        this.subscribeToLogs();
      }
      subscribeToLogs() {
        const subscribeRequest = {
          jsonrpc: '2.0',
          id: 1,
          method: 'logsSubscribe',
          params: [
            {
              mentions: [MIGRATION_ACCOUNT]
            },
            {
              commitment: 'confirmed'
            }
          ]
        };
    
        console.log('📡 Subscribing to migration events...');
        this.ws.send(JSON.stringify(subscribeRequest));
      }
      async handleMessage(data) {
        try {
          const message = JSON.parse(data.toString());
    
          if (message.result && !message.params) {
            this.subscriptionId = message.result;
            console.log(`✅ Subscribed with ID: ${this.subscriptionId}`);
            console.log('⏳ Listening for migrations...\n');
            return;
          }
    
          if (message.params && message.params.result) {
            await this.processLog(message.params.result);
          }
        } catch (error) {
          console.error('❌ Error handling message:', error.message);
        }
      }
      async processLog(result) {
        const { value } = result;
        this.totalLogsReceived++;
        
        console.log(`📨 Log #${this.totalLogsReceived} - TX: ${value.signature.substring(0, 20)}...`);
    
        if (value.err) {
          console.log('   ↳ Skipped (failed transaction)');
          return;
        }
    
        const hasMigration = value.logs.some(
          (log) =>
            log.includes("Instruction: Migrate") ||
            log.includes("migrate") ||
            log.includes("initialize2")
        );
    
        if (hasMigration) {
          console.log("   ↳ 🎯 MIGRATION DETECTED!");
          await this.fetchAndProcessTransaction(value.signature);
        } else {
          console.log("   ↳ Not a migration");
        }
      }
      async fetchAndProcessTransaction(signature) {
        try {
          await new Promise((resolve) => setTimeout(resolve, 1000));
    
          const tx = await this.connection.getTransaction(signature, {
            maxSupportedTransactionVersion: 0,
            commitment: 'confirmed'
          });
    
          if (!tx) {
            console.log('⚠️  Transaction not found, skipping...');
            return;
          }
    
          const migrationData = this.extractMigrationData(tx, signature);
    
          if (migrationData) {
            this.migrations.push(migrationData);
            
            if (migrationData.type === 'raydium') {
              this.raydiumMigrationCount++;
            } else if (migrationData.type === 'pumpswap') {
              this.pumpswapMigrationCount++;
            }
            
            this.displayMigration(migrationData);
          }
        } catch (error) {
          console.error('❌ Error fetching transaction:', error.message);
        }
      }
      extractMigrationData(tx, signature) {
        try {
          let accountKeys, instructions;
    
          if (tx.transaction.message.addressTableLookups) {
            accountKeys = tx.transaction.message.staticAccountKeys || 
                         tx.transaction.message.accountKeys;
            instructions = tx.transaction.message.compiledInstructions || 
                          tx.transaction.message.instructions;
          } else {
            accountKeys = tx.transaction.message.accountKeys;
            instructions = tx.transaction.message.instructions;
          }
    
          if (!Array.isArray(instructions)) {
            instructions = Object.values(instructions);
          }
    
          for (const instruction of instructions) {
            let programId;
            
            if (instruction.programIdIndex !== undefined) {
              programId = accountKeys[instruction.programIdIndex];
            } else if (instruction.programId) {
              programId = instruction.programId;
            }
    
            // Check for Raydium migration
            if (programId && programId.toString() === RAYDIUM_PROGRAM) {
              const accounts = instruction.accounts;
              
              if (!accounts || accounts.length < 7) continue;
    
              return {
                type: 'raydium',
                signature: signature,
                slot: tx.slot,
                blockTime: tx.blockTime,
                poolAddress: accountKeys[accounts[1]].toString(),
                tokenAddress: accountKeys[accounts[5]].toString(),
                quoteMint: accountKeys[accounts[6]].toString(),
                lpMint: accountKeys[accounts[4]].toString(),
              };
            }
    
            // Check for PumpSwap migration
            if (programId && programId.toString() === PUMPFUN_PROGRAM) {
              return {
                type: 'pumpswap',
                signature: signature,
                slot: tx.slot,
                blockTime: tx.blockTime,
                tokenAddress: accountKeys[2] ? accountKeys[2].toString() : 'Unknown',
                bondingCurve: accountKeys[1] ? accountKeys[1].toString() : 'Unknown',
                destination: 'PumpSwap',
              };
            }
          }
        } catch (error) {
          console.error('❌ Error extracting migration data:', error.message);
        }
    
        return null;
      }
      displayMigration(data) {
        if (data.type === 'raydium') {
          console.log('\n🚀 ═══════════════════════════════════════════════════');
          console.log('   NEW PUMP.FUN → RAYDIUM MIGRATION DETECTED!');
          console.log('═══════════════════════════════════════════════════\n');
          console.log(`Migration #${this.raydiumMigrationCount} (Raydium)\n`);
          console.log(`📊 Token Address:  ${data.tokenAddress}`);
          console.log(`🏊 Pool Address:   ${data.poolAddress}`);
          console.log(`💧 LP Mint:        ${data.lpMint}`);
          console.log(`💰 Quote Token:    ${data.quoteMint}\n`);
          console.log(`📝 Transaction:    ${data.signature}`);
          console.log(`🔢 Slot:           ${data.slot}`);
    
          if (data.blockTime) {
            console.log(`⏰ Time:           ${new Date(data.blockTime * 1000).toISOString()}`);
          }
    
          console.log(`\n🔗 View on Solscan:`);
          console.log(`   https://solscan.io/tx/${data.signature}\n`);
          console.log(`🔗 Trade on Raydium:`);
          console.log(`   https://raydium.io/swap/?inputMint=sol&outputMint=${data.tokenAddress}\n`);
          console.log('═══════════════════════════════════════════════════\n');
        } else if (data.type === 'pumpswap') {
          console.log('\n💧 ═══════════════════════════════════════════════════');
          console.log('   NEW PUMP.FUN → PUMPSWAP MIGRATION DETECTED!');
          console.log('═══════════════════════════════════════════════════\n');
          console.log(`Migration #${this.pumpswapMigrationCount} (PumpSwap)\n`);
          console.log(`📊 Token Address:      ${data.tokenAddress}`);
          console.log(`🎯 Bonding Curve:      ${data.bondingCurve}`);
          console.log(`🏪 Destination:        ${data.destination}\n`);
          console.log(`📝 Transaction:        ${data.signature}`);
          console.log(`🔢 Slot:               ${data.slot}`);
    
          if (data.blockTime) {
            console.log(`⏰ Time:               ${new Date(data.blockTime * 1000).toISOString()}`);
          }
    
          console.log(`\n🔗 View on Solscan:`);
          console.log(`   https://solscan.io/tx/${data.signature}\n`);
          console.log(`🔗 View Token:`);
          console.log(`   https://pump.fun/${data.tokenAddress}\n`);
          console.log('═══════════════════════════════════════════════════\n');
        }
      }
      handleError(error) {
        console.error('❌ WebSocket error:', error.message);
      }
    
      handleClose() {
        this.isConnected = false;
        console.log('🔌 Connection closed');
    
        if (this.reconnectAttempts < this.maxReconnectAttempts) {
          this.reconnectAttempts++;
          const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);
    
          console.log(`🔄 Reconnecting in ${delay / 1000}s (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);
    
          setTimeout(() => {
            this.connect();
          }, delay);
        } else {
          console.error('❌ Max reconnection attempts reached. Exiting...');
          process.exit(1);
        }
      }
    
      stop() {
        console.log('👋 Stopping listener...');
        if (this.ws) {
          this.ws.close();
        }
      }
    }
    
    const listener = new PumpFunMigrationListener();
    listener.start();
    
    process.on('SIGINT', () => {
      console.log('\n👋 Shutting down...');
      listener.stop();
      process.exit(0);
    });
    
    process.on('SIGTERM', () => {
      listener.stop();
      process.exit(0);
    });
    
    process.on('uncaughtException', (error) => {
      console.error('💥 Uncaught exception:', error);
      listener.stop();
      process.exit(1);
    });
    
    process.on('unhandledRejection', (error) => {
      console.error('💥 Unhandled rejection:', error);
      listener.stop();
      process.exit(1);
    });
    npm start
    ✅ Configuration loaded successfully
    🚀 Starting Pump.fun Migration Listener...
    📡 Monitoring account: 39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg
    🎯 Tracking: Raydium + PumpSwap migrations
    
    🔌 Connecting to GetBlock WebSocket...
    ✅ Connected to GetBlock WebSocket
    📡 Subscribing to migration events...
    ✅ Subscribed with ID: 17473
    ⏳ Listening for migrations...
    📨 Log #4 - TX: 2QAbbdjj8P5qk3gzoey5...
      📊 Token Address:      3MSQF3mHFL9CuzKtUg6zp3GDdmGgDpPs7tQ1VPoXabTq
    🎯 Bonding Curve:      39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg
    🏪 Destination:        PumpSwap
    
    📝 Transaction:        G6YuhMQtC5vonGFDwGDUsy5Uukb7JvkzQeB91FDfbRCYL8fNzvig4so4ZXVnqWNsNZWjLWf2rs5xf55KDZ7wXTW
    🔢 Slot:               382201040
    ⏰ Time:               2025-11-24T12:30:13.000Z
    
    🔗 View on Solscan:
       https://solscan.io/tx/G6YuhMQtC5vonGFDwGDUsy5Uukb7JvkzQeB91FDfbRCYL8fNzvig4so4ZXVnqWNsNZWjLWf2rs5xf55KDZ7wXTW
    
    🔗 View Token:
       https://pump.fun/3MSQF3mHFL9CuzKtUg6zp3GDdmGgDpPs7tQ1VPoXabTq
    📨 Log #7 - TX: 5yK8TqPAL2kNXj9bVZmF...
       ↳ 🎯 MIGRATION DETECTED!
    
    🚀 ═══════════════════════════════════════════════════
       NEW PUMP.FUN → RAYDIUM MIGRATION DETECTED!
    ═══════════════════════════════════════════════════
    
    Migration #1 (Raydium)
    
    📊 Token Address:  8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj
    ...
    💓 Alive | Runtime: 0h 15m 30s | Logs: 23 | Raydium: 1 | PumpSwap: 18
    //Missing api key or environment variable
    ❌ Missing required environment variables
    Please set GETBLOCK_WS_ENDPOINT and GETBLOCK_HTTP_ENDPOINT in .env file
    
    //Connection error(403)
    🔌 Connecting to GetBlock WebSocket...
    ❌ WebSocket error: Unexpected server response: 403
    🔌 Connection closed

    How To Build a Base Flashblocks Listener

    A step-by-step guide to subscribing to Base Flashblocks and building trading applications around ultra-fast blockchain data.

    Traditional blockchain confirmations are slow. On Ethereum Layer 2 networks, such as Base, blocks are produced every 2 seconds. While this is already faster than Ethereum's ~12-second blocks, it's still an eternity for time-sensitive applications like trading bots, real-time games, or DeFi protocols where milliseconds matter.

    Flashblocks break the limitation of traditional blocks by creating mini-blocks every 200 milliseconds, providing users with instant transaction status while still retaining cryptographic security.

    In this guide, you'll learn what base flashblocks are, their importance, data structure and step-by-step instructions on how to build a base flashblocks listener.

    hashtag
    What Are Base Flashblocks?

    Flashblocks are sub-blocks (or "mini-blocks") streamed every 200 milliseconds — that's 10x faster than Base's standard 2-second block time. Developed in collaboration with Flashbots and launched on Base Mainnet in July 2025, Flashblocks provide preconfirmations: ultra-fast signals that arrive before the next full block is sealed.

    Here's how it works:

    • Standard Base blocks: Created every 2 seconds, containing all transactions

    • Flashblocks: 10 sub-blocks per full block, streamed every 200ms

    • Each Flashblock contains ~10% of the transactions (by gas) of a regular block

    circle-info

    Think of it like texting vs. email. Traditional blocks are like writing an entire email, proofreading it, and hitting send. Flashblocks are like texting — you send each line instantly and keep going.

    hashtag
    Importance of Flashblocks for Trading

    For trading applications, Flashblocks unlock several critical advantages:

    1. Near-instant transaction feedback: Know within 200ms if your transaction was included

    2. Front-running prevention: Once a Flashblock is built and broadcast, its transaction ordering is locked. Later-arriving transactions with higher fees can't jump ahead

    3. Real-time state updates: See balance changes, liquidity shifts, and price movements as they happen

    hashtag
    What You're Building

    In this tutorial, you'll build a Go application that:

    • Connects to the Base Flashblocks WebSocket stream

    • Handles both plain JSON and Brotli-compressed messages

    • Parses Flashblock data structures (transactions, receipts, balance updates)

    This forms the foundation for building trading bots, monitoring tools, or any application that needs ultra-low-latency blockchain data.

    hashtag
    Understanding the Flashblock Data Structure

    Before diving into code, let's understand what data you'll receive. Each Flashblock message contains three main components:

    hashtag
    1. The Root Structure

    The Index field tells you which of the 10 Flashblocks within a full block you're receiving (0 through 9).

    hashtag
    2. BlockDiff — The Block Changes

    Key fields for trading applications:

    • Transactions: Array of raw transaction data included in this Flashblock

    • StateRoot: Cryptographic proof of the blockchain state after these transactions

    hashtag
    3. Metadata — Balances and Receipts

    This is where the trading gold is:

    • BlockNumber: The full block number this Flashblock belongs to

    • NewAccountBalances: Map of addresses to their updated ETH balances

    hashtag
    4. Receipts — Transaction Results

    Receipts come in two flavors: EIP-1559 (modern) and Legacy. The Logs array contains event emissions — crucial for detecting swaps, transfers, and other contract events.

    hashtag
    Prerequisites

    Before we begin, make sure you have:

    • Go 1.21+ installed ()

    • Basic understanding of WebSockets and blockchain concepts

    • A terminal/command line environment

    hashtag
    Dependencies

    This application uses two external packages:

    1. (Flashblocks are compressed)

    hashtag
    Project Setup

    1. Create a new directory for your project and initialize the Go module:

    1. Install the required dependencies:

    1. Your go.mod file should look like this:

    hashtag
    Building the Listener

    1. Create main.go and start with the package and imports:

    This imports standard library packages for JSON handling, logging, and signal management, plus our two external dependencies.

    1. Define WebSocket endpoints and the data structures described earlier:

    Now define all the data structures:

    The GetData() and GetType() helper methods on Receipt let us work with receipts without worrying about whether they're EIP-1559 or Legacy format.

    1. Implement the main routine: flag parsing, selecting the endpoint, connecting via WebSocket, and setting up message processing and graceful shutdown.

    This covers:

    • Flag parsing for -network

    • WebSocket connection via gorilla/websocket

    • Signal handling for graceful shutdown

    1. Flashblock messages are typically Brotli-compressed. Decompress them with:

    1. Unmarshal JSON into structs and print a readable summary.

    Pretty-print the flashblock:

    This output shows:

    • Flashblock index (0-9)

    • Block number and hash

    • Gas usage and roots

    • Transaction list (truncated hashes)

    hashtag
    Running the Listener

    1. Build and Run

    1. Expected Output

    When running, you'll see Flashblocks streaming in real-time:

    You'll see new Flashblocks appear approximately every 200 milliseconds.

    1. Shutting Down

    Press Ctrl+C to stop the listener. It will send a proper WebSocket close message before exiting:

    hashtag
    Extending for Trading Applications

    Now that you have the basic listener working, here are some ways to extend it for trading:

    hashtag
    1. Filter Transactions by Address

    Monitor specific addresses (your wallet, a DEX router, etc.):

    hashtag
    2. Detect Swap Events

    Watch for Uniswap V2/V3 swap events by checking the first topic (event signature):

    hashtag
    3. Track Balance Changes

    Monitor when specific addresses receive or send ETH:

    hashtag
    Important Considerations

    1. Preconfirmation vs. Finality

    Flashblocks provide preconfirmations, not final confirmations. While extremely reliable, there's a small chance (during rare reorgs) that a Flashblock's data might differ from the final block.

    For critical transactions:

    • Use Flashblocks for fast UI feedback

    • Wait for full block confirmation for settlement

    1. Rate Limits

    The public endpoints (wss://mainnet.flashblocks.base.org/ws) are rate-limited. For production applications:

    • Use a node provider () with Flashblocks support

    • Consider running your own Flashblocks-aware node

    1. Handling Disconnections

    In production, add reconnection logic:

    hashtag
    Complete Code

    Here's the full main.go file:

    chevron-rightFull Codehashtag

    hashtag
    Conclusion

    You've built a real-time Base Flashblocks listener in Go that:

    • Connects to the Flashblocks WebSocket stream

    • Handles Brotli-compressed messages

    • Parses and displays transaction data, receipts, and balance updates

    hashtag
    Resources

    How to Build a Hyperliquid Whale Tracker Bot with GetBlock

    A step by step guide on how to build an Hyperliquid Whale Tracker Bot using GetBlock API

    Whales are entities, such as DAOs or companies, that hold a large amount of a particular cryptocurrency, sufficient to influence the market price through their transactions. Their trade alone can either deflate or inflate the market price. While some whales engage in large trades that have a natural market effect, others may intentionally try to manipulate the market for profit. The Whale Tracking Bot is a bot that monitors on-chain activities of whales. It reports their transactions to you, thereby providing a clear analysis to inform predictions about potential market movements.

    In this guide, you will learn:

    • Create a Telegram bot using

    A series of Flashblocks can be combined to recreate a full block

    CEX-like experience on DEXs: Trading feels instant, not sluggish

    Displays real-time blockchain activity
    GasUsed
    : Total gas consumed by transactions in this Flashblock
    Receipts
    : Transaction receipts with execution results and event logs
    Message loop reading text or binary (Brotli) messages
  • Balance update count

  • Receipt summaries

  • Flashbots Documentationarrow-up-right
  • GetBlock Dashboardarrow-up-right

  • download herearrow-up-right
    WebSocket client libraryarrow-up-right
    Brotli decompressionarrow-up-right
    GetBlockarrow-up-right
    Base Flashblocks Documentationarrow-up-right
    Base Blog: Flashblocks Deep Divearrow-up-right
    Base Flashblocks Listener Repoarrow-up-right
    type Flashblock struct {
        Diff     BlockDiff `json:"diff"`      // Block differences/updates
        Index    int       `json:"index"`     // Flashblock index (0-9 within a block)
        Metadata Metadata  `json:"metadata"`  // Block metadata
    }
    type BlockDiff struct {
        BlobGasUsed     string   `json:"blob_gas_used"`
        BlockHash       string   `json:"block_hash"`
        GasUsed         string   `json:"gas_used"`
        LogsBloom       string   `json:"logs_bloom"`
        ReceiptsRoot    string   `json:"receipts_root"`
        StateRoot       string   `json:"state_root"`
        Transactions    []string `json:"transactions"`
        Withdrawals     []any    `json:"withdrawals"`
        WithdrawalsRoot string   `json:"withdrawals_root"`
    }
    type Metadata struct {
        BlockNumber        uint64             `json:"block_number"`
        NewAccountBalances map[string]string  `json:"new_account_balances"`
        Receipts           map[string]Receipt `json:"receipts"`
    }
    type Receipt struct {
        Eip1559 *ReceiptData `json:"Eip1559,omitempty"`
        Legacy  *ReceiptData `json:"Legacy,omitempty"`
    }
    
    type ReceiptData struct {
        CumulativeGasUsed string `json:"cumulativeGasUsed"`
        Logs              []Log  `json:"logs"`
        Status            string `json:"status"`
    }
    
    type Log struct {
        Address string   `json:"address"`
        Data    string   `json:"data"`
        Topics  []string `json:"topics"`
    }
    mkdir flashblocks-listener
    cd flashblocks-listener
    go mod init flashblocks-listener
    go get github.com/gorilla/websocket
    go get github.com/andybalholm/brotli
    module flashblocks-listener
    
    go 1.23.0
    
    require (
        github.com/andybalholm/brotli v1.2.0
        github.com/gorilla/websocket v1.5.3
    )
    package main
    
    import (
        "bytes"
        "encoding/json"
        "flag"
        "fmt"
        "io"
        "log"
        "os"
        "os/signal"
        "syscall"
    
        "github.com/andybalholm/brotli"
        "github.com/gorilla/websocket"
    )
    const (
        mainnetWSURL = "wss://mainnet.flashblocks.base.org/ws"
        sepoliaWSURL = "wss://sepolia.flashblocks.base.org/ws"
    )
    // Flashblock represents the root structure of a flashblock message
    type Flashblock struct {
        Diff     BlockDiff `json:"diff"`
        Index    int       `json:"index"`
        Metadata Metadata  `json:"metadata"`
    }
    
    // BlockDiff contains the block differences/updates
    type BlockDiff struct {
        BlobGasUsed     string   `json:"blob_gas_used"`
        BlockHash       string   `json:"block_hash"`
        GasUsed         string   `json:"gas_used"`
        LogsBloom       string   `json:"logs_bloom"`
        ReceiptsRoot    string   `json:"receipts_root"`
        StateRoot       string   `json:"state_root"`
        Transactions    []string `json:"transactions"`
        Withdrawals     []any    `json:"withdrawals"`
        WithdrawalsRoot string   `json:"withdrawals_root"`
    }
    
    // Metadata contains block metadata including balances and receipts
    type Metadata struct {
        BlockNumber        uint64             `json:"block_number"`
        NewAccountBalances map[string]string  `json:"new_account_balances"`
        Receipts           map[string]Receipt `json:"receipts"`
    }
    
    // Receipt represents a transaction receipt (can be EIP-1559 or Legacy)
    type Receipt struct {
        Eip1559 *ReceiptData `json:"Eip1559,omitempty"`
        Legacy  *ReceiptData `json:"Legacy,omitempty"`
    }
    
    // GetData returns the receipt data regardless of type
    func (r *Receipt) GetData() *ReceiptData {
        if r.Eip1559 != nil {
            return r.Eip1559
        }
        return r.Legacy
    }
    
    // GetType returns the receipt type as a string
    func (r *Receipt) GetType() string {
        if r.Eip1559 != nil {
            return "EIP-1559"
        }
        if r.Legacy != nil {
            return "Legacy"
        }
        return "Unknown"
    }
    
    // ReceiptData contains the actual receipt information
    type ReceiptData struct {
        CumulativeGasUsed string `json:"cumulativeGasUsed"`
        Logs              []Log  `json:"logs"`
        Status            string `json:"status"`
    }
    
    // Log represents an event log
    type Log struct {
        Address string   `json:"address"`
        Data    string   `json:"data"`
        Topics  []string `json:"topics"`
    }
    func main() {
        // Parse command-line flags
        network := flag.String("network", "mainnet", "Network to connect to: mainnet or sepolia")
        flag.Parse()
    
        // Select the appropriate WebSocket URL
        var wsURL string
        switch *network {
        case "mainnet":
            wsURL = mainnetWSURL
        case "sepolia":
            wsURL = sepoliaWSURL
        default:
            log.Fatalf("Invalid network: %s. Use 'mainnet' or 'sepolia'", *network)
        }
    
        log.Printf("Connecting to Base flashblocks on %s: %s", *network, wsURL)
    
        // Establish WebSocket connection
        conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
        if err != nil {
            log.Fatalf("Failed to connect to WebSocket: %v", err)
        }
        defer conn.Close()
    
        log.Println("Connected! Listening for flashblocks...")
    
        // Set up graceful shutdown
        sigChan := make(chan os.Signal, 1)
        signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
    
        done := make(chan struct{})
    
        // Message processing goroutine
        go func() {
            defer close(done)
            for {
                messageType, message, err := conn.ReadMessage()
                if err != nil {
                    if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) {
                        log.Println("WebSocket closed normally")
                        return
                    }
                    log.Printf("Error reading message: %v", err)
                    return
                }
    
                switch messageType {
                case websocket.TextMessage:
                    handleFlashblockJSON(message)
                case websocket.BinaryMessage:
                    decoded, err := decodeBrotli(message)
                    if err != nil {
                        log.Printf("Error decoding Brotli: %v", err)
                        log.Printf("Raw binary message length: %d bytes", len(message))
                        continue
                    }
                    handleFlashblockJSON(decoded)
                default:
                    log.Printf("Received unknown message type: %d", messageType)
                }
            }
        }()
    
        // Wait for shutdown signal or connection close
        select {
        case <-done:
            log.Println("Connection closed")
        case sig := <-sigChan:
            log.Printf("Received signal %v, shutting down...", sig)
            err := conn.WriteMessage(websocket.CloseMessage, 
                websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
            if err != nil {
                log.Printf("Error sending close message: %v", err)
            }
        }
    }
    func decodeBrotli(data []byte) ([]byte, error) {
        reader := brotli.NewReader(bytes.NewReader(data))
        return io.ReadAll(reader)
    }
    func handleFlashblockJSON(data []byte) {
        var flashblock Flashblock
        if err := json.Unmarshal(data, &flashblock); err != nil {
            log.Printf("Error parsing flashblock JSON: %v", err)
            log.Printf("Raw data: %s", string(data))
            return
        }
    
        printFlashblock(&flashblock)
    }
    func printFlashblock(fb *Flashblock) {
        fmt.Println("═══════════════════════════════════════════════════════════════")
        fmt.Printf("FLASHBLOCK #%d | Block: %d | Hash: %s\n",
            fb.Index,
            fb.Metadata.BlockNumber,
            truncateHash(fb.Diff.BlockHash))
        fmt.Println("═══════════════════════════════════════════════════════════════")
    
        fmt.Printf("  Gas Used:       %s\n", fb.Diff.GasUsed)
        fmt.Printf("  Blob Gas Used:  %s\n", fb.Diff.BlobGasUsed)
        fmt.Printf("  State Root:     %s\n", truncateHash(fb.Diff.StateRoot))
        fmt.Printf("  Receipts Root:  %s\n", truncateHash(fb.Diff.ReceiptsRoot))
    
        fmt.Printf("\n  Transactions: %d\n", len(fb.Diff.Transactions))
        for i, tx := range fb.Diff.Transactions {
            fmt.Printf("    [%d] %s...\n", i, truncateHash(tx))
        }
    
        fmt.Printf("\n  Account Balance Updates: %d\n", len(fb.Metadata.NewAccountBalances))
    
        fmt.Printf("\n  Receipts: %d\n", len(fb.Metadata.Receipts))
        receiptCount := 0
        for txHash, receipt := range fb.Metadata.Receipts {
            if receiptCount >= 3 {
                fmt.Printf("    ... and %d more receipts\n", len(fb.Metadata.Receipts)-3)
                break
            }
            data := receipt.GetData()
            if data != nil {
                fmt.Printf("    [%s] %s - Status: %s, Logs: %d\n",
                    receipt.GetType(),
                    truncateHash(txHash),
                    data.Status,
                    len(data.Logs))
            }
            receiptCount++
        }
    
        fmt.Println()
    }
    
    func truncateHash(hash string) string {
        if len(hash) <= 20 {
            return hash
        }
        return hash[:10] + "..." + hash[len(hash)-8:]
    }
    # Build the application
    go build -o flashblocks-listener
    
    # Run on mainnet (default)
    ./flashblocks-listener
    
    # Run on Sepolia testnet
    ./flashblocks-listener -network=sepolia
    2026/01/23 12:06:55 Connecting to Base flashblocks on mainnet: wss://mainnet.flashblocks.base.org/ws
    2026/01/23 12:06:57 Connected! Listening for flashblocks...
    ═══════════════════════════════════════════════════════════════
    FLASHBLOCK #3 | Block: 41188536 | Hash: 0x1832098f...7ebd4a7f
    ═══════════════════════════════════════════════════════════════
      Gas Used:       0x124f501
      Blob Gas Used:  0x22e3d6
      State Root:     0x00000000...00000000
      Receipts Root:  0xa83fdcff...1e433d49
    
      Transactions: 16
        [0] 0x02f90133...60eff264...
        [1] 0x02f90133...4732f1c0...
        [2] 0x02f90133...01fd3ba7...
        [3] 0x02f90133...470392b3...
        [4] 0x02f90196...e4134811...
        [5] 0x02f901f3...0e62c9ff...
        [6] 0x02f90153...b0328e40...
        [7] 0x02f90153...f04b2f4f...
        [8] 0x02f8c082...7ceecf2b...
        [9] 0x02f90153...1f75269c...
        [10] 0x02f90151...c9b5718a...
        [11] 0xf86c822a...3bd176a3...
        [12] 0xf9014183...06eeeac4...
        [13] 0x02f88482...1d4b11e4...
        [14] 0x02f88482...97783f64...
        [15] 0x02f90354...def1bfb6...
    
      Account Balance Updates: 205
    
      Receipts: 16
        [EIP-1559] 0x7c69632d...c315f13a - Status: 0x1, Logs: 0
        [EIP-1559] 0xda9e6136...1fdde572 - Status: 0x1, Logs: 0
        [EIP-1559] 0xe2030a9f...399a02ce - Status: 0x1, Logs: 0
        ... and 13 more receipts
    ^C2026/01/23 12:06:59 Received signal interrupt, shutting down...
    func filterByAddress(fb *Flashblock, targetAddress string) {
        for txHash, receipt := range fb.Metadata.Receipts {
            data := receipt.GetData()
            if data == nil {
                continue
            }
            for _, logEntry := range data.Logs {
                if strings.EqualFold(logEntry.Address, targetAddress) {
                    fmt.Printf("Activity detected! TX: %s\n", txHash)
                    // Process the event...
                }
            }
        }
    }
    const (
        // Uniswap V2 Swap event signature
        uniswapV2Swap = "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822"
        // Uniswap V3 Swap event signature  
        uniswapV3Swap = "0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67"
    )
    
    func detectSwaps(fb *Flashblock) {
        for txHash, receipt := range fb.Metadata.Receipts {
            data := receipt.GetData()
            if data == nil {
                continue
            }
            for _, logEntry := range data.Logs {
                if len(logEntry.Topics) > 0 {
                    switch logEntry.Topics[0] {
                    case uniswapV2Swap:
                        fmt.Printf("Uniswap V2 Swap in TX: %s\n", txHash)
                    case uniswapV3Swap:
                        fmt.Printf("Uniswap V3 Swap in TX: %s\n", txHash)
                    }
                }
            }
        }
    }
    func trackBalanceChanges(fb *Flashblock, watchAddresses []string) {
        for _, addr := range watchAddresses {
            if newBalance, exists := fb.Metadata.NewAccountBalances[addr]; exists {
                fmt.Printf("Balance update for %s: %s\n", addr, newBalance)
            }
        }
    }
    func connectWithRetry(wsURL string, maxRetries int) (*websocket.Conn, error) {
        for i := 0; i < maxRetries; i++ {
            conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
            if err == nil {
                return conn, nil
            }
            log.Printf("Connection attempt %d failed: %v", i+1, err)
            time.Sleep(time.Second * time.Duration(i+1))
        }
        return nil, fmt.Errorf("failed after %d attempts", maxRetries)
    }
    main.go
    package main
    
    import (
    	"bytes"
    	"encoding/json"
    	"flag"
    	"fmt"
    	"io"
    	"log"
    	"os"
    	"os/signal"
    	"syscall"
    
    	"github.com/andybalholm/brotli"
    	"github.com/gorilla/websocket"
    )
    
    const (
    	mainnetWSURL = "wss://mainnet.flashblocks.base.org/ws"
    	sepoliaWSURL = "wss://sepolia.flashblocks.base.org/ws"
    )
    
    // Flashblock represents the root structure of a flashblock message
    type Flashblock struct {
    	Diff     BlockDiff `json:"diff"`
    	Index    int       `json:"index"`
    	Metadata Metadata  `json:"metadata"`
    }
    
    // BlockDiff contains the block differences/updates
    type BlockDiff struct {
    	BlobGasUsed     string   `json:"blob_gas_used"`
    	BlockHash       string   `json:"block_hash"`
    	GasUsed         string   `json:"gas_used"`
    	LogsBloom       string   `json:"logs_bloom"`
    	ReceiptsRoot    string   `json:"receipts_root"`
    	StateRoot       string   `json:"state_root"`
    	Transactions    []string `json:"transactions"`
    	Withdrawals     []any    `json:"withdrawals"`
    	WithdrawalsRoot string   `json:"withdrawals_root"`
    }
    
    // Metadata contains block metadata including balances and receipts
    type Metadata struct {
    	BlockNumber        uint64             `json:"block_number"`
    	NewAccountBalances map[string]string  `json:"new_account_balances"`
    	Receipts           map[string]Receipt `json:"receipts"`
    }
    
    // Receipt represents a transaction receipt (can be EIP-1559 or Legacy)
    type Receipt struct {
    	Eip1559 *ReceiptData `json:"Eip1559,omitempty"`
    	Legacy  *ReceiptData `json:"Legacy,omitempty"`
    }
    
    // GetData returns the receipt data regardless of type
    func (r *Receipt) GetData() *ReceiptData {
    	if r.Eip1559 != nil {
    		return r.Eip1559
    	}
    	return r.Legacy
    }
    
    // GetType returns the receipt type as a string
    func (r *Receipt) GetType() string {
    	if r.Eip1559 != nil {
    		return "EIP-1559"
    	}
    	if r.Legacy != nil {
    		return "Legacy"
    	}
    	return "Unknown"
    }
    
    // ReceiptData contains the actual receipt information
    type ReceiptData struct {
    	CumulativeGasUsed string `json:"cumulativeGasUsed"`
    	Logs              []Log  `json:"logs"`
    	Status            string `json:"status"`
    }
    
    // Log represents an event log
    type Log struct {
    	Address string   `json:"address"`
    	Data    string   `json:"data"`
    	Topics  []string `json:"topics"`
    }
    
    func main() {
    	network := flag.String("network", "mainnet", "Network to connect to: mainnet or sepolia")
    	flag.Parse()
    
    	var wsURL string
    	switch *network {
    	case "mainnet":
    		wsURL = mainnetWSURL
    	case "sepolia":
    		wsURL = sepoliaWSURL
    	default:
    		log.Fatalf("Invalid network: %s. Use 'mainnet' or 'sepolia'", *network)
    	}
    
    	log.Printf("Connecting to Base flashblocks on %s: %s", *network, wsURL)
    
    	conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
    	if err != nil {
    		log.Fatalf("Failed to connect to WebSocket: %v", err)
    	}
    	defer conn.Close()
    
    	log.Println("Connected! Listening for flashblocks...")
    
    	// Handle graceful shutdown
    	sigChan := make(chan os.Signal, 1)
    	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
    
    	done := make(chan struct{})
    
    	go func() {
    		defer close(done)
    		for {
    			messageType, message, err := conn.ReadMessage()
    			if err != nil {
    				if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) {
    					log.Println("WebSocket closed normally")
    					return
    				}
    				log.Printf("Error reading message: %v", err)
    				return
    			}
    
    			switch messageType {
    			case websocket.TextMessage:
    				handleFlashblockJSON(message)
    			case websocket.BinaryMessage:
    				decoded, err := decodeBrotli(message)
    				if err != nil {
    					log.Printf("Error decoding Brotli: %v", err)
    					log.Printf("Raw binary message length: %d bytes", len(message))
    					continue
    				}
    				handleFlashblockJSON(decoded)
    			default:
    				log.Printf("Received unknown message type: %d", messageType)
    			}
    		}
    	}()
    
    	select {
    	case <-done:
    		log.Println("Connection closed")
    	case sig := <-sigChan:
    		log.Printf("Received signal %v, shutting down...", sig)
    		err := conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
    		if err != nil {
    			log.Printf("Error sending close message: %v", err)
    		}
    	}
    }
    
    func decodeBrotli(data []byte) ([]byte, error) {
    	reader := brotli.NewReader(bytes.NewReader(data))
    	return io.ReadAll(reader)
    }
    
    func handleFlashblockJSON(data []byte) {
    	var flashblock Flashblock
    	if err := json.Unmarshal(data, &flashblock); err != nil {
    		log.Printf("Error parsing flashblock JSON: %v", err)
    		log.Printf("Raw data: %s", string(data))
    		return
    	}
    
    	printFlashblock(&flashblock)
    }
    
    func printFlashblock(fb *Flashblock) {
    	fmt.Println("═══════════════════════════════════════════════════════════════")
    	fmt.Printf("FLASHBLOCK #%d | Block: %d | Hash: %s\n",
    		fb.Index,
    		fb.Metadata.BlockNumber,
    		truncateHash(fb.Diff.BlockHash))
    	fmt.Println("═══════════════════════════════════════════════════════════════")
    
    	fmt.Printf("  Gas Used:       %s\n", fb.Diff.GasUsed)
    	fmt.Printf("  Blob Gas Used:  %s\n", fb.Diff.BlobGasUsed)
    	fmt.Printf("  State Root:     %s\n", truncateHash(fb.Diff.StateRoot))
    	fmt.Printf("  Receipts Root:  %s\n", truncateHash(fb.Diff.ReceiptsRoot))
    
    	fmt.Printf("\n  Transactions: %d\n", len(fb.Diff.Transactions))
    	for i, tx := range fb.Diff.Transactions {
    		fmt.Printf("    [%d] %s...\n", i, truncateHash(tx))
    	}
    
    	fmt.Printf("\n  Account Balance Updates: %d\n", len(fb.Metadata.NewAccountBalances))
    
    	fmt.Printf("\n  Receipts: %d\n", len(fb.Metadata.Receipts))
    	receiptCount := 0
    	for txHash, receipt := range fb.Metadata.Receipts {
    		if receiptCount >= 3 {
    			fmt.Printf("    ... and %d more receipts\n", len(fb.Metadata.Receipts)-3)
    			break
    		}
    		data := receipt.GetData()
    		if data != nil {
    			fmt.Printf("    [%s] %s - Status: %s, Logs: %d\n",
    				receipt.GetType(),
    				truncateHash(txHash),
    				data.Status,
    				len(data.Logs))
    		}
    		receiptCount++
    	}
    
    	fmt.Println()
    }
    
    func truncateHash(hash string) string {
    	if len(hash) <= 20 {
    		return hash
    	}
    	return hash[:10] + "..." + hash[len(hash)-8:]
    }
    Get a GetBlock API access token
  • Build the Hyperliquid whale tracker bot that:

    • Tracks all trades on Hyperliquid as they happen

    • Identifies large trades based on configurable thresholds

    • Detects whale walls in the orderbook

    • Tracks and profiles recurring whale addresses

    • Sends an instant alert to your phone via Telegram

    • Utilizes smart batching to avoid Telegram API limits

    • Provides periodic summaries of whale activity

  • hashtag
    Prerequisites

    1. Basic knowledge of JavaScript

    2. Must have installed Nodearrow-up-right and npmarrow-up-right

    3. A GetBlock accountarrow-up-right

    4. A

    hashtag
    Step 1. Create Telegram Bot

    1. Bot Token:

      • Open Telegram and search for @BotFather

      • Send /newbot and follow instructions

      • Copy the token provided and save it in .env file

    2. Chat ID:

      • Search for @raw_data_bot in Telegram

      • Send /start

    hashtag
    Step 2. Set up Development Environment

    Before you begin, you need to set up your development environment:

    hashtag
    Step 3. Getting your HyperEVM Websocket Token

    1. Log in to your GetBlock accountarrow-up-right

    2. On your dashboard, scroll and click on Get Endpoint

    3. Select the HyperEVM Mainnet network

    4. Under API Interface, select WebSocket

    5. Click on Create to get your endpoint

    circle-exclamation

    Keep your endpoint safe, as it contains an access token

    hashtag
    Project Structure

    Create the following files to have a basic structure for your project:

    hashtag
    Step 4. Set up Environment Variables

    Update the .env file in the root of your project and add the following variables:

    hashtag
    Step 5. Build Whale Tracker Bot

    hashtag
    1. Import dependencies:

    Import the dependencies and load the environment variables from .env file

    hashtag
    2. Set up configuration settings:

    Set up configuration settings for your application, including environment variables and other constants.

    hashtag
    3. Create the Main Class with Private Fields:

    Why private fields?

    • # prefix makes fields private (ES2022 feature)

    • Prevents external code from modifying internal state

    • Better encapsulation and code organization

    hashtag
    4. Connect to Hyperliquid WebSocket:

    Event handlers:

    • open - Triggered when the connection is established

    • message - Receives data from the server

    • error - Handles connection errors

    • close - Handles disconnection

    hashtag
    5. Subscribe to Data Streams:

    Subscription types:

    • allMids - Current market prices for all symbols

    • trades - Real-time trade executions

    • l2Book - Level 2 orderbook (buy/sell walls)

    hashtag
    6. Handle Incoming Messages:

    Message routing:

    • Parse JSON data from WebSocket

    • Route to the appropriate handler based on channel type

    • Graceful error handling with try-catch

    hashtag
    7. Update Price Cache

    Why cache prices?

    • Used for calculating USD value of trades

    • Avoids repeated API calls

    • Provides a fallback when price data is missing

    hashtag
    8. Analyze Trades for Whales

    Trade data structure:

    • coin - Market symbol (BTC, ETH, etc.)

    • side - 'B' for buy, 'A' for ask/sell

    • px - Price (as string)

    • sz - Size/quantity (as string)

    • user - Wallet address of trader

    • hash - Transaction hash

    • tid - Trade ID

    hashtag
    9. Track Whale Addresses

    Whale profile includes:

    • Total trading volume (cumulative)

    • Number of trades executed

    • First and last seen timestamps

    • Set of markets they trade in

    hashtag
    10. Analyze Orderbook for Whale Walls

    Orderbook structure:

    • levels[0] - Bid side (buy orders)

    • levels[1] - Ask side (sell orders)

    • Each level is [price, size] array

    Whale walls:

    • Large limit orders in the orderbook

    • Can act as support (bids) or resistance (asks)

    • Indicate where whales are defending price levels

    hashtag
    11. Send Trade Notifications

    Notification features:

    • Color-coded emojis (green=buy, red=sell)

    • Shortened wallet address for readability

    • Historical stats for known whales

    • Special highlight for mega trades ($500k+)

    • Optional Telegram integration

    hashtag
    12. Implement Telegram Batching

    Why batch alerts?

    • Telegram has rate limits (1 message/second)

    • Batching prevents hitting limits during high activity

    • Combines multiple alerts into one clean summary

    • Configurable interval (default: 10 seconds)

    hashtag
    13. Implement Telegram Queue System

    Queue system benefits:

    • Messages are queued and processed sequentially

    • Respects Telegram's rate limits

    • Automatic retry on 429 errors

    • Non-blocking (uses async/await)

    hashtag
    14. Test Telegram Connection

    Connection test:

    • Validates bot token on startup

    • Shows bot username

    • Sends test message

    • Provides helpful error messages

    hashtag
    15. Implement Auto-Reconnection

    Reconnection strategy:

    • Exponential backoff (delays increase)

    • Maximum 5 attempts

    • Caps at 30 seconds between tries

    • Separate handling for different connections

    hashtag
    16. Generate Statistics Dashboard

    Statistics include:

    • Total number of whale trades detected

    • Number of unique whale addresses

    • Top 10 whales ranked by volume

    • Individual whale profiles with activity metrics

    hashtag
    17. Create the Start Method

    Startup sequence:

    1. Display configuration

    2. Test Telegram connection

    3. Connect to Hyperliquid WebSocket

    4. Optionally connect to HyperEVM

    5. Start periodic statistics reporting

    hashtag
    18. Initialize and Run the Bot

    Proper shutdown:

    • Closes WebSocket connections properly

    • Prevents data loss or hanging connections

    hashtag
    Running and Testing the Application

    1. Open your terminal and run the following command:

    1. Expected result in console:

    1. Expected result in Telegram:

    hashtag
    Troubleshooting

    You may run into a WebSocket 503 Error:

    • This means that your WebSocket endpoint is incorrect. Check your .env file and ensure it's in this pattern:

    Then, restart the server.

    hashtag
    Conclusion

    In this guide, you have successfully learn and built a Hyperliquid Whale Tracker Bot that monitors and alerts all whale trade activities — from major buys to large sell-offs — and even detects whale walls in the order book.

    By integrating the GetBlock WebSocket API, you can rest assured of fast, reliable, and real-time data delivery, ensuring you never miss significant market movements.

    Botfatherarrow-up-right
    mkdir hyperliquid-whale-alert-bot
    cd hyperliquid-whale-alert-bot
    npm init -y
    npm i dotenv ws
    npm i -D nodemon
    ├── index.js            // Main apllication
    └── .env                // Environment variables
    └── .gitignore          // Git ignore file
    # Telegram Configuration (Get from @BotFather and @userinfobot)
    TELEGRAM_BOT_TOKEN=your-telegram-bot-token
    TELEGRAM_CHAT_ID=your-ID
    
    # Whale Detection Thresholds
    WHALE_THRESHOLD_USD=100000
    WHALE_THRESHOLD_SIZE=50
    
    # Telegram Settings
    TELEGRAM_BATCH_ALERTS=true
    TELEGRAM_BATCH_INTERVAL=10000
    
    # Markets to Track (comma-separated)
    TRACKED_SYMBOLS=BTC,ETH,SOL,ARB,AVAX,HYPE
    
    # Optional: HyperEVM WebSocket from GetBlock
    HYPEREVM_WSS=wss://go.getblock.io/<ACCESS_TOKEN>
    // dependencies
    import WebSocket from 'ws';
    import { config } from 'dotenv';
    
    // Load environment variables from .env file
    config();
    const CONFIG = {
      // HyperEVM WebSocket endpoint from GetBlock
      HYPEREVM_WSS: process.env.HYPEREVM_WSS,
      
      // Whale thresholds
      WHALE_THRESHOLD_USD: Number(process.env.WHALE_THRESHOLD_USD) || 100000,
      WHALE_THRESHOLD_SIZE: Number(process.env.WHALE_THRESHOLD_SIZE) || 50,
      
      // Notification settings
      TELEGRAM_BOT_TOKEN: process.env.TELEGRAM_BOT_TOKEN || '',
      TELEGRAM_CHAT_ID: process.env.TELEGRAM_CHAT_ID || '',
      TELEGRAM_BATCH_ALERTS: process.env.TELEGRAM_BATCH_ALERTS !== 'false',
      TELEGRAM_BATCH_INTERVAL: Number(process.env.TELEGRAM_BATCH_INTERVAL) || 60 * 10000,
      
      // Tracked markets
      TRACKED_SYMBOLS: (process.env.TRACKED_SYMBOLS || 'BTC,ETH,SOL,ARB,AVAX,HYPE').split(','),
    };
    class HyperliquidWhaleTracker {
      // Private fields (only accessible within the class)
      #ws = null;                    // Hyperliquid WebSocket connection
      #wsHyperEVM = null;            // HyperEVM WebSocket connection
      #reconnectAttempts = 0;        // Track reconnection attempts
      #maxReconnectAttempts = 5;     // Maximum reconnection tries
      #priceCache = new Map();       // Store current prices
      #whaleAddresses = new Map();   // Track whale wallet addresses
      #tradeCount = 0;               // Total whale trades detected
      #telegramQueue = [];           // Queue for Telegram messages
      #isSendingTelegram = false;    // Flag for queue processing
      #lastTelegramSent = 0;         // Timestamp of last message
      #TELEGRAM_DELAY = 1500;        // Delay between messages (ms)
      #pendingAlerts = [];           // Batch alerts before sending
      #batchTimer = null;            // Timer for batching
    
      constructor() {
        this.HYPERLIQUID_WS_URL = 'wss://api.hyperliquid.xyz/ws';
      }
    }
    async connectHyperliquid() {
      console.log('Connecting to Hyperliquid Info WebSocket...');
      
      this.#ws = new WebSocket(this.HYPERLIQUID_WS_URL);
    
      this.#ws.on('open', () => {
        console.log('✅ Connected to Hyperliquid Info API');
        this.#subscribeToTrades();
        this.#subscribeToOrderbook();
      });
    
      this.#ws.on('message', (data) => this.#handleHyperliquidMessage(data));
      this.#ws.on('error', (error) => console.error('Hyperliquid error:', error.message));
      this.#ws.on('close', () => this.#handleReconnect('hyperliquid'));
    }
    #subscribeToTrades() {
      // Subscribe to price updates
      this.#ws.send(JSON.stringify({
        method: 'subscribe',
        subscription: { type: 'allMids' }
      }));
      
      // Subscribe to trades for each tracked symbol
      for (const symbol of CONFIG.TRACKED_SYMBOLS) {
        this.#ws.send(JSON.stringify({
          method: 'subscribe',
          subscription: { type: 'trades', coin: symbol }
        }));
      }
    
      console.log('📡 Subscribed to Hyperliquid trades');
    }
    
    #subscribeToOrderbook() {
      // Subscribe to orderbook depth for whale wall detection
      for (const symbol of CONFIG.TRACKED_SYMBOLS) {
        this.#ws.send(JSON.stringify({
          method: 'subscribe',
          subscription: { type: 'l2Book', coin: symbol }
        }));
      }
    
      console.log('📊 Subscribed to orderbook data');
    }
    #handleHyperliquidMessage(data) {
      try {
        const message = JSON.parse(data.toString());
        
        // Route messages based on channel type
        switch (message.channel) {
          case 'trades':
            message.data?.forEach(trade => this.#analyzeTrade(trade));
            break;
          case 'allMids':
            this.#updatePrices(message.data);
            break;
          case 'l2Book':
            this.#analyzeOrderbook(message.data);
            break;
        }
      } catch (error) {
        console.error('Error parsing message:', error.message);
      }
    }
    #updatePrices(midsData) {
      if (!midsData?.mids) return;
      
      // Store current prices in a Map for quick lookup
      for (const [symbol, price] of Object.entries(midsData.mids)) {
        this.#priceCache.set(symbol, parseFloat(price));
      }
    }
    #analyzeTrade(trade) {
      try {
        const { coin, side, px, sz, time, user, hash, tid } = trade;
        const price = parseFloat(px);
        const size = parseFloat(sz);
        const value = price * size;  // Calculate USD value
    
        // Check if trade meets whale threshold
        if (value < CONFIG.WHALE_THRESHOLD_USD && size < CONFIG.WHALE_THRESHOLD_SIZE) {
          return;  // Not a whale trade, skip
        }
    
        // Track the whale's address
        if (user) {
          this.#trackWhaleAddress(user, value, coin);
        }
    
        // Send notification
        this.#notifyWhaleTrade({
          coin,
          side,
          price,
          size,
          value,
          time: new Date(time).toLocaleString(),
          user: user || 'Unknown',
          hash: hash || null,
          tradeId: tid || null
        });
        
        this.#tradeCount++;
      } catch (error) {
        console.error('Error analyzing trade:', error.message);
      }
    }
    #trackWhaleAddress(address, value, coin) {
      const whale = this.#whaleAddresses.get(address);
      
      if (whale) {
        // Existing whale - update stats
        whale.totalVolume += value;
        whale.tradeCount++;
        whale.lastSeen = new Date();
        whale.coins.add(coin);
      } else {
        // New whale - create profile
        this.#whaleAddresses.set(address, {
          address,
          totalVolume: value,
          tradeCount: 1,
          firstSeen: new Date(),
          lastSeen: new Date(),
          coins: new Set([coin])
        });
      }
    }
    #analyzeOrderbook(bookData) {
      try {
        const { coin, levels } = bookData;
        
        if (!Array.isArray(levels)) return;
    
        const largeOrders = [];
    
        // Analyze both bid (buy) and ask (sell) sides
        for (const [index, side] of ['BID', 'ASK'].entries()) {
          if (!Array.isArray(levels[index])) continue;
    
          for (const level of levels[index]) {
            // Handle different data formats
            const [price, size] = Array.isArray(level) 
              ? level 
              : [level.px, level.sz];
    
            if (!price || !size) continue;
    
            const value = parseFloat(price) * parseFloat(size);
            
            // Check if it's a whale-sized order
            if (value >= CONFIG.WHALE_THRESHOLD_USD) {
              largeOrders.push({ 
                side, 
                price: parseFloat(price), 
                size: parseFloat(size), 
                value 
              });
            }
          }
        }
    
        if (largeOrders.length > 0) {
          this.#notifyWhaleOrder(coin, largeOrders);
        }
      } catch (error) {
        console.error('Error analyzing orderbook:', error.message);
      }
    }
    #notifyWhaleTrade(trade) {
      const emoji = trade.side === 'B' ? '🟢' : '🔴';
      const sideText = trade.side === 'B' ? 'BUY' : 'SELL';
      const shortAddress = trade.user !== 'Unknown' 
        ? `${trade.user.slice(0, 6)}...${trade.user.slice(-4)}`
        : 'Unknown';
      
      // Get whale statistics if available
      let whaleStats = '';
      const whale = this.#whaleAddresses.get(trade.user);
      if (whale) {
        whaleStats = `\n📈 Whale Stats: ${whale.tradeCount} trades | $${whale.totalVolume.toLocaleString()} total volume`;
      }
      
      const consoleMessage = `
    🐋 WHALE TRADE ALERT! 🐋
    
    ${emoji} ${sideText} ${trade.coin}
    
    💰 Size: ${trade.size.toFixed(2)} contracts
    💵 Price: $${trade.price.toFixed(2)}
    📊 Value: $${trade.value.toLocaleString()}
    👤 Trader: ${shortAddress}
    ${trade.user !== 'Unknown' ? `🔗 Address: ${trade.user}` : ''}${whaleStats}
    ${trade.hash ? `📝 TX Hash: ${trade.hash}` : ''}
    ${trade.tradeId ? `🆔 Trade ID: ${trade.tradeId}` : ''}
    🕐 Time: ${trade.time}
    
    ${trade.value >= 500000 ? '🚨 MEGA WHALE! 🚨' : ''}
      `;
    
      console.log(consoleMessage);
      
      // Send to Telegram if configured
      if (CONFIG.TELEGRAM_BOT_TOKEN && CONFIG.TELEGRAM_CHAT_ID) {
        if (CONFIG.TELEGRAM_BATCH_ALERTS) {
          this.#addToBatch({ type: 'trade', emoji, sideText, ...trade });
        } else {
          this.#sendTelegramMessage(consoleMessage);
        }
      }
    }
    #addToBatch(alert) {
      this.#pendingAlerts.push(alert);
      
      // Start batch timer if not already running
      if (!this.#batchTimer) {
        this.#batchTimer = setTimeout(() => {
          this.#sendBatchedAlerts();
        }, CONFIG.TELEGRAM_BATCH_INTERVAL);
      }
    }
    
    #sendBatchedAlerts() {
      console.log(`📦 Sending batched alerts: ${this.#pendingAlerts.length} trades`);
      
      if (this.#pendingAlerts.length === 0) {
        this.#batchTimer = null;
        return;
      }
    
      const totalValue = this.#pendingAlerts.reduce((sum, alert) => sum + alert.value, 0);
      const trades = this.#pendingAlerts.length;
      
      // Build compact batch message
      const alertsList = this.#pendingAlerts
        .map((alert, index) => {
          const shortAddr = alert.user !== 'Unknown' 
            ? `${alert.user.slice(0, 6)}...${alert.user.slice(-4)}`
            : 'Unknown';
          
          let line = `${index + 1}. ${alert.emoji} ${alert.sideText} ${alert.coin}\n`;
          line += `   💰 $${alert.value.toLocaleString()} | 👤 ${shortAddr}\n`;
          if (alert.value >= 500000) line += `   🚨 MEGA WHALE!\n`;
          return line;
        })
        .join('\n');
      
      const message = `🐋 WHALE ACTIVITY BATCH (${trades} trades, $${totalValue.toLocaleString()} total) 🐋\n\n${alertsList}\n🕐 ${new Date().toLocaleString()}`;
      
      console.log('📤 Adding batch message to Telegram queue...');
      this.#sendTelegramMessage(message);
      this.#pendingAlerts = [];
      this.#batchTimer = null;
    }
    async #sendTelegramMessage(message) {
      if (!CONFIG.TELEGRAM_BOT_TOKEN || !CONFIG.TELEGRAM_CHAT_ID) return;
    
      // Add to queue instead of sending immediately
      this.#telegramQueue.push(message);
      
      // Start processing if not already running
      if (!this.#isSendingTelegram) {
        this.#processTelegramQueue();
      }
    }
    
    async #processTelegramQueue() {
      if (this.#telegramQueue.length === 0) {
        this.#isSendingTelegram = false;
        return;
      }
    
      this.#isSendingTelegram = true;
      const message = this.#telegramQueue.shift();
    
      try {
        // Respect rate limit (1.5 seconds between messages)
        const timeSinceLastSend = Date.now() - this.#lastTelegramSent;
        if (timeSinceLastSend < this.#TELEGRAM_DELAY) {
          await new Promise(resolve => 
            setTimeout(resolve, this.#TELEGRAM_DELAY - timeSinceLastSend)
          );
        }
    
        // Send to Telegram API
        const url = `https://api.telegram.org/bot${CONFIG.TELEGRAM_BOT_TOKEN}/sendMessage`;
        
        const response = await fetch(url, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            chat_id: CONFIG.TELEGRAM_CHAT_ID,
            text: message,
            parse_mode: 'HTML'
          })
        });
    
        this.#lastTelegramSent = Date.now();
    
        if (!response.ok) {
          const errorData = await response.json();
          console.error('❌ Telegram API error:', response.status, errorData.description || '');
          
          // Handle rate limiting
          if (response.status === 429) {
            const retryAfter = errorData.parameters?.retry_after || 5;
            console.log(`⏳ Rate limited. Waiting ${retryAfter}s...`);
            await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
            this.#telegramQueue.unshift(message);  // Re-add to front
          }
        } else {
          console.log('✅ Telegram message sent');
        }
      } catch (error) {
        console.error('❌ Telegram error:', error.message);
      }
    
      // Process next message in queue
      setTimeout(() => this.#processTelegramQueue(), this.#TELEGRAM_DELAY);
    }
    async #testTelegramConnection() {
      try {
        const url = `https://api.telegram.org/bot${CONFIG.TELEGRAM_BOT_TOKEN}/getMe`;
        const response = await fetch(url);
        const data = await response.json();
        
        if (data.ok) {
          console.log(`✅ Telegram bot connected: @${data.result.username}`);
          await this.#sendTelegramMessage('🤖 Whale Tracker Started!\n\nMonitoring Hyperliquid for whale activity...');
          console.log('✅ Test message sent\n');
        } else {
          console.error('❌ Telegram error:', data.description);
        }
      } catch (error) {
        console.error('❌ Failed to connect to Telegram:', error.message);
        console.log('💡 Check your TELEGRAM_BOT_TOKEN\n');
      }
    }
    #handleReconnect(connection) {
      if (this.#reconnectAttempts >= this.#maxReconnectAttempts) {
        console.error(`Max reconnection attempts reached for ${connection}`);
        return;
      }
    
      this.#reconnectAttempts++;
      
      // Exponential backoff: 2s, 4s, 8s, 16s, 30s (max)
      const delay = Math.min(1000 * 2 ** this.#reconnectAttempts, 30000);
      
      console.log(`Reconnecting ${connection} in ${delay/1000}s... (Attempt ${this.#reconnectAttempts})`);
      
      setTimeout(() => {
        connection === 'hyperevm' ? this.connectHyperEVM() : this.connectHyperliquid();
      }, delay);
    }
    #printWhaleStats() {
      console.log('\n' + '='.repeat(60));
      console.log('📊 WHALE STATISTICS SUMMARY');
      console.log('='.repeat(60));
      console.log(`Total Whale Trades: ${this.#tradeCount}`);
      console.log(`Unique Whales: ${this.#whaleAddresses.size}\n`);
    
      if (this.#whaleAddresses.size === 0) {
        console.log('='.repeat(60) + '\n');
        return;
      }
    
      console.log('Top 10 Whales by Volume:');
      console.log('-'.repeat(60));
      
      // Sort whales by total volume and get top 10
      const topWhales = Array.from(this.#whaleAddresses.values())
        .sort((a, b) => b.totalVolume - a.totalVolume)
        .slice(0, 10);
    
      topWhales.forEach((whale, index) => {
        const shortAddr = `${whale.address.slice(0, 8)}...${whale.address.slice(-6)}`;
        console.log(`${index + 1}. ${shortAddr}`);
        console.log(`   Volume: $${whale.totalVolume.toLocaleString()}`);
        console.log(`   Trades: ${whale.tradeCount}`);
        console.log(`   Markets: ${Array.from(whale.coins).join(', ')}`);
        console.log(`   Last Active: ${whale.lastSeen.toLocaleString()}\n`);
      });
    
      console.log('='.repeat(60) + '\n');
    }
    async start() {
      console.log('🚀 Starting Hyperliquid Whale Tracker...');
      console.log(`📊 Tracking: ${CONFIG.TRACKED_SYMBOLS.join(', ')}`);
      console.log(`💰 Whale threshold: $${CONFIG.WHALE_THRESHOLD_USD.toLocaleString()}\n`);
      
      // Test Telegram if configured
      if (CONFIG.TELEGRAM_BOT_TOKEN && CONFIG.TELEGRAM_CHAT_ID) {
        console.log('✅ Telegram notifications: ENABLED');
        console.log(`📱 Chat ID: ${CONFIG.TELEGRAM_CHAT_ID}`);
        console.log(`📦 Batch mode: ${CONFIG.TELEGRAM_BATCH_ALERTS ? `ON (every ${CONFIG.TELEGRAM_BATCH_INTERVAL/1000}s)` : 'OFF'}\n`);
        
        await this.#testTelegramConnection();
      } else {
        console.log('⚠️  Telegram notifications: DISABLED\n');
      }
      
      // Connect to Hyperliquid
      await this.connectHyperliquid();
      
      // Optional: Connect to HyperEVM
      if (CONFIG.HYPEREVM_WSS) {
        await this.connectHyperEVM();
      } else {
        console.log('ℹ️  HyperEVM WebSocket not configured (optional)\n');
      }
    
      // Print statistics every 5 minutes
      setInterval(() => this.#printWhaleStats(), 5 * 60 * 1000);
    }
    
    stop() {
      this.#ws?.close();
      this.#wsHyperEVM?.close();
      console.log('Bot stopped');
    }
    // Create bot instance
    const bot = new HyperliquidWhaleTracker();
    await bot.start();
    
    // Handle graceful shutdown
    process.on('SIGINT', () => {
      console.log('\n👋 Shutting down...');
      bot.stop();
      process.exit(0);
    });
    node index.js
    🐋 WHALE TRADE ALERT! 🐋
    
    🟢 BUY AVAX
    
    💰 Size: 56.00 contracts
    💵 Price: 17.88
    📊 Value: 1,001.392
    👤 Trader: Unknown
    
    📝 TX Hash: 0xc806e65080fb77e5c980042f145c7302024000361bfe96b76bcf91a33fff51d0
    🆔 Trade ID: 720410117733902
    🕐 Time: 11/8/2025, 12:07:11 PM
    
    🐋 WHALE TRADE ALERT! 🐋
    
    🔴 SELL HYPE
    
    💰 Size: 61.56 contracts
    💵 Price: 41.46
    📊 Value: 2,552.154
    👤 Trader: Unknown
    📝 TX Hash: 0x03f399453dfc2d42056d042f145c12020235002ad8ff4c14a7bc4497fcf0072c
    🆔 Trade ID: 438223268535475
    🕐 Time: 11/8/2025, 12:07:04 PM
    
        
    
    🐳 WHALE WALL DETECTED! 🐳
    
    📈 ETH Orderbook
    🟢 BID: $3442.20 × 47.29 = $162,787.146
    🟢 BID: $3442.10 × 182.11 = $626,825.342
    🔴 ASK: $3444.20 × 336.14 = $1,157,739.243
    🔴 ASK: $3444.30 × 64.56 = $222,347.131
    🔴 ASK: $3444.40 × 119.15 = $410,398.538
    
    🕐 11/8/2025, 12:07:16 PM
        
    ^C
    👋 Shutting down ...
    Bot stopped
    Connecting to GetBlock WebSocket...
    WebSocket error: Error: Unexpected server response: 503
    WebSocket connection closed
    Reconnecting in 16 seconds... (Attempt 4)
    # correct format
    HYPEREVM_WSS=wss://go.getblock.io/<ACCESS_TOKEN>
    node index.js

    Copy your user ID

    Telegram account

    How to Build a Pay-Per-Request Blockchain API With x402 and GetBlock

    Build a pay-per-request blockchain data API using the x402 protocol and GetBlock's node infrastructure.

    hashtag
    Overview

    The x402 protocol is an open payment method that enables developers and service providers to charge for and sell their APIs and content via HTTP without requiring third-party integrations, credential setup, or gas fees.

    The x402 protocol brings the HTTP 402 "Payment Required" status codearrow-up-right to life. Originally reserved in the HTTP specification for future use with digital payments, x402 finally implements this vision, enabling micropayments to be made directly over HTTP.

    hashtag
    How it works

    1. Frank adds "payment required" to his API endpoints

    2. His client requests a protected resource,

    3. The server responds with 402 Payment Required along with payment details.

    All of this happens in seconds, without traditional payment infrastructure.

    Traditional API monetization requires
    With x402

    hashtag
    Components of x402

    The x402 ecosystem consists of three main components, which are:

    1. Client Side:

    This is the interface e.g frontend, that users interact with, which initiates a request to access a paid resource. It handles the payment requirements, prepare payment payload and resubmits the request with payment.

    circle-exclamation

    Clients do not need to manage accounts, credentials, or session tokens beyond their crypto wallet. All interactions are stateless and occur over standard HTTP requests.

    1. Server Side:

    The server is the resource provider enforcing payment for access to its services, such as API services, content providers, or any HTTP-accessible resource requiring monetization. It defines payment requirements, verifies payment payloads, settles transactions, and provides the resources.

    circle-exclamation

    Servers do not need to manage client identities or maintain session state. Verification and settlement are handled per request.

    1. Facilitators:

    The facilitator is an optional but recommended service that verifies and settles payment between clients and servers.

    hashtag
    Architecture Overview

    Key Components Explained:

    Component
    Role
    SDK to Use

    hashtag
    Who is x402 For?

    • API Developers — Monetize your APIs without managing subscriptions or API keys

    • AI Agents — Enable autonomous systems to pay for resources programmatically

    • Content Creators — Charge per article, image, or download

    hashtag
    Real-Life Use Cases

    1. AI Agent Economy — AI agents paying for web searches, API calls, or compute resources

    2. Pay-Per-Article News — Read individual articles without monthly subscriptions

    3. Blockchain Data Services — Pay-per-query for on-chain analytics

    hashtag
    What You're Building

    In this guide, you'll build a complete pay-per-request blockchain data API:

    • Backend: Express.js server with x402 payment middleware

    • Frontend: Vanilla JavaScript dApp with MetaMask integration

    • Data Source: GetBlock's Ethereum node API

    Endpoints you'll create:

    Endpoint
    Price
    Description

    hashtag
    Prerequisites

    • Node.js 18+

    • MetaMask wallet

    • Base Sepolia USDC (from )

    hashtag
    A. Project Setup

    hashtag
    Step 1: Create Project Directories

    hashtag
    Step 2: Initialize Server Package

    hashtag
    Step 3: Install Dependencies

    Dependency Overview:

    Package
    Purpose

    hashtag
    Step 4: Configure package.json

    Update server/package.json:

    hashtag
    Folder Structure

    Create the following project structure:

    hashtag
    Backend: Express Server with x402

    hashtag
    Step 1: Environment Configuration

    Create server/.env:

    circle-info

    Replace 0xYourWalletAddressHere with your actual MetaMask wallet address. This is where you'll receive USDC payments.

    hashtag
    Step 2: Create the Server

    Create server/server.js and add the following code:

    hashtag
    Frontend: Vanilla JS dApp

    Create client/index.html and add the following code:

    hashtag
    Running the Application

    hashtag
    Step 1: Start the Server

    You should see:

    hashtag
    Step 2: Access the Frontend

    Open your browser and navigate to:

    Your frontend should look like this:

    1. Connect your wallet

    2. Select any of the endpoints you want to access

    3. Sign the request

    1. The payment is then verified, scroll down to see the result

    hashtag
    Troubleshooting

    1. "Failed to create payment payload: Address undefined": This means the wallet client was not properly initialized. Make sure you're using getAddress() to normalize the address:

    1. CORS Errors: This means the server not configured for x402 headers. Ensure CORS middleware includes x402 headers:

    1. "Facilitator does not support scheme": This mean the facilitator is unreachable or doesn't support your network. To resolve this:

    i. Check internet connection

    ii. Try an alternative facilitator: https://facilitator.payai.network

    iii. Verify you're using the correct network ID: eip155:84532

    1. "Facilitator Connectivity Issues"

    If the default facilitator is down, you can try:

    1. Wallet Signing Problems

    If MetaMask shows an error during signing:

    1. Check network — Ensure you're on Base Sepolia (Chain ID 84532)

    2. Check balance — Ensure you have enough USDC for the request

    hashtag
    Debug Mode

    Enable the debug log by clicking "Toggle Debug Log" at the bottom of the page. This shows:

    • Connection steps

    • Network switching

    • Signing requests

    • API responses

    hashtag
    Resources

    hashtag
    Conclusion

    In this guide, you learnt what x402 is all about, including its use cases, components, architecture diagram etc. You also learnt how to set up the project and built a complete pay-per-request blockchain data API using x402 and GetBlock.

    The client signs a payment authorisation
  • He/she retries the request and receives the data.

  • Instant micropayments — Charge per request

    Fraud prevention and rate limiting

    Built-in rate limiting — Users only call what they pay for

    Transaction or gas fee

    Gasless fee

    Third-party service that verifies payment signatures and settles USDC transfers.

    • https://x402.org/facilitator

    • https://facilitator.payai.network

    Data Providers — Sell real-time data feeds with per-request pricing
  • Blockchain Services — Offer RPC access, indexing, or analytics with micropayments

  • Premium API Access — Charge for rate-limited or enhanced API endpoints
  • Decentralized CDN — Pay nodes for bandwidth and storage per request

  • Payment: USDC on Base Sepolia testnet
    (free tier available)
  • Basic knowledge of JavaScript/Express

  • x402 core utilities (Resource Server, Facilitator Client)

    EVM blockchain support (Base, Ethereum)

    Express middleware for payment protection

    Error details

    Base Sepolia Explorerarrow-up-right
  • x402 + GetBlock dApp Repoarrow-up-right

  • User registration and account management

    No accounts needed — The wallet is the identity

    API key generation and rotation

    No API keys — Payment is the authentication

    Payment processing integration (e.gStripe, PayPal)

    Global access — Anyone with USDC can use your API

    Client (dApp)

    Browser app with wallet connection. Uses @x402/fetch to handle payments automatically.

    • @x402/evmarrow-up-right

    • @x402/fetcharrow-up-right

    Server (Express)

    Your API server. Uses @x402/express middleware to protect routes and define prices.

    • @x402/corearrow-up-right

    • @x402/expressarrow-up-right

    GET /api/eth/block/latest

    $0.001 USDC

    Get the latest Ethereum block number

    GET /api/eth/gas

    $0.001 USDC

    Get the current gas price

    expressarrow-up-right

    Web server framework

    corsarrow-up-right

    Cross-origin resource sharing

    axiosarrow-up-right

    HTTP client for GetBlock API

    dotenvarrow-up-right

    Circle Faucetarrow-up-right
    x402 Protocol Docsarrow-up-right
    GetBlock Account Dashboardarrow-up-right
    Circle Faucetarrow-up-right
    Result of the latest block number

    Subscription tiers and billing cycles

    Facilitator

    Environment variable management

    GetBlock API keyarrow-up-right
    mkdir getblock-x402-dapp
    cd getblock-x402-dapp
    mkdir server client
    cd server
    npm init -y
    npm install express cors axios dotenv @x402/core @x402/evm @x402/express
    {
      "name": "getblock-x402-server",
      "version": "1.0.0",
      "description": "",
      "main": "server.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start": "node server.js",
      },
      "keywords": ["x402", "getblock"]serv,
      "author": "",
      "license": "ISC",
      "type": "module",
      "dependencies": {
        "@x402/core": "^2.2.0",
        "@x402/evm": "^2.2.0",
        "@x402/express": "^2.2.0",
        "axios": "^1.13.2",
        "cors": "^2.8.5",
        "dotenv": "^17.2.3",
        "express": "^5.2.1"
      }
    }
    getblock-x402-dapp/
    ├── server/
    │   ├── server.js        # Express server with x402 middleware
    │   ├── package.json     # Server dependencies
    │   └── .env             # Environment variables (API keys)
    └── client/
        └── index.html       # Frontend dApp (single file)
    # Your wallet address to receive payments
    PAYMENT_WALLET_ADDRESS=0xYourWalletAddressHere
    
    # GetBlock API key (optional - will use mock data if not set)
    GETBLOCK_API_KEY=your_getblock_api_key_here
    
    # Server port
    PORT=4021
    server/server.js
    import express from "express";
    import cors from "cors";
    import path from "path";
    import { fileURLToPath } from "url";
    import { paymentMiddleware } from "@x402/express";
    import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server";
    import { registerExactEvmScheme } from "@x402/evm/exact/server";
    import axios from "axios";
    import "dotenv/config";
    
    // ES Module directory resolution
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = path.dirname(__filename);
    
    const app = express();
    
    // =============================================================================
    // CORS Configuration
    // =============================================================================
    // x402 uses custom headers for payment data, so we need to expose them
    app.use(
      cors({
        origin: true,
        credentials: true,
        methods: ["GET", "POST", "OPTIONS"],
        allowedHeaders: [
          "Content-Type",
          "Authorization",
          "X-PAYMENT",
          "X-Payment",
          "x-payment",
        ],
        exposedHeaders: [
          "X-PAYMENT-RESPONSE",
          "X-Payment-Response",
          "x-payment-response",
          "X-PAYMENT-REQUIRED",
          "X-Payment-Required",
          "x-payment-required",
        ],
      })
    );
    
    app.use(express.json());
    
    // =============================================================================
    // Request Logging (for debugging)
    // =============================================================================
    app.use((req, res, next) => {
      console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);
      
      const paymentHeader = req.headers["x-payment"] || req.headers["X-PAYMENT"];
      if (paymentHeader) {
        console.log("  Payment header present (length:", paymentHeader.length, ")");
      }
      
      next();
    });
    
    // =============================================================================
    // Configuration
    // =============================================================================
    const payTo = process.env.PAYMENT_WALLET_ADDRESS;
    const GETBLOCK_API_KEY = process.env.GETBLOCK_API_KEY;
    const GETBLOCK_URL = GETBLOCK_API_KEY
      ? `https://go.getblock.io/${GETBLOCK_API_KEY}`
      : null;
    
    console.log("\n📋 Configuration:");
    console.log(`   Payment wallet: ${payTo}`);
    console.log(`   GetBlock API: ${GETBLOCK_API_KEY ? "Configured" : "Not configured (using mock data)"}`);
    
    // Validate required config
    if (!payTo) {
      console.error("❌ Missing PAYMENT_WALLET_ADDRESS in .env");
      process.exit(1);
    }
    
    // =============================================================================
    // GetBlock API Helper
    // =============================================================================
    async function callGetBlock(method, params = []) {
      // If no API key, return mock data for demo purposes
      if (!GETBLOCK_URL) {
        console.log("  Using mock data (no GetBlock API key)");
        if (method === "eth_blockNumber") {
          const mockBlock = Math.floor(Date.now() / 1000);
          return { result: "0x" + mockBlock.toString(16) };
        }
        if (method === "eth_gasPrice") {
          return { result: "0x" + (20 * 1e9).toString(16) }; // 20 Gwei
        }
        return { result: null };
      }
    
      // Call GetBlock API
      try {
        const response = await axios.post(GETBLOCK_URL, {
          jsonrpc: "2.0",
          id: "getblock",
          method,
          params,
        });
        return response.data;
      } catch (error) {
        console.error("  GetBlock API error:", error.message);
        throw error;
      }
    }
    
    // =============================================================================
    // x402 Setup
    // =============================================================================
    
    // Initialize the facilitator client
    // The facilitator verifies payment signatures and settles transactions
    const facilitatorUrl = "https://facilitator.payai.network";
    console.log(`   Facilitator: ${facilitatorUrl}`);
    
    const facilitatorClient = new HTTPFacilitatorClient({
      url: facilitatorUrl,
    });
    
    // Create the resource server and register the EVM payment scheme
    const server = new x402ResourceServer(facilitatorClient);
    registerExactEvmScheme(server);
    
    // =============================================================================
    // Payment Route Configuration
    // =============================================================================
    // Define which routes require payment and how much they cost
    const paymentConfig = {
      "GET /api/eth/block/latest": {
        accepts: [
          {
            scheme: "exact",           // Payment scheme (exact amount)
            price: "$0.001",           // Price in USD
            network: "eip155:84532",   // Base Sepolia (CAIP-2 format)
            payTo,                     // Your wallet address
          },
        ],
        description: "Get latest Ethereum block number",
        mimeType: "application/json",
      },
      
      "GET /api/eth/gas": {
        accepts: [
          {
            scheme: "exact",
            price: "$0.001",
            network: "eip155:84532",
            payTo,
          },
        ],
        description: "Get current gas price",
        mimeType: "application/json",
      },
    };
    
    // Apply the payment middleware
    // This intercepts requests to protected routes and verifies payment
    app.use(paymentMiddleware(paymentConfig, server));
    
    // =============================================================================
    // Static Files & Routes
    // =============================================================================
    
    // Serve the frontend
    app.use(express.static(__dirname));
    
    app.get("/", (req, res) => {
      res.sendFile(path.join(__dirname, "../client/index.html"));
    });
    
    // Free endpoint: API information
    app.get("/api", (req, res) => {
      res.json({
        message: "GetBlock x402 API",
        version: "1.0.0",
        network: "Base Sepolia (eip155:84532)",
        facilitator: facilitatorUrl,
        payTo,
        endpoints: [
          {
            path: "/api/eth/block/latest",
            price: "$0.001 USDC",
            description: "Get latest Ethereum block number",
          },
          {
            path: "/api/eth/gas",
            price: "$0.001 USDC",
            description: "Get current gas price",
          },
        ],
      });
    });
    
    // =============================================================================
    // Protected Endpoints (require payment)
    // =============================================================================
    
    // Get latest block number
    app.get("/api/eth/block/latest", async (req, res) => {
      console.log("  ✓ Payment verified - serving block data");
      try {
        const result = await callGetBlock("eth_blockNumber");
        res.json({
          blockNumber: result.result,
          decimal: parseInt(result.result, 16),
          timestamp: new Date().toISOString(),
          source: GETBLOCK_URL ? "getblock" : "mock",
        });
      } catch (error) {
        console.error("  Error fetching block number:", error.message);
        res.status(500).json({ error: error.message });
      }
    });
    
    // Get current gas price
    app.get("/api/eth/gas", async (req, res) => {
      console.log("  ✓ Payment verified - serving gas data");
      try {
        const result = await callGetBlock("eth_gasPrice");
        const gasPriceWei = BigInt(result.result);
        res.json({
          gasPriceWei: result.result,
          gasPriceGwei: (Number(gasPriceWei) / 1e9).toFixed(2),
          timestamp: new Date().toISOString(),
          source: GETBLOCK_URL ? "getblock" : "mock",
        });
      } catch (error) {
        console.error("  Error fetching gas price:", error.message);
        res.status(500).json({ error: error.message });
      }
    });
    
    // =============================================================================
    // Error Handling
    // =============================================================================
    app.use((err, req, res, next) => {
      console.error("Server error:", err);
      res.status(500).json({ error: err.message });
    });
    
    // =============================================================================
    // Start Server
    // =============================================================================
    const PORT = process.env.PORT || 4021;
    app.listen(PORT, () => {
      console.log(`Server running at http://localhost:${PORT}`);
      console.log("Protected endpoints:");
      Object.entries(paymentConfig).forEach(([route, config]) => {
        console.log(`   ${route} - ${config.accepts[0].price} USDC`);
      })
    });
    client/index.html
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>GetBlock x402 dApp</title>
        <style>
          * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
          }
          body {
            font-family: -apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", sans-serif;
            background: rgb(0, 0, 0);
            min-height: 100vh;
            color: #fff;
            padding: 2rem;
          }
          .container {
            max-width: 700px;
            margin: 0 auto;
          }
          header {
            text-align: center;
            margin-bottom: 2rem;
          }
          h1 {
            font-size: 2.2rem;
            margin-bottom: 0.5rem;
            background: linear-gradient(90deg, #00d4ff, #7b2cbf);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
          }
          .subtitle {
            color: #888;
            margin-bottom: 1.5rem;
          }
          .wallet-section {
            text-align: center;
            margin-bottom: 2rem;
          }
          #connectBtn {
            background: #7b2cbf;
            color: white;
            border: none;
            padding: 1rem 2rem;
            border-radius: 12px;
            font-size: 1.1rem;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
          }
          #connectBtn:hover {
            opacity: 0.9;
            transform: translateY(-2px);
          }
          #walletInfo {
            background: rgba(0, 212, 255, 0.1);
            border: 1px solid rgba(0, 212, 255, 0.3);
            padding: 1rem;
            border-radius: 12px;
            display: none;
          }
          #walletInfo.connected {
            display: block;
          }
          .wallet-address {
            font-family: monospace;
            color: #00d4ff;
          }
          .endpoints {
            margin-top: 2rem;
          }
          .endpoints h2 {
            font-size: 1.2rem;
            color: #888;
            margin-bottom: 1rem;
          }
          .endpoint-card {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 1.25rem;
            background: rgba(255, 255, 255, 0.05);
            border-radius: 12px;
            margin-bottom: 0.75rem;
            border: 1px solid rgba(255, 255, 255, 0.1);
            transition: all 0.3s ease;
          }
          .endpoint-card:hover {
            background: rgba(255, 255, 255, 0.08);
            border-color: rgba(0, 212, 255, 0.3);
          }
          .endpoint-name {
            font-weight: 600;
            margin-bottom: 0.25rem;
          }
          .endpoint-price {
            color: #00d4ff;
            font-size: 0.9rem;
          }
          .pay-btn {
            background: #7b2cbf;
            color: white;
            border: none;
            padding: 0.6rem 1.2rem;
            border-radius: 8px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
          }
          .pay-btn:hover {
            opacity: 0.9;
          }
          .pay-btn:disabled {
            opacity: 0.5;
            cursor: not-allowed;
          }
          #status {
            margin-top: 1.5rem;
            padding: 1rem;
            border-radius: 12px;
            display: none;
          }
          #status.error {
            display: block;
            background: rgba(255, 0, 0, 0.1);
            border: 1px solid rgba(255, 0, 0, 0.3);
            color: #ff6b6b;
          }
          #status.loading {
            display: block;
            background: rgba(255, 255, 0, 0.1);
            border: 1px solid rgba(255, 255, 0, 0.3);
            color: #ffd93d;
          }
          #status.success {
            display: block;
            background: rgba(0, 255, 0, 0.1);
            border: 1px solid rgba(0, 255, 0, 0.3);
            color: #00ff88;
          }
          #result {
            margin-top: 1.5rem;
            display: none;
          }
          #result.show {
            display: block;
          }
          #result h3 {
            color: #00ff88;
            margin-bottom: 0.75rem;
          }
          #result pre {
            background: rgba(0, 0, 0, 0.4);
            padding: 1rem;
            border-radius: 8px;
            overflow-x: auto;
            font-size: 0.9rem;
          }
          footer {
            text-align: center;
            margin-top: 3rem;
            color: #666;
            font-size: 0.85rem;
          }
          .network-badge {
            display: inline-block;
            background: rgba(123, 44, 191, 0.2);
            color: #b57edc;
            padding: 0.25rem 0.75rem;
            border-radius: 20px;
            font-size: 0.8rem;
            margin-top: 0.5rem;
          }
          .info-box {
            background: rgba(255, 255, 255, 0.05);
            border: 1px solid rgba(255, 255, 255, 0.1);
            border-radius: 12px;
            padding: 1rem;
            margin-bottom: 1.5rem;
            font-size: 0.9rem;
            color: #aaa;
          }
          .info-box a {
            color: #00d4ff;
            text-decoration: none;
          }
          .info-box a:hover {
            text-decoration: underline;
          }
          .debug-log {
            background: rgba(0, 0, 0, 0.3);
            padding: 0.5rem;
            margin-top: 1rem;
            border-radius: 8px;
            font-family: monospace;
            font-size: 0.75rem;
            max-height: 200px;
            overflow-y: auto;
            display: none;
          }
          .debug-log.show {
            display: block;
          }
        </style>
      </head>
      <body>
        <div class="container">
          <header>
            <h1>GetBlock x402 dApp</h1>
            <p class="subtitle">Pay-per-request blockchain data powered by x402</p>
          </header>
    
          <div class="info-box">
            <strong>Requirements:</strong> MetaMask wallet with USDC on Base Sepolia testnet.<br />
            Get test USDC from <a href="https://faucet.circle.com/" target="_blank">Circle Faucet</a>
          </div>
    
          <div class="wallet-section">
            <button id="connectBtn">Connect Wallet</button>
            <div id="walletInfo">
              <p>Connected: <span class="wallet-address" id="walletAddress"></span></p>
              <p style="margin-top: 0.5rem; font-size: 0.85rem; color: #888">
                USDC Balance: <span id="usdcBalance">Loading...</span>
              </p>
              <span class="network-badge">Base Sepolia Testnet</span>
            </div>
          </div>
    
          <div class="endpoints" id="endpoints" style="display: none">
            <h2>Available Endpoints</h2>
            <div class="endpoint-card">
              <div>
                <div class="endpoint-name">Latest Block Number</div>
                <div class="endpoint-price">$0.001 USDC</div>
              </div>
              <button class="pay-btn" data-endpoint="/api/eth/block/latest">Pay & Fetch</button>
            </div>
            <div class="endpoint-card">
              <div>
                <div class="endpoint-name">Current Gas Price</div>
                <div class="endpoint-price">$0.001 USDC</div>
              </div>
              <button class="pay-btn" data-endpoint="/api/eth/gas">Pay & Fetch</button>
            </div>
          </div>
    
          <div id="status"></div>
          <div id="result">
            <h3>✓ Result</h3>
            <pre id="resultData"></pre>
          </div>
    
          <footer>
            <p>Network: Base Sepolia | Powered by GetBlock & x402</p>
            <a href="#" id="toggleDebug" style="color: #666; font-size: 0.75rem">Toggle Debug Log</a>
            <div class="debug-log" id="debugLog"></div>
          </footer>
        </div>
    
        <!-- Load dependencies from CDN -->
        <script type="module">
          // =======================================================================
          // Import Dependencies
          // =======================================================================
          import {
            createWalletClient,
            custom,
            getAddress,
          } from "https://esm.sh/[email protected]";
          import { baseSepolia } from "https://esm.sh/[email protected]/chains";
          import {
            x402Client,
            wrapFetchWithPayment,
          } from "https://esm.sh/@x402/fetch";
          import { registerExactEvmScheme } from "https://esm.sh/@x402/evm/exact/client";
    
          // =======================================================================
          // Configuration
          // =======================================================================
          const API_URL = "http://localhost:4021";
          const BASE_SEPOLIA_CHAIN_ID = "0x14a34"; // 84532 in hex
          const USDC_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e"; // Base Sepolia USDC
    
          // =======================================================================
          // State
          // =======================================================================
          let fetchWithPayment = null;
          let userAddress = null;
    
          // =======================================================================
          // DOM Elements
          // =======================================================================
          const connectBtn = document.getElementById("connectBtn");
          const walletInfo = document.getElementById("walletInfo");
          const walletAddressEl = document.getElementById("walletAddress");
          const usdcBalanceEl = document.getElementById("usdcBalance");
          const endpointsSection = document.getElementById("endpoints");
          const statusEl = document.getElementById("status");
          const resultEl = document.getElementById("result");
          const resultData = document.getElementById("resultData");
          const debugLog = document.getElementById("debugLog");
          const toggleDebug = document.getElementById("toggleDebug");
    
          // =======================================================================
          // Debug Logging
          // =======================================================================
          function log(msg, type = "info") {
            const time = new Date().toLocaleTimeString();
            const color =
              type === "error" ? "#ff6b6b" : type === "success" ? "#00ff88" : "#aaa";
            debugLog.innerHTML += `<div style="color:${color}">[${time}] ${msg}</div>`;
            debugLog.scrollTop = debugLog.scrollHeight;
            console.log(`[${type}]`, msg);
          }
    
          toggleDebug.addEventListener("click", (e) => {
            e.preventDefault();
            debugLog.classList.toggle("show");
          });
    
          function showStatus(message, type) {
            statusEl.textContent = message;
            statusEl.className = type || "";
          }
    
          // =======================================================================
          // USDC Balance Helper
          // =======================================================================
          async function getUsdcBalance(address) {
            try {
              // Call balanceOf(address) on USDC contract
              const data = "0x70a08231" + address.slice(2).padStart(64, "0");
              const result = await window.ethereum.request({
                method: "eth_call",
                params: [{ to: USDC_ADDRESS, data }, "latest"],
              });
              const balance = parseInt(result, 16) / 1e6; // USDC has 6 decimals
              return balance.toFixed(6);
            } catch (e) {
              log("Error getting USDC balance: " + e.message, "error");
              return "0.000000";
            }
          }
    
          // =======================================================================
          // Create x402-Compatible Signer
          // =======================================================================
          /**
           * Creates a signer object that x402 can use to sign payment authorizations.
           * This wraps MetaMask's signing capabilities in the interface x402 expects.
           */
          function createMetaMaskSigner(address, walletClient) {
            return {
              address: address,
    
              async signTypedData(typedData) {
                log("Signing payment authorization...");
                log("Domain: " + JSON.stringify(typedData.domain));
    
                try {
                  // Use viem's signTypedData which handles EIP-712 formatting
                  const signature = await walletClient.signTypedData({
                    account: address,
                    domain: typedData.domain,
                    types: typedData.types,
                    primaryType: typedData.primaryType,
                    message: typedData.message,
                  });
    
                  log("Signature obtained: " + signature.substring(0, 20) + "...", "success");
                  return signature;
                } catch (error) {
                  log("Signing error: " + error.message, "error");
                  throw error;
                }
              },
            };
          }
    
          // =======================================================================
          // Connect Wallet Handler
          // =======================================================================
          connectBtn.addEventListener("click", async () => {
            try {
              if (!window.ethereum) {
                showStatus("Please install MetaMask!", "error");
                return;
              }
    
              showStatus("Connecting wallet...", "loading");
              log("Requesting wallet connection...");
    
              // Request account access
              const accounts = await window.ethereum.request({
                method: "eth_requestAccounts",
              });
              userAddress = getAddress(accounts[0]); // Normalize address checksum
              log("Connected to: " + userAddress, "success");
    
              // Switch to Base Sepolia network
              log("Checking network...");
              try {
                await window.ethereum.request({
                  method: "wallet_switchEthereumChain",
                  params: [{ chainId: BASE_SEPOLIA_CHAIN_ID }],
                });
                log("On Base Sepolia", "success");
              } catch (switchError) {
                // Network not added - add it
                if (switchError.code === 4902) {
                  log("Adding Base Sepolia network...");
                  await window.ethereum.request({
                    method: "wallet_addEthereumChain",
                    params: [
                      {
                        chainId: BASE_SEPOLIA_CHAIN_ID,
                        chainName: "Base Sepolia",
                        nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 },
                        rpcUrls: ["https://sepolia.base.org"],
                        blockExplorerUrls: ["https://sepolia.basescan.org"],
                      },
                    ],
                  });
                } else {
                  throw switchError;
                }
              }
    
              // Create viem wallet client
              log("Creating wallet client...");
              const walletClient = createWalletClient({
                account: userAddress,
                chain: baseSepolia,
                transport: custom(window.ethereum),
              });
    
              // Create x402-compatible signer
              log("Creating x402 signer...");
              const signer = createMetaMaskSigner(userAddress, walletClient);
    
              // Initialize x402 client with EVM scheme
              log("Initializing x402 client...");
              const x402client = new x402Client();
              registerExactEvmScheme(x402client, { signer });
    
              // Wrap fetch with automatic payment handling
              fetchWithPayment = wrapFetchWithPayment(fetch, x402client);
              log("x402 client ready!", "success");
    
              // Update UI
              walletAddressEl.textContent = `${userAddress.slice(0, 6)}...${userAddress.slice(-4)}`;
    
              const balance = await getUsdcBalance(userAddress);
              usdcBalanceEl.textContent = balance + " USDC";
              log("USDC Balance: " + balance);
    
              walletInfo.classList.add("connected");
              connectBtn.style.display = "none";
              endpointsSection.style.display = "block";
              showStatus("", "");
            } catch (error) {
              log("Connection error: " + error.message, "error");
              showStatus("Connection failed: " + error.message, "error");
            }
          });
    
          // =======================================================================
          // Endpoint Button Click Handlers
          // =======================================================================
          document.querySelectorAll(".pay-btn").forEach((btn) => {
            btn.addEventListener("click", async () => {
              if (!fetchWithPayment) {
                showStatus("Please connect wallet first", "error");
                return;
              }
    
              const endpoint = btn.dataset.endpoint;
              const fullUrl = API_URL + endpoint;
    
              // Disable buttons during request
              document.querySelectorAll(".pay-btn").forEach((b) => (b.disabled = true));
              btn.textContent = "Processing...";
              showStatus("Making request...", "loading");
              resultEl.classList.remove("show");
    
              try {
                log("Request: GET " + fullUrl);
    
                // Make the paid request - x402 handles payment automatically
                const response = await fetchWithPayment(fullUrl, { method: "GET" });
    
                log("Response status: " + response.status);
    
                if (response.status === 402) {
                  const text = await response.text();
                  log("402 response: " + text.substring(0, 200), "error");
    
                  try {
                    const data = JSON.parse(text);
                    if (data.accepts) {
                      log("Payment requirements received", "error");
                      throw new Error("Payment failed - check USDC balance and try again");
                    }
                    throw new Error(data.error || "Payment required");
                  } catch (e) {
                    if (e.message.includes("Payment") || e.message.includes("USDC")) throw e;
                    throw new Error("Payment required");
                  }
                }
    
                if (!response.ok) {
                  const text = await response.text();
                  log("Error: " + text, "error");
                  throw new Error(`Failed (${response.status}): ${text}`);
                }
    
                // Success! Display the data
                const data = await response.json();
                log("Success!", "success");
                resultData.textContent = JSON.stringify(data, null, 2);
                resultEl.classList.add("show");
                showStatus("✓ Payment successful!", "success");
    
                // Refresh USDC balance
                const newBalance = await getUsdcBalance(userAddress);
                usdcBalanceEl.textContent = newBalance + " USDC";
              } catch (error) {
                log("Error: " + error.message, "error");
                showStatus("Error: " + error.message, "error");
              } finally {
                // Re-enable buttons
                document.querySelectorAll(".pay-btn").forEach((b) => {
                  b.disabled = false;
                  b.textContent = "Pay & Fetch";
                });
              }
            });
          });
    
          // =======================================================================
          // Handle Wallet Events
          // =======================================================================
          if (window.ethereum) {
            window.ethereum.on("accountsChanged", () => location.reload());
            window.ethereum.on("chainChanged", () => location.reload());
          }
    
          // =======================================================================
          // Initialize
          // =======================================================================
          log('Ready. Click "Connect Wallet" to start.');
          log("Toggle this debug log with the link below.");
        </script>
      </body>
    </html>
    cd server
    npm start
    📋 Configuration:
       Payment wallet: 0xYourWalletAddress
       GetBlock API: Configured
       Facilitator: https://facilitator.payai.network
    
    Server running at http://localhost:4021
    Protected endpoints:
       GET /api/eth/block/latest - $0.001 USDC
       GET /api/eth/gas - $0.001 USDC
    http://localhost:4021
    userAddress = getAddress(accounts[0]);
    allowedHeaders: ["X-PAYMENT", ...],
    exposedHeaders: ["X-PAYMENT-REQUIRED", ...],
    const facilitatorClient = new HTTPFacilitatorClient({
      url: "https://x402.org/facilitator", // Alternative facilitator
    });
    @x402/corearrow-up-right
    @x402/evmarrow-up-right
    @x402/expressarrow-up-right
    spinner