# Welcome

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

<figure><img src="/files/5YNCRFNRjbeZ4Xn0lpL8" alt=""><figcaption></figcaption></figure>

With our tools and services, you can focus on building your dApp 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.

{% embed url="<https://www.youtube.com/watch?v=fl3NwMBIxOQ>" %}
GetBlock Product Demo
{% endembed %}

### Core GetBlock Services

| Services                 | Description                                                                                                                               |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| **Plug-and-Play access** | <p></p><p>Our ready-to-use blockchain nodes and APIs help you get started immediately.</p>                                                |
| **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**  | <p></p><p>Our team is here to help with integrations, troubleshooting, and scaling.</p>                                                   |

## Discover GetBlock

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:blue;"><strong>Getting Started</strong></mark></td><td>Create your account, explore plans &#x26; features, and make your first API call</td><td></td><td><a href="/files/xWUoQfpc0XaLni2YLMgb">/files/xWUoQfpc0XaLni2YLMgb</a></td><td><a href="/pages/mVgnRqAFZCAbhLhEnSZG">/pages/mVgnRqAFZCAbhLhEnSZG</a></td></tr><tr><td><mark style="color:blue;"><strong>Guides</strong></mark></td><td>Set up endpoints, manage access tokens, and integrate GetBlock APIs step-by-step</td><td></td><td><a href="/files/zlQhfk77YmHREgWyPMp6">/files/zlQhfk77YmHREgWyPMp6</a></td><td><a href="/pages/R4pUHuTKY14ectSvd4TO">/pages/R4pUHuTKY14ectSvd4TO</a></td></tr><tr><td><mark style="color:blue;"><strong>API Reference</strong></mark></td><td>View supported networks, available endpoints, and full API specifications</td><td></td><td><a href="/files/YxptuIB6Qew9b78pWSJX">/files/YxptuIB6Qew9b78pWSJX</a></td><td><a href="/pages/411OdmnFkdjqCUVWSdSO">/pages/411OdmnFkdjqCUVWSdSO</a></td></tr></tbody></table>

## Popular chains

Get started with our most in-demand blockchain networks.

| [<img src="/files/gMsJNoQfWkKzgpysX1q2" alt="" data-size="line">](/api-reference/ethereum-eth) [**Ethereum**](/api-reference/ethereum-eth)                      | [<img src="/files/fTRlK0YynPulf6r8ROek" alt="" data-size="line">](/api-reference/tron-trx) [**Tron**](/api-reference/tron-trx)                  | [<img src="/files/uclOIwOetMhbyAj6P5hJ" alt="" data-size="line">](/api-reference/arbitrum-arb) [**Arbitrum**](/api-reference/arbitrum-arb) |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| [<img src="/files/F66kIpOv6GEbREOxgUw4" alt="" data-size="line">](/api-reference/bnb-smart-chain-bsc) [**BNB Smart Chain**](/api-reference/bnb-smart-chain-bsc) | [<img src="/files/BKJlM7C7P0WqZBNPizh4" alt="" data-size="line">](/api-reference/solana-sol) [**Solana**](/api-reference/solana-sol)            | [<img src="/files/magJuiefWcvVHpY8SNuH" alt="" data-size="line">](/api-reference/optimism-op) [**Optimism**](/api-reference/optimism-op)   |
| [<img src="/files/PeSfp4Sb3w2vzluuPuZA" alt="" data-size="line">](/api-reference/polygon-matic) [**Polygon**](/api-reference/polygon-matic)                     | [<img src="/files/HOHD0wP53ft1vSCRx8U0" alt="" data-size="line">](/api-reference/avalanche-avax) [**Avalanche**](/api-reference/avalanche-avax) | [<img src="/files/nVfu7B15Tg3dV23vDq5M" alt="" data-size="line">](/api-reference/base) [**Base**](/api-reference/base)                     |


# How to set up an account

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

### How to Sign Up

{% stepper %}
{% step %}
**Go to GetBlock**

Visit the [homepage](https://getblock.io/) and click on the 'Dashboard' button in the upper-right corner, or use [this direct link](https://account.getblock.io/sign-up).

<figure><img src="/files/mlX4Z1RPNQEV7bDX8XBh" alt="How to create an account on GetBlock"><figcaption><p>GetBlock's Sign-Up page, where users can register to access blockchain services</p></figcaption></figure>
{% endstep %}

{% step %}
**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.
* **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.
  {% endstep %}

{% step %}
**Review and accept policies**

During registration, you will be asked to accept our [Terms of Service](https://getblock.io/terms-of-service/) and [Privacy Policy](https://getblock.io/privacy-policy/).
{% endstep %}
{% endstepper %}

### Access the dashboard

Once you've created an account and signed in, you'll be directed to the GetBlock [**Dashboard**](https://account.getblock.io).&#x20;

* You can create endpoints
* Monitor your usage plan
* Access statistics.

<figure><img src="/files/Z9Fq94lA3AdJQUivVJpS" alt="GetBlock user dashboard for managing blockchain node access"><figcaption><p>GetBlock user Dashboard</p></figcaption></figure>

### Check your User ID

1. Click on your profile icon

<figure><img src="/files/3YwQHV0SonHoFV9w4FAu" alt="profile icon"><figcaption></figcaption></figure>

2. Click on the **Copy** Icon to copy your **User ID**

<figure><img src="/files/2LXniyVHDAYzyCpNvMwa" alt="Where to find the GetBlock user ID"><figcaption></figcaption></figure>


# 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:** 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.

***

### 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](/getting-started/how-to-set-up-an-account).
2. Click on the **profile icon** in the bottom-left corner of the sidebar. Select "**Create new team**" from the dropdown menu.

<figure><img src="/files/kItmybm0mNkclcd2Qj5R" alt="How to create a team account on GetBlock"><figcaption></figcaption></figure>

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

<figure><img src="/files/8geS11qm2WUt1FAm4nns" alt="Creating an enterprise account with RPC node provider GetBlock"><figcaption></figcaption></figure>

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

<figure><img src="/files/W3UBGBeVGbN7494ZYWrx" alt="Collaboration feature for GetBlock enterprise users"><figcaption></figcaption></figure>

***

### Adding teammates

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

{% hint style="warning" %}
**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.**
  {% endhint %}

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.

{% tabs %}
{% tab title="The teammate has a GetBlock account" %}

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 I&#x44;**,** and **send the invite**.

<figure><img src="/files/mcyg6W3JMQtKzaqmwcTb" alt="Adding users to the team account on GetBlock"><figcaption></figcaption></figure>

The user gets a notification and can accept the invite.
{% endtab %}

{% tab title="The teammate is not registered on GetBlock" %}

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.**
4. Send the invite.

{% hint style="warning" %}
The invite link is valid for 30 minutes. If it expires, please resend an invitation.
{% endhint %}

<figure><img src="/files/F8ScRTmSqXQW7VKacGPk" alt="Inviting teammates to GetBlock&#x27;s team account"><figcaption></figcaption></figure>

The user will receive an invitation email with a link to sign up and join the team.
{% endtab %}
{% endtabs %}

A team member is marked as ![Active](/files/Si6CXUCrAV8zdC9KoIh8) when they have successfully accepted the invitation and joined the team.

If the invitation has been sent but not yet accepted, their status remains ![Pending](/files/oTjPRgnkWTz8GmCy1qyS).

***

### 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.

<figure><img src="/files/k921inX4pjYzmNVGFB7d" alt="Managing team account user permissions and roles"><figcaption></figcaption></figure>

{% hint style="warning" %}
If a Member has no permissions assigned, they will have **View-Only access** by default.
{% endhint %}

#### **Roles-based permissions**

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

<table><thead><tr><th width="358.49609375">Action</th><th width="103.0234375" align="center">Owner</th><th width="108.4375" align="center">Admin</th><th align="center">Member</th></tr></thead><tbody><tr><td>Create &#x26; manage access tokens</td><td align="center">✅</td><td align="center">✅</td><td align="center"><a data-footnote-ref href="#user-content-fn-1">🔓</a></td></tr><tr><td>Manage subscriptions &#x26; payments</td><td align="center">✅</td><td align="center">✅</td><td align="center"><a data-footnote-ref href="#user-content-fn-2">🔓</a></td></tr><tr><td>Add &#x26; remove team members</td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td></tr><tr><td>Edit access levels</td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td></tr><tr><td>Promote to Admin</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td></tr></tbody></table>

{% hint style="success" %}
If you need someone to help manage other team members, be sure to give them **Admin** status.
{% endhint %}

***

### 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.

<figure><img src="/files/VvLZWgS5eHy9UDrRydXi" alt="Instructions to remove a team user from the GetBlock team account"><figcaption></figcaption></figure>

{% hint style="success" %}
When removed from a team, users lose access to that team workspace but keep their personal account.
{% endhint %}

***

### 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.

{% tabs %}
{% tab title="Registered on GetBlock" %}
When you have a pending team invitation, a notification badge appears on your account icon <img src="/files/W7VI6Y1VJbrTvuJxdrT5" alt="" data-size="line">.

1. Click your **account icon** to view an invitation.
2. Click **"Accept"** if you're ready to join.

<figure><img src="/files/oWFSGYzrmqL0iuS244DB" alt="How to join a team account on GetBlock"><figcaption></figcaption></figure>

3. After accepting the invitation, you are given access to your team’s workspace. Your [role and permissions](#roles-based-permissions) will be **determined by the team owner or admin**.

<figure><img src="/files/6C8PF9PwpJm92kBcuxEX" alt="Viewing permissions for team account users"><figcaption></figcaption></figure>
{% endtab %}

{% tab title="New to GetBlock" %}
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 **secure password** for your new account.
4. Check the boxes to agree to the **Terms of Service and Privacy Policy** and complete the registration.

{% hint style="warning" %}
The invite link is **valid for 30 minutes**. If it expires, ask the team **owner** or **admin** to send a new invitation.
{% endhint %}

<figure><img src="/files/4V61vN8ljFhM8jtrt7IV" alt="GetBlock sign-up page"><figcaption></figcaption></figure>

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

{% hint style="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.
* [**Managing Endpoints** ](/getting-started/endpoint-setup)– How to create and manage node endpoints.
* [**Plans & Limits**](/getting-started/plans-and-limits) – Understanding plans and payments.
  {% endhint %}
  {% endtab %}
  {% endtabs %}

***

### **Switching between personal & team accounts**

{% hint style="success" %}
A team user **does not lose** access to their personal account. They can still use and manage their own endpoints and subscriptions.
{% endhint %}

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.

<figure><img src="/files/1XLBvWs0ZJXFQq65af5q" alt="Using GetBlock&#x27;s personal and team accounts"><figcaption></figcaption></figure>

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

***

### **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.

***

### **Need help?**

If you run into any issues or have questions, please check out our [FAQ](https://getblock.io/faq/) or visit our [Contact Center](https://getblock.io/contact/). You can also use the **Help** button within your GetBlock dashboard to access support or submit a request.

[^1]: Not enabled by default; must be assigned by an Owner or Admin

[^2]: Not enabled by default, must be assigned by an Owner or Admin


# 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 [endpoint](/getting-started/endpoint-setup) you create is assigned a unique access token:

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

The \<ACCESS\_TOKEN> authenticates requests directly through the endpoint URL.

***

### Making an authenticated request

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

{% hint style="info" %}
Access tokens **cannot** **be** **sent** in **headers**.
{% endhint %}

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

```bash
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"
}'
```

Response:

```json
{"jsonrpc":"2.0","id":"getblock.io","result":"0x1449641"}
```

***

### 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 (![](/files/AMlx63gJ4QN41nifFWGU)) next to the endpoint.
4. Select the option to either **roll** (regenerate) or **delete** the token.

<figure><img src="/files/hVyKUhcuOQY0jX4JK6AR" alt="How to manage GetBlock access tokens"><figcaption><p>Regenerate or delete your access token</p></figcaption></figure>

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


# 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.

***


# 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 <https://getblock.io/pricing/>.

***

### Shared nodes

Shared nodes operate on a **resource-sharing model**, where multiple clients access the same underlying node infrastructure maintained by GetBlock.

<figure><img src="/files/D7NnZZBWSUnKDQtZsaPa" alt="GetBlock shared RPC node pricing options"><figcaption><p>GetBlock shared node service options</p></figcaption></figure>

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

* **Cost efficiency:** Benefit from our pricing model based on [**Compute Units (CU)**](/getting-started/plans-and-limits/what-counts-as-a-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.

{% hint style="success" %}
This option is ideal for developers and teams looking for reliable connectivity to various blockchain networks without the higher costs of dedicated server resources.
{% endhint %}

***

### 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.

{% hint style="success" %}
If your project demands the fastest, most reliable blockchain infrastructure, a Dedicated Node from GetBlock is a perfect choice.
{% endhint %}

<figure><img src="/files/tkmU70qml6vzDGdiYAK6" alt="What does it cost to deploy a private blockchain node"><figcaption><p>GetBlock private node features and pricing</p></figcaption></figure>

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.

{% hint style="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.
{% endhint %}

***

### 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 page](https://getblock.io/enterprise-api/) to learn more about how we tailor services to fit complex, high-demand environments.


# 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.

***

### Tracking subscription status

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

#### 1. Dashboard

<figure><img src="/files/p9P2gZiDY3GsD0yjj8P1" alt="tracking the status of dedicated blockchain node subscriptions from GetBlock account"><figcaption></figcaption></figure>

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.

#### 2. Plan manager

<figure><img src="/files/02Z5gOfXRybEgVAQ60T9" alt="How to manage dedicated node plans and subsciriptions from GetBlock&#x27;s user account"><figcaption></figcaption></figure>

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.

#### 3. "Endpoints" list

<figure><img src="/files/gTKvaG4tWK6EKs7NdA3v" alt="Checking the status of dedicated node subscriptions from the main GetBlock user dashboard"><figcaption></figcaption></figure>

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

***

#### Subscription status breakdown

<table><thead><tr><th width="201.48828125" align="center">Status</th><th width="219.43359375" align="center">Dashboard View</th><th align="center" valign="middle">Manage Plans View</th></tr></thead><tbody><tr><td align="center"><p><a data-footnote-ref href="#user-content-fn-1">Active</a></p><p>(<mark style="color:orange;">Recurring Payment)</mark></p></td><td align="center"><img src="/files/5uf5HpRoKauVq3womB0i" alt=""></td><td align="center" valign="middle"><img src="/files/LeXSfeoAx4JOYTgXrSPh" alt=""></td></tr><tr><td align="center"><p><a data-footnote-ref href="#user-content-fn-2">Active</a></p><p>(<mark style="color:green;">One-Time Payment)</mark></p></td><td align="center"><img src="/files/lI8vFCLGNkOiqapTfZWB" alt=""></td><td align="center" valign="middle"><img src="/files/BpDlS4c6unOEZLR8008h" alt=""></td></tr><tr><td align="center"><p><a data-footnote-ref href="#user-content-fn-3">Expiring Soon</a></p><p>(<mark style="color:green;">One-Time Payment</mark>)</p></td><td align="center"><img src="/files/gOWT6G9M14mQlUntvTtu" alt=""></td><td align="center" valign="middle"><img src="/files/1y7Tc82n0MeyFwn9BIJZ" alt=""></td></tr><tr><td align="center"><p><a data-footnote-ref href="#user-content-fn-4">In Grace Period</a></p><p>(<mark style="color:orange;">Recurring</mark> /<mark style="color:green;">One-Time</mark>)</p></td><td align="center"><img src="/files/mfUYh9EDziFrbGFZK3qb" alt=""></td><td align="center" valign="middle"><img src="/files/FYhLgzwU35lZB1b84zga" alt=""></td></tr></tbody></table>

***

### 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 car&#x64;**.**

{% hint style="warning" %}
**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.
{% endhint %}

#### Available options

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

* 1 month
* 6 months
* 12 months

***

### How to extend your Dedicated Node plan

There are three ways to extend your subscription.

#### Option 1: The Dedicated Nodes dashboard

1. Go to **Dedicated Nodes** tab from your dashboar&#x64;**.** Look for the subscription alert widget.

<figure><img src="/files/vHaVWNfVJ55OMUJnw1ys" alt="How to manage node subscriptions from the GetBlock dashboard"><figcaption></figcaption></figure>

2. 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**).

<figure><img src="/files/Y1GAunMkFL6lfmxDJ3lm" alt="How to extend dedicated node plan using GetBlock"><figcaption></figcaption></figure>

2. **Choose a new period** and review details. Proceed to checkout.
3. Complete the payment by following the instructions provided.
4. Check the "**Payment History**" under the **Pricing** tab to track the progress.

#### Video guide

{% tabs %}
{% tab title="Fiat payments" %}
**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.

{% embed url="<https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFOeg95CadVyFvyLi70Bh%2Fuploads%2F8pIYDgoi9y0CC2FAKCOb%2FExtendingDedicNodes_Widget_Paddle.mp4?alt=media&token=e5db1173-11ce-43a7-9ca0-af3de0a6e62c>" %}
How to extend your node subscription with a card payment
{% endembed %}
{% endtab %}

{% tab title="Cryptocurrency payments" %}
**For crypto payments**:

* Payments are processed via **NOWPayments**.
* Make sure to account for **network fees** to avoid payment issues.
* The extension is applied **after blockchain confirmation**, which may take a few minutes.

{% embed url="<https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFOeg95CadVyFvyLi70Bh%2Fuploads%2FakJE50bGOIdiyyIyo61n%2FExtending_nodes_CryptoPayments.mp4?alt=media&token=f539d7e3-d430-4665-a39c-d09f7a6f1ce9>" fullWidth="false" %}
{% endtab %}
{% endtabs %}

#### 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.

<figure><img src="/files/RsqaBhaSDk7aMeXsRYDx" alt="Managing RPC node subscriptions from the main dashboard&#x27;s endpoints list"><figcaption></figcaption></figure>

#### 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.

<figure><img src="/files/butcYG5XnDue5If8KD51" alt="Flexible dedicated RPC node plan subscription"><figcaption></figcaption></figure>

***

### How to keep your Dedicated Node running smoothly

* [ ] **Keep an eye on your subscription.** Check your dashboard or plan manager to track expiration dates. Status tracking is now easier with our latest updates.
* [ ] Avoid disruptions by **renewing before your subscription ends**. This ensures your node remains active and accessible without downtime.
* [ ] For **recurring payments**, ensure your card information is up to date. Payment failures (e.g., expired card) can interrupt service.

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

[^1]: Your node subscription renews automatically at the end of each billing cycle using a saved payment method.

[^2]: The node is active under a one-time payment plan and will not renew automatically. To continue using the service, you’ll need to manually extend the subscription before it expires.

[^3]: The subscription will expire soon (within 3 days). Renewal is required.

[^4]: After the subscription expires, there is a 3-day grace period where the node remains active. During this time, you can renew your subscription or resolve payment issues (update billing details).


# 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.

{% hint style="success" %}

* **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.
  {% endhint %}

***

### 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:

* [**CU (Compute Units)**](/getting-started/plans-and-limits/what-counts-as-a-cu): 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**](/getting-started/authentication-with-access-tokens)**:** 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.

<table><thead><tr><th width="120.7734375">Plan</th><th width="90.09765625">Free</th><th width="116.25">Starter</th><th width="124.421875">Advanced</th><th width="125.66015625">Pro</th><th>Enterprise</th></tr></thead><tbody><tr><td><a data-footnote-ref href="#user-content-fn-1">Price/month</a></td><td>$0</td><td>$49</td><td>$199</td><td>$499</td><td>from $999</td></tr><tr><td>CU Allocation</td><td>50k/day</td><td>50M/month</td><td>220M/month</td><td>600M/month</td><td>Custom</td></tr><tr><td>RPS Limit</td><td>20 RPS</td><td>100 RPS</td><td>300 RPS</td><td>500 RPS</td><td>Custom</td></tr><tr><td>Access Tokens</td><td>2</td><td>10</td><td>25</td><td>50</td><td>Custom</td></tr><tr><td>Extra CU Purchase</td><td>❌</td><td>✅</td><td>✅</td><td>✅</td><td>✅</td></tr></tbody></table>

To see the full comparison table, navigate to <https://getblock.io/pricing/>.

{% hint style="info" %}
Your **balance of CUs for Shared Nodes** is distributed on **all endpoints** added under the ‘Shared nodes’ tab.
{% endhint %}

{% tabs %}
{% tab title="1) Free plan" %}
The plan is ideal if you’re **just starting out** and do not have complex calls or large request volumes.

<figure><img src="/files/8mZNbqMDhJ0YPPb9UIbG" alt="GetBlock&#x27;s free RPC node plan limits"><figcaption></figcaption></figure>

* **CU**: 50,000/day
* **Throughput**: 20 requests per second (RPS)
* **Access Tokens**: 2

{% hint style="warning" %}
**Compute Units** are **renewed daily**, but unused CUs cannot be transferred to the next day.
{% endhint %}

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

{% tab title="2) Starter plan" %}
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.

<figure><img src="/files/G6PnPWGcWBYJQdtPCfI1" alt="Starter plan limits for Shared RPC nodes by GetBlock"><figcaption></figcaption></figure>

* **CU**: 50M per month (\~1.6M/day)
* **Throughput**: 100 requests per second (RPS)
* **Access Tokens**: 10
* Additional CU packages can be purchased as needed.
  {% endtab %}

{% tab title="3) Advanced plan" %}
The Advanced Plan is a **mid-to-upper tier, production-ready** plan, suitable for moderate-to-high traffic applications.

<figure><img src="/files/qY1yQrZkBp3qcauNcC4Z" alt=""><figcaption></figcaption></figure>

* **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
  {% endtab %}

{% tab title="4) Pro plan" %}
The Pro Plan is built for applications that need significantly **higher throughput** and **increased resource availability** compared to lower tier plans.

<figure><img src="/files/s66ScJA0jak5VzYky9hO" alt="RPC node with higher-limit access"><figcaption></figcaption></figure>

* **CU**: 600M per month (\~20M/day)
* **Throughput**: 500 requests per second (RPS)
* **Access Tokens**: 50
* Purchase additional CU packages when required
  {% endtab %}

{% tab title="5) Enterprise plan" %}
The Enterprise plan is **fully customizable** with tailored CU allocations, rate limits, and access tokens to meet exceptionally high call volumes and performance requirements.

<figure><img src="/files/asn5nO6hEHO8HKjcTi9U" alt="GetBlock&#x27;s Enterprise plan with custom usage limit settings"><figcaption></figcaption></figure>

* **CU**: Custom monthly allocation based on your demands
* **Throughput**: Custom
* **Access Tokens**: Custom
* Additional CU packages can be purchased on demand
  {% endtab %}
  {% endtabs %}

***

#### 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.

{% hint style="success" %}
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.

* [Top up CUs and boost limits](/getting-started/plans-and-limits/top-up-cus-and-boost-limits)
  {% endhint %}

***

### Dedicated node limits

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

<figure><img src="/files/ssghd4RcFuMt41sF8tX3" alt="Dedicated node for scalable and unlimited RPC node access"><figcaption></figcaption></figure>

* **CU**: Unlimited
* **Rate**: Unlimited

***

If you’re unsure which plan best fits your needs, our team is ready to help! [Contact our support team](https://getblock.io/contact/) or visit our [Choosing your plan](/getting-started/plans-and-limits/choosing-your-plan) page for more information.\\

[^1]: Prices are based on monthly billing. Opt for **annual subscriptions** to save up to **$200 per month**


# 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.

{% hint style="info" %}

#### Request vs CU

**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.
{% endhint %}

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

<figure><img src="/files/koaP376V4kQTrPFXSnL5" alt="How to check your CU balance in GetBlock accounts"><figcaption></figcaption></figure>

This model ensures costs are aligned with actual infrastructure usage.

{% hint style="info" %}
**Learn More**

* [CU and rate limits](/getting-started/plans-and-limits/cu-and-rate-limits) — Check how many CUs are included in each plan.
  {% endhint %}

***

### 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:

$$
\text{Total CU} = \text{Chain Multiplier} \times \text{Method Multiplier} \times \text{Archive Modifier}
$$

Where:

* **Archive Modifier = 1** for standard full-node requests
* **Archive Modifier = 2** for requests served by archive endpoint

***

#### 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:

<table><thead><tr><th width="340.78125" align="center">Chains</th><th width="110.8125" align="center">Multiplier</th><th align="center">Explanation</th></tr></thead><tbody><tr><td align="center">Algorand, Bitcoin, Bitcoin Cash, Dash, Dogecoin, Ethereum Classic, Kusama, Litecoin, Near, OKB, Polkadot, Rootstock, Scroll, Shiba Inu, Sonic, Syscoin, Telos, Zcash, <em>others</em></td><td align="center">10</td><td align="center">Low per-request resource cost and write/read complexity</td></tr><tr><td align="center">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</td><td align="center">20</td><td align="center">Moderate resource intensity</td></tr><tr><td align="center">Allora, Avail, Bahamut, Chiliz, Ronin, Stellar, Zilliqa, Xphere</td><td align="center">30</td><td align="center">Moderate–high resource intensity</td></tr><tr><td align="center">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</td><td align="center">50</td><td align="center">High resource intensity: high throughput, large state or complex execution environments</td></tr></tbody></table>

***

#### 2. Method-specific multipliers

Different API methods **put different loads on backend nodes**. For example:

* <mark style="color:green;">`eth_blockNumber`</mark> is lightweight since it just returns the latest block number.
* <mark style="color:green;">`trace_replayBlockTransactions`</mark> 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**.

<table><thead><tr><th width="271.0625">Ethereum RPC Method</th><th align="center">Method Multiplier</th><th align="center">Base Chain Multiplier</th><th align="center">Total CU</th></tr></thead><tbody><tr><td><code>eth_blockNumber</code></td><td align="center">1</td><td align="center">20</td><td align="center">20</td></tr><tr><td><code>eth_getTransactionByHash</code></td><td align="center">1</td><td align="center">20</td><td align="center">20</td></tr><tr><td><code>debug_traceTransaction</code></td><td align="center">2</td><td align="center">20</td><td align="center">40</td></tr><tr><td><code>debug_traceBlock</code></td><td align="center">2</td><td align="center">20</td><td align="center">40</td></tr><tr><td><code>trace_call</code></td><td align="center">2</td><td align="center">20</td><td align="center">40</td></tr><tr><td><code>trace_transaction</code></td><td align="center">2</td><td align="center">20</td><td align="center">40</td></tr><tr><td><code>txpool_status</code></td><td align="center">2</td><td align="center">20</td><td align="center">40</td></tr><tr><td><code>trace_replayTransaction</code></td><td align="center">4</td><td align="center">20</td><td align="center">80</td></tr></tbody></table>

> Calculation example for <mark style="color:green;">`debug_traceTransaction`</mark>:\
> \
> $$20\ (\text{Ethereum base multiplier}) \times 2\ (\text{method multiplier}) = \mathbf{40\ CU}$$

For full details on all methods - including exact multipliers and total CU values for each protocol - please refer to our [Compute Units page](https://getblock.io/pricing/compute-units/).

***

#### 3. Archive modifier

GetBlock Shared Node endpoints can be configured in [Archive Mode](/getting-started/endpoint-setup/enabling-archive-mode) to provide historical state access from managed archive nodes.&#x20;

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).

<table data-full-width="false"><thead><tr><th width="227.4296875">Ethereum RPC Method</th><th align="right">Method Multiplier</th><th align="right">Base Chain Multiplier</th><th align="right">Archive Modifier</th><th align="right">Total CU (Archive Endpoint)</th></tr></thead><tbody><tr><td><code>eth_blockNumber</code></td><td align="right">1</td><td align="right">20</td><td align="right">2</td><td align="right">40</td></tr><tr><td><code>eth_getTransactionByHash</code></td><td align="right">1</td><td align="right">20</td><td align="right">2</td><td align="right">40</td></tr><tr><td><code>debug_traceTransaction</code></td><td align="right">2</td><td align="right">20</td><td align="right">2</td><td align="right">80</td></tr><tr><td><code>debug_traceBlock</code></td><td align="right">2</td><td align="right">20</td><td align="right">2</td><td align="right">80</td></tr><tr><td><code>trace_call</code></td><td align="right">2</td><td align="right">20</td><td align="right">2</td><td align="right">80</td></tr><tr><td><code>trace_transaction</code></td><td align="right">2</td><td align="right">20</td><td align="right">2</td><td align="right">80</td></tr><tr><td><code>txpool_status</code></td><td align="right">2</td><td align="right">20</td><td align="right">2</td><td align="right">80</td></tr><tr><td><code>trace_replayTransaction</code></td><td align="right">4</td><td align="right">20</td><td align="right">2</td><td align="right">160</td></tr></tbody></table>

{% hint style="info" %}

#### 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.
{% endhint %}

The tables above includes selected RPC methods for illustration purposes. The complete list of all CU costs is maintained on the [Compute Units page](https://getblock.io/pricing/compute-units/).&#x20;

***

### Why we use the CU system at GetBlock?

#### 🛡️ **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.

#### 💰 **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.

#### ⚙️ To h**elp 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.


# 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.

***

### Add Compute Units: Paid plan users

<figure><img src="/files/x5zpPQpzy5Ti6cLAa7ZX" alt="managing GetBlock CU balance"><figcaption></figcaption></figure>

**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.

<figure><img src="/files/LjQxNUd91ZpFN18ngx8m" alt="How to add CU to your GetBlock RPC node package balance"><figcaption></figcaption></figure>

Your account balance will be updated immediately upon successful payment.

***

### **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.

<figure><img src="/files/8IULlrhl7MleJCKtcvKW" alt="Switching from free GetBlock free plan to higher limit plans"><figcaption></figcaption></figure>

***

### 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.

<figure><img src="/files/3IDl0haXPxxzJz928Hib" alt="Increasing RPC node limits"><figcaption></figcaption></figure>

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

<figure><img src="/files/ebGVh5T4GiFUZHRCsgeq" alt="Customizing GetBlock&#x27;s Enterprise plan usage limits"><figcaption></figcaption></figure>

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

{% hint style="success" %}
This feature is perfect for users who need higher transaction throughput without changing their plan. For more demanding needs, consider [Dedicated Nodes](https://getblock.io/dedicated-nodes/).
{% endhint %}


# Payment methods

GetBlock supports both fiat and crypto payments.

### 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.

<figure><img src="/files/POwQpYrLhKCBhUUXIbO8" alt="How to pay with fiat on GetBlock"><figcaption><p>Selecting fiat as a payment method</p></figcaption></figure>

{% hint style="warning" %}
Please, account for VAT when planning your payments.
{% endhint %}

***

#### 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.

<figure><img src="/files/cD1QC5GjzR1RBmzLN7YS" alt="changing billing data in GetBlock accounts"><figcaption></figcaption></figure>

***

### 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.

<figure><img src="/files/KjhnBo6jd4MpnqpBRIYX" alt="How to pay for RPC nodes with crypto"><figcaption><p>Crypto payments</p></figcaption></figure>

{% hint style="warning" %}
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**.
{% endhint %}


# 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.


# 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.

{% hint style="success" %}
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:

* [Access token management](/getting-started/authentication-with-access-tokens)
* [GetBlock Deploys Major Security Upgrade: Introducing Access Tokens](https://getblock.io/blog/getblock-deploys-major-security-upgrade-introducing-access-tokens/)
  {% endhint %}

***

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

{% stepper %}
{% step %}
Log in to your GetBlock account and navigate to the **Dashboard**
{% endstep %}

{% step %}
Find the **Endpoints** section on the Dashboard
{% endstep %}

{% step %}
Click **Get endpoint** to open the endpoint setup menu

<figure><img src="/files/XJy1ecljbs82vXL4jsxG" alt="GetBlock RPC endpoint setup interface"><figcaption></figcaption></figure>
{% endstep %}

{% step %}
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)

<figure><img src="/files/8hEmvkS3RnWI3iXVCPV9" alt="How to create a node endpoint for blockchain API access"><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Click 'Get' and have the endpoint URL with an access token generated.
{% endstep %}
{% endstepper %}

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.

{% hint style="info" %}
All GetBlock endpoints follow a predictable format. The visible difference is the hostname reflecting the region selected during the setup.

**Endpoint examples**:

```markup
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>/
```

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

***

### 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.

{% hint style="info" %}
Selecting the Archive mode for an endpoint changes how requests are billed in Compute Units (CU). Learn more in the [Archive mode guide](/getting-started/endpoint-setup/enabling-archive-mode).
{% endhint %}

***

### 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 (![](/files/AMlx63gJ4QN41nifFWGU)) to roll (regenerate) or delete the endpoint from the list.

<figure><img src="/files/NQfXmLQFpsMIL6Y2THvu" alt="Blockchain RPC nodes list within the GetBlock account"><figcaption></figcaption></figure>

{% hint style="warning" %}
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.
{% endhint %}


# 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`](/api-reference/ethereum-eth/eth_getbalance-ethereum)`(address, blockNumber)`, [`eth_getStorageAt`](/api-reference/ethereum-eth/eth_getstorageat-ethereum)`(contract, slot, blockNumber)`, [`eth_getCode`](/api-reference/ethereum-eth/eth_getcode-ethereum)`(address, blockNumber)`, etc.
* Call view functions against historical state: e.g. [`eth_call`](/api-reference/ethereum-eth/eth_call-ethereum)`(..., 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.

***

### 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 ( <img src="/files/vHlQIWlk4BmghSpqJ2Yh" alt="history/clock icon" data-size="original"> ) when picking a protocol during the [endpoint setup](/getting-started/endpoint-setup/creating-node-endpoints). It indicates that Archive mode is available for that blockchain.

<figure><img src="/files/SFNzvTrak0DXkMcykOld" alt="Archive blockchain data access via GetBlock RPC endpoints"><figcaption></figcaption></figure>

{% hint style="success" %}
If you need an archive data for a chain not covered by shared Archive mode, request a [Dedicated Node](/getting-started/endpoint-setup/configuring-dedicated-nodes). **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
2. Unlimited query capacity
3. Custom node builds & tooling
   {% endhint %}

***

### 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.

<figure><img src="/files/yRCMZAsEm1cxecK9uhKO" alt="Get RPC endpoint button on GetBlock&#x27;s dashboard"><figcaption></figcaption></figure>

3. Find the Mode toggle and switch the **Archive** **mode** on.

<figure><img src="/files/MVsNLqc9fDVDrrMSN3Oo" alt=""><figcaption></figcaption></figure>

3. 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.

***

### CU billing for Shared Archive endpoints

Archive endpoints usage remains subject to your plan’s [CU limits and performance characteristics](https://docs.getblock.io/getting-started/plans-and-limits/cu-and-rate-limits).

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 [Compute Units](https://getblock.io/pricing/compute-units/) 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.

***

### 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.

***

#### 💬 Need help with archive blockchain data?

[Tell us](https://getblock.io/contact/) what you’re building — our team can guide you to the most efficient archive node setup.


# 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.

<figure><img src="/files/vsxh7ihkhP3TAozMzrVm" alt="How to set up a private blockchain node with GetBlock"><figcaption></figcaption></figure>

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.

### Step 1: Configure your node

<figure><img src="/files/iJJmVkA5tVF4vBEaz8yK" alt="GetBlock dedicated node configuration tool"><figcaption></figcaption></figure>

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
   2. **Pick a deployment location**: Germany (Frankfurt), USA (New York), Singapore
   3. **Node client**: Choose your preferred node implementation (e.g., Geth)
   4. **API interface**: Review available interface types
3. Under the **Performance** section, select a [performance tier](/getting-started/endpoint-setup/configuring-dedicated-nodes/dedicated-node-performance-tiers):
   1. **High**: premium specs, max throughput
   2. **Standard**: enterprise specs, optimized pricing for moderate-high loads
4. Choose a subscription length — 1, 6, or 12 months — at the top of the summary panel (available discounts are applied automatically)

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

### 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

<figure><img src="/files/JSlDDiBcbXH3qriR9JDF" alt="GetBlock Dedicated RPC node add-ons "><figcaption></figcaption></figure>

Select any add-ons you need and click **Next**.

### Step 3: Payment

<figure><img src="/files/ac6nA7oslQQ4ONk2NbIa" alt="GetBlock private blockchain server ordering"><figcaption></figcaption></figure>

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.&#x20;
3. **Payment method** — Choose between **Credit Card** or **Crypto**.
4. **Subscription** — Enable the subscription toggle if you want to ensure your node renews automatically each billing cycle.
5. When ready, click **Go to Payment**.

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. &#x20;

{% hint style="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.
{% endhint %}

***

### Managing your dedicated node

<figure><img src="/files/36uB39dxUZC4RhlCVH4p" alt="How to use GetBlock dedicated nodes"><figcaption></figcaption></figure>

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.&#x20;


# 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.

***

### 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.

{% hint style="success" %}
Always check available configurations in your dashboard
{% endhint %}

#### *Reference High vs Standard tier comparison*&#x20;

<table><thead><tr><th width="208.7109375">Feature</th><th>High Performance</th><th>Standard Performance</th></tr></thead><tbody><tr><td><strong>Resource allocation</strong></td><td>Maximum hardware and bandwidth</td><td>Balanced hardware profile</td></tr><tr><td><strong>Throughput</strong></td><td>Highest supported</td><td>High</td></tr><tr><td><strong>SLA</strong></td><td>99.9% uptime</td><td>99.5% uptime</td></tr><tr><td><strong>Recommended for</strong></td><td>Applications with high transaction volumes &#x26; large user bases, mission-critical systems, and any workflow where latency and throughput are the top priority</td><td>Most production dApps, wallets, and enterprise tools or projects that need guaranteed resources but do not require the maximum performance tier</td></tr></tbody></table>

***

### 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.
4. **Client parameters**.

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

{% hint style="success" %}
Monthly costs are always shown during configuration in the **Dashboard** for each supported network and region.
{% endhint %}

<figure><img src="/files/g0jKSA07jDiHGknhsUYr" alt="GetBlock private node configuration tool with pricing" width="533"><figcaption><p>Dedicated Node pricing in the GetBlock Dashboard</p></figcaption></figure>

***

### 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).

<figure><img src="/files/wipq46ZFsXhAX2TViy9L" alt="Setting up a Dedicated Node performance tier via GetBlock dashboard" width="375"><figcaption></figcaption></figure>

3. 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.

***

#### **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. [Contact us](https://getblock.io/contact/) for tailored deployments.


# 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.

## 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:

1. Download the `getblock.config.json` file from your GetBlock account;
2. Make sure you have [jq](https://jqlang.github.io/jq/download/) installed. jq is a versatile command-line tool that enables extracting values from JSON files;
3. Navigate to your workspace or directory where you have imported the `getblock.config.json` file and open a terminal;
4. Now, you can make a GET request to a selected node endpoint using the curl command:

```bash
curl -X GET https://go.getblock.io/"$(jq -r '.shared.btc.mainnet.rest[0]' getblock.config.json)"/rest/chaininfo.json
```

## 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`

2. Download the `getblock.config.js` file from your GetBlock account. Add this file to your project directory.
3. Import the `getblock` module to a .js file that configures a new Web3 instance:

```javascript
const { getblock } = require('./getblock.config.js');
```

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

```javascript
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()}`
));
```

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

## 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:

```bash
npm install --save-dev hardhat
```

2. Navigate to your GetBlock account and install the `getblock.config.js` file. Copy and paste it into your working directory;
3. Open the `hardhat.config.js` file from your project directory and import the `getblock` module:

```javascript
const { getblock } = require('./getblock.config.js');
```

4. 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.

```javascript
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
  }
}
```


# Testing RPC connection

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


# 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.

### Fetch the current block number

Run the following command to retrieve the latest block number:

```bash
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"
}'
```

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

```json
{
    "jsonrpc": "2.0",
    "id": "getblock.io",
    "result": "0x1449641"
}
```

### Get the chain ID

Identify the blockchain network with the `eth_chainId` method:

```bash
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"
}'
```

Response example:

```json
{
  "jsonrpc": "2.0",
  "id": "getblock.io",
  "result": "0x1"
}
```

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

### Check account balance by address

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

```bash
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"
}'
```

Example response:

```json
{
    "jsonrpc": "2.0",
    "id": "getblock.io",
    "result": "0x5a70dac3910910"
}
```

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

{% hint style="info" %}
For a list of supported RPC methods with examples, navigate to [API Reference](https://github.com/GetBlock-io/getblock-docs/blob/main/guides/testing-rpc-connection/broken-reference/README.md).
{% endhint %}


# 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: <https://documenter.getpostman.com/view/28751185/2s9YRDzqcX>.

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.
3. Paste the access token copied from your account instead of `{YOUR_ACCESS_TOKEN}`.

<figure><img src="/files/MvZOv8csBMYiZR5fwi2t" alt="Using Postman Collection for Ethereum JSON-RPC request"><figcaption><p>Using Postman to send a JSON-RPC request to an Ethereum node via GetBlock</p></figcaption></figure>

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


# Errors and troubleshooting

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

### Connection issues

<table><thead><tr><th width="205">Code</th><th width="154">Error message</th><th>Solution</th></tr></thead><tbody><tr><td>401</td><td>Access denied</td><td>Double-check that <code>&#x3C;ACCESS_TOKEN></code> is correctly replaced with your actual token. Ensure there are no trailing spaces.</td></tr><tr><td>404</td><td>Could not resolve host</td><td>Verify that the URL <code>https://go.getblock.io/&#x3C;ACCESS_TOKEN>/</code> is correct.</td></tr><tr><td>429</td><td>Too many requests</td><td>Check your GetBlock account for usage limits. Upgrade your plan if necessary.</td></tr></tbody></table>

### JSON-RPC errors

<table><thead><tr><th width="205">Code</th><th width="158">Error message</th><th>Solution</th></tr></thead><tbody><tr><td>32601</td><td>The method does not exist/is not available</td><td>Verify the method name (<code>eth_blockNumber</code>, <code>eth_getBalance</code>, etc.) against the blockchain's JSON-RPC <a href="https://github.com/GetBlock-io/getblock-docs/blob/main/guides/testing-rpc-connection/broken-reference/README.md">specifications</a>.</td></tr><tr><td>32602</td><td>Invalid argument</td><td>Ensure the parameters in the <code>params</code> array match the expected format for the method.</td></tr><tr><td>32700</td><td>Parse error</td><td>Double-check your JSON syntax. Ensure your request is properly formatted.</td></tr></tbody></table>


# 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.

### Dashboard

<figure><img src="/files/TpvVqSoraiCgXNd3Hizz" alt="How to track your blockchain node service usage statistics"><figcaption></figcaption></figure>

The Dashboard provides a quick snapshot of key metrics:

* Your current plan details
* Remaining CU balance
* Rate limit based on your plan
* Total requests made in the last 24 hours

***

### Detailed statistics

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

{% hint style="info" %}
Customize the data view by **parameters** or by **access** **tokens** using the dropdown menu.
{% endhint %}

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

<figure><img src="/files/zYUQbQyTlV5NFKcIvCFA" alt="How to track your blokchain API usage"><figcaption><p>The Statistics tab shows more in-depth and customizable data analysis for your endpoints</p></figcaption></figure>

All data is displayed through infographics, including:

* Number of requests and CUs
* Response statuses
* Method call distribution
* Rate limit rejections

***

### 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&#x20;
* Dedicated node deployed and activated
* Recurring payment cancelled

{% hint style="warning" %}
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.
{% endhint %}

<figure><img src="/files/IJTUaSIJvz5423l5N1WV" alt="Managing your blockchain RPC node usage with notifications" width="375"><figcaption></figcaption></figure>

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.


# 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.

{% hint style="success" %}
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
  {% endhint %}

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

***

### Before you start

#### Set up your wallet

If you don’t already have MetaMask, download and install it from the official website: <https://metamask.io/download>.

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

#### Get a custom RPC URL

Generate a JSON-RPC URL for the selected network from your GetBlock [account](https://getblock.io/) and copy it.

<figure><img src="/files/z4ksvaEeyRTZMrhiZREV" alt="How to get a custom RPC URL for MetaMask"><figcaption><p>Generate an RPC URL for MetaMask</p></figcaption></figure>

{% hint style="info" %}
Rename your endpoints to clearly indicate their purpose.
{% endhint %}

***

### 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 menu<img src="/files/4DWWQRq8EOlSbU9OjM18" alt="" data-size="original">next to it. Select 'Edit'.

<figure><img src="/files/24qkOY9g88Tl3vMkOXTn" alt="How to set up the custom RPC URL on MetaMask"><figcaption></figcaption></figure>

3. Open the ‘**Default RPC URL**’ dropdown and select '**Add RPC URL'**.
4. Paste the JSON-RPC endpoint URL from your GetBlock account (`https://go.getblock.io/<ACCESS_TOKEN>/`).
5. Name the new RPC URL for easier identification.

<figure><img src="/files/ifGsEdAX80kR4ietgU9j" alt="How to change the RPC URL on MetaMask"><figcaption></figcaption></figure>

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

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

***

### 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**'.

<figure><img src="/files/ClEy7losBbtDZR6EJsTN" alt="Adding a new network to MetaMask using custom RPC URL"><figcaption></figcaption></figure>

3. Fill in the required fields:

<table><thead><tr><th width="147">Field</th><th width="256">Description</th><th width="353">Example</th></tr></thead><tbody><tr><td><strong>RPC URL</strong></td><td>The network's JSON-RPC URL from your GetBlock account</td><td><em><mark style="color:blue;">https://go.getblock.io/&#x3C;ACCESS_TOKEN>/</mark></em></td></tr><tr><td><strong>Chain ID</strong></td><td>The ID of the network</td><td><em><mark style="color:blue;">1101</mark></em></td></tr><tr><td><strong>Network name</strong></td><td>Fetched automatically based on Chain ID</td><td><em><mark style="color:blue;">Polygon zkEVM</mark></em></td></tr><tr><td><strong>Currency symbol</strong></td><td>Suggested automatically based on Chain ID</td><td><em><mark style="color:blue;">ETH</mark></em></td></tr><tr><td><strong>Block explorer URL</strong></td><td>Optional field</td><td><em><mark style="color:blue;">https://zkevm.polygonscan.com/</mark></em></td></tr></tbody></table>

4. Click 'Save', and the custom network will be added and selected as default.

{% hint style="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:

```bash
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"
  }'
```

{% endhint %}


# 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/> and get one of the 100+ available chain endpoints.

{% hint style="success" %}
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
  {% endhint %}

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

***

### Before you start

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

#### Download Brave and set up the wallet

Brave Wallet is inseparable from the Brave browser. So, download and install the browser from the [official website](https://brave.com/wallet/). It’s available for desktop, Android, and iOS.

<figure><img src="/files/D7PWQq9wsTVtKyTC2qTJ" alt="Downloading Brave browser with integrated wallet"><figcaption></figcaption></figure>

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.

<figure><img src="/files/aRO3NKkqy1EkBCOSYRzU" alt="How to start using a Brave browser wallet"><figcaption></figcaption></figure>

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

#### Get a custom RPC API endpoint

<figure><img src="/files/OAC9d9LynEqbmbfqa27j" alt="Creating Ethereum access token in GetBlock"><figcaption></figcaption></figure>

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.
4. Click Get, and the endpoint is ready.

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

<figure><img src="/files/JY8LuompeNMTske0g9da" alt="Getting an ETH RPC URL for Brave wallet"><figcaption></figcaption></figure>

{% hint style="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.
{% endhint %}

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.

***

### Modify an existing EVM network

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

{% stepper %}
{% step %}
**Go to Brave Wallet settings**

In the upper right corner of the wallet interface, click on the three-dot options (![three-dot menu](/files/4DWWQRq8EOlSbU9OjM18)) button and select **Settings**. Here, a list of supported networks can be found.

<figure><img src="/files/3f25INnDNLkz9naAgeCz" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
**Locate the network in the list**

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

<figure><img src="/files/MMlKdBSs3ZJu6pCc7Qae" alt="Exploring Brave Wallet network accounts"><figcaption></figcaption></figure>

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.
{% endstep %}

{% step %}
**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.

<figure><img src="/files/JIpsbiQvXDJe001SBsxz" alt="Adding GetBlock Ethereum endpoint to Brave Wallet"><figcaption></figcaption></figure>
{% endstep %}
{% endstepper %}

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 [compute unit](/getting-started/plans-and-limits/cu-and-rate-limits) balance.

***

### 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.

{% hint style="success" %}
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 [contact us](https://getblock.io/contact/) and suggest it.
{% endhint %}

{% stepper %}
{% step %}
**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.

<figure><img src="/files/eK8X6v0L9cHT8oXdnMeT" alt="Adding Polygon to Brave"><figcaption></figcaption></figure>

After clicking on it, Brave fills all required fields automatically.
{% endstep %}

{% step %}
**Get a network’s RPC URL at GetBlock**

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.

<figure><img src="/files/myWyKr3uT4tECZsWOZm3" alt="Creating zkEVM access token in GetBlock"><figcaption></figcaption></figure>

Voila—the free and highly secure Polygon zkEVM node endpoint is ready.
{% endstep %}

{% step %}
**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.

<figure><img src="/files/Yj1mNYUpNhVKppvcT3eD" alt="Adding GetBlock zkEVM endpoint to Brave Wallet’"><figcaption></figcaption></figure>
{% endstep %}
{% endstepper %}

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.

<figure><img src="/files/MY0IRNt0AZ5ZDZ1JZjbT" alt="New Polygon zkEVM account with GetBlock endpoint"><figcaption></figcaption></figure>

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


# 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?*** [***Reach us***](https://getblock.io/contact) ***for more information.***

### How It Works

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

{% @mermaid/diagram content="graph TD
subgraph "Standard setup(200-500ms)"
A\[Validator] --> B\[P2P Network]
B --> C\[Your Node]
C --> D\[Your Application]
end" %}

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

{% @mermaid/diagram content="graph TD
subgraph "Accelerated Node(<50ms)"
A\[BDN] --> B\[GetBlock Data Center]
B --> C\[Your Dedicated Node]

end" %}

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

### 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.

### 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                                              |
| **State Transitions** | Account and contract state     | Fresher data for decisions                                             |
| **Transaction**       | Submiting Trsanction           | Submit single transactions or bundles with optimized propagation paths |

### 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.

### 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

{% hint style="success" %}
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.
{% endhint %}

### 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](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/how-to-subscribe-to-stream) for direct access to BDN data
* [Submitting transactions to public mempool ](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/how-to-submit-transactions-to-public-mempool)with accelerated propagation
* Using private transactions for [MEV protection ](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/sending-transactions-to-private-mempool-priority-fee)or [without MEV Protection](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/how-to-submit-transaction-to-private-mempool)


# 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

### Code Sample

Here, you will be checking if you are connected to streams

{% tabs %}
{% tab title="Endpoint" %}

```bash
wss://go.getblock.io/<ACCESS_TOKEN>
```

{% endtab %}

{% tab title="Code" %}
{% code title="index.js" %}

```javascript
//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);
});
```

{% endcode %}
{% endtab %}

{% tab title="Response" %}

```bash
> bsc-node@1.0.0 start
> node index.js

Connected to BSC streams
```

{% endtab %}
{% endtabs %}

### How to Subscribe to Streams

To subscribe to streams, there are four parameters you can make use of as seen below:&#x20;

| Stream       | Description                              | Use Case                    |
| ------------ | ---------------------------------------- | --------------------------- |
| `bdnBlocks`  | New blocks with headers and transactions | Block monitoring, analytics |
| `newTxs`     | New transactions entering mempool        | MEV detection, copy trading |
| `pendingTxs` | Pending transactions                     | Front-running protection    |
| `txReceipts` | Transaction receipts after confirmation  | Trade confirmation          |

#### 1. Block Streams (bdnBlocks)

Subscribe to new blocks as they're produced.

**Include Options**

| Field          | Description                                               |
| -------------- | --------------------------------------------------------- |
| `header`       | Block header (number, hash, timestamp, gasUsed, gasLimit) |
| `transactions` | Full transaction list                                     |
| `hash`         | Block hash only                                           |

**Example: Subscribe to Blocks**

{% tabs %}
{% tab title="Code" %}
{% code title="subscribe-blocks.js" %}

```javascript
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,
    });
  }
});

```

{% endcode %}
{% endtab %}

{% tab title="Response" %}

```json
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 }
```

{% endtab %}
{% endtabs %}

#### 2. Transaction Streams (newTxs / pendingTxs)

Subscribe to mempool transactions as they propagate through the network.

**Include Options**

| Field       | Description             |
| ----------- | ----------------------- |
| `tx_hash`   | Transaction hash        |
| `from`      | Sender address          |
| `to`        | Recipient address       |
| `value`     | Transaction value (hex) |
| `gas_price` | Gas price (hex)         |
| `input`     | Transaction calldata    |

**Filters**

Reduce bandwidth by filtering server-side:

| Filter      | Type  | Description                                    |
| ----------- | ----- | ---------------------------------------------- |
| `to`        | array | Transaction recipient addresses                |
| `from`      | array | Transaction sender addresses                   |
| `method_id` | array | Function selectors (first 4 bytes of calldata) |

**Example: Monitor PancakeSwap Transactions**

{% tabs %}
{% tab title="pendingTxs code" %}

<pre class="language-javascript" data-title="monitor-pancakeswap.js"><code class="lang-javascript">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");

<strong>    ws.send(
</strong><strong>      JSON.stringify({
</strong><strong>        jsonrpc: "2.0",
</strong><strong>        id: 1,
</strong><strong>        method: "subscribe",
</strong><strong>        params: [
</strong><strong>          "pendingTxs",
</strong><strong>          {
</strong><strong>            include: ["tx_hash", "from", "to", "value", "input", "gas_price"],
</strong><strong>            filters: {
</strong><strong>              to: [PANCAKE_ROUTER],
</strong><strong>            },
</strong><strong>          },
</strong><strong>        ],
</strong><strong>      }),
</strong><strong>    );
</strong><strong>  });
</strong>
  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();

</code></pre>

{% endtab %}

{% tab title="Response" %}

```json
{
  "tx_hash": "0xdef456...",
  "from": "0xabc...",
  "to": "0x10ED43C718714eb63d5aA57B78B54704E256024E",
  "value": "0x16345785d8a0000",
  "gas_price": "0xb2d05e00",
  "input": "0x38ed1739..."
}
```

{% endtab %}

{% tab title="newTx code" %}

<pre class="language-js" data-overflow="wrap"><code class="lang-js">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');

<strong>    ws.send(JSON.stringify({
</strong><strong>      jsonrpc: '2.0',
</strong><strong>      id: 1,
</strong><strong>      method: 'subscribe',
</strong><strong>      params: ['newTxs', {
</strong><strong>        include: ['tx_hash', 'from', 'to', 'value', 'input'],
</strong><strong>        filters: {
</strong><strong>          to: [PANCAKE_ROUTER],
</strong><strong>          method_id: Object.keys(SWAP_METHODS)
</strong><strong>        }
</strong><strong>      }]
</strong><strong>    }));
</strong><strong>  });
</strong>
  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();

</code></pre>

{% endtab %}

{% tab title="Response" %}
{% code overflow="wrap" %}

```bash
{
    "jsonrpc":"2.0",
    "id":1,
    "result":"0x11"
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### 3. Transaction Receipts (txReceipts)

Subscribe to transaction confirmations.

**Include Options**

| Field     | Description              |
| --------- | ------------------------ |
| `receipt` | Full transaction receipt |
| `logs`    | Event logs emitted       |

Example:&#x20;

{% tabs %}
{% tab title="Code" %}

<pre class="language-javascript"><code class="lang-javascript">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
<strong>  ws.send(JSON.stringify({
</strong><strong>    jsonrpc: '2.0',
</strong><strong>    id: 1,
</strong><strong>    method: 'subscribe',
</strong><strong>    params: ['txReceipts', {
</strong><strong>      include: ['receipt', 'logs']
</strong><strong>    }]
</strong><strong>  }));
</strong><strong>});
</strong>
ws.on("message", (data) => {
  const message = JSON.parse(data);
  console.log(message)})
</code></pre>

{% endtab %}

{% tab title="Response" %}
{% code overflow="wrap" %}

```bash
{ 
  jsonrpc: '2.0', 
  id: 1, 
  result: '0x10' 
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### Unsubscribing

To stop receiving notifications, unsubscribe using the subscription ID:

{% tabs %}
{% tab title="code sample" %}
{% code title="unsubscribe.js" overflow="wrap" %}

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

{% endcode %}
{% endtab %}

{% tab title="Response" %}
{% code overflow="wrap" %}

```bash
{ 
    jsonrpc: '2.0', 
    id: 10, 
    result: true 
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Best Practices

1\. Request Only What You Need

{% tabs %}
{% tab title="Don't ❌" %}

```js
// ❌ Bad: Request everything
include: ['tx_contents']  // Large payloads, high bandwidth
```

{% endtab %}

{% tab title="Do ✅" %}

```js
// ✅ Good: Request specific fields
include: ['tx_hash', 'from', 'to', 'value']  // Small payloads
```

{% endtab %}
{% endtabs %}

2. Use Server-Side Filters

{% tabs %}
{% tab title="Don't ❌" %}

```js
// ❌ Bad: Filter client-side
params: ['newTxs', { include: ['tx_contents'] }]
// Then filter in your code... wasteful!
```

{% endtab %}

{% tab title="Do ✅" %}

```js
// ✅ Good: Filter server-side
params: ['newTxs', {
  include: ['tx_hash', 'to', 'input'],
  filters: { to: ['0xTargetContract'] }
}]
```

{% endtab %}
{% endtabs %}

3. Handle Reconnection

```javascript
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;
}
```

4. Process Messages Asynchronously

```javascript
ws.on('message', async (data) => {
  // Don't block the message loop
  setImmediate(() => {
    processMessage(JSON.parse(data));
  });
});
```

## Rate Limits

| Tier       | Concurrent Subscriptions | Message Rate |
| ---------- | ------------------------ | ------------ |
| Standard   | 5                        | 1,000/sec    |
| Pro        | 20                       | 10,000/sec   |
| Enterprise | Unlimited                | Unlimited    |

***Contact*** [***support***](mailto:support@getblock.io) ***to upgrade your tier.***

## Troubleshooting

| Problem              | Solution                                                                                                                                                                                 |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| No messages received | <p></p><ul><li>Check subscription response—did you receive a subscription ID?</li><li>Verify filters aren't too restrictive</li><li>Confirm your API key is valid and active</li></ul>   |
| High latency         | <p></p><ul><li>Reduce the number of <code>include</code> fields</li><li>Add filters to reduce message volume</li><li>Check your network connection</li></ul>                             |
| Missed messages      | <p></p><ul><li>Process messages asynchronously</li><li>Increase your message queue buffer</li><li>Consider multiple connections for different streams</li></ul>                          |
| Connection Drop      | <p></p><ul><li>Implement automatic reconnection (see example above)</li><li>Re-subscribe after each reconnect—subscriptions don't persist</li><li>Check your network stability</li></ul> |

### Next Step

1. [Submitting transactions to public mempool ](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/how-to-submit-transactions-to-public-mempool)with accelerated propagation
2. Using private transactions for [MEV protection ](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/sending-transactions-to-private-mempool-priority-fee)or [without MEV Protection](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/how-to-submit-transaction-to-private-mempool)


# 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.

### When to Use Public Mempool

Use public mempool submission when:

* 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*](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/sending-transactions-to-private-mempool-priority-fee) *instead.*

### Sample Request

{% tabs %}
{% tab title="Endpoint" %}

```bash
wss://go.getblock.io/<ACCESS_TOKEN>
```

{% endtab %}

{% tab title="Method" %}

```bash
blxr_tx
```

{% endtab %}

{% tab title="Transaction Parameters" %}

| Parameter    | Type   | Required | Description                        |
| ------------ | ------ | -------- | ---------------------------------- |
| `nonce`      | int    | Yes      | Transaction count for your address |
| `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               |
| {% endtab %} |        |          |                                    |

{% tab title="Request Format" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "blxr_tx",
  "params": ["0x<signed_transaction_hex>"]
}
```

{% endtab %}

{% tab title="Response Format" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x<transaction_hash>"
}
```

{% endtab %}
{% endtabs %}

### How to Submit a Transaction to Public Mempool

{% stepper %}
{% step %}
Set up the project

{% tabs %}
{% tab title="npm" %}

```bash
mkdir transaction-public-mempool
cd transaction-public-mempool
npm init -y
npm install ws ethers dotenv
```

{% endtab %}

{% tab title="yarn" %}

```bash
mkdir transaction-public-mempool
cd transaction-public-mempool
yarn init -y
yarn ws ethers dotenv
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}
Create a new file named `index.js`. This is where you will make your first call.
{% endstep %}

{% step %}
Set the ES module `"type": "module"` in your `package.json`.
{% endstep %}

{% step %}
Create `.env` file and add the following:

{% code overflow="wrap" %}

```js
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
```

{% endcode %}
{% endstep %}

{% step %}
Add the following code to `index.js`:
{% endstep %}

{% step %}

```javascript
import WebSocket from "ws";
import { ethers } from "ethers";
import "dotenv/config";
```

{% endstep %}

{% step %}
Create and Sign Your Transaction

```javascript
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;
```

{% endstep %}

{% step %}
Submit via WebSocket

```javascript
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();
});
```

{% endstep %}

{% step %}
Response

```bash
01f86c380384b2d05e0082520894d26ea0f03100358b2ebd4c9638f042aada9a1bcf87038d7ea4c6800080c001a04647f98754480337ae409bcc225f2d62b706b47f31385221421cea20e41080b0a03ae32f07bb7110c4153c2ab121c152db7d3030d54cc0c5341f0b75b20e3d439d
TX Hash: 00d4fe2db5c667ce549318cf621913af1bcb130022ec51020cbb6cae2b7eedce
https://bscscan.com/tx/00d4fe2db5c667ce549318cf621913af1bcb130022ec51020cbb6cae2b7eedce
```

{% endstep %}
{% endstepper %}

<details>

<summary>Complete Example: BNB Transfer</summary>

```javascript
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: "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();
});
```

</details>

<details>

<summary>Complete Example: Token Swap on PancakeSwap</summary>

```javascript
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);
```

</details>

### Gas Price Recommendations

| Priority | Gas Price | Use Case              |
| -------- | --------- | --------------------- |
| Standard | 3 gwei    | Regular transfers     |
| Fast     | 5 gwei    | Time-sensitive trades |
| Urgent   | 10+ gwei  | Competitive scenarios |

{% hint style="info" %}
Note: Higher gas prices increase inclusion priority but also increase transaction cost.
{% endhint %}

### Troubleshooting

1. **"nonce too low"**

Your nonce is behind the network state. Fetch the latest:

```javascript
const nonce = await provider.getTransactionCount(wallet.address, 'pending');
```

2. **"insufficient funds"**

Ensure you have enough BNB for both the transaction value and gas:

```
Required = value + (gasPrice × gasLimit)
```

3. **"replacement transaction underpriced"**

If replacing a pending transaction, increase the gas price by at least 10%:

```javascript
const newGasPrice = existingGasPrice * 110n / 100n;
```

4. **Transaction not included**

* Increase gas price for higher priority
* Check that the transaction is valid
* Verify sufficient balance

## Next Steps

For transactions that need MEV protection, see:

* [Private Transactions](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/how-to-submit-transaction-to-private-mempool) — Hidden from public mempool
* [Private Transactions with Tips](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/sending-transactions-to-private-mempool-priority-fee) — Prioritized private submission


# 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
* **Back-run you:** Profit from the price impact you create

Meanwhile, Private transactions eliminate this exposure by hiding your transactions until they are included.

<figure><img src="/files/ml3rLGTnkZljG6Tn5Udj" alt="" width="563"><figcaption></figcaption></figure>

### Private TX vs Public Mempool

| Aspect          | Public Mempool              | Private TX             |
| --------------- | --------------------------- | ---------------------- |
| Visibility      | Everyone sees it            | Only builders see it   |
| MEV exposure    | Vulnerable                  | Protected              |
| Inclusion speed | Gas price dependent         | Builder dependent      |
| Best for        | Speed-competitive scenarios | Value-sensitive trades |

### 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

### Request Sample

{% tabs %}
{% tab title="Endpoint" %}

```bash
wss://go.getblock.io/<ACCESS_TOKEN>
```

{% endtab %}

{% tab title="Method" %}

```bash
bsc_private_tx
```

{% endtab %}

{% tab title="Parameters" %}

| Parameter      | Type   | Required | Description                             |
| -------------- | ------ | -------- | --------------------------------------- |
| `transaction`  | string | Yes      | Signed raw transaction hex              |
| `mev_builders` | array  | No       | Builders to send to. Default: `["all"]` |
| {% endtab %}   |        |          |                                         |

{% tab title="Request Format" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "bsc_private_tx",
  "params": {
    "transaction": "0xf86c...",
    "mev_builders": ["all"]
  }
}
```

{% endtab %}

{% tab title="Response Format" %}

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "txHash": "0x..."
  }
}
```

{% endtab %}
{% endtabs %}

### How to Submit Transaction to Private Mempool

{% stepper %}
{% step %}
Set up the project

{% tabs %}
{% tab title="npm" %}

```bash
mkdir transaction-private-mempool
cd transaction-private-mempool
npm init -y
npm install ws ethers dotenv
```

{% endtab %}

{% tab title="yarn" %}

```bash
mkdir transaction-private-mempool
cd transaction-private-mempool
yarn init -y
yarn ws ethers
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}
Set the ES module `"type": "module"` in your package.json.
{% endstep %}

{% step %}
Create a file and name it `index.js`
{% endstep %}

{% step %}
Create `.env` file and add the following:

{% code overflow="wrap" %}

```js
ACCESS_TOKEN=your-accelerated-node-endpoint
RPC_URL=your-normal-bsc-node-endppoint //e.g https
PRIVATE_KEY=your-wallet-private-key
```

{% endcode %}
{% endstep %}

{% step %}
Import the dependencies

```javascript
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
```

{% endstep %}

{% step %}
Create and Sign Your Transaction

```javascript
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);
```

{% endstep %}

{% step %}
Submit Privately

```javascript
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();
});
```

{% endstep %}

{% step %}
Response

{% code overflow="wrap" %}

```bash
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
```

{% endcode %}
{% endstep %}
{% endstepper %}

<details>

<summary>Complete Example: Private BNB Transfer</summary>

```javascript
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);

```

</details>

<details>

<summary>Complete Example: MEV-Protected PancakeSwap Trade</summary>

```javascript
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);
```

</details>

### 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`

```javascript
params: {
  transaction: signedTx,
  mev_builders: ['48club', 'bloxroute']  // Specific builders only
}
```

### Troubleshooting

| Problem                  | Solution                                                                                                                                                                                                                                                                                                                                                                                             |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Transaction not included | <p></p><p>Without a priority tip, private transactions compete based on gas fees alone. If your transaction isn't being included:</p><ul><li>Increase gas price — Higher gas = higher priority for builders</li><li>Add a priority tip — See <a href="/pages/Wtc83r35jvlheJeDOrVs">Private Transactions with Tips</a></li><li>Try specific builders — Some builders may be more responsive</li></ul> |
| "Invalid transaction"    | <p></p><ul><li>Verify your transaction is properly signed</li><li>Check the chain ID is <code>56</code> (BSC Mainnet)</li><li>Ensure the nonce is correct</li></ul>                                                                                                                                                                                                                                  |
| Connection issues        | <p></p><ul><li>Verify your API key is valid</li><li>Check network connectivity</li><li>Try reconnecting after a few seconds</li></ul>                                                                                                                                                                                                                                                                |

### Next Steps

To increase the priority for inclusion in your private transactions, see [Private Transactions with Tips.](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/sending-transactions-to-private-mempool-priority-fee)


# 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

## Choosing a Method

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

| Method                                                                                                                                            | Best For                                           | Trade-offs                                          |
| ------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | --------------------------------------------------- |
| [**Multicall3**](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/sending-transactions-to-private-mempool-priority-fee/how-to-use-multicall3) | Most use cases                                     | Single nonce, atomic execution, slightly higher gas |
| [**Bundle**](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/sending-transactions-to-private-mempool-priority-fee/how-to-use-bundle)         | Advanced scenarios requiring separate transactions | Two nonces, more complex setup                      |

### Different Between Bundles and  Transactions

Choose the appropriate method based on your use case:

| **Method**                | `bsc_privateTx`                    | `mev_sendBundle`                 |
| ------------------------- | ---------------------------------- | -------------------------------- |
| **Transaction count**     | Single                             | Multiple                         |
| **Atomicity**             | Not applicable                     | All-or-nothing execution         |
| **Use cases**             | Simple transfers, individual swaps | Arbitrage, multi-step operations |
| **Adding priority fees**  | Via Multicall3                     | Separate transaction in bundle   |
| **`mev_builders` format** | Array: `["all"]`                   | Object: `{"all": ""}`            |

### Next Steps

Learn how to submit transactions via [Multicall3](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/sending-transactions-to-private-mempool-priority-fee/how-to-use-multicall3) or [Bundle](/bsc-advanced-tooling/bsc-accelerated-dedicated-node/sending-transactions-to-private-mempool-priority-fee/how-to-use-bundle) method to the private mempool.&#x20;


# 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.&#x20;

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.

### **How it works**

This is how Multicall3 works:

{% @mermaid/diagram content="graph TD
A(\[Your Wallet]) --> B

```
subgraph Execution ["Smart Contract Execution"]
    B[Multicall3 Contract]
    B --> C[Call 1: Send tip to gateway fee address]
    B --> D[Call 2: Execute your actual transaction]
end

C --> E
D --> E

subgraph Submission ["MEV-Protected Submission"]
    E[bsc_private_tx]
end" %}
```

### 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

### Reference Addresses

| Address                                      | Purpose               |
| -------------------------------------------- | --------------------- |
| `0xcA11bde05977b3631167028862bE2a173976CA11` | Multicall3 contract   |
| `0x6374Ca2da5646C73Eb444aB99780495d61035f9b` | Gateway fee recipient |

### Example

{% stepper %}
{% step %}
Set up the project

{% tabs %}
{% tab title="npm" %}

```bash
mkdir multicall3-example
cd multicall3-example
npm init -y
npm install ws ethers dotenv
```

{% endtab %}

{% tab title="yarn" %}

```bash
mkdir multicall3-example
cd multicall3-example
yarn init -y
yarn ws ethers
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}
Create a new file named `index.js`. This is where you will make your first call.
{% endstep %}

{% step %}
Set the ES module `"type": "module"` in your `package.json`.
{% endstep %}

{% step %}
Create `.env` file and add the following:

{% code overflow="wrap" %}

```js
ACCESS_TOKEN=your-accelerated-node-endpoint
RPC_URL=your-normal-bsc-node-endppoint //e.g https
PRIVATE_KEY=your-wallet-private-key
```

{% endcode %}
{% endstep %}

{% step %}
Add the following code to `index.js`:

The following example demonstrates a simple BNB transfer with a priority fee:

{% code overflow="wrap" %}

```js
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);

```

{% endcode %}
{% endstep %}

{% step %}
Run the code using this command:

```bash
node index.js
```

{% endstep %}

{% step %}
Sample response

{% code overflow="wrap" %}

```bash
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
```

{% endcode %}
{% endstep %}
{% endstepper %}

### Extension sample&#x20;

You can extend this code for a DEX swap by encoding the router call and including it as the second Multicall3 call:

{% code overflow="wrap" %}

```javascript
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
  }
];
```

{% endcode %}

### Troubleshooting

| Problem                   | Solution                                                                                                                                                       |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| "Multicall3: call failed" | <p></p><ul><li>Check you have enough BNB for all calls + gas</li><li>Increase gas limit to 200000</li><li>Verify target addresses are correct</li></ul>        |
| TX not included           | <p></p><ul><li>Increase tip amount</li><li>Check if you're rate limited</li><li>Verify TX is valid (simulate first)</li></ul>                                  |
| Low priority despite tip  | <p></p><ul><li>Increase tip amount</li><li>Check builder status</li><li>Try different builders: <code>mev\_builders: \["48club", "bloxroute"]</code></li></ul> |

### 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. &#x20;


# 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

### 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

### Sample Request

{% tabs %}
{% tab title="Endpoint" %}
Connect to the MEV WebSocket endpoint with your API key:

```bash
wss://go.getblock.io/<ACCESS_TOKEN>
```

{% endtab %}

{% tab title="Parameters" %}

| Parameter      | Type    | Required | Description                                                                         |
| -------------- | ------- | -------- | ----------------------------------------------------------------------------------- |
| `transactions` | array   | Yes      | Array of signed raw transactions (hex-encoded)                                      |
| `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                  |
| {% endtab %}   |         |          |                                                                                     |

{% tab title="Request Format" %}
Submit bundles using the `mev_sendBundle` method:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "mev_sendBundle",
  "params": {
    "transactions": ["0xf86c...", "0xf86c..."],
    "mev_builders": { "all": "" },
    "blocks_count": 5
  }
}
```

{% endtab %}

{% tab title="Response Format" %}
A successful submission returns a bundle hash:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "bundleHash": "0x..."
  }
}
```

{% endtab %}
{% endtabs %}

### Example

{% stepper %}
{% step %}
Set up the project

{% tabs %}
{% tab title="npm" %}

```bash
mkdir bundle-example
cd bundle-example
npm init -y
npm install ws ethers dotenv
```

{% endtab %}

{% tab title="yarn" %}

```bash
mkdir bundle-example
cd bundle-example
yarn init -y
yarn ws ethers dotenv
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}
Create a new file named `index.js`. This is where you will make your first call.
{% endstep %}

{% step %}
Set the ES module `"type": "module"` in your `package.json`.
{% endstep %}

{% step %}
Create `.env` file and add the following:

{% code overflow="wrap" %}

```js
ACCESS_TOKEN=your-accelerated-node-endpoint
RPC_URL=your-normal-bsc-node-endppoint //e.g https
PRIVATE_KEY=your-wallet-private-key
```

{% endcode %}
{% endstep %}

{% step %}
Add the following code to `index.js`:

The following example demonstrates a simple BNB transfer with a priority fee:

{% code overflow="wrap" %}

```js
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();
```

{% endcode %}
{% endstep %}

{% step %}
Run the code using this command:

```bash
node index.js
```

{% endstep %}

{% step %}
Sample response

```
```

{% endstep %}
{% endstepper %}

### Example: DEX Arbitrage

<details>

<summary>This 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.</summary>

#### Reference Addresses

| Address                                      | Purpose                |
| -------------------------------------------- | ---------------------- |
| `0x10ED43C718714eb63d5aA57B78B54704E256024E` | PancakeSwap V2 Router  |
| `0x13f4EA83D0bd40E75C8222255bc855a974568Dd4` | PancakeSwap V3 Router  |
| `0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c` | WBNB                   |
| `0x6374Ca2da5646C73Eb444aB99780495d61035f9b` | Priority fee recipient |

#### Code Example

{% code overflow="wrap" %}

```javascript
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();
```

{% endcode %}

</details>

### Comparing Bundles and Private Transactions

Choose the appropriate method based on your use case:

| Aspect                | `bsc_privateTx`                    | `mev_sendBundle`                 |
| --------------------- | ---------------------------------- | -------------------------------- |
| Transaction count     | Single                             | Multiple                         |
| Atomicity             | Not applicable                     | All-or-nothing execution         |
| Use cases             | Simple transfers, individual swaps | Arbitrage, multi-step operations |
| Adding priority fees  | Via Multicall3                     | Separate transaction in bundle   |
| `mev_builders` format | Array: `["all"]`                   | Object: `{"all": ""}`            |

### Best Practices

1\. Use Sequential Nonces

All transactions in a bundle must have consecutive nonces starting from your wallet's current nonce:

```javascript
const nonce = await provider.getTransactionCount(wallet.address);

// Transaction 1: nonce
// Transaction 2: nonce + 1
// Transaction 3: nonce + 2
```

2\. Include a Priority Fee

Adding a fee payment as the final transaction increases the likelihood of bundle inclusion:

```javascript
const feeTx = await wallet.signTransaction({
  nonce: lastNonce,
  to: '0x6374Ca2da5646C73Eb444aB99780495d61035f9b',
  value: ethers.parseEther('0.001'),
  gasPrice: ethers.parseUnits('3', 'gwei'),
  gasLimit: 21000,
  chainId: 56
});
```

### 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 |
| ------------------------ | ------------------------- |
| Time-sensitive arbitrage | 2–3                       |
| Standard bundles         | 5                         |
| Less urgent operations   | 10–20                     |

## Simulate Before Submitting

Test your transaction logic before submitting a bundle by simulating each transaction:

```javascript
await provider.call({
  to: tx1.to,
  data: tx1.data,
  value: tx1.value
});
```

### Troubleshooting

| Problem                | Solution                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Bundle Not Included    | <p>If your bundle is not included after the specified block count:</p><ul><li><strong>Increase the priority fee</strong> — Add a higher fee payment transaction</li><li><strong>Verify nonce sequence</strong> — Nonces must be strictly consecutive with no gaps</li><li><strong>Reduce blocks\_count</strong> — Shorter validity signals higher priority to builders</li><li><strong>Validate each transaction</strong> — Ensure every transaction in the bundle is valid independently</li></ul> |
| "Invalid bundle" Error | <p></p><p>This error indicates a formatting or validation issue:</p><ul><li><strong>Check parameter format</strong> — The <code>transactions</code> parameter must be an array; <code>mev\_builders</code> must be an object</li><li><strong>Verify signatures</strong> — All transactions must be properly signed</li><li><strong>Confirm chain ID</strong> — Use chain ID 56 for BSC Mainnet</li></ul>                                                                                            |
| Partial Execution      | <p></p><p>Bundles execute atomically, so partial execution should not occur. If you observe partial execution:</p><ul><li><strong>Contact support</strong> — This indicates a potential builder issue</li><li><strong>Verify using the bundle hash</strong> — Check the bundle status on a block explorer</li></ul>                                                                                                                                                                                 |


# 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.&#x20;

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?*** [***Reach us***](https://getblock.io/contact) ***for more information.***

### 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

### How It Works

#### 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

#### 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.&#x20;
* **Early state reconstruction:** Rebuilds block data before it's fully confirmed and distributed via standard RPC

#### 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

![](/files/dumPwd6r76oKKrkaJLdq)

* 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.

### 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

### Why StreamFirst is Important for Developers

#### 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

{% hint style="success" %}
**Typical latency improvements:** 25-30ms faster than standard Yellowstone gRPC&#x20;
{% endhint %}

#### 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

#### 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

### 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

### 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 team](https://getblock.io/contact/)

<br>


# 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 us***](https://getblock.io/contact) ***for more information.***

#### 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
   3. GetBlock-operated infrastructure with validator peering
2. **Leased SWQoS Connections**
   1. Higher priority than unstaked RPC traffic, ensuring transactions cut ahead during congestion
   2. Reserve priority bandwidth specifically for LandFirst traffic
3. **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

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

### Technical Architecture

#### 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.

{% @mermaid/diagram content="
flowchart TD

A\[Our Transaction] --> B\[LandFirst Intelligent Router]

B --> C\[Path Selection Algorithm]

C --> C1\[Analyze: Priority fee, Jito tip, network conditions]
C --> C2\[Check: Current or upcoming leader schedule]
C --> C3\[Select: Optimal routing path]

C --> D\[Parallel Submission]

D --> D1\[GetBlock SWQoS --> Validator GetBlock partner leader]
D --> D2\[Leased SWQoS --> Validator leased partner leader]
D --> D3\[Jito Bundle --> Jito Block Engine]

D --> E\[Block Leader Receives Transaction]

E --> F\[Transaction Lands in Block]

" %}

#### 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
* Geographic Location: network topology that defines the lowest-path latency to the current leader.

#### Use Cases

1. **HFT & Arbitrage**

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

2. **MEV & Keeper / Liquidation Bots**

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

3. **NFT Sniping & High-Demand Mints**

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

4. **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.

### 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.

| Aspect              | Standard RPC    | LandFirst                  |
| ------------------- | --------------- | -------------------------- |
| Routing paths       | Single path     | Three paths (SWQoS + Jito) |
| Validator priority  | None (unstaked) | High (stake-weighted)      |
| Congestion handling | Fails or delays | Adaptive routing           |
| Bundle support      | No              | Yes (via Jito)             |
| MEV protection      | No              | Yes (via Jito)             |
| Landing probability | 60-90% (varies) | 95%+ (measured)            |

### 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 [GetBlock support team](https://getblock.io/contact/)

<br>


# 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:&#x20;

* fast data streaming (StreamFirst)
* intelligent transaction routing (LandFirst)

into a single, integrated solution for professional trading operations.

***Interested in building on Solana with TradeFirst?*** [***Reach us***](https://getblock.io/contact) ***for more information.***

#### 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.

#### 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**&#x20;
   1. Geo routing
   2. Stake density topology
   3. Leadership scheduling

{% hint style="success" %}
Future Addition:

* Shred Stream Access (coming soon): Direct raw shred delivery for even earlier data access
  {% endhint %}

### Technical Architecture

#### How TradeFirst Works

![](/files/7G3PqeyhvypimJenGcxt)

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

### Use cases

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

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 team](https://getblock.io/contact/)

<br>


# 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?* [*Reach us*](https://getblock.io/contact) *for more information.*

### The Indexed Archive Solution

* **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
* &#x20;**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.

### Technical Architecture

#### 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

#### 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

### 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
   4. Error messages (if failed)
   5. Fee paid (lamports)
   6. Compute units used
   7. List of program invocations
3. Instructions
   1. Program ID (which program was called)
   2. Instruction index (order within transaction)
   3. Instruction data (decoded where possible)
   4. Accounts array (all accounts involved)
   5. Nested/inner instructions
4. Logs
   1. Program log messages
   2. Associated transaction signature
   3. Log level and content
   4. Timestamp
5. Account Updates
   1. Account public key
   2. Pre-transaction balance (lamports)
   3. Post-transaction balance (lamports)
   4. Owner program (pre and post)
   5. Data changes (what was modified)
   6. Rent epoch information

### Use Cases

#### Analytics and Trading

1. Deep historical analysis and backtesting
2. Real-time liquidity and TVL monitoring
3. Pattern recognition and signal generation

#### 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

#### 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 team](https://getblock.io/contact/).&#x20;


# Overview

Learn about GetBlock Tron Energy, how to rent Tron energy and bandwidth through API or Dashboard UI

GetBlock Tron Energy is a service that lets you rent TRON Energy and Bandwidth via a simple API or dashboard UI. Instead of locking up large amounts of TRX to stake, you pay in USD and receive delegated resources instantly.

### Key Benefits

* Save up to 68% compared to burning TRX for fees
* Pay in USD: no need to hold or stake TRX
* Instant delegation: resources are available immediately
* Flexible durations: 1 hour to 14 days
* RESTful API for automation: ideal for exchanges and payment services
* Dashboard UI for manual operations and monitoring
* Rate limit: 30 requests/min per API key

### **How It Works**

1. **You top up** your GetBlock account with USD (using your card)
2. **You request delegation** via API or dashboard — specifying target address, Energy amount, and duration
3. **GetBlock delegates Energy** from their staked TRX pool to your target address instantly
4. **Your target address transacts** using the delegated Energy (no TRX burning)
5. **Energy recovers** over 24 hours if partially used
6. **Delegation expires** at the end of the rental period — resources return to GetBlock

<figure><img src="/files/2pkxz61gB0zHinCLRwO7" alt=""><figcaption></figcaption></figure>

#### Available Operations

| Operation          | Description                                                                                    |
| ------------------ | ---------------------------------------------------------------------------------------------- |
| Delegate Energy    | Delegate 30,000–5,000,000 Energy for 1h–14d to any TRON address                                |
| Delegate Bandwidth | Delegate 1,000–200,000 Bandwidth for 1 hour to any TRON address                                |
| Activate Address   | Activate a new TRON address on the blockchain (required before delegation to unused addresses) |
| Check Price        | Get a real-time price estimate for Energy delegation                                           |
| Check Order Status | Retrieve details of a previously placed order                                                  |

### Next Steps

1. [Getting started](/tron-energy/getting-started)
2. [Tron Fee Model](/tron-energy/tron-fee-model)
3. [Pricing](/tron-energy/api-reference)
4. [API Reference](/tron-energy/api-reference)


# Getting Started

Learn how to access Tron energy, top your balance, delegate resources, check prices and manage API key from your dashboard.

The Dashboard tab gives you a comprehensive overview of your activity:

* USD Balance: your current balance with a quick Top Up button
* Usage: bar chart showing delegation activity (filter by 24h, 7 days, month, or all time)
* Deposit History: table of all top-ups with date, method, and amount
* TRON Energy Activity: full order history with address, type, volume, duration, price, status, and date
* Export: download order history as XLS or PDF

In this guide, you will learn how to easily navigate through the dashboard to get the following:

1. How to gain access to Tron energy
2. How to top up your balanace&#x20;
3. Delegate Resources
4. Check Prices
5. Manage API Keys

### How to Access Dashboard

{% stepper %}
{% step %}
Create an account on [GetBlock](https://account.getblock.io) using Gmail, Metamask, or GitHub
{% endstep %}

{% step %}
Under **products**, click on **Tron energy**. The system will automatically sync your GetBlock account with the Energy service.

The dashboard consists of three main tabs:

1. Dashboard — view your balance, usage charts, deposit history, and order activity
2. Delegate — delegate Energy or Bandwidth to TRON addresses, manage API keys
3. API Docs — reference documentation with cURL examples for all endpoints
   {% endstep %}
   {% endstepper %}

### How to Top Up Your Balance

Before you can delegate resources, you need to fund your USD balance:

{% stepper %}
{% step %}
Click the "Top Up" button in the balance bar at the top of the dashboard
{% endstep %}

{% step %}
Select a preset amount ($50, $100, $500) or enter a custom amount (minimum $10)
{% endstep %}

{% step %}
Choose your payment method: Card or Crypto
{% endstep %}

{% step %}
Complete the payment — your balance updates instantly

{% hint style="info" %}
Your USD balance is shared across all GetBlock products.
{% endhint %}
{% endstep %}
{% endstepper %}

### How to Delegate Resources

Go to the Delegate tab and select Manual mode.

#### 1. Delegate Energy

{% stepper %}
{% step %}
Select the Energy sub-tab
{% endstep %}

{% step %}
Enter the target TRON address (starts with T, 34 characters)
{% endstep %}

{% step %}
Set the Energy amount (30,000–5,000,000)
{% endstep %}

{% step %}
Choose the duration: 1h, 3h, 6h, 12h, or 1 day
{% endstep %}

{% step %}
Click "Delegate Energy"
{% endstep %}
{% endstepper %}

#### 2. Delegate Bandwidth

{% stepper %}
{% step %}
Select the Bandwidth sub-tab
{% endstep %}

{% step %}
Enter the target TRON address
{% endstep %}

{% step %}
Set the Bandwidth amount (1,000–200,000)
{% endstep %}

{% step %}
Duration is fixed at 1 hour for Bandwidth
{% endstep %}

{% step %}
Click "Delegate Bandwidth"
{% endstep %}
{% endstepper %}

#### 3. Activate Address

If you need to delegate to a brand-new TRON address that has never been used, you must activate it first:

{% stepper %}
{% step %}
Select the Activate sub-tab
{% endstep %}

{% step %}
Enter the target TRON address
{% endstep %}

{% step %}
Click "Activate Address

{% hint style="info" %}
Activation costs a fixed 1.87 TRX, charged in USD at the current TRX/USD rate.
{% endhint %}
{% endstep %}
{% endstepper %}

### How to Check Price

The Check Price panel is available on the right side of the Delegate form (Manual mode). Use it to get a real-time estimate before placing an order:

{% stepper %}
{% step %}
Enter Energy amount (30,000–5,000,000)
{% endstep %}

{% step %}
Select duration: 1 hour, 1 day, 3 days, 7 days, or 14 days
{% endstep %}

{% step %}
Click "Check Price"
{% endstep %}

{% step %}
The result shows: price in SUN per unit, total TRX, and total USD
{% endstep %}
{% endstepper %}

### How to Manage API Keys

To use the API, you need an API key:

{% stepper %}
{% step %}
Go to Delegate → API mode
{% endstep %}

{% step %}
Click "+ Add Key" (requires a funded balance)
{% endstep %}

{% step %}
Copy and securely store the key immediately — it is shown only once
{% endstep %}

{% step %}
You can create up to 5 API keys
{% endstep %}

{% step %}
To revoke a key, click "Revoke" next to it — the key stops working immediately
{% endstep %}
{% endstepper %}

### Next Steps

1. [Tron Fee Mode](/tron-energy/tron-fee-model)
2. [API Reference](/tron-energy/api-reference)


# TRON Fee Model

Learn how to calculate transaction fees in TRON

In Bitcoin and Ethereum, transaction fees are paid in the network’s native asset — in its smallest unit (satoshi, wei). TRON works differently; every transaction consumes two types of resources:

1. Bandwidth
2. Energy.&#x20;

If these resources are insufficient, TRX is burned to cover the costs.

#### SUN: The Base Unit of TRX

SUN is the smallest unit of TRX, analogous to **satoshi** in Bitcoin or **wei** in Ethereum.

```bash
1 TRX = 1,000,000 SUN
```

The cost of Energy and Bandwidth when burning TRX is expressed in SUN.

### Bandwidth

Bandwidth is the network throughput required to transmit transaction data.

* Consumed by every transaction
* 1 Bandwidth = 1 byte of transaction data
* Each account receives a free daily allowance of 600 Bandwidth, which resets automatically
* If Bandwidth is insufficient → TRX is burned

```bash
Cost when burning: 1 Bandwidth = 1,000 SUN (0.001 TRX)
```

#### Bandwidth Consumption Examples

| Operation             | Bandwidth Used  |
| --------------------- | --------------- |
| Sending TRX           | \~268 Bandwidth |
| Sending USDT (TRC-20) | \~345 Bandwidth |

TRC-10 token transfers consume only Bandwidth. TRC-20 token transfers (USDT and other smart contract tokens) consume both Bandwidth and Energy.

### Energy

Energy is the computational power required to execute smart contracts on the TRON Virtual Machine (TVM).

* Consumed only when calling a smart contract
* 1 Energy ≈ 1 microsecond of computation on TVM
* No free daily allowance
* If Energy is insufficient → TRX is burned

```bash
Cost when burning: 1 Energy = 100 SUN (0.0001 TRX)
```

#### Example: USDT (TRC-20) Transfer Energy Cost

A typical USDT transfer calls the function transfer(address to, uint256 value). The TVM executes a balance check, a storage write for the sender (debit), and a storage write for the recipient (credit).

The amount of Energy depends on whether a storage slot already exists for the recipient:

| Scenario                                     | Energy    | Reason                            |
| -------------------------------------------- | --------- | --------------------------------- |
| Activated address (has received USDT before) | \~65,000  | Updating an existing storage slot |
| Non-activated address (never received USDT)  | \~131,000 | Creating a new storage slot       |

### Transaction Cost When Burning TRX

Current network parameters (set via governance) can be retrieved with the following request:

```bash
GET https://api.trongrid.io/wallet/getchainparameters
Current rates: 1 Energy = 100 SUN (0.0001 TRX), 1 Bandwidth = 1,000 SUN (0.001 TRX)
```

#### Cost Calculation: USDT Transfer to Activated Address (\~65,000 Energy)

* Energy: 65,000 × 100 SUN = 6,500,000 SUN = 6.5 TRX
* Bandwidth: 345 × 1,000 SUN = 345,000 SUN = 0.345 TRX
* Total: \~6.85 TRX

#### Cost Calculation: USDT Transfer to New Address (\~131,000 Energy)

* Energy: 131,000 × 100 SUN = 13,100,000 SUN = 13.1 TRX
* Bandwidth: 345 × 1,000 SUN = 345,000 SUN = 0.345 TRX
* Total: \~13.45 TRX

### Where Energy Comes From: Staking and Delegation

TRON has a Stake 2.0 mechanism that allows users to obtain Energy without burning TRX:

#### 1. Staking (Freezing TRX)

A TRX holder freezes tokens via a system contract and receives Energy proportional to their share of the total network stake. The more TRX is frozen across the network, the less Energy each participant receives per unit of TRX. When unstaking, TRX is locked for a 14-day waiting period before it is returned.

#### 2. Delegation

An owner of staked TRX can delegate their resources (Energy or Bandwidth) to another address via delegateResource. The recipient uses the Energy, while the staker retains their TRX. Delegation can be locked for a minimum of 3 days, after which it can be revoked.

#### 3. Rental Market

This mechanism forms the basis of the Energy rental market: providers stake large amounts of TRX and delegate Energy to clients for a fee. The client receives Energy without having to lock up their own capital.

### Why Renting Energy Is More Cost-Effective Than Burning TRX

Rental providers buy Energy in bulk (by staking large amounts of TRX) and sell it at a price below the cost of burning. Current market prices range from 30 to 50 SUN per 1 Energy, depending on the provider and terms.

Example calculation at a rental price of 32 SUN per 1 Energy:

| Scenario                         | Renting   | Burning TRX | Savings |
| -------------------------------- | --------- | ----------- | ------- |
| Activated address (\~65K Energy) | \~2.1 TRX | 6.5 TRX     | \~68%   |
| New address (\~131K Energy)      | \~4.2 TRX | 13.1 TRX    | \~68%   |

For high-volume clients (exchanges, payment services, dApps), renting Energy significantly reduces operational costs.

### Energy Recovery

After being used, Energy on an account recovers linearly over 24 hours. This means that if an account has staked TRX and its Energy has been spent, the full amount will be available again after 24 hours. This also applies to rented (delegated) Energy — it is recovered on the recipient’s account during the rental period.

### Next Steps

1. [Pricing](broken://pages/e7LJxCH0Sl7Chxp5lyqW)
2. [API Reference](/tron-energy/api-reference)


# API Reference

This contain all the endpoints, pricing and error codes to access TRON energy

The GetBlock TRON Energy API lets you programmatically delegate Energy and Bandwidth to any TRON address. Automate fee optimization for exchanges, payment services, and dApps.

### Base URL

```bash
https://api.getblock.io/tron-energy
```

### Authentication

All requests require an API key in the header:

```bash
Authorization: Bearer YOUR_API_KEY
```

### Quick Example

* Generate keys in your dashboard under **Delegate → API**.

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.getblock.io/tron-energy/delegateEnergy \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"target_address": "TUo8...", "volume": 65000, "duration": "1d"}'
```

{% endtab %}

{% tab title="Response" %}
All responses return JSON. Successful delegations include:

```json
{
  "order_id": "clxyz123...",
  "status": "success",
  "price_usd": "1.58",
  "txid": "abc123..."
}
```

{% endtab %}
{% endtabs %}

### Endpoints

| Endpoint              | Method | Description                         |
| --------------------- | ------ | ----------------------------------- |
| `/delegateEnergy`     | POST   | Delegate Energy (30K–5M) for 1h–14d |
| `/delegateBandwidth`  | POST   | Delegate Bandwidth (1K–200K) for 1h |
| `/addressActivate`    | POST   | Activate a new TRON address         |
| `/orders/{order_id}`  | GET    | Check order status                  |
| `/api/price-estimate` | POST   | Get real-time price quote           |

### Rate Limits

* **30 requests/minute** per API key
* Up to **5 API keys** per account

### Error Codes

<table data-header-hidden><thead><tr><th width="138.765625"></th><th></th></tr></thead><tbody><tr><td>HTTP Status</td><td>Meaning</td></tr><tr><td>400</td><td>Invalid request parameters (bad address, volume, duration, or resource type)</td></tr><tr><td>401</td><td>Missing or invalid API key</td></tr><tr><td>402</td><td>Insufficient balance — top up your account</td></tr><tr><td>429</td><td>Rate limit exceeded (30 requests/min per API key)</td></tr><tr><td>502</td><td>Provider error — the upstream delegation service is temporarily unavailable</td></tr></tbody></table>

### Pricing

You pay in USD. The price is calculated based on the current TRX/USD rate. You are charged only after the delegation is confirmed — if the order fails, nothing is deducted.

For example, 32,000 Energy for 24h costs approximately $1.60–$1.80, depending on the current TRX rate.


# delegateEnergy - TRON energy

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

This endpoint delegates energy to a TRON address. In most cases, the order completes immediately with status "success".

#### Parameter

| Parameter       | Type    | Required | Description                                        |
| --------------- | ------- | -------- | -------------------------------------------------- |
| target\_address | string  | Yes      | TRON wallet address (starts with T, 34 characters) |
| volume          | integer | Yes      | Energy amount: 30,000 — 5,000,000                  |
| duration        | string  | Yes      | "1h", "1d", "3d", "7d", "14d"                      |

#### Request

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl -X POST https://api.getblock.io/tron-energy/delegateEnergy \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD",
    "volume": 65000,
    "duration": "3d"
  }'
```

{% endcode %}
{% endtab %}

{% tab title="Axios" %}
{% code overflow="wrap" %}

```javascript
import axios from 'axios';
const data = JSON.stringify({
    "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD",
    "volume": 65000,
    "duration": "3d"
  });

const config = {
    method: 'post',
    url: 'https://api.getblock.io/tron-energy/delegateEnergy',
    headers: {
        'Content-Type': 'application/json',
        'Authorization: Bearer YOUR_API_KEY'
    },
    data: data
};
axios(config)
    .then(response => console.log(JSON.stringify(response.data)))
    .catch(error => console.log(error));
```

{% endcode %}
{% endtab %}

{% tab title="Request" %}
{% code overflow="wrap" %}

```python
import requests
import json

url = "https://api.getblock.io/tron-energy/delegateEnergy"

payload = json.dumps({
    "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD",
    "volume": 65000,
    "duration": "3d"
  })

headers = {
        'Content-Type': 'application/json',
        'Authorization: Bearer YOUR_API_KEY'
    },
response = requests.post(url, headers=headers, data=payload)
print(response.text)
```

{% endcode %}
{% endtab %}

{% tab title="Rust" %}
{% code overflow="wrap" %}

```rust
use reqwest::header;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = reqwest::Client::new();

    let url = "https://api.getblock.io/tron-energy/delegateEnergy";
    let payload = r#"{
        "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD",
        "volume": 65000,
        "duration": "1d"
    }"#;

    let response = client
        .post(url)
        .header(header::CONTENT_TYPE, "application/json")
        .header(header::AUTHORIZATION, "Bearer YOUR_API_KEY")
        .body(payload)
        .send()
        .await?;

    println!("{}", response.text().await?);

    Ok(())
}
```

{% endcode %}
{% endtab %}

{% tab title="GO" %}

```go
package main
import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
)
func main() {
    url := "https://api.getblock.io/tron-energy/delegateEnergy"
    payload := map[string]interface{}{
        "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD",
        "volume":         65000,
        "duration":       "3d",
    }
    jsonData, _ := json.Marshal(payload)
    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
    req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
    req.Header.Set("Content-Type", "application/json")
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    var result map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&result)
    fmt.Println(result)
}
```

{% endtab %}
{% endtabs %}

#### &#x20;Response&#x20;

```json
{
  "order_id": "clxyz123...",
  "status": "success",
  "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD",
  "resource_type": "energy",
  "volume": 65000,
  "duration": "3d",
  "price_usd": "4.97",
  "trx_spent": 20.12,
  "provider_order_id": 12345,
  "txid": "abc123def...",
  "message": "Order completed successfully."
}
```


# delegateBandwidth - TRON energy

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

This delegates bandwidth to a TRON address. Same flow as Energy — instant result in most cases.

### Body Parameter

| Parameter       | Type    | Required | Description                                        |
| --------------- | ------- | -------- | -------------------------------------------------- |
| target\_address | string  | Yes      | TRON wallet address (starts with T, 34 characters) |
| volume          | integer | Yes      | Bandwidth amount: 1,000 — 200,000                  |
| duration        | string  | Yes      | "1h" (only 1 hour supported for Bandwidth)         |

### Request Sample

#### Request

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl -X POST https://api.getblock.io/tron-energy/delegateBandwidth \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD",
    "volume": 5000,
    "duration": "1h"
  }
'
```

{% endcode %}
{% endtab %}

{% tab title="Axios" %}
{% code overflow="wrap" %}

```javascript
import axios from 'axios';
const data = JSON.stringify({
    "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD",
    "volume": 5000,
    "duration": "1h"
  }
);

const config = {
    method: 'post',
    url: 'https://api.getblock.io/tron-energy/delegateBandwidth',
    headers: {
        'Content-Type': 'application/json',
        'Authorization: Bearer YOUR_API_KEY'
    },
    data: data
};
axios(config)
    .then(response => console.log(JSON.stringify(response.data)))
    .catch(error => console.log(error));
```

{% endcode %}
{% endtab %}

{% tab title="Request" %}
{% code overflow="wrap" %}

```python
import requests
import json

url = "https://api.getblock.io/tron-energy/delegateBandwidth"

payload = json.dumps({
    "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD",
    "volume": 5000,
    "duration": "1h"
  }
)

headers = {
        'Content-Type': 'application/json',
        'Authorization: Bearer YOUR_API_KEY'
    },
response = requests.post(url, headers=headers, data=payload)
print(response.text)
```

{% endcode %}
{% endtab %}

{% tab title="Rust" %}
{% code overflow="wrap" %}

```rust
use reqwest::header;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = reqwest::Client::new();

    let url = "https://api.getblock.io/tron-energy/delegateBandwidth";
    let payload = r#"{
    "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD",
    "volume": 5000,
    "duration": "1h"
  }
"#;

    let response = client
        .post(url)
        .header(header::CONTENT_TYPE, "application/json")
        .header(header::AUTHORIZATION, "Bearer YOUR_API_KEY")
        .body(payload)
        .send()
        .await?;

    println!("{}", response.text().await?);

    Ok(())
}
```

{% endcode %}
{% endtab %}

{% tab title="GO" %}

```go
package main
import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
)
func main() {
    url := "https://api.getblock.io/tron-energy/delegateBandwidth"
    payload := map[string]interface{}{
    "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD",
    "volume": 5000,
    "duration": "1h"
  }

    jsonData, _ := json.Marshal(payload)
    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
    req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
    req.Header.Set("Content-Type", "application/json")
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    var result map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&result)
    fmt.Println(result)
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Bandwidth only supports "1h" duration.
{% endhint %}

### Response Sample

```bash
{
  "order_id": "clxyz123...",
  "status": "success",
  "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD",
  "resource_type": "energy",
  "volume": 65000,
  "duration": "3d",
  "price_usd": "4.97",
  "trx_spent": 20.12,
  "provider_order_id": 12345,
  "txid": "abc123def...",
  "message": "Order completed successfully."
}
```


# addressActivate - TRON energy

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

This activates a TRON address on the blockchain. Required before delegating Energy or Bandwidth to a new (never-used) address.

{% hint style="info" %}
Fixed cost: 1.87 TRX, charged in USD at the current TRX/USD rate.
{% endhint %}

### Body Parameter

| Parameter       | Type   | Required | Description                                            |
| --------------- | ------ | -------- | ------------------------------------------------------ |
| target\_address | string | Yes      | TRON wallet to activate (starts with T, 34 characters) |

### Request Sample

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl -X POST https://api.getblock.io/tron-energy/addressActivate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD"
  }'
```

{% endcode %}
{% endtab %}

{% tab title="Axios" %}
{% code overflow="wrap" %}

```javascript
import axios from 'axios';
const data = JSON.stringify({
    "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD"
  }
);

const config = {
    method: 'post',
    url: 'https://api.getblock.io/tron-energy/addressActivate',
    headers: {
        'Content-Type': 'application/json',
        'Authorization: Bearer YOUR_API_KEY'
    },
    data: data
};
axios(config)
    .then(response => console.log(JSON.stringify(response.data)))
    .catch(error => console.log(error));
```

{% endcode %}
{% endtab %}

{% tab title="Request" %}
{% code overflow="wrap" %}

```python
import requests
import json

url = "https://api.getblock.io/tron-energy/addressActivate"

payload = json.dumps({
    "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD"
  }
)

headers = {
        'Content-Type': 'application/json',
        'Authorization: Bearer YOUR_API_KEY'
    },
response = requests.post(url, headers=headers, data=payload)
print(response.text)
```

{% endcode %}
{% endtab %}

{% tab title="Rust" %}
{% code overflow="wrap" %}

```rust
use reqwest::header;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = reqwest::Client::new();

    let url = "https://api.getblock.io/tron-energy/addressActivate";
    let payload = r#"{
    "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD"
  }
"#;

    let response = client
        .post(url)
        .header(header::CONTENT_TYPE, "application/json")
        .header(header::AUTHORIZATION, "Bearer YOUR_API_KEY")
        .body(payload)
        .send()
        .await?;

    println!("{}", response.text().await?);

    Ok(())
}
```

{% endcode %}
{% endtab %}

{% tab title="GO" %}

```go
package main
import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
)
func main() {
    url := "https://api.getblock.io/tron-energy/addressActivate"
    payload := map[string]interface{}{
    "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD"
  }

    jsonData, _ := json.Marshal(payload)
    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
    req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
    req.Header.Set("Content-Type", "application/json")
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    var result map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&result)
    fmt.Println(result)
}
```

{% endtab %}
{% endtabs %}

### Response Sample

```bash
{
  "order_id": 12345,
  "status": "success",
  "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD",
  "trx_spent": 1.87,
  "price_usd": "0.52",
  "txid": "abc123def..."
}
```


# orders/{order\_id} - TRON energy

Example code for the orders/{order\_id} JSON RPC method. Сomplete guide on how to use orders/{order\_id} JSON RPC in GetBlock Web3 documentation.

This retrieves the details of a previously placed order. Useful if you received a 202 response and need to check the final status.

### Path Parameter

| pending | Order is being processed                          |
| ------- | ------------------------------------------------- |
| success | Order completed successfully, resources delegated |
| failed  | Order failed — no charge applied                  |

### Request Sample

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl -X GET "https://api.getblock.io/tron-energy/orders/success" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

{% endcode %}
{% endtab %}

{% tab title="Axios" %}
{% code overflow="wrap" %}

```javascript
const axios = require('axios');

const orderId = "success";
const url = `https://api.getblock.io/tron-energy/orders/${orderId}`;

axios.get(url, {
    headers: {
        'Authorization': 'Bearer YOUR_API_KEY'
    }
})
.then(response => {
    console.log(response.data);
})
.catch(error => {
    console.error(error.response.data);
});
```

{% endcode %}
{% endtab %}

{% tab title="Request" %}
{% code overflow="wrap" %}

```python
import requests

order_id = "success"
url = f"https://api.getblock.io/tron-energy/orders/{order_id}"

headers = {
    'Authorization': 'Bearer YOUR_API_KEY'
}

response = requests.get(url, headers=headers)
print(response.text)
```

{% endcode %}
{% endtab %}

{% tab title="Rust" %}
{% code overflow="wrap" %}

```rust
use reqwest::header;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = reqwest::Client::new();

    let order_id = "success";
    let url = format!("https://api.getblock.io/tron-energy/orders/{}", order_id);

    let response = client
        .get(&url)
        .header(header::AUTHORIZATION, "Bearer YOUR_API_KEY")
        .send()
        .await?;

    println!("{}", response.text().await?);

    Ok(())
}
```

{% endcode %}
{% endtab %}

{% tab title="GO" %}

```go
package main

import (
    "fmt"
    "io"
    "net/http"
)

func main() {
    orderId := "success"
    url := fmt.Sprintf("https://api.getblock.io/tron-energy/orders/%s", orderId)

    req, _ := http.NewRequest("GET", url, nil)
    req.Header.Set("Authorization", "Bearer YOUR_API_KEY")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    fmt.Println(string(body))
}
```

{% endtab %}
{% endtabs %}

### Response Sample

```bash
{
  "order_id": "clxyz123...",
  "status": "success",
  "target_address": "TUo8pycbvje9w2XYsNnnzw67bpPs4GLFyD",
  "resource_type": "energy",
  "volume": 65000,
  "duration": "3d",
  "price_usd": "4.97",
  "trx_spent": 20.12,
  "provider_order_id": "12345",
  "created_at": "2026-02-08T12:00:00.000Z"
}

```


# price-estimate - TRON Energy

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

This get a real-time price estimate for Energy delegation before placing an order.

### Body Parameter

| Parameter    | Type    | Required | Description                       |
| ------------ | ------- | -------- | --------------------------------- |
| resourceType | string  | Yes      | "energy"                          |
| volume       | integer | Yes      | Energy amount: 30,000 — 5,000,000 |
| duration     | string  | Yes      | "1h", "1d", "3d", "7d", "14d"     |

### Request Sample

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl -X POST https://api.getblock.io/tron-energy/api/price-estimate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "resourceType": "energy",
    "volume": 50000,
    "duration": "1h"
  }
'
```

{% endcode %}
{% endtab %}

{% tab title="Axios" %}
{% code overflow="wrap" %}

```javascript
import axios from 'axios';
const data = JSON.stringify({
    "resourceType": "energy",
    "volume": 50000,
    "duration": "1h"
  }
);

const config = {
    method: 'post',
    url: 'https://api.getblock.io/tron-energy/api/price-estimate ',
    headers: {
        'Content-Type': 'application/json',
        'Authorization: Bearer YOUR_API_KEY'
    },
    data: data
};
axios(config)
    .then(response => console.log(JSON.stringify(response.data)))
    .catch(error => console.log(error));
```

{% endcode %}
{% endtab %}

{% tab title="Request" %}
{% code overflow="wrap" %}

```python
import requests
import json

url = "https://api.getblock.io/tron-energy/api/price-estimate"

payload = json.dumps({
    "resourceType": "energy",
    "volume": 50000,
    "duration": "1h"
  }
)

headers = {
        'Content-Type': 'application/json',
        'Authorization: Bearer YOUR_API_KEY'
    },
response = requests.post(url, headers=headers, data=payload)
print(response.text)
```

{% endcode %}
{% endtab %}

{% tab title="Rust" %}
{% code overflow="wrap" %}

```rust
use reqwest::header;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = reqwest::Client::new();

    let url = "https://api.getblock.io/tron-energy/api/price-estimate";
    let payload = r#"{
    "resourceType": "energy",
    "volume": 50000,
    "duration": "1h"
  }
"#;

    let response = client
        .post(url)
        .header(header::CONTENT_TYPE, "application/json")
        .header(header::AUTHORIZATION, "Bearer YOUR_API_KEY")
        .body(payload)
        .send()
        .await?;

    println!("{}", response.text().await?);

    Ok(())
}
```

{% endcode %}
{% endtab %}

{% tab title="GO" %}

```go
package main
import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
)
func main() {
    url := "https://api.getblock.io/tron-energy/api/price-estimate"
    payload := map[string]interface{}{
    "resourceType": "energy",
    "volume": 50000,
    "duration": "1h"
  }

    jsonData, _ := json.Marshal(payload)
    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
    req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
    req.Header.Set("Content-Type", "application/json")
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    var result map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&result)
    fmt.Println(result)
}
```

{% endtab %}
{% endtabs %}

### Response Sample

```bash
{
  "price_sun": 32,
  "trx": "2.08",
  "price_usd": "0.58",
  "provider": "default"
}
```


# Wallet Audit

Learn about GetBlock Wallet Audit, its benefits and how to use to analyze wallet address

Wallet audit is a service that conducts risk assessments for an automated wallet on the blockchain. The service analyzes on-chain wallet behavior and provides a comprehensive report that includes a trust score, an AML check, a behavioral profile, a protocol interaction history, and predictive intentions.

{% hint style="warning" %}
*Wallet Audit provides automated risk indicators based on publicly available on-chain data. The results are for informational purposes only and do not constitute AML compliance verification, legal advice, or regulatory screening. We do not guarantee the accuracy or completeness of the data. The decision to interact with an address is made by the user.*
{% endhint %}

### Use Cases

Wallet Audit provides a complete behavioral wallet profile, not just a "fraud / not fraud" check. Below are six key scenarios where a full audit creates measurable value.

#### **1.  DeFi Protocol — Personalized Onboarding**

All users connecting to the protocol see the same interface, regardless of their experience, preferences, or financial capabilities. Beginners get lost in complex products, while experienced users don't see what they need.

With Wallet Audit, the moment a wallet connects, an audit runs instantly. Based on Risk Willingness, Experience, and Intentions, the protocol surfaces relevant products.&#x20;

**Example**:

* Beginner (Experience = 2, Risk Willingness = 3) → simple ETH staking, basic pools
* Experienced user (Experience = 10, Intentions: Leveraged Lending = HIGH) → directly to margin products, concentrated liquidity

> **Parameters used:** Experience Level, Risk Willingness, Intentions, Protocols

#### **2. Lending Protocol — Borrower Assessment**

In DeFi lending, all borrowers are assessed equally — only by collateral volume. There is no data on the borrower's financial stability or behavioral history.

With Wallet Audit, Risk Capability, Total Balance, and Experience, determine maximum loan size and collateral requirements.&#x20;

**Example**:

* Wallet A: Risk Capability = 1, balance $0.09, Experience = 10 → experienced but without funds. High collateral, low limit.
* Wallet B: Risk Capability = 8, balance $100K, Experience = 9 → experienced and financially stable. Standard collateral, increased limit.

> **Parameters used:** Risk Capability, Total Balance, Experience Level, Risk Willingness

#### **3. Growth/Marketing — User Base Segmentation**

Marketing campaigns in Web3 operate "blindly". The protocol only knows wallet addresses but doesn't understand who its users are, what they do, or what they need.

With Wallet Audit, a mass audit of connected wallets uses Transaction Categories, Protocols, and Intentions to split the base into cohorts for targeted marketing.&#x20;

Example:

* 40% of users with Prob\_Trade = HIGH and Uniswap interaction → launch a DEX aggregator for them
* 25% with Prob\_Lend = HIGH and Aave, Compound protocols → cross-promo with lending product
* 15% with Prob\_NFT = HIGH → partnership with NFT marketplace

> **Parameters used:** Transaction Categories, Protocols, Intentions, Experience Level

#### **4. Token Sale/Launchpad — Investor Quality Filtering**

Token sales are filled with airdrop farmers and bots who dump tokens on the first day of listing. Real investors don't receive allocation.

With Wallet Audit, Wallet Rank, Experience, and Risk Capability, provide objective applicant scoring. Allocation priority goes to wallets with a verified history.&#x20;

Example:

* Investor A: Wallet Rank in top 10K, Experience = 9, Risk Capability = 7, Intentions: Staking = HIGH → long-term holder, priority allocation
* Investor B: fresh wallet, 3 transactions, Wallet Rank = 0, Experience = 1 → likely farmer, low priority

> **Parameters used:** Wallet Rank, Experience Level, Risk Capability, Intentions, Transaction Count

#### **5. Quest Platforms — Adaptive Tasks and Sybil Protection**

Quest platforms (Layer3, Zealy, Galxe) offer the same tasks to everyone. Too difficult for beginners, too easy for experienced users. Bot farms collect rewards intended for real users.

With Wallet Audit, Experience and Protocols determine different quests for different levels, while Wallet Rank filters sybil accounts from real users.&#x20;

Example:

* Beginner (Experience = 2) → quest: "Make your first swap on Uniswap", "Stake ETH via Lido"
* Experienced (Experience = 8, Protocols: Aave, Lido, Curve) → quest: "Provide concentrated liquidity on Uniswap V3", "Create a leveraged position on Aave"
* Sybil filter: Wallet Rank < threshold or Transaction Count < 15 → wallet does not receive rewards

> **Parameters used:** Experience Level, Protocols, Wallet Rank, Transaction Count, Intentions

#### **6. Airdrop Campaigns — Farmer Filtering**

Most airdrop campaigns distribute tokens indiscriminately to everyone. Result — 80%+ of recipients sell on the first day, the price crashes, and real protocol users don't receive a fair allocation.

With Wallet Audit, Wallet Rank, Experience, and Transaction Categories objectively assess whether a wallet belongs to a real protocol user.

Example:

* Tier 1 (increased airdrop): Wallet Rank in top 20K, Experience >= 7, Transaction Categories include the protocol core category, AML = clean
* Tier 2 (standard airdrop): Wallet Rank in top 100K, Experience >= 4
* Exclusion: Wallet Rank = 0, Experience = 1, fewer than 15 transactions → airdrop farmer, does not receive allocation

> **Parameters used:** Wallet Rank, Experience Level, Transaction Categories, Predicted Trust, AML Analysis

{% hint style="danger" %}

### Limitations

* The service only works with regular wallets (EOA — Externally Owned Accounts). **Contract addresses are not supported.**
* A minimum of 10–15 transactions is required to calculate an accurate predictive score. Wallets with less history lack sufficient data for a reliable assessment
  {% endhint %}

### Supported Network

1. Ethereum(ETH)
2. BNB Smart Chain(BSC)
3. Base

### How to Audit a Wallet Address

1. Go to your [GetBlock Account Dashboard](https://account.getblock.io/products/address-audit#check)

<figure><img src="/files/u8IbGyaJUxek1mn9OKL9" alt=""><figcaption></figcaption></figure>

2. Select the network you want to work with:

<figure><img src="/files/gO1qaWhfmdpQh42OpTZg" alt=""><figcaption></figcaption></figure>

3. Enter the wallet address you want to analyze:

<figure><img src="/files/M618gVF8rp8iZxqbupjQ" alt=""><figcaption></figcaption></figure>

4. Click on **Run Check:**<br>

<figure><img src="/files/OjSzIggHN1JmJGxXAweL" alt=""><figcaption></figcaption></figure>

5. Scroll down to see the analysis:

<figure><img src="/files/RIFVSH4VwMTB3hvJM4Nw" alt=""><figcaption></figcaption></figure>

<details>

<summary><strong>This report includes the following:</strong></summary>

1. Wallet balance, age, and number of transactions
2. Risk Willingness / Experience Level / Risk Capability scale

&#x20;         i. Risk Willingness: This measures psychological willingness to take risks. Determined by on-chain behavior: leverage usage, volatile assets, experimental protocols.

&#x20;          ii. Experience Level: This measures the depth and duration of Web3 activity: number of protocols, activity duration, transaction complexity, and multi-chain activity.

&#x20;           iii. Risk Capability: This measures financial ability to withstand losses, weighted by behavioral risk appetite.&#x20;

&#x20;      Roughly: available capital × Risk Willingness. A wallet with high willingness but a small balance gets a low Risk Capability — it can act riskily but cannot absorb meaningful loss.&#x20;

&#x20;       The reverse is also true: a large balance with low willingness scores low because the capital stays idle. ChainAware does not disclose the exact formula but considers asset size, diversification, and portfolio composition.&#x20;

3. Predicted trust score: The main safety indicator — the probability that the wallet is legitimate. Displayed as a percentage from 0% to 100%.

   | Range     | Level       | Interpretation                                           |
   | --------- | ----------- | -------------------------------------------------------- |
   | 80–100%   | Low Risk    | Behavior typical of legitimate wallets                   |
   | 50–80%    | Medium Risk | Warning signals present, additional analysis recommended |
   | Below 50% | High Risk   | Behavioral patterns match known fraud schemes            |
4. Intentions: This predicts the next actions across categories, each receiving a score of HIGH, MEDIUM, or LOW, calculated based on the wallet's entire historical activity.
5. Recommendations: These show activities based on the wallet's risk profile. Examples: WBTC holding, ETH holding, Stablecoin lending.
6. Transaction: This shows the breakdown of historical transactions by type: DeFi, Decentralized Exchanges, Layer 1, Layer 2, NFT, Bridge, Lending & Borrowing, Business Services, Gaming. Shows the number of transactions in each category.
7. Protocols: This lists the specific protocols and services the wallet has interacted with, along with transaction counts. Examples: 1inch, Uniswap, Wrapped Ether, Tether, Zora, Arbitrum, Starknet, Opensea.
8. AML Analysis: This shows wallet check across 18+ parameters for links to criminal activity. Each parameter is displayed as Yes or No.

</details>

### Next Step

1. [Wallet Risk](/crypto-address-audit/wallet-risk)
2. [Rug Pull Checker](/crypto-address-audit/wallet-audit)
3. [Address Audit API Reference](/crypto-address-audit/api-reference)


# Wallet Risk

Learn about GetBlock Wallet Risk, its benefits and how to use to analyze wallet address

Wallet Risk Check is a quick blockchain wallet risk assessment service. It returns an AI-predictive trust score, screening across 18 AML risk categories, and a sanctions check — in a single API call with response time under 100ms.

This is a lightweight version of [Wallet Audit](/crypto-address-audit/wallet-audit). Wallet Risk Check provides a quick go/no-go signal e.g Can this wallet be trusted?&#x20;

{% hint style="info" %}
For a full behavioral profile (intentions, experience, protocols, transactions), use [Wallet Audit.](/crypto-address-audit/wallet-audit)
{% endhint %}

### What Wallet Risk Does?

* Predicted Trust Score (0–100%): AI-predictive trust score
* AML Risk Screening: screening across 18 risk categories (cybercrime, money laundering, phishing, etc.)
* Sanctions Check: verification against sanctions lists

### Difference Between Wallet Risk from Wallet Audit

| <p><br></p>                   | Wallet Risk Check                 | Wallet Audit                      |
| ----------------------------- | --------------------------------- | --------------------------------- |
| Response time                 | < 100ms                           | Several seconds                   |
| Trust Score                   | ✅ Yes                             | ✅ Yes                             |
| AML Screening (18 categories) | ✅ Yes                             | ✅ Yes                             |
| Sanctions Check               | ✅ Yes                             | ✅ Yes                             |
| Intentions (14 categories)    | ❌ No                              | ✅ Yes                             |
| Experience / Risk Profile     | ❌ No                              | ✅ Yes                             |
| Protocols / Categories        | ❌ No                              | ✅ Yes                             |
| Wallet Overview / Rank        | ❌ No                              | ✅ Yes                             |
| Networks                      | 5 (ETH, BNB, Base, Polygon, TRON) | 3 (ETH, BNB, Base)                |
| When to use                   | Quick screening: allow / reject   | Deep analysis: who is this wallet |

### How Predicated Trust Score is Calculated

They are two-step logic involved in this calculation:

#### Step 1: AML Check (hard override)

If at least one field in forensic\_details = "1" → probabilityFraud is automatically set to 1.0 (Predicted Trust = 0%). The ML model is not invoked. Any AML flag = automatic maximum risk.

#### Step 2: ML Model (if AML is clean)

If all forensic\_details fields = "0" → the predictive AI model analyzes on-chain wallet behavior and returns probabilityFraud from 0.0 to 1.0. Predicted Trust = 1 − probabilityFraud.

Examples:

* vitalik.eth: all forensic\_details = "0" → ML model → probabilityFraud = 0.042 → Predicted Trust = 95.8%
* Fraudulent wallet: money\_laundering = "1" → hard override → probabilityFraud = 1.0 → Predicted Trust = 0%

{% hint style="danger" %}

### Limitations

* The service only works with regular wallets (EOA — Externally Owned Accounts). **Contract addresses are not supported.**
* A minimum of 10–15 transactions is required to calculate an accurate predictive score. Wallets with less history lack sufficient data for a reliable assessment
  {% endhint %}

### Supported Networks

1. Ethereum(ETH)
2. BNB Smart Chain
3. Base&#x20;
4. Polygon
5. TRON

### How to Check the Risk In A Wallet Address

1. Go to your [GetBlock Account Dashboard](https://account.getblock.io/products/address-audit#check) and click **Wallet Risk**

<figure><img src="/files/mlMuZFimMxvKIX9Fhknm" alt="wallet risk"><figcaption></figcaption></figure>

2. Select the choice of your network using the dropdown:

<figure><img src="/files/fNWUdiiNW8lPSFsL7K6i" alt="network selection"><figcaption></figcaption></figure>

3. Enter the wallet address:

<figure><img src="/files/KWgt8uiaG8hzDENOwnzK" alt=""><figcaption></figcaption></figure>

4. Click on **Run Check:**

<figure><img src="/files/OjSzIggHN1JmJGxXAweL" alt=""><figcaption></figcaption></figure>

5. Scroll down to see the analysis:

<figure><img src="/files/vll6qw5eVnFhQv8NmTD5" alt=""><figcaption></figcaption></figure>

<details>

<summary><strong>This report includes the following:</strong></summary>

1. Predicted trust score: This is the main indicator of a wallet's level of trust, ranging from 0% to 100%. Calculated as 1 − probability of fraud. Displayed with a status badge (Not Fraud / Fraud / New Address) and a sanctions badge (Not Sanctioned / Sanctioned).

| Predicted Trust | Level       | Interpretation                                                 |
| --------------- | ----------- | -------------------------------------------------------------- |
| 80–100%         | Low Risk    | Wallet with clean history                                      |
| 50–79%          | Medium Risk | Risk factors detected, full Wallet Audit recommended           |
| 0–49%           | High Risk   | Wallet is highly likely associated with fraudulent activity    |
| 0% (auto)       | AML Flag    | At least one AML flag detected — score automatically set to 0% |

2. AML Analysis: This shows 18 risk categories with each parameter displayed as  No (clean) or Yes (flag detected).

{% hint style="warning" %}
*If at least one parameter forensic\_details = "1" → probabilityFraud is automatically set to 1.0 (i.e. Predicted Trust = 0%). This is a hard override; the ML model is not used.*
{% endhint %}

3. Sanctions Check: This shows sanctions list verification. It displayed as a badge: Not Sanctioned (green) or Sanctioned (red). If the wallet is sanctioned, the category, name, and source link are displayed.

</details>

### Next Step

1. [Wallet Audit](/crypto-address-audit/wallet-audit)
2. [Rug Pull Checker](/crypto-address-audit/wallet-audit)
3. [Address Audit API Reference](/crypto-address-audit/api-reference)


# Rug Pull Checker

Learn about GetBlock Rug Pull Checker, its benefits and how to use to analyze contract address

Rug Pull Checks is a smart-contract rug-pull risk assessment service. The service analyzes contracts across two independent dimensions and returns an overall risk score.

Two independent analysis blocks:

1. Rug Pull Probability: AI-predictive score (0–100%). Analyzes the behavior of the contract creator and liquidity providers (LPs) based on their on-chain history. Does not analyze contract code.
2. Contract Details: verification of basic contract properties (open source, proxy, self-destruct, withdrawal rights, blacklist). Does not affect the Rug Pull Probability.

{% hint style="warning" %}
These are two independent blocks. Contract Details (green checkmarks) do not affect the Rug Pull Probability. A contract with clean code, but a suspicious creator will receive a high risk score.
{% endhint %}

### Difference Between Rug Pull Checker And Wallet Audit

| <p><br></p>      | **Rug Pull Checks**                                | **Wallet Audit**                       |
| ---------------- | -------------------------------------------------- | -------------------------------------- |
| Input            | Smart contract address                             | Wallet address (EOA)                   |
| What it analyzes | Creator behavior + LPs + basic contract properties | On-chain wallet behavior, AML, intent  |
| Primary score    | Rug Pull Probability (0–100%)                      | Predicted Trust (0–100%)               |
| When to use      | Before investing in a contract/pool/token          | Before transacting with a counterparty |

### Difference Between Rug Pull Checker And Risk API (Hexens Glider)

GetBlock also provides the Risk API service, powered by Hexens Glider Token Risks. This is a fundamentally different product; they do not compete but complement each other.

| <p><br></p>      | **Rug Pull Checks**                                            | **Risk API**                                                                                                    |
| ---------------- | -------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| Provider         | ChainAware.ai                                                  | Hexens (Glider Token Risks)                                                                                     |
| What it analyzes | Behavior of the contract creator and liquidity providers (LPs) | Smart contract code — logic of each function and dependencies                                                   |
| Method           | Behavioral AI/ML — analysis of on-chain wallet history         | Static code analysis — parsing of ERC-20 function logic                                                         |
| Key question     | "Can the people behind this contract be trusted?"              | "Is there malicious code in this contract?"                                                                     |
| What it catches  | Suspicious creators, new LP addresses, links to fraud wallets  | Honeypot, hidden mint, blacklist, selfdestruct, hidden fees, backdoors, pausable proxy, etc. (22+ threat types) |
| Networks         | ETH, BNB, Base                                                 | 32+ EVM chains                                                                                                  |
| Analogy          | Catches the "bomber by handwriting"                            | Catches the "bomb in the code"                                                                                  |

{% hint style="info" %}
Both products complement each other: ChainAware may give a green light to a contract with a clean deployer, but with a honeypot in the code. Hexens may show clean code, but the contract was created by a wallet that previously executed a rug pull. Using the two gives a full picture.
{% endhint %}

{% hint style="warning" %}
Disclaimer

Rug Pull Check provides automated risk indicators based on publicly available on-chain data. Results are informational in nature and do not constitute investment advice, a security audit, or legal counsel. The predictive model accuracy is 68% — 32% of rug pulls may go undetected. We do not guarantee the accuracy or completeness of the data. The decision to interact with a contract is made by the user.
{% endhint %}

### Supported Networks

| **Network**     | **API Value** | **Note**     |
| --------------- | ------------- | ------------ |
| Ethereum        | ETH           | Full support |
| BNB Smart Chain | BNB           | Full support |
| Base            | BASE          | Full support |

### How Rug Pull Probability Is Calculated&#x20;

There are four steps involved, which are:

1. Find the contract creator: It identifies the wallet that deployed the contract and runs it through the Fraud Detector to obtain the creator's Trust Score.
2. Trace the deployment chain: if the contract was deployed by another contract, it follows the chain to the actual wallet. **The obfuscation through the chain itself is a red flag.**
3. Analyze the liquidity providers (LPs): run each LP through the Fraud Detector and obtain the Trust Score for each LP.
4. Generate the Rug Pull Probability: based on the combination of the creator's Trust Score + LP Trust Scores.

#### What increases the risk score:

* New creator address (no history to evaluate)
* Low Trust Score for the creator (behavioral history matches fraud patterns)
* New addresses adding liquidity (classic rug pull pattern)
* Low Trust Score for LPs
* Obfuscated deployment chain (contract deploys contract)

#### What decreases the risk score:

* Creator with a long clean on-chain history
* LPs with high Trust Scores
* Transparent addresses without routing through mixers

> Accuracy: 68%

The algorithm correctly identifies 68 out of 100 rug pulls based on purely behavioral analysis, without code analysis. The 32% miss rate consists of more sophisticated operators who invest in building a legitimate-looking wallet history before executing a rug pull.

{% hint style="danger" %}

#### Limitations

* The service works only with smart contracts. If a regular wallet address (EOA) is submitted, an empty result will be returned. To check wallets, use Wallet Audit.
* Rug Pull Probability does not analyze the contract source code. It evaluates the behavior of the people behind the contract, not the code.
* Data freshness depends on the last ChainAware scan (lastChecked field).
  {% endhint %}

### How to Check the Risk In A Wallet Address

1. Go to your [GetBlock Account Dashboard](https://account.getblock.io/products/address-audit#check) and click **Rug Pull**

<figure><img src="/files/Yay5sTjdQ2BuZNGW15Bu" alt=""><figcaption></figcaption></figure>

2. Select the choice of your network using the dropdown:

<figure><img src="/files/nAJUbpn1mQhg3ZGZyrrJ" alt=""><figcaption></figcaption></figure>

3. Enter the contract address:

<figure><img src="/files/qJKCcdTNI4UTaiRjVbvN" alt=""><figcaption></figcaption></figure>

4. Click on **Run Check**
5. Scroll down to see the analysis:

<figure><img src="/files/0I4QUmivxkAQgyT0VaYV" alt=""><figcaption></figcaption></figure>

<details>

<summary><strong>This report includes the following:</strong></summary>

1. Contract name
2. Contract address
3. Creator wallet address
4. Network
5. Badges
6. Rug Pull probability: The primary indicator, ranging from 0% to 100%, is displayed with a progress bar and a High Risk / Medium Risk / Low Risk label.
7. Contract details: This contains parameters that are displayed as a green checkmark (safe) or a red flag (risk).

</details>

### Next Step

* [Address Audit API Reference](/crypto-address-audit/api-reference)


# API Reference

This contain all the endpoints, pricing and error codes to access Address Audit service

The GetBlock Address Audit API provides access to all address audit services, which you can integrate into your dApp, including wallet audit, wallet riska nd rug pull checker

### Base URL

{% code overflow="wrap" %}

```bash
https://services.getblock.io/v1
```

{% endcode %}

### Authentication

All requests require an API key in the header:

```bash
Authorization: Bearer <API_KEY>
```

### How to Get Address Audit API Key

1. Go to your [account dashboard](https://account.getblock.io/)
2. Click on the product icon on the Navbar

<figure><img src="/files/sfUZ0q2P1TnSU6uuMX6p" alt=""><figcaption></figcaption></figure>

3. Scroll down and Select **Address Audit**
4. After that, select the **API key** tab
5. On the **API Key** tab, click on the plus icon, and your API key will be generated for you automatically

<figure><img src="/files/UIjTyWYUs4q7O59XzWgr" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Ensure you store your API Key securely
{% endhint %}

### QuickStart

In this example, you will be auditing a wallet address:&#x20;

* **Axios** (JavaScript / Node.js)
* **Python** (Requests library)

Before you begin, you must have already installed [`npm`](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) or [`yarn`](https://classic.yarnpkg.com/lang/en/docs/install) on your local machine (for the Axios example) or Python and pip (for the Python example).

{% tabs %}
{% tab title="JavaScript (Axios)" %}
{% stepper %}
{% step %}

#### Setup project

Create and initialize a new project:

```bash
mkdir wallet-audit-quickstart
cd wallet-audit-quickstart
npm init --yes
```

{% endstep %}

{% step %}

#### Install Axios

```bash
npm install axios
```

{% endstep %}

{% step %}

#### Create file

Create a new file named `index.js`. This is where you will make your first call.
{% endstep %}

{% step %}

#### Set ES module type

Set the ES module `"type": "module"` in your `package.json`.
{% endstep %}

{% step %}

#### Add code

Add the following code to `index.js`:

{% code title="index.js" %}

```javascript
import axios from "axios";

const data = 
  {  "network": "ETH", "address": "0xa45f...a675"};

const config = {
  method: "post",
  url: "https://services.getblock.io/v1/wallet-audit/check",
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  data: data,
};

axios(config)
  .then((response) => console.log(JSON.stringify(response.data, null, 2)))
  .catch((error) => console.log(error));

```

{% endcode %}

> Replace `<YOUR_API_KEY>` with your actual API Key from the GetBlock dashboard.
> {% endstep %}

{% step %}

#### Run the script

```bash
node index.js
```

Expected output (example):

```json
{
    "data": {
        "message": "Success",
        "walletAddress": "0xa45f...a675",
        "status": "Fraud",
        "probabilityFraud": "0.9329851866",
        "token": null,
        "chain": "ETH",
        "lastChecked": "2026-03-19T07:02:56.000Z",
        "forensic_details": {
            "cybercrime": "0",
            "money_laundering": "0",
            "number_of_malicious_contracts_created": "0",
            "gas_abuse": "0",
            "financial_crime": "0",
            "darkweb_transactions": "0",
            "reinit": "0",
            "phishing_activities": "0",
            "fake_kyc": "0",
            "blacklist_doubt": "0",
            "fake_standard_interface": "0",
            "data_source": "",
            "stealing_attack": "0",
            "blackmail_activities": "0",
            "sanctioned": "0",
            "malicious_mining_activities": "0",
            "mixer": "0",
            "fake_token": "0",
            "honeypot_related_address": "0"
        },
        "checked_times": 3,
        "createdAt": "2026-03-19T06:52:28.000Z",
        "updatedAt": "2026-05-15T17:01:48.000Z",
        "sanctionData": [
            {
                "id": 205813,
                "trustscore_id": 18360032,
                "category": null,
                "name": null,
                "description": null,
                "url": null,
                "isSanctioned": false,
                "createdAt": "2026-05-15T17:01:48.000Z",
                "updatedAt": "2026-05-15T17:01:48.000Z"
            }
        ]
    }
}
```

{% endstep %}
{% endstepper %}
{% endtab %}

{% tab title="Python (Requests)" %}
{% stepper %}
{% step %}

#### Setup the project directory

```bash
mkdir wallet-audit-quickstart
cd wallet-audit-quickstart
```

{% endstep %}

{% step %}

#### Create and activate a virtual environment

```bash
python -m venv venv
source venv/bin/activate

# On Windows, use:
venv\Scripts\activate
```

{% endstep %}

{% step %}

#### Install requests

```bash
pip install requests
```

{% endstep %}

{% step %}

#### Create script

Create a file called `main.py` with the following content:

{% code title="main.py" overflow="wrap" %}

```python
import requests
import json

url = "https://services.getblock.io/v1/wallet-audit/check"

payload = json.dumps({  "network": "ETH", "address": "0xa45f...a675"})

headers = {
      "Authorization": "Bearer YOUR_API_KEY",
  "Content-Type": "application/json",
}

response = requests.post(url, headers=headers, data=payload)
print(response.text)
```

{% endcode %}

> Replace `<YOUR_API_KEY>` with your actual GetBlock API Key.
> {% endstep %}

{% step %}

#### Run the script

```bash
python main.py
```

{% endstep %}
{% endstepper %}
{% endtab %}
{% endtabs %}

### Next Step

* [Wallet Risk endpoint](/crypto-address-audit/api-reference/wallet-risk-endpoint)
* [Wallet Audit endpoint](/crypto-address-audit/api-reference/wallet-audit-endpoint)
* Rug Pull Checker endpoint


# Wallet Audit Endpoint

Example code for the /wallet-audit/audit method. Сomplete guide on how to use /wallet-audit/audit in GetBlock Address Audit documentation.

This method performs a comprehensive fraud audit on a wallet address. Proxied to ChainAware.

## Body Parameters

| Parameter | Type   | Required | Description                                         |
| --------- | ------ | -------- | --------------------------------------------------- |
| network   | string | Yes      | The blockchain network to verify(ETH, BNB, or BASE) |
| address   | string | Yes      | the wallet address                                  |

## Request Example

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl --location --request POST 'https://services.getblock.io/v1/wallet-audit/audit' \
-- header 'Authorization: Bearer YOUR_API_KEY',
--header 'Content-Type: application/json' \
--data-raw ' {  "network": "ETH", "address": "0xa45f...a675"}'
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript (Axios)" %}

```javascript
import axios from "axios";

const data = 
  {  "network": "ETH", "address": "0xa45f...a675"};

const config = {
  method: "post",
  url: "https://services.getblock.io/v1/wallet-audit/audit",
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  data: data,
};

axios(config)
  .then((response) => console.log(JSON.stringify(response.data, null, 2)))
  .catch((error) => console.log(error));

```

{% endtab %}

{% tab title="Python (Requests)" %}

```python
import requests
import json

url = "https://services.getblock.io/v1/wallet-audit/audit"

payload = json.dumps({  "network": "ETH", "address": "0xa45f...a675"})

headers = {
      "Authorization": "Bearer YOUR_API_KEY",
  "Content-Type": "application/json",
}

response = requests.post(url, headers=headers, data=payload)
print(response.text)
```

{% endtab %}

{% tab title="Rust (Reqwest)" %}

```rust
use reqwest::Client;
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new();

    let payload = json!({  "network": "ETH", "address": "0xa45f...a675"});

    let response = client
        .post("https://services.getblock.io/v1/wallet-audit/audit")
        .header("Content-Type", "application/json")
        .header("Authorization: "Bearer YOUR_API_KEY")
        .json(&payload)
        .send()
        .await?;

    let result: serde_json::Value = response.json().await?;
    println!("{:#?}", result);

    Ok(())
}
```

{% endtab %}
{% endtabs %}

## Response Example

{% code overflow="wrap" %}

```json
{
    "data": {
        "message": "Success",
        "walletAddress": "0xa45f...a675",
        "status": "Fraud",
        "probabilityFraud": "0.9329851866",
        "token": null,
        "chain": "ETH",
        "lastChecked": "2026-03-19T07:02:56.000Z",
        "forensic_details": {
            "cybercrime": "0",
            "money_laundering": "0",
            "number_of_malicious_contracts_created": "0",
            "gas_abuse": "0",
            "financial_crime": "0",
            "darkweb_transactions": "0",
            "reinit": "0",
            "phishing_activities": "0",
            "fake_kyc": "0",
            "blacklist_doubt": "0",
            "fake_standard_interface": "0",
            "data_source": "",
            "stealing_attack": "0",
            "blackmail_activities": "0",
            "sanctioned": "0",
            "malicious_mining_activities": "0",
            "mixer": "0",
            "fake_token": "0",
            "honeypot_related_address": "0"
        },
        "categories": [],
        "riskProfile": [
            {
                "Category": "Stable Coin",
                "Balance_age": 0
            },
            {
                "Category": "1to10",
                "Balance_age": 100
            },
            {
                "Category": "10to20",
                "Balance_age": 0
            },
            {
                "Category": "20to30",
                "Balance_age": 0
            },
            {
                "Category": "30to50",
                "Balance_age": 0
            },
            {
                "Category": "50to100",
                "Balance_age": 0
            },
            {
                "Category": "100to200",
                "Balance_age": 0
            },
            {
                "Category": "200to300",
                "Balance_age": 0
            },
            {
                "Category": "300+",
                "Balance_age": 0
            },
            {
                "Category": "Meme Token",
                "Balance_age": 0
            },
            {
                "Category": "Risk_Profile",
                "Balance_age": 2
            }
        ],
        "segmentInfo": "{\"Maker\":0,\"Aave_borrow\":0,\"Aave_lend\":0,\"Lido\":0,\"Compound_lend\":0,\"Compound_borrow\":0}",
        "experience": {
            "Type": "Experience",
            "Value": 0
        },
        "intention": {
            "Type": "Intentions",
            "Value": {
                "Prob_Borrow": "Low",
                "Prob_Gamble": "Low",
                "Prob_Game": "Medium",
                "Prob_Lend": "High",
                "Prob_Leverage_Long": "Low",
                "Prob_Leverage_Long_ETH": "Low",
                "Prob_Leveraged_Lend": "Low",
                "Prob_Leveraged_Stake": "Low",
                "Prob_Leveraged_Stake_ETH": "Low",
                "Prob_NFT": "Medium",
                "Prob_Stake": "Low",
                "Prob_Stake_ETH": "Medium",
                "Prob_Trade": "High",
                "Prob_Yield_Farm": "Low"
            }
        },
        "protocols": [],
        "userDetails": {
            "wallet_age_days": 349,
            "total_balance_usd": 0.26,
            "transaction_count": 2,
            "wallet_rank": 0
        },
        "riskCapability": 1,
        "recommendation": {
            "Type": "Recommendation",
            "Value": [
                "WBTC holding",
                "ETH holding",
                "Stablecoin lending",
                "Stablecoin lending with FIFs (SmartCredit.io)"
            ]
        },
        "checked_times": 6,
        "createdAt": "2026-03-19T06:52:28.000Z",
        "updatedAt": "2026-05-15T17:17:02.000Z",
        "sanctionData": [
            {
                "id": 205878,
                "trustscore_id": 18360032,
                "category": null,
                "name": null,
                "description": null,
                "url": null,
                "isSanctioned": false,
                "createdAt": "2026-05-15T17:17:02.000Z",
                "updatedAt": "2026-05-15T17:17:02.000Z"
            }
        ]
    }
}
```

{% endcode %}

## Response Parameters

| **Field Path**                             | **Type**          | **Example**                                            | **Description**                                                                                                                                                                                                                                                 |
| ------------------------------------------ | ----------------- | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| status                                     | string            | `"Not Fraud"`                                          | ML model verdict. Possible values: `"Not Fraud"`, `"Fraud"`, `"New Address"`.                                                                                                                                                                                   |
| probabilityFraud                           | string            | `"0.0191140026"`                                       | Fraud probability score ranging from `0.0` to `1.0`.                                                                                                                                                                                                            |
| walletAddress                              | string            | `"0xa45f..."`                                          | The audited blockchain wallet address.                                                                                                                                                                                                                          |
| chain                                      | string            | `"ETH"`                                                | The network/blockchain name (e.g., `"ETH"`).                                                                                                                                                                                                                    |
| lastChecked                                | string (ISO 8601) | `"2026-04-15T12:02:21Z"`                               | Timestamp of the most recent fraud analysis.                                                                                                                                                                                                                    |
| checked\_times                             | number            | `183`                                                  | Total number of times this address has been checked.                                                                                                                                                                                                            |
| createdAt                                  | string (ISO 8601) | `"2023-07-19T10:15:00Z"`                               | Record creation timestamp.                                                                                                                                                                                                                                      |
| updatedAt                                  | string (ISO 8601) | `"2026-05-08T14:30:22Z"`                               | Last update timestamp.                                                                                                                                                                                                                                          |
| forensic\_details                          | object            | *See sub-fields below*                                 | Contains 18 AML flags. Each is `"0"` (clean) or `"1"` (flagged). If any flag is `"1"`, `probabilityFraud` defaults to `1.0`.                                                                                                                                    |
| ↳ `.cybercrime`                            | string            | `"0"`                                                  | Cybercrime activity.                                                                                                                                                                                                                                            |
| ↳ `.money_laundering`                      | string            | `"0"`                                                  | Money laundering activity.                                                                                                                                                                                                                                      |
| ↳ `.number_of_malicious_contracts_created` | string            | `"0"`                                                  | Creation of malicious smart contracts.                                                                                                                                                                                                                          |
| ↳ `.gas_abuse`                             | string            | `"0"`                                                  | Gas price manipulation behavior.                                                                                                                                                                                                                                |
| ↳ `.financial_crime`                       | string            | `"0"`                                                  | General financial crime flag.                                                                                                                                                                                                                                   |
| ↳ `.darkweb_transactions`                  | string            | `"0"`                                                  | Transactions associated with darkweb marketplaces.                                                                                                                                                                                                              |
| ↳ `.reinit`                                | string            | `"0"`                                                  | Smart contract reinitialization abuse.                                                                                                                                                                                                                          |
| ↳ `.phishing_activities`                   | string            | `"0"`                                                  | Phishing vector participation.                                                                                                                                                                                                                                  |
| ↳ `.fake_kyc`                              | string            | `"0"`                                                  | Use or association with fake KYC data.                                                                                                                                                                                                                          |
| ↳ `.blacklist_doubt`                       | string            | `"0"`                                                  | Association with blacklisted entities.                                                                                                                                                                                                                          |
| ↳ `.fake_standard_interface`               | string            | `"0"`                                                  | Spoofed/fake token interface usage.                                                                                                                                                                                                                             |
| ↳ `.stealing_attack`                       | string            | `"0"`                                                  | Active theft or exploit activity.                                                                                                                                                                                                                               |
| ↳ `.blackmail_activities`                  | string            | `"0"`                                                  | Blackmail or extortion activities.                                                                                                                                                                                                                              |
| ↳ `.sanctioned`                            | string            | `"0"`                                                  | Presence on known sanctions lists.                                                                                                                                                                                                                              |
| ↳ `.malicious_mining_activities`           | string            | `"0"`                                                  | Malicious or hijacked mining operations.                                                                                                                                                                                                                        |
| ↳ `.mixer`                                 | string            | `"0"`                                                  | Interaction with crypto mixing services (e.g., Tornado Cash).                                                                                                                                                                                                   |
| ↳ `.fake_token`                            | string            | `"0"`                                                  | Creation or deployment of fake/honeypot tokens.                                                                                                                                                                                                                 |
| ↳ `.honeypot_related_address`              | string            | `"0"`                                                  | Association with honeypot contract setups.                                                                                                                                                                                                                      |
| categories                                 | array (object)    | `[{"Category": "NFT", "Count": 12}]`                   | Transaction count breakdown by category. Examples: `"Decentralized Exchanges"`, `"Bridge"`, `"NFT"`, `"Layer 1"`, `"Layer 2"`, `"Lending & Borrowing"`.                                                                                                         |
| riskProfile                                | array (object)    | `[{"Category": "Stable Coin", "Balance_age": "..."}]`  | Balance distribution. Categories include: `"Stable Coin"`, `"1to10"`, `"10to20"`, ..., `"300+"`, `"Meme Token"`, `"Risk_Profile"`. *Note: The "Risk\_Profile" entry represents the Risk Willingness score in the UI.*                                           |
| segmentInfo                                | string (JSON)     | `"{\"Maker\":0,\"Aave_borrow\":0,...}"`                | Protocol interaction flags packed as a JSON string. `1` = interacted, `0` = not. Supported keys: `Maker`, `Aave_borrow`, `Aave_lend`, `Lido`, `Uniswap`, `Compound_lend`, `Compound_borrow`.                                                                    |
| experience                                 | object            | `{"Type": "Experience", "Value": 8}`                   | User experience rating mapped on a scale of `1-10`.                                                                                                                                                                                                             |
| intention                                  | object            | *See description*                                      | Expected behavior map. Format: `{"Type": "Intentions", "Value": { ... }}` where `Value` contains 14 sub-keys, each rated as `"Low"`, `"Medium"`, or `"High"`.                                                                                                   |
| ↳ *Sub-keys*                               | string            | `"Low"`, `"Medium"`, `"High"`                          | `Prob_Borrow`, `Prob_Gamble`, `Prob_Game`, `Prob_Lend`, `Prob_Leverage_Long`, `Prob_Leverage_Long_ETH`, `Prob_Leveraged_Lend`, `Prob_Leveraged_Stake`, `Prob_Leveraged_Stake_ETH`, `Prob_NFT`, `Prob_Stake`, `Prob_Stake_ETH`, `Prob_Trade`, `Prob_Yield_Farm`. |
| protocols                                  | array (object)    | `[{"Protocol": "Uniswap", "Count": 45}]`               | Array of specific protocols the wallet has interacted with alongside their usage frequency.                                                                                                                                                                     |
| userDetails                                | object            | *See sub-fields below*                                 | General metadata and structural metrics of the wallet.                                                                                                                                                                                                          |
| ↳ `.wallet_age_days`                       | number            | `1024`                                                 | Age of the wallet in days.                                                                                                                                                                                                                                      |
| ↳ `.total_balance_usd`                     | number            | `15430.50`                                             | Current aggregate wallet balance in USD.                                                                                                                                                                                                                        |
| ↳ `.transaction_count`                     | number            | `450`                                                  | Cumulative historical transaction count.                                                                                                                                                                                                                        |
| ↳ `.wallet_rank`                           | number            | `88`                                                   | Internal wallet ranking score.                                                                                                                                                                                                                                  |
| riskCapability                             | number            | `7`                                                    | User's risk capability evaluated on a scale of `1-10`.                                                                                                                                                                                                          |
| recommendation                             | object            | `{"Type": "Recommendation", "Value": ["ETH holding"]}` | Tailored system recommendations. `Value` is an array of strings (e.g., `["ETH holding", "Stablecoin lending"]`).                                                                                                                                                |
| sanctionData                               | array (object)    | *See sub-fields below*                                 | Definitive sanction matches associated with this address.                                                                                                                                                                                                       |
| ↳ `.isSanctioned`                          | boolean           | `false`                                                | `true` if sanctioned, `false` if clean.                                                                                                                                                                                                                         |
| ↳ `.category`                              | string (nullable) | `"Terrorism"`                                          | Category of sanction if applicable; otherwise `null`.                                                                                                                                                                                                           |
| ↳ `.name`                                  | string (nullable) | `"Entity Name"`                                        | Official name of the sanctioned entity/person; otherwise `null`.                                                                                                                                                                                                |
| ↳ `.description`                           | string (nullable) | `"Details here..."`                                    | Contextual details regarding the sanction; otherwise `null`.                                                                                                                                                                                                    |
| ↳ `.url`                                   | string (nullable) | `"https://..."`                                        | Reference URL providing sanction evidence; otherwise `null`.                                                                                                                                                                                                    |

## Error Handling

| Status | Description                       |
| ------ | --------------------------------- |
| 400    | Invalid network or missing fields |
| 401    | Missing or invalid auth           |
| 402    | Insufficient balance              |
| 502    | Provider error                    |


# Wallet Risk Endpoint

Example code for the /wallet-audit/check method. Сomplete guide on how to use /wallet-audit/check in GetBlock Address Audit documentation.

This method performs a quick risk score check on a wallet address. Supports more networks than the full audit.

## Body Parameters

| Parameter | Type   | Required | Description                                                   |
| --------- | ------ | -------- | ------------------------------------------------------------- |
| network   | string | Yes      | The blockchain network to verify(ETH, BNB,POLY, TRON or BASE) |
| address   | string | Yes      | the wallet address                                            |

## Request Example

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl --location --request POST 'https://services.getblock.io/v1/wallet-audit/check' \
-- header 'Authorization: Bearer YOUR_API_KEY',
--header 'Content-Type: application/json' \
--data-raw ' {  "network": "ETH", "address": "0xa45f...a675"}'
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript (Axios)" %}

```javascript
import axios from "axios";

const data = 
  {  "network": "ETH", "address": "0xa45f...a675"};

const config = {
  method: "post",
  url: "https://services.getblock.io/v1/wallet-audit/check",
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  data: data,
};

axios(config)
  .then((response) => console.log(JSON.stringify(response.data, null, 2)))
  .catch((error) => console.log(error));

```

{% endtab %}

{% tab title="Python (Requests)" %}

```python
import requests
import json

url = "https://services.getblock.io/v1/wallet-audit/check"

payload = json.dumps({  "network": "ETH", "address": "0xa45f...a675"})

headers = {
      "Authorization": "Bearer YOUR_API_KEY",
  "Content-Type": "application/json",
}

response = requests.post(url, headers=headers, data=payload)
print(response.text)
```

{% endtab %}

{% tab title="Rust (Reqwest)" %}

```rust
use reqwest::Client;
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new();

    let payload = json!({  "network": "ETH", "address": "0xa45f...a675"});

    let response = client
        .post("https://services.getblock.io/v1/wallet-audit/check")
        .header("Content-Type", "application/json")
        .header("Authorization: "Bearer YOUR_API_KEY")
        .json(&payload)
        .send()
        .await?;

    let result: serde_json::Value = response.json().await?;
    println!("{:#?}", result);

    Ok(())
}
```

{% endtab %}
{% endtabs %}

## Response Example

{% code overflow="wrap" %}

```json
{
    "data": {
        "message": "Success",
        "walletAddress": "0xa45f...a675",
        "status": "Fraud",
        "probabilityFraud": "0.9329851866",
        "token": null,
        "chain": "ETH",
        "lastChecked": "2026-03-19T07:02:56.000Z",
        "forensic_details": {
            "cybercrime": "0",
            "money_laundering": "0",
            "number_of_malicious_contracts_created": "0",
            "gas_abuse": "0",
            "financial_crime": "0",
            "darkweb_transactions": "0",
            "reinit": "0",
            "phishing_activities": "0",
            "fake_kyc": "0",
            "blacklist_doubt": "0",
            "fake_standard_interface": "0",
            "data_source": "",
            "stealing_attack": "0",
            "blackmail_activities": "0",
            "sanctioned": "0",
            "malicious_mining_activities": "0",
            "mixer": "0",
            "fake_token": "0",
            "honeypot_related_address": "0"
        },
        "checked_times": 7,
        "createdAt": "2026-03-19T06:52:28.000Z",
        "updatedAt": "2026-05-18T11:11:19.000Z",
        "sanctionData": [
            {
                "id": 212143,
                "trustscore_id": 18360032,
                "category": null,
                "name": null,
                "description": null,
                "url": null,
                "isSanctioned": false,
                "createdAt": "2026-05-18T11:11:19.000Z",
                "updatedAt": "2026-05-18T11:11:19.000Z"
            }
        ]
    }
}
```

{% endcode %}

## Response Parameters

| **Field Path**                             | **Type**          | **Example**              | **Description**                                                                                                              |
| ------------------------------------------ | ----------------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
| status                                     | string            | `"Not Fraud"`            | ML model verdict. Possible values: `"Not Fraud"`, `"Fraud"`, `"New Address"`.                                                |
| probabilityFraud                           | string            | `"0.0191140026"`         | Fraud probability score ranging from `0.0` to `1.0`.                                                                         |
| walletAddress                              | string            | `"0xa45f..."`            | The audited blockchain wallet address.                                                                                       |
| chain                                      | string            | `"ETH"`                  | The network/blockchain name (e.g., `"ETH"`).                                                                                 |
| lastChecked                                | string (ISO 8601) | `"2026-04-15T12:02:21Z"` | Timestamp of the most recent fraud analysis.                                                                                 |
| checked\_times                             | number            | `169`                    | Total number of times this address has been checked.                                                                         |
| createdAt                                  | string (ISO 8601) | `"2023-07-19T10:15:00Z"` | Record creation timestamp.                                                                                                   |
| updatedAt                                  | string (ISO 8601) | `"2026-05-08T14:30:22Z"` | Last update timestamp.                                                                                                       |
| forensic\_details                          | object            | *See sub-fields below*   | Contains 18 AML flags. Each is `"0"` (clean) or `"1"` (flagged). If any flag is `"1"`, `probabilityFraud` defaults to `1.0`. |
| ↳ `.cybercrime`                            | string            | `"0"`                    | Cybercrime activity flag.                                                                                                    |
| ↳ `.money_laundering`                      | string            | `"0"`                    | Money laundering flag.                                                                                                       |
| ↳ `.number_of_malicious_contracts_created` | string            | `"0"`                    | Creation of malicious smart contracts flag.                                                                                  |
| ↳ `.gas_abuse`                             | string            | `"0"`                    | Gas price manipulation behavior flag.                                                                                        |
| ↳ `.financial_crime`                       | string            | `"0"`                    | General financial crime flag.                                                                                                |
| ↳ `.darkweb_transactions`                  | string            | `"0"`                    | Transactions associated with darkweb marketplaces flag.                                                                      |
| ↳ `.reinit`                                | string            | `"0"`                    | Smart contract reinitialization abuse flag.                                                                                  |
| ↳ `.phishing_activities`                   | string            | `"0"`                    | Phishing vector participation flag.                                                                                          |
| ↳ `.fake_kyc`                              | string            | `"0"`                    | Use or association with fake KYC data flag.                                                                                  |
| ↳ `.blacklist_doubt`                       | string            | `"0"`                    | Association with blacklisted entities flag.                                                                                  |
| ↳ `.fake_standard_interface`               | string            | `"0"`                    | Spoofed/fake token interface usage flag.                                                                                     |
| ↳ `.stealing_attack`                       | string            | `"0"`                    | Active theft or exploit activity flag.                                                                                       |
| ↳ `.blackmail_activities`                  | string            | `"0"`                    | Blackmail or extortion activities flag.                                                                                      |
| ↳ `.sanctioned`                            | string            | `"0"`                    | Presence on known sanctions lists flag.                                                                                      |
| ↳ `.malicious_mining_activities`           | string            | `"0"`                    | Malicious or hijacked mining operations flag.                                                                                |
| ↳ `.mixer`                                 | string            | `"0"`                    | Interaction with crypto mixing services (e.g., Tornado Cash) flag.                                                           |
| ↳ `.fake_token`                            | string            | `"0"`                    | Creation or deployment of fake/honeypot tokens flag.                                                                         |
| ↳ `.honeypot_related_address`              | string            | `"0"`                    | Association with honeypot contract setups flag.                                                                              |
| sanctionData                               | array (object)    | *See sub-fields below*   | Definitive sanction matches associated with this address.                                                                    |
| ↳ `.isSanctioned`                          | boolean           | `false`                  | `true` if sanctioned, `false` if clean.                                                                                      |
| ↳ `.category`                              | string (nullable) | `"Terrorism"`            | Category of sanction if applicable; otherwise `null`.                                                                        |
| ↳ `.name`                                  | string (nullable) | `"Entity Name"`          | Official name of the sanctioned entity/person; otherwise `null`.                                                             |
| ↳ `.description`                           | string (nullable) | `"Details here..."`      | Contextual details regarding the sanction; otherwise `null`.                                                                 |
| ↳ `.url`                                   | string (nullable) | `"https://..."`          | Reference URL providing sanction evidence; otherwise `null`.                                                                 |

## Error Handling

| Status | Description                       |
| ------ | --------------------------------- |
| 400    | Invalid network or missing fields |
| 401    | Missing or invalid auth           |
| 402    | Insufficient balance              |
| 502    | Provider error                    |


# Rug Pull Checker Endpoint

Example code for the /rug-pull/check method. Сomplete guide on how to use /rug-pull/check in GetBlock Address Audit documentation.

This method checks a smart contract for rug pull indicators. Proxied to ChainAware.

## Body Parameters

| Parameter         | Type   | Required | Description                                                   |
| ----------------- | ------ | -------- | ------------------------------------------------------------- |
| network           | string | Yes      | The blockchain network to verify(ETH, BNB,POLY, TRON or BASE) |
| contract\_address | string | Yes      | the contract address                                          |

## Request Example

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl --location --request POST 'https://services.getblock.io/v1/rug-pull/check' \
-- header 'Authorization: Bearer YOUR_API_KEY',
--header 'Content-Type: application/json' \
--data-raw ' {  "network": "ETH", "address": "0xdac17f958d2ee523a2206206994597c13d831ec7"}'
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript (Axios)" %}

```javascript
import axios from "axios";

const data = 
  {  "network": "ETH", "address": "0xdac17f958d2ee523a2206206994597c13d831ec7"};

const config = {
  method: "post",
  url: "https://services.getblock.io/v1/rug-pull/check",
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  data: data,
};

axios(config)
  .then((response) => console.log(JSON.stringify(response.data, null, 2)))
  .catch((error) => console.log(error));

```

{% endtab %}

{% tab title="Python (Requests)" %}
{% code overflow="wrap" %}

```python
import requests
import json

url = "https://services.getblock.io/v1/rug-pull/check"

payload = json.dumps({  "network": "ETH", "address": "0xdac17f958d2ee523a2206206994597c13d831ec7"})

headers = {
      "Authorization": "Bearer YOUR_API_KEY",
  "Content-Type": "application/json",
}

response = requests.post(url, headers=headers, data=payload)
print(response.text)
```

{% endcode %}
{% endtab %}

{% tab title="Rust (Reqwest)" %}
{% code overflow="wrap" %}

```rust
use reqwest::Client;
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new();

    let payload = json!({  "network": "ETH", "address": "0xdac17f958d2ee523a2206206994597c13d831ec7"});

    let response = client
        .post("https://services.getblock.io/v1/rug-pull/check")
        .header("Content-Type", "application/json")
        .header("Authorization: "Bearer YOUR_API_KEY")
        .json(&payload)
        .send()
        .await?;

    let result: serde_json::Value = response.json().await?;
    println!("{:#?}", result);

    Ok(())
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Response Example

{% code overflow="wrap" %}

```json
{
    "data": {
        "message": "Success",
        "contractAddress": "0xdac17f958d2ee523a2206206994597c13d831ec7",
        "pairAddress": null,
        "contractCreatorAddress": "0x36928500bc1dcd7af6a2b4008875cc336b927d57",
        "risk_score": 0,
        "risk_status": null,
        "risk_indicators": {},
        "status": "Not Fraud",
        "probabilityFraud": "0.0028322712",
        "chain": "ETH",
        "lastChecked": "2026-05-14T14:23:18.000Z",
        "contractCreationTime": "2017-11-28T00:41:21.000Z",
        "forensic_details": {
            "owner": {
                "owner_address": "0xc6cde7c39eb2f0f0095f41570af89efc2c1ea828",
                "owner_name": "owner",
                "owner_type": "contract"
            },
            "privilege_withdraw": 0,
            "withdraw_missing": 0,
            "is_open_source": 1,
            "blacklist": 1,
            "contract_name": "TetherToken",
            "selfdestruct": 0,
            "is_proxy": 0,
            "approval_abuse": 0
        },
        "checked_times": 1,
        "createdAt": "2025-09-04T04:55:17.000Z",
        "updatedAt": "2026-05-14T14:23:20.000Z"
    }
}
```

{% endcode %}

## Response Parameters

| **Field Path**          | **Type**          | **Example**                  | **Description**                                                                                                                               |
| ----------------------- | ----------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| status                  | string            | `"Fraud"`                    | Model verdict. Possible values: `"Fraud"`, `"Not Fraud"`, `"Investable"`, `"Not Investable"`, `"Safe"`.                                       |
| probabilityFraud        | number            | `0.5488`                     | Rug pull probability score ranging from `0.0` to `1.0`.                                                                                       |
| contractCreationTime    | string (ISO 8601) | `"2021-11-10T12:00:00.000Z"` | Exact timestamp when the smart contract was deployed.                                                                                         |
| lastChecked             | string (ISO 8601) | `"2026-03-25T18:42:00.000Z"` | Timestamp of the most recent security and fraud analysis.                                                                                     |
| chain                   | string            | `"ETH"`                      | The network/blockchain name (e.g., `"ETH"`).                                                                                                  |
| forensic\_details       | object            | *See sub-fields below*       | Deep analysis of the contract's security properties. Core flags are binary: `0` (clean) or `1` (flagged).                                     |
| ↳ `.contract_name`      | string            | `"PFToken"`                  | The registered name of the smart contract.                                                                                                    |
| ↳ `.is_open_source`     | number (0/1)      | `1`                          | Indicates if the source code is verified on the network explorer.                                                                             |
| ↳ `.is_proxy`           | number (0/1)      | `0`                          | Indicates if the contract uses a proxy pattern (allowing the underlying logic to be replaced).                                                |
| ↳ `.selfdestruct`       | number (0/1)      | `0`                          | Indicates if the contract contains a `selfdestruct` function capability.                                                                      |
| ↳ `.privilege_withdraw` | number (0/1)      | `0`                          | Indicates if the owner has excessive privileges to arbitrarily withdraw user assets.                                                          |
| ↳ `.withdraw_missing`   | number (0/1)      | `0`                          | Indicates if critical withdrawal mechanisms are missing, preventing users from recovering funds.                                              |
| ↳ `.blacklist`          | number (0/1)      | `0`                          | Indicates if the contract owner has the power to blacklist specific wallet addresses.                                                         |
| ↳ `.approval_abuse`     | number (0/1)      | `0`                          | Indicates if the owner can potentially abuse token allowances/approvals given by users.                                                       |
| ↳ \`.owner\*\*          | object            | *See sub-fields below*       | Details regarding the administrative ownership of the smart contract.                                                                         |
| ↳ `.owner_type`         | string            | `"contract"`                 | The type of owner account. Possible values: `"contract"` (Multi-sig/DAO/Other contract) or `"eoa"` (Externally Owned Account/Regular wallet). |
| ↳ `.owner_address`      | string (nullable) | `null`                       | The public address of the owner. Returns `null` if the contract ownership has been renounced.                                                 |

## Error Handling

| Status | Description                       |
| ------ | --------------------------------- |
| 400    | Invalid network or missing fields |
| 401    | Missing or invalid auth           |
| 402    | Insufficient balance              |
| 502    | Provider error                    |


# 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.

## 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.

***

## 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
* **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

***

## Supported Data Streams

Yellowstone gRPC supports streaming the full range of Solana events:

| Stream Type      | Description                                                   |
| ---------------- | ------------------------------------------------------------- |
| **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**        | Slot notifications as they're processed by the leader         |
| **Block Meta**   | Block metadata with transaction counts and execution status   |

***

## 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
* DEX monitors and price feeds
* DeFi strategy engines
* Alerting and notification systems
* NFT marketplace trackers
* Wallet activity monitors

{% hint style="info" %}
**Note**: gRPC is not supported in browsers. Yellowstone is designed for backend services and server-side applications.
{% endhint %}

***

## Getting Started

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:blue;"><strong>Overview</strong></mark></td><td>Learn how Yellowstone gRPC works and why it's essential for real-time Solana applications</td><td><a href="/pages/fzc2q4ipTlaoOG6NspDZ">/pages/fzc2q4ipTlaoOG6NspDZ</a></td></tr><tr><td><mark style="color:blue;"><strong>Quickstart Guide</strong></mark></td><td>Enable the add-on and start streaming data with code examples in TypeScript, Python, Go, and Rust</td><td><a href="/pages/dNGDBl1qjPbE6crdV7nN">/pages/dNGDBl1qjPbE6crdV7nN</a></td></tr></tbody></table>

***

## Prerequisites

To use Yellowstone gRPC on GetBlock:

* A GetBlock account (sign up at [getblock.io](https://getblock.io))
* A [Dedicated Solana Node](https://docs.getblock.io/getting-started/plans-and-limits/choosing-your-plan) subscription
* Yellowstone gRPC add-on enabled (included at no extra cost with Dedicated Nodes)

***

## Quick Example

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

```typescript
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}`);
  }
});
```

***

## Additional Resources

* [Yellowstone gRPC GitHub Repository](https://github.com/rpcpool/yellowstone-grpc)
* [GetBlock Solana Nodes](https://getblock.io/nodes/sol/)
* [GetBlock Support](https://getblock.io/contact/)

***

## Need Help?

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

* Add-on activation and endpoint setup
* Integration guidance and troubleshooting
* Performance optimization
* Custom solutions for enterprise needs

Contact us through the [GetBlock dashboard](https://getblock.io) or visit our [support page](https://getblock.io/contact/).


# 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.

### 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.

By plugging directly into validators, it pushes new **blocks**, **transactions**, and **account** updates to your backend the moment they occur.

### 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.

#### **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`](/api-reference/solana-sol/gettransaction-solana) or [`getProgramAccounts`](/api-reference/solana-sol/getprogramaccounts-solana) 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.

***

### 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.

***

### 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.

{% hint style="info" %}
Note that gRPC is not supported in browsers, so Yellowstone is intended for backend services.
{% endhint %}

***

### 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


# Quickstart guide

Follow these steps to activate the Solana Yellowstone gRPC add-on on GetBlock

GetBlock offers[ SOL nodes](https://getblock.io/nodes/sol/) 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.

### Prerequisites

* A GetBlock account with a Dedicated Solana Node subscription
* Your gRPC endpoint URL with access token (found in GetBlock dashboard)

#### Enabling the Solana gRPC add-on on GetBlock

The Yellowstone gRPC add-on to Solana currently requires a [Dedicated Node](https://docs.getblock.io/getting-started/plans-and-limits/choosing-your-plan) 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**.

<figure><img src="/files/SyavVgTPYr72R5gWYCVj" alt="Deploying a private Solana node with GetBlock RPC provider"><figcaption></figcaption></figure>

3. **Enable the gRPC add-on**: In Step 3 (Select API and Add‑ons) of your node setup, check **Yellowstone gRPC** under Add‑ons.

<figure><img src="/files/nZkHjtJAMtsbbW7gY9cy" alt="Configuring a dedicated SOL node on GetBlock"><figcaption></figcaption></figure>

{% hint style="success" %}
All **Dedicated Node plan subscribers** receive the Yellowstone gRPC API **at no extra cost** together with their Solana node.
{% endhint %}

Once your node is live, you’ll be able to create gRPC endpoints to begin using the add-on.

#### Get your gRPC endpoint

Return to **My endpoints** in your Dedicated node dashboard and generate a gRPC [Access Token](https://docs.getblock.io/getting-started/authentication-with-access-tokens).

<p align="center"><img src="/files/5PLcUrNzdO3xT3TfdotN" alt=""><br></p>

The dashboard will generate your new HTTPS‐style gRPC endpoint URL.

#### 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).

{% hint style="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.
{% endhint %}

Example endpoint URLs:

```http
// 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>/

```

When establishing your gRPC channel, the authentication is handled via an access token:

```typescript
ENDPOINT = 'https://go.getblock.io';
TOKEN = 'YOUR_GETBLOCK_ACCESS_TOKEN';
```

{% hint style="info" %}
GetBlock provides a single TLS endpoint – you don’t need to open or configure a different port for gRPC access.
{% endhint %}

***

### 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 repository](https://github.com/rpcpool/yellowstone-grpc/tree/master), 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)        |
| `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                         |

{% hint style="info" %}
All filters can be combined in the same request.
{% endhint %}

Developers can integrate Yellowstone streams using standard gRPC client libraries. Triton’s Yellowstone repository includes [example clients](https://github.com/rpcpool/yellowstone-grpc/tree/master/examples) 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.

***

#### 1. CLI (using `grpcurl`)

A generic tool like grpcurl is perfect to just poke at the API and explore method calls:

```bash
# 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": []{} } }'

```

***

#### 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**:

```bash
npm install @triton-one/yellowstone-grpc
# or
yarn add @triton-one/yellowstone-grpc
```

**Connect to the gRPC endpoint and subscribe to the stream**:

```typescript
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);

```

***

#### 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.

{% tabs %}
{% tab title="Go" %}
**Setup & run**:

```bash
cd go-client
go mod tidy
go run main.go
```

Make sure the following **dependencies** are installed:

```bash
go get github.com/rpcpool/yellowstone-grpc/examples/golang@latest
go get google.golang.org/grpc@latest
```

**Go Example** (`go-client/main.go`):

```go
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())
   }
}
```

{% endtab %}

{% tab title="Python" %}
Make sure you clone the Yellowstone repo (for the `examples.grpc` module):

```bash
git clone https://github.com/rpcpool/yellowstone-grpc
export PYTHONPATH=$PYTHONPATH:$(pwd)/yellowstone-grpc/examples/python
```

**Python Example** (`python-client/stream.py`):

```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)
```

{% endtab %}

{% tab title="Rust" %}
**Setup**:

```bash
cd rust-client
cargo build
cargo run
```

Ensure your **Cargo.toml** includes:

```toml
[dependencies]
yellowstone-grpc = { git = "https://github.com/rpcpool/yellowstone-grpc", branch = "main" }
tonic = "0.9"
tokio = { version = "1", features = ["full"] }
```

**Rust Example** (`rust-client/src/main.rs`):

```rust
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);
   }
}
```

{% endtab %}
{% endtabs %}

***

### 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.

***

### 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`](/api-reference/solana-sol/sol_getblock), [`sendTransaction`](/api-reference/solana-sol/sol_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.

{% hint style="info" %}

#### 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.*
{% endhint %}

***

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.

### 💬 Need help?

Check out the [Yellowstone gRPC docs](https://github.com/rpcpool/yellowstone-grpc) or reach out via [GetBlock support](https://getblock.io/contact/).


# How to Get an Ethereum RPC Endpoint

Step-by-step guide to getting a fast, reliable Ethereum RPC endpoint. Set up free or production-grade ETH RPC access  with GetBlock in under 2 minutes.

An Ethereum RPC (Remote Procedure Call) endpoint is a URL that your application uses to send requests to an Ethereum node. When your dApp needs to:

* Check a wallet balance (`eth_getBalance`)
* Read a smart contract (`eth_call`)
* Send a transaction (`eth_sendRawTransaction`)
* Get block data (`eth_getBlockByNumber`)
* Fetch transaction receipts (`eth_getTransactionReceipt`)

It sends a JSON-RPC request to an Ethereum node through an RPC endpoint. The node processes the request and returns the data.

**For example:**

{% tabs %}
{% tab title="Request" %}
{% code overflow="wrap" %}

```json
{
    "jsonrpc": "2.0",
    "method": "eth_blockNumber",
    "params": [],
    "id": "getblock.io"
  }
```

{% endcode %}
{% endtab %}

{% tab title="Response" %}
{% code overflow="wrap" %}

```json
{
  "jsonrpc": "2.0",
  "id": "getblock.io",
  "result": "0x134A5B2"
}
// The result field contains the latest block number in hexadecimal.
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Step-by-Step: Get Your Ethereum RPC Endpoint

{% stepper %}
{% step %}

#### Create a GetBlock Account

Go to [GetBlock Dashboard](https://account.getblock.io) and sign up. You can register with email or via Google/GitHub OAuth.&#x20;
{% endstep %}

{% step %}

#### Create an Ethereum Endpoint

Once logged in:

1. Click **"Shared Nodes"** in the left sidebar
2. Click **"Create New Endpoint"** or the **"+"** button

<figure><img src="/files/y9oTEPlbkrRH0ws32yUK" alt=""><figcaption></figcaption></figure>

3. Configure your endpoint:

* **Protocol:** Ethereum (ETH)
* **Network:** Mainnet (or Sepolia/Holesky for testing)
* **API Interface:** JSON-RPC (most common), WebSocket, or Beacon API
* **Region:** Choose the closest — Frankfurt (EU), New York (US), or Singapore (APAC)

<figure><img src="/files/mGLS44eSKSJxfWgpzYDD" alt=""><figcaption></figcaption></figure>

4. Click **"Create":** Your endpoint URL will be generated immediately.
   {% endstep %}

{% step %}

#### Copy Your Endpoint URL

Your endpoint URL looks like this:

```
https://go.getblock.io/a1b2c3d4e5f6789012345678abcdef01/
```

{% hint style="warning" %}
The long string after `go.getblock.io/` is your **access token** — keep it private.
{% endhint %}
{% endstep %}

{% step %}

#### Test the Connection

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://go.getblock.io/<YOUR-ACCESS-TOKEN>/ \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "eth_blockNumber",
    "params": [],
    "id": "getblock.io"
  }'
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "id": "getblock.io",
  "result": "0x134A5B2"
}
// The result field contains the latest block number in hexadecimal.
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

### Using Your Endpoint with Popular Libraries

{% tabs %}
{% tab title="ethers.js (v6)" %}
{% code overflow="wrap" %}

```javascript
import { JsonRpcProvider } from "ethers";

const provider = new JsonRpcProvider(
  "https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"
);

// Get latest block number
const blockNumber = await provider.getBlockNumber();
console.log("Latest block:", blockNumber);

// Get ETH balance
const balance = await provider.getBalance("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045");
console.log("Balance:", balance.toString(), "wei");
```

{% endcode %}
{% endtab %}

{% tab title="Python (web3.py)" %}

```python
from web3 import Web3

w3 = Web3(Web3.HTTPProvider("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"))

# Check connection
print("Connected:", w3.is_connected())

# Get latest block
block_number = w3.eth.block_number
print(f"Latest block: {block_number}")

# Get balance
balance = w3.eth.get_balance("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045")
print(f"Balance: {w3.from_wei(balance, 'ether')} ETH")
```

{% endtab %}

{% tab title="Python (requests — no SDK needed)" %}

```python
import requests

url = "https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"
headers = {"Content-Type": "application/json"}

# Get gas price
payload = {
    "jsonrpc": "2.0",
    "method": "eth_gasPrice",
    "params": [],
    "id": "getblock.io"
}

response = requests.post(url, headers=headers, json=payload)
gas_price = int(response.json()["result"], 16)
print(f"Gas price: {gas_price / 1e9:.2f} Gwei")
```

{% endtab %}
{% endtabs %}

### WebSocket Endpoint for Real-Time Data

For real-time events (new blocks, pending transactions, log subscriptions), use a WebSocket connection:

**WebSocket endpoint format:**

```
wss://go.getblock.io/<YOUR-ACCESS-TOKEN>/
```

#### Subscribe to new blocks

{% tabs %}
{% tab title="ethers.js" %}

```javascript
import { WebSocketProvider } from "ethers";

const provider = new WebSocketProvider(
  "wss://go.getblock.io/<YOUR-ACCESS-TOKEN>/"
);

provider.on("block", (blockNumber) => {
  console.log("New block:", blockNumber);
});
```

{% endtab %}

{% tab title="Python" %}

```python
import asyncio
import websockets
import json

async def listen_blocks():
    uri = "wss://go.getblock.io/<YOUR-ACCESS-TOKEN>/"
    async with websockets.connect(uri) as ws:
        # Subscribe to new block headers
        await ws.send(json.dumps({
            "jsonrpc": "2.0",
            "method": "eth_subscribe",
            "params": ["newHeads"],
            "id": 1
        }))
        
        print("Subscribed to new blocks")
        
        while True:
            response = json.loads(await ws.recv())
            if "params" in response:
                block = response["params"]["result"]
                print(f"Block {int(block['number'], 16)}: {block['hash']}")

asyncio.run(listen_blocks())
```

{% endtab %}
{% endtabs %}

### Ethereum Testnet Endpoints

For development and testing, use testnet endpoints. GetBlock supports:

| Testnet     | Purpose                  | How to Get Tokens                              |
| ----------- | ------------------------ | ---------------------------------------------- |
| **Sepolia** | Primary Ethereum testnet | [Sepolia faucets](https://getblock.io/faucet/) |

### Archive Data Access

Need to query the historical state at any past block? Enable **archive mode** on your endpoint.

Archive data lets you:

* Call `eth_getBalance` at any historical block
* Execute `eth_call` against old contract state
* Run `debug_traceTransaction` for any past transaction
* Use `trace_block` and `trace_call` for deep analysis

Archive mode is available on all paid plans and Dedicated Nodes.

**Example — get balance at a specific historical block:**

```bash
curl -X POST https://go.getblock.io/<YOUR-ACCESS-TOKEN>/ \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "eth_getBalance",
    "params": ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "0xE8D4A5"],
    "id": "getblock.io"
  }'
```

### What's Next?

* [Full Ethereum API Reference](https://docs.getblock.io/api-reference/ethereum-eth)
* [Using Ethers.js with GetBlock](https://docs.getblock.io/guides/using-web3-libraries/ethers.js-integration)

*Need help choosing the right setup for your Ethereum project?* [*Contact our team*](mailto:support@getblock.io)*, and we'll help you find the best configuration.*


# How to Get a Solana RPC Endpoint

Step-by-step guide to getting a fast, reliable Solana RPC endpoint.

Solana is the go-to chain for high-frequency trading, DeFi, and real-time applications — which means your RPC infrastructure needs to keep up.&#x20;

A Solana RPC endpoint is a URL that connects your application to a Solana validator node. Through this endpoint, your app can:

* Query account balances and token holdings (`getBalance`, `getTokenAccountsByOwner`)
* Fetch transaction data (`getTransaction`, `getSignaturesForAddress`)
* Submit transactions (`sendTransaction`)
* Monitor real-time events via WebSocket (`accountSubscribe`, `logsSubscribe`)
* Access slot and block information (`getSlot`, `getBlock`)

Solana's JSON-RPC API follows a different specification than Ethereum — it's not EVM-based, so you'll use Solana-specific libraries like `@solana/web3.js` or `solana-py`.

**Endpoint format:**

```bash
https://go.getblock.io/<YOUR-ACCESS-TOKEN>/
```

### Step-by-Step: Get Your Solana RPC Endpoint

{% stepper %}
{% step %}

#### Create a GetBlock Account

Go to [GetBlock Dashboard](https://account.getblock.io) and sign up. You can register with email or via Google/GitHub OAuth.&#x20;
{% endstep %}

{% step %}

#### Create a Solana Endpoint

Once logged in:

1. Click **"Shared Nodes"** in the left sidebar
2. Click **"Create New Endpoint"** or the **"+"** button

<figure><img src="/files/y9oTEPlbkrRH0ws32yUK" alt=""><figcaption></figcaption></figure>

3. Select:
   * **Protocol:** Solana (SOL)
   * **Network:** Mainnet
   * **API Interface:** JSON-RPC or WebSocket or MEV protected (JSON-RPC)
   * **Region:** Frankfurt (EU), New York (US), or Singapore (APAC)

<figure><img src="/files/NudG5mRvXjgVL5BXPWOQ" alt=""><figcaption></figcaption></figure>

4. Click **"Create":** Your endpoint URL will be generated immediately.
   {% endstep %}

{% step %}

#### Copy Your Endpoint URL

Your endpoint URL looks like this:

```
https://go.getblock.io/a1b2c3d4e5f6789012345678abcdef01/
```

{% hint style="warning" %}
The long string after `go.getblock.io/` is your **access token** — keep it private.
{% endhint %}
{% endstep %}

{% step %}

#### Test the Connection

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://go.getblock.io/<YOUR-ACCESS-TOKEN>/ \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getSlot",
    "params": []
  }'
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 298765432,
  "id": 1
}
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

### Code Examples

{% tabs %}
{% tab title="JavaScript (@solana/web3.js)" %}

```javascript
import { Connection, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js";

const connection = new Connection(
  "https://go.getblock.io/<YOUR-ACCESS-TOKEN>/",
  "confirmed"
);

// Get current slot
const slot = await connection.getSlot();
console.log("Current slot:", slot);

// Get SOL balance
const pubkey = new PublicKey("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU");
const balance = await connection.getBalance(pubkey);
console.log(`Balance: ${balance / LAMPORTS_PER_SOL} SOL`);

// Get recent blockhash (needed for transactions)
const { blockhash } = await connection.getLatestBlockhash();
console.log("Blockhash:", blockhash);
```

{% endtab %}

{% tab title="Python (solana-py)" %}

```python
from solana.rpc.api import Client
from solders.pubkey import Pubkey

client = Client("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/")

# Get current slot
slot = client.get_slot()
print(f"Current slot: {slot.value}")

# Get SOL balance
pubkey = Pubkey.from_string("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU")
balance = client.get_balance(pubkey)
print(f"Balance: {balance.value / 1e9} SOL")

# Get recent transactions for an address
sigs = client.get_signatures_for_address(pubkey, limit=5)
for sig in sigs.value:
    print(f"  TX: {sig.signature}")
```

{% endtab %}

{% tab title="Python (requests — no SDK)" %}

```python
import requests

url = "https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"
headers = {"Content-Type": "application/json"}

# Get token accounts for a wallet
payload = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getTokenAccountsByOwner",
    "params": [
        "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
        {"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"},
        {"encoding": "jsonParsed"}
    ]
}

response = requests.post(url, headers=headers, json=payload)
accounts = response.json()["result"]["value"]
for acc in accounts:
    info = acc["account"]["data"]["parsed"]["info"]
    print(f"Token: {info['mint']}, Amount: {info['tokenAmount']['uiAmountString']}")
```

{% endtab %}

{% tab title="Rust (solana-client)" %}

```rust
use solana_client::rpc_client::RpcClient;
use solana_sdk::pubkey::Pubkey;
use std::str::FromStr;

fn main() {
    let client = RpcClient::new("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/");
    
    // Get current slot
    let slot = client.get_slot().unwrap();
    println!("Current slot: {}", slot);
    
    // Get balance
    let pubkey = Pubkey::from_str("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU").unwrap();
    let balance = client.get_balance(&pubkey).unwrap();
    println!("Balance: {} SOL", balance as f64 / 1e9);
}
```

{% endtab %}
{% endtabs %}

### WebSocket for Real-Time Solana Data

Solana's WebSocket API is essential for real-time monitoring:

{% tabs %}
{% tab title="Base URL" %}

```bash
wss://go.getblock.io/<YOUR-ACCESS-TOKEN>/
```

{% endtab %}

{% tab title="Subscribe to account changes" %}

```javascript
import WebSocket from "ws";

const ws = new WebSocket("wss://go.getblock.io/<YOUR-ACCESS-TOKEN>/");

ws.on("open", () => {
  // Subscribe to SOL balance changes for an address
  ws.send(JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "accountSubscribe",
    params: [
      "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
      { encoding: "jsonParsed", commitment: "confirmed" }
    ]
  }));
});

ws.on("message", (data) => {
  const msg = JSON.parse(data);
  if (msg.method === "accountNotification") {
    console.log("Account updated:", msg.params.result.value);
  }
});
```

{% endtab %}

{% tab title="SubscSubcribe to program logs (e.g., monitor DEX trades)" %}

```javascript
// Monitor Raydium AMM trades
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 2,
  method: "logsSubscribe",
  params: [
    { mentions: ["675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"] },  // Raydium v4
    { commitment: "confirmed" }
  ]
}));
```

{% endtab %}
{% endtabs %}

### Why You Need a Dedicated RPC Provider for Solana

Solana is especially demanding on RPC infrastructure:

| Challenge                       | Public RPC              | GetBlock               |
| ------------------------------- | ----------------------- | ---------------------- |
| Rate limits                     | Aggressive (2-5 RPS)    | Up to 500 RPS          |
| `getSignaturesForAddress` depth | Often limited to recent | Full history available |
| WebSocket stability             | Frequent disconnects    | Persistent connections |
| `getProgramAccounts` support    | Usually blocked         | Available              |
| MEV protection                  | None                    | Available (Dedicated)  |
| gRPC streaming (Yellowstone)    | Not available           | Available as add-on    |
| Archive/historical data         | Limited                 | Full history           |
| Transaction landing rate        | Low priority            | High via LandFirst     |

### Advanced Solana Infrastructure on GetBlock

#### 1. Yellowstone gRPC (Geyser Plugin)

For applications that need the fastest possible data e.g., trading bots, MEV searchers, indexers. GetBlock offers managed Yellowstone gRPC endpoints as an add-on to Dedicated Solana Nodes.

**Why Yellowstone gRPC over standard RPC:**

* **Near-zero latency:** streams data directly from validators
* **Millions of events per minute:** handles Solana's full throughput
* **Rich filtering:** subscribe only to accounts/programs you care about
* **Protobuf encoding:** parsed, typed data instead of base64

[*Learn more about Yellowstone gRPC*](https://docs.getblock.io/add-ons/yellowstone-grpc-api)

#### 2. StreamFirst: Ultra-Low Latency Data

GetBlock's proprietary StreamFirst infrastructure delivers on-chain data faster than standard Yellowstone by combining:

* **Accelerated Yellowstone gRPC** with optimized serialization
* **Shred-stream delivery:** receives block fragments directly via UDP before blocks are fully confirmed

The Frankfurt data center provides 6ms latency within Europe and is positioned near the highest density of Solana validators.

[*Learn more about StreamFirst*](https://docs.getblock.io/solana-advanced-data-tools/streamfirst)

#### 3. LandFirst: Smart Transaction Routing

For sending transactions with high landing probability:

* **SWQoS connections** to high-stakes validators
* **Jito Block Engine integration** for bundle support
* **Intelligent routing** based on leader schedule and network conditions

[*Learn more about LandFirst*](https://docs.getblock.io/solana-advanced-data-tools/landfirst)

#### 4. TradeFirst — Complete HFT Infrastructure

Combines StreamFirst (data) + LandFirst (execution) + Jito integration for high-frequency trading:

* See opportunities \~17ms faster than standard RPC
* Execute trades via optimal routing paths
* Bundle support for atomic multi-transaction operations

[*Learn more about TradeFirst*](https://docs.getblock.io/solana-advanced-data-tools/tradefirst)

### What's Next?

* [Full Solana API Reference ](https://docs.getblock.io/api-reference/solana-sol)
* [Yellowstone gRPC Quickstart ](https://docs.getblock.io/add-ons/yellowstone-grpc-api/quickstart-guide)
* [How to Track Pump.fun Token Mints](https://docs.getblock.io/guides/how-to-track-pump.fun-token-mints-with-getblocks-yellowstone-grpc)
* [Sniping New Solana Tokens (Python Tutorial)](https://docs.getblock.io/guides/blockchain-api-guides/solana-guides/sniping-new-solana-tokens-python-bot-tutorial)
* [Solana Indexed Archive](https://docs.getblock.io/solana-advanced-data-tools/solana-indexed-archive)
* [Configure a Dedicated Solana Node](https://getblock.io/dedicated-nodes/)

*Building something ambitious on Solana?* [*Talk to our team*](mailto:support@getblock.io) *about custom infrastructure — we specialize in high-performance Solana deployments.*


# How to Get a Base RPC Endpoint

Step-by-step guide to getting a fast, reliable Base RPC endpoint

Base has become one of the most active Ethereum Layer 2 networks for DeFi, social apps, and onchain consumer products.&#x20;

If you're building on Base for the first time or scaling a production application, this guide gets you set up with a reliable RPC endpoint in minutes.

### Step-by-Step: Get Your Base RPC Endpoint

{% stepper %}
{% step %}

#### Create a GetBlock Account

Go to [GetBlock Dashboard](https://account.getblock.io) and sign up. You can register with email or via Google/GitHub OAuth.&#x20;
{% endstep %}

{% step %}

#### Create an Avalanche Endpoint

Once logged in:

1. Click **"Shared Nodes"** in the left sidebar
2. Click **"Create New Endpoint"** or the **"+"** button

<figure><img src="/files/y9oTEPlbkrRH0ws32yUK" alt=""><figcaption></figcaption></figure>

3. Select:

   * **Protocol:** Base
   * **Network:** Mainnet or Sepolia
   * **API Interface:** JSON-RPC or Websocket or MEV-Protected(JSON-RPC) or MEV-protected(Websocket)
   * **Region:** Frankfurt (EU) or Singapore or New York

   <figure><img src="/files/WXLNOP4yIRoQmTJmtYuQ" alt=""><figcaption></figcaption></figure>
4. Click **"Create":** Your endpoint URL will be generated immediately.
   {% endstep %}

{% step %}

#### Copy Your Endpoint URL

Your endpoint URL looks like this:

{% code overflow="wrap" %}

```bash
https://go.getblock.io/a1b2c3d4e5f6789012345678abcdef01/
```

{% endcode %}

{% hint style="warning" %}
The long string after `go.getblock.io/` is your **access token,** keep it private.
{% endhint %}
{% endstep %}

{% step %}

#### Test the Connection

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl -X POST https://go.getblock.io/<YOUR-ACCESS-TOKEN>/ \
  -H "Content-Type: application/json" \
  -d '{
  "jsonrpc":"2.0",
  "method":"eth_chainId",
  "params":[],
  "id":1
  }'
```

{% endcode %}
{% endtab %}

{% tab title="Response" %}
{% code overflow="wrap" %}

```bash
{
  "result": "0x2105"
}
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

### Code Examples

{% tabs %}
{% tab title="Ethers.js" %}
{% code overflow="wrap" %}

```javascript
import { JsonRpcProvider, formatEther } from "ethers";

const provider = new JsonRpcProvider(
  "https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"
);

const blockNumber = await provider.getBlockNumber();
console.log("Latest Base block:", blockNumber);

const balance = await provider.getBalance("0xYOUR_ADDRESS");
console.log(`Balance: ${formatEther(balance)} ETH`);
```

{% endcode %}
{% endtab %}

{% tab title="Python(Web3.py)" %}
{% code overflow="wrap" %}

```python
from web3 import Web3

w3 = Web3(Web3.HTTPProvider("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"))

print("Chain ID:", w3.eth.chain_id)  # 8453
print("Latest block:", w3.eth.block_number)
```

{% endcode %}
{% endtab %}

{% tab title="Viem(Typescript)" %}
{% code overflow="wrap" %}

```typescript
import { createPublicClient, http } from "viem";
import { base } from "viem/chains";

const client = createPublicClient({
  chain: base,
  transport: http("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"),
});

const blockNumber = await client.getBlockNumber();
console.log("Block:", blockNumber);

const balance = await client.getBalance({
  address: "0xYOUR_ADDRESS",
});
console.log("Balance:", balance);
```

{% endcode %}
{% endtab %}
{% endtabs %}

### How to Connect MetaMask to Base via GetBlock

1. MetaMask → **Add Network** → **Add manually**
2. Enter:
   * **Network Name:** Base Mainnet (GetBlock)
   * **RPC URL:** `https://go.getblock.io/<YOUR-ACCESS-TOKEN>/`
   * **Chain ID:** `8453`
   * **Symbol:** `ETH`
   * **Explorer:** `https://basescan.org`
3. Save

**Base Sepolia Testnet:**

* Chain ID: `84532`
* Explorer: `https://sepolia.basescan.org`

### Why a Dedicated RPC Provider For Base?

Base inherits Ethereum's security while offering:

* **Low gas fees** (\~$0.01 per transaction)
* **EVM compatibility** — deploy existing Solidity contracts without changes
* **Coinbase ecosystem** — seamless fiat on-ramp integration
* **Growing DeFi ecosystem** — Aerodrome, Uniswap, Aave, and more

But Base's popularity means public RPC endpoints are frequently congested. A dedicated provider like GetBlock gives you consistent performance with up to 500 RPS and 99.9%+ uptime.

### Base Flashblocks Support

Base introduced **Flashblocks** — a mechanism for pre-confirmation of transactions at sub-second speeds. GetBlock supports Flashblocks, enabling your application to react to transactions inclusions faster than waiting for full block confirmation.

[How to Build a Base Flashblocks Listener →](https://docs.getblock.io/guides/how-to-build-a-base-flashblocks-listener)

### Choosing Your Plan

| Use Case                 | Plan                           | Why                                 |
| ------------------------ | ------------------------------ | ----------------------------------- |
| Building on Base         | **Free** ($0)                  | 50K CU/day, perfect for development |
| Production dApp          | **Starter** ($49/mo)           | 50M CU/month, 100 RPS               |
| High-traffic DeFi app    | **Advanced** ($199/mo)         | 220M CU/month, 300 RPS              |
| Onchain consumer product | **Pro** ($499/mo)              | 600M CU/month, 24/7 support         |
| Infrastructure provider  | **Dedicated** (from $1,000/mo) | Unlimited, custom SLA               |

### What's Next?

* [Full Base API Reference →](https://docs.getblock.io/api-reference/base)
* [How to Build a Base Flashblocks Listener →](https://docs.getblock.io/guides/how-to-build-a-base-flashblocks-listener)
* [Using Ethers.js with GetBlock →](https://docs.getblock.io/guides/using-web3-libraries/ethers.js-integration)
* [Configure a Dedicated Base Node →](https://getblock.io/dedicated-nodes/)
* Get testnet ETH from [Base Sepolia faucets](https://getblock.io/faucet/).

*Scaling on Base?* [*Contact us*](https://getblock.io/contact/) *for dedicated infrastructure with custom performance tuning.*


# How to Get a Polygon RPC Endpoint

Step-by-step guide to getting a fast, reliable Polygon RPC endpoint.

Polygon PoS is one of the most widely used Ethereum scaling solutions, powering DeFi protocols, NFT marketplaces, gaming applications, and enterprise solutions.&#x20;

### Available Service on GetBlock

* **Archive data:** query historical state at any block (all plans)
* **Trace & Debug:** `debug_traceTransaction`, `trace_block` (Starter+)
* **WebSocket: r**eal-time subscriptions via `wss://go.getblock.io/<TOKEN>/`
* **Multi-region:** Frankfurt, New York, Singapore
* **Dedicated Nodes:** unlimited RPS, from $1,000/mo

This guide shows you how to get a reliable Polygon RPC endpoint — from free development access to production-grade infrastructure.

### Step-by-Step: Get Your Polygon RPC Endpoint

{% stepper %}
{% step %}

#### Create a GetBlock Account

Go to [GetBlock Dashboard](https://account.getblock.io) and sign up. You can register with email or via Google/GitHub OAuth.&#x20;
{% endstep %}

{% step %}

#### Create a Polygon Endpoint

Once logged in:

1. Click **"Shared Nodes"** in the left sidebar
2. Click **"Create New Endpoint"** or the **"+"** button

<figure><img src="/files/y9oTEPlbkrRH0ws32yUK" alt=""><figcaption></figcaption></figure>

3. Select:

   * **Protocol:** Polygon
   * **Network:** Mainnet or Amoy(test network)
   * **API Interface:** JSON-RPC or WebSocket
   * **Region:** Frankfurt (EU), New York (US), or Singapore (APAC)

   <figure><img src="/files/EiFrT6N4aUOl7iPxgonx" alt=""><figcaption></figcaption></figure>
4. Click **"Create":** Your endpoint URL will be generated immediately.
   {% endstep %}

{% step %}

#### Copy Your Endpoint URL

Your endpoint URL looks like this:

```
https://go.getblock.io/a1b2c3d4e5f6789012345678abcdef01/
```

{% hint style="warning" %}
The long string after `go.getblock.io/` is your **access token** — keep it private.
{% endhint %}
{% endstep %}

{% step %}

#### Test the Connection

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://go.getblock.io/<YOUR-ACCESS-TOKEN>/ \
  -H "Content-Type: application/json" \
  -d '{
 "jsonrpc":"2.0",
 "method":"eth_chainId",
 "params":[],
 "id":1
}'
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "jsonrpc": "2.0",
  "result": 0x89,
  "id": 1
}
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

### Code Example

{% tabs %}
{% tab title="Ethers.js" %}

```javascript
import { JsonRpcProvider } from "ethers";

const provider = new JsonRpcProvider("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/");
const block = await provider.getBlockNumber();
console.log("Latest Polygon block:", block);
```

{% endtab %}

{% tab title="Python" %}

```python
from web3 import Web3

w3 = Web3(Web3.HTTPProvider("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"))
print("Chain ID:", w3.eth.chain_id)  # 137
print("Block:", w3.eth.block_number)
```

{% endtab %}
{% endtabs %}

### Plans

| Use Case     | Plan                    | CU        | RPS       |
| ------------ | ----------------------- | --------- | --------- |
| Learning     | **Free**                | 50K/day   | 20        |
| Side project | **Starter** ($49/mo)    | 50M/mo    | 100       |
| Production   | **Advanced** ($199/mo)  | 220M/mo   | 300       |
| High-traffic | **Pro** ($499/mo)       | 600M/mo   | 500       |
| Enterprise   | **Dedicated** ($1K+/mo) | Unlimited | Unlimited |

[You can learn more about our pricing here](https://getblock.io/pricing/)

### What's Next?

* [Full Polygon API Reference](https://docs.getblock.io/api-reference/polygon-matic)
* [Using Web3.js with GetBlock ](https://docs.getblock.io/guides/using-web3-libraries/web3.js-integration)
* [Configure a Dedicated Polygon Node ](https://getblock.io/dedicated-nodes/)

*Need enterprise Polygon infrastructure?* [*Contact us*](https://getblock.io/contact/)*.*


# How to Get a TON RPC Endpoint

Step-by-step guide to getting a fast, reliable TON RPC endpoint

The Open Network (TON) has become the leading blockchain for Telegram-integrated applications, mini-apps, and payments. With TON's unique architecture (TVM, not EVM) and the massive Telegram user base, demand for reliable TON RPC access is growing fast. Here's how to set up a TON endpoint with GetBlock.

### TON's API is Different from EVM Chains

TON uses its own HTTP API — not the JSON-RPC standard used by Ethereum and EVM chains. TON API methods include:

* `getAddressInformation` — get account balance and state
* `getTransactions` — fetch transaction history
* `detectAddress` — normalize address formats
* `estimateFee` — estimate transaction cost
* `sendBoc` — submit transactions

{% hint style="info" %}
GetBlock supports the full TON HTTP API specification.
{% endhint %}

### Step-by-Step: Get Your TON RPC Endpoint

{% stepper %}
{% step %}

#### Create a GetBlock Account

Go to [GetBlock Dashboard](https://account.getblock.io) and sign up. You can register with email or via Google/GitHub OAuth.&#x20;
{% endstep %}

{% step %}

#### Create a TON Endpoint

Once logged in:

1. Click **"Shared Nodes"** in the left sidebar
2. Click **"Create New Endpoint"** or the **"+"** button

<figure><img src="/files/y9oTEPlbkrRH0ws32yUK" alt=""><figcaption></figcaption></figure>

3. Select:

   * **Protocol:** TON
   * **Network:** Mainnet
   * **API Interface:** JSON-RPC or JSON-RPC(v3) or HTTP API(v4)
   * **Region:** Frankfurt (EU)

     <figure><img src="/files/9yrAPjmzKGl3hl3Z07r9" alt=""><figcaption></figcaption></figure>

4. Click **"Create":** Your endpoint URL will be generated immediately.
   {% endstep %}

{% step %}

#### Copy Your Endpoint URL

Your endpoint URL looks like this:

```
https://go.getblock.io/a1b2c3d4e5f6789012345678abcdef01/
```

{% hint style="warning" %}
The long string after `go.getblock.io/` is your **access token** — keep it private.
{% endhint %}
{% endstep %}

{% step %}

#### Test the Connection

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl "https://go.getblock.io/853387a2f5fb45938bc031b8dca61109/getTransactions?address=EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2&limit=10"
```

{% endcode %}
{% endtab %}

{% tab title="Response" %}
{% code overflow="wrap" %}

```json
{
    "ok": true,
    "result": [
        {
            "@type": "raw.transaction",
            "address": {
                "@type": "accountAddress",
                "account_address": "EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2"
            },
            "utime": 1776290803,
            "data": "te6cckECBgEAAWoAA7V+0WkTBwUARxF7mYtWHY3oLTH7+EkQztbrX8kudIXvinAABAWCj9eUOD7/OUrBX59ddg7e3dzvZoID+aKx+fen8wasJez5upJwAAQFZjZhbDaeAL8wABRhp1GIAQIDAQGgBACCch7Abw4H6w6slWcoil9zY7JBOborq1xVIKW99Tsth1ejdzUxO3jSz9uuy9Y1yGPJMw/Wr1dV7299L8x9tJpO574BIQSA7wjD0JAQYabaDQDBhqAQBQC5aAAkFnkPv5yCP72kT5+cJ0xbYR+O+oNCl+CYiPHg8WnI4QA7RaRMHBQBHEXuZi1YdjegtMfv4SRDO1utfyS50he+Kcw9CQAGCCNaAACAsFH68oTTwBfmAAAAAAVAAJxBDqgnEAAAAAB8AAAARgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASDQZX",
            "transaction_id": {
                "@type": "internal.transactionId",
                "lt": "70747389000003",
                "hash": "02cNpr7ukamUPb7hxvpcD2X9o4wzFR/ur0m5tfh6bXM="
            },
            "fee": "866956",
            "storage_fee": "956",
            "other_fee": "866000",
            "in_msg": {
                "@type": "raw.message",
                "hash": "q36VnTxNsF94CFWxG9ACJ7WY/6hNABx9i2YSMW4in5I=",
                "source": "EQASCzyH385BH97SJ8_OE6YtsI_HfUGhS_BMRHjweLTkcOnQ",
                "destination": "EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2",
                "value": "1000000",
                "extra_currencies": [],
                "fwd_fee": "266669",
                "ihr_fee": "0",
                "created_lt": "70747389000002",
                "body_hash": "F99CaqBqWUd2tl2GzHTvFJZ3LcXszDAxo+ZkWq9ydzo=",
                "msg_data": {
                    "@type": "msg.dataText",
                    "text": "Cg=="
                },
                "message": "\n"
            },
            "out_msgs": []
        },
]
}
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

### Code Example

{% tabs %}
{% tab title="JavaScript (tonweb)" %}
{% code overflow="wrap" %}

```javascript
import TonWeb from "tonweb";

const tonweb = new TonWeb(
  new TonWeb.HttpProvider("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/")
);

// Get balance
const balance = await tonweb.getBalance("EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2");
console.log(`Balance: ${TonWeb.utils.fromNano(balance)} TON`);
```

{% endcode %}
{% endtab %}

{% tab title="Python" %}

```python
import requests

base_url = "https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"

# Get address info
response = requests.get(
    f"{base_url}getAddressInformation",
    params={"address": "EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2"}
)
data = response.json()
balance = int(data["result"]["balance"]) / 1e9
print(f"Balance: {balance} TON")
```

{% endtab %}
{% endtabs %}

### Why GetBlock for TON?

* **Reliable infrastructure** — 99.9%+ uptime vs unreliable public endpoints
* **No rate limiting drama** — up to 500 RPS vs public endpoint throttling
* **Global reach** — Frankfurt, New York, Singapore
* **Telegram Mini App scaling** — handle sudden user surges from Telegram viral growth

### Plans

| Use Case               | Plan                   | CU        | RPS       |
| ---------------------- | ---------------------- | --------- | --------- |
| Mini App prototype     | **Free**               | 50K/day   | 20        |
| Production Mini App    | **Starter** ($49/mo)   | 50M/mo    | 100       |
| Growing Telegram app   | **Advanced** ($199/mo) | 220M/mo   | 300       |
| Viral Telegram app     | **Pro** ($499/mo)      | 600M/mo   | 500       |
| Payment infrastructure | **Dedicated** (custom) | Unlimited | Unlimited |

### What's Next?

* [Full TON API Reference →](https://docs.getblock.io/api-reference/the-open-network-ton)
* [TON Documentation →](https://docs.ton.org)
* [Configure a Dedicated TON Node →](https://getblock.io/dedicated-nodes/)
* [Learn more about our pricing](https://getblock.io/pricing/)

*Building a Telegram Mini App at scale?* [*Contact us*](https://getblock.io/contact/) *for custom TON infrastructure.*


# How to Get an Arbitrum RPC Endpoint

Step-by-step guide to getting a fast, reliable Arbitrum RPC endpoint

Arbitrum One is the leading Ethereum L2 by TVL, hosting major DeFi protocols like GMX, Aave, Uniswap, and Camelot. If you're building on Arbitrum, you need a reliable RPC endpoint that can handle the network's high throughput without rate-limiting your application.

### Features

* **EVM-compatible** — use the same tools as Ethereum (ethers.js, web3.js, Hardhat, Foundry)
* **Archive data** — full historical state queries
* **Trace & Debug** — `debug_traceTransaction` and related methods (Starter+)
* **WebSocket** — `wss://go.getblock.io/<TOKEN>/` for real-time subscriptions
* **Multi-region** — Frankfurt, New York, Singapore

{% hint style="info" %}
Arbitrum mainnet Dedicated Nodes may have custom pricing due to higher infrastructure requirements. [Contact sales](https://getblock.io/contact/) for details.
{% endhint %}

### Step-by-Step: Get Your Arbitrum RPC Endpoint

{% stepper %}
{% step %}

#### Create a GetBlock Account

Go to [GetBlock Dashboard](https://account.getblock.io) and sign up. You can register with email or via Google/GitHub OAuth.&#x20;
{% endstep %}

{% step %}

#### Create a Arbitrum Endpoint

Once logged in:

1. Click **"Shared Nodes"** in the left sidebar
2. Click **"Create New Endpoint"** or the **"+"** button

<figure><img src="/files/y9oTEPlbkrRH0ws32yUK" alt=""><figcaption></figcaption></figure>

3. Select:

   * **Protocol:** Arbitrum
   * **Network:** Mainnet or Sepolia
   * **API Interface:** JSON-RPC or Websocket
   * **Region:** Frankfurt (EU) or New York, USA

   <figure><img src="/files/U5r5bSk34ByqWvvwGCSf" alt=""><figcaption></figcaption></figure>
4. Click **"Create":** Your endpoint URL will be generated immediately.
   {% endstep %}

{% step %}

#### Copy Your Endpoint URL

Your endpoint URL looks like this:

```
https://go.getblock.io/a1b2c3d4e5f6789012345678abcdef01/
```

{% hint style="warning" %}
The long string after `go.getblock.io/` is your **access token** — keep it private.
{% endhint %}
{% endstep %}

{% step %}

#### Test the Connection

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl -X POST https://go.getblock.io/<YOUR-ACCESS-TOKEN>/ \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'
```

{% endcode %}
{% endtab %}

{% tab title="Response" %}
{% code overflow="wrap" %}

```json
"result": "0xa4b1" 
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

#### Code Sample

{% tabs %}
{% tab title="Ethers.js" %}

```javascript
import { JsonRpcProvider } from "ethers";

const provider = new JsonRpcProvider("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/");
const block = await provider.getBlockNumber();
console.log("Latest Arbitrum block:", block);
```

{% endtab %}

{% tab title="Python" %}

```python
from web3 import Web3

w3 = Web3(Web3.HTTPProvider("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"))
print("Chain ID:", w3.eth.chain_id)  # 42161
```

{% endtab %}

{% tab title="Viem" %}

```typescript
import { createPublicClient, http } from "viem";
import { arbitrum } from "viem/chains";

const client = createPublicClient({
  chain: arbitrum,
  transport: http("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"),
});
```

{% endtab %}
{% endtabs %}

### Arbitrum Testnets

| Network          | Chain ID | Purpose               |
| ---------------- | -------- | --------------------- |
| Arbitrum Sepolia | 421614   | Development & testing |

> Get testnet ETH from [Arbitrum faucets](https://getblock.io/faucet/).

### Plans

| Use Case        | Plan                   | CU        | RPS       |
| --------------- | ---------------------- | --------- | --------- |
| Development     | **Free**               | 50K/day   | 20        |
| Production dApp | **Starter** ($49/mo)   | 50M/mo    | 100       |
| DeFi / DEX      | **Advanced** ($199/mo) | 220M/mo   | 300       |
| High-traffic    | **Pro** ($499/mo)      | 600M/mo   | 500       |
| Institutional   | **Dedicated** (custom) | Unlimited | Unlimited |

### What's Next?

* [Full Arbitrum API Reference →](https://docs.getblock.io/api-reference/arbitrum-arb)
* [How to Build a Hyperliquid Whale Tracker Bot →](https://docs.getblock.io/guides/how-to-build-a-hyperliquid-whale-tracker-bot-with-getblock)
* [Configure a Dedicated Arbitrum Node →](https://getblock.io/dedicated-nodes/)
* [Learn more about our pricing](https://getblock.io/pricing/)

*Building DeFi on Arbitrum?* [*Talk to us*](https://getblock.io/contact/) *about enterprise-grade infrastructure.*


# How to Get an Avalanche RPC Endpoint

Step-by-step guide to getting a fast, reliable Avalanche RPC endpoint

Avalanche's C-Chain provides EVM-compatible smart contract execution with sub-second finality. Whether you're building DeFi protocols, NFT platforms, or gaming applications on Avalanche, this guide gets you connected in minutes.

### Features

* **C-Chain** — full EVM compatibility
* Archive data access (all plans)
* Trace & Debug methods (Starter+)
* WebSocket support
* Multi-region (Frankfurt, New York, Singapore)
* Dedicated Nodes available

### Step-by-Step: Get Your Avalanche RPC Endpoint

{% stepper %}
{% step %}

#### Create a GetBlock Account

Go to [GetBlock Dashboard](https://account.getblock.io) and sign up. You can register with email or via Google/GitHub OAuth.&#x20;
{% endstep %}

{% step %}

#### Create an Avalanche Endpoint

Once logged in:

1. Click **"Shared Nodes"** in the left sidebar
2. Click **"Create New Endpoint"** or the **"+"** button

<figure><img src="/files/y9oTEPlbkrRH0ws32yUK" alt=""><figcaption></figcaption></figure>

3. Select:

   * **Protocol:** Avalanche
   * **Network:** Mainnet or Testnet
   * **API Interface:** JSON-RPC or Websocket
   * **Region:** Frankfurt (EU)

   <figure><img src="/files/ILORNy56l3HvSTrviLuG" alt=""><figcaption></figcaption></figure>
4. Click **"Create":** Your endpoint URL will be generated immediately.
   {% endstep %}

{% step %}

#### Copy Your Endpoint URL

Your endpoint URL looks like this:

{% code overflow="wrap" %}

```bash
https://go.getblock.io/a1b2c3d4e5f6789012345678abcdef01/
```

{% endcode %}

{% hint style="warning" %}
The long string after `go.getblock.io/` is your **access token** — keep it private.
{% endhint %}
{% endstep %}

{% step %}

#### Test the Connection

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl -X POST https://go.getblock.io/<YOUR-ACCESS-TOKEN>/ \
  -H "Content-Type: application/json" \
  -d '{
  "jsonrpc":"2.0",
  "method":"eth_chainId",
  "params":[],
  "id":1
  }'
```

{% endcode %}
{% endtab %}

{% tab title="Response" %}
{% code overflow="wrap" %}

```bash
{ 
   "result": "0xa86a" (Chain ID 43114)
}
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

#### Code Sample

{% tabs %}
{% tab title="Ethers.js" %}
{% code overflow="wrap" %}

```javascript
import { JsonRpcProvider } from "ethers";
const provider = new JsonRpcProvider("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/");
console.log("Block:", await provider.getBlockNumber());
```

{% endcode %}
{% endtab %}

{% tab title="Python" %}

```python
from web3 import Web3
w3 = Web3(Web3.HTTPProvider("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"))
print("Chain ID:", w3.eth.chain_id)  # 43114
```

{% endtab %}

{% tab title="Viem" %}

```typescript
import { createPublicClient, http } from "viem";
import { arbitrum } from "viem/chains";

const client = createPublicClient({
  chain: avalanche,
  transport: http("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"),
});
```

{% endtab %}
{% endtabs %}

### What's Next?

* [Full Avalanche API Reference](https://docs.getblock.io/api-reference/avalanche-avax)
* [Dedicated Nodes](https://getblock.io/dedicated-nodes/)
* [Learn about our pricing](https://getblock.io/pricing/)

*Building on Avalanche?* [*Contact us*](https://getblock.io/contact/) *for custom infrastructure.*


# How to Get a BNB Smart Chain (BSC) RPC Endpoint

Step-by-step guide to getting a fast, reliableBSC RPC endpoint

BNB Smart Chain remains one of the most active blockchains for DeFi, trading bots, and dApp development. With block times under 3 seconds and significantly lower gas fees than Ethereum, BSC handles massive transaction volumes, and your RPC infrastructure needs to keep pace.&#x20;

This guide walks you through setting up BSC RPC access with GetBlock, from free development endpoints to Accelerated Dedicated Nodes with private mempool support.

### Step-by-Step: Get Your BSC RPC Endpoint

{% stepper %}
{% step %}

#### Create a GetBlock Account

Go to [GetBlock Dashboard](https://account.getblock.io) and sign up. You can register with email or via Google/GitHub OAuth.&#x20;
{% endstep %}

{% step %}

#### Create a BSC Endpoint

Once logged in:

1. Click **"Shared Nodes"** in the left sidebar
2. Click **"Create New Endpoint"** or the **"+"** button

<figure><img src="/files/y9oTEPlbkrRH0ws32yUK" alt=""><figcaption></figcaption></figure>

3. Select:

   * **Protocol:** BSC
   * **Network:** Mainnet or Testnet
   * **API Interface:** JSON-RPC or Websocket or GraphQL or MEV-Protected(JSON-RPC) or MEV-Protected(Websocket)
   * **Region:** Frankfurt (EU) or Singapore or New York

   <figure><img src="/files/WdwgqgFdl3tN4oWV6L64" alt=""><figcaption></figcaption></figure>
4. Click **"Create":** Your endpoint URL will be generated immediately.
   {% endstep %}

{% step %}

#### Copy Your Endpoint URL

Your endpoint URL looks like this:

{% code overflow="wrap" %}

```bash
https://go.getblock.io/a1b2c3d4e5f6789012345678abcdef01/
```

{% endcode %}

{% hint style="warning" %}
The long string after `go.getblock.io/` is your **access token** — keep it private.
{% endhint %}
{% endstep %}

{% step %}

#### Test the Connection

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl -X POST https://go.getblock.io/<YOUR-ACCESS-TOKEN>/ \
  -H "Content-Type: application/json" \
  -d '{
  "jsonrpc":"2.0",
  "method":"eth_chainId",
  "params":[],
  "id":1
  }'
```

{% endcode %}
{% endtab %}

{% tab title="Response" %}
{% code overflow="wrap" %}

```bash
{
   "jsonrpc":"2.0",
    "id":1,
    "result":"0x38"
 }
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

### Code Examples

{% tabs %}
{% tab title="cURL — Get BEP-20 Token Balance" %}
{% code overflow="wrap" %}

```bash
# Get USDT balance on BSC using eth_call
curl -X POST https://go.getblock.io/<YOUR-ACCESS-TOKEN>/ \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "eth_call",
    "params": [{
      "to": "0x55d398326f99059fF775485246999027B3197955",
      "data": "0x70a08231000000000000000000000000YOUR_ADDRESS_WITHOUT_0x"
    }, "latest"],
    "id": "getblock.io"
  }'
```

{% endcode %}
{% endtab %}

{% tab title="ethers.js" %}
{% code overflow="wrap" %}

```javascript
import { JsonRpcProvider, formatEther } from "ethers";

const provider = new JsonRpcProvider(
  "https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"
);

// Get BNB balance
const balance = await provider.getBalance("0x8894E0a0c962CB723c1ef41B18a7bb7E76FB4675");
console.log(`Balance: ${formatEther(balance)} BNB`);

// Get gas price
const gasPrice = await provider.getFeeData();
console.log(`Gas price: ${gasPrice.gasPrice} wei`);

// Read a BEP-20 token balance (e.g., USDT on BSC)
const usdtContract = new Contract(
  "0x55d398326f99059fF775485246999027B3197955", // BSC USDT
  ["function balanceOf(address) view returns (uint256)"],
  provider
);
const tokenBalance = await usdtContract.balanceOf("0x...");
```

{% endcode %}
{% endtab %}

{% tab title="Python (web3.py)" %}
{% code overflow="wrap" %}

```python
from web3 import Web3

w3 = Web3(Web3.HTTPProvider("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"))

print("Connected:", w3.is_connected())
print("Chain ID:", w3.eth.chain_id)  # 56 for BSC Mainnet
print("Latest block:", w3.eth.block_number)

# Get BNB balance
balance = w3.eth.get_balance("0x8894E0a0c962CB723c1ef41B18a7bb7E76FB4675")
print(f"Balance: {w3.from_wei(balance, 'ether')} BNB")
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Connect MetaMask to BSC via GetBlock

1. Open MetaMask → **Add Network** → **Add manually**
2. Enter:
   * **Network Name:** BSC Mainnet (GetBlock)
   * **RPC URL:** `https://go.getblock.io/<YOUR-ACCESS-TOKEN>/`
   * **Chain ID:** `56`
   * **Symbol:** `BNB`
   * **Explorer:** `https://bscscan.com`
3. Save

### Public BSC RPC vs GetBlock

| Feature             | Public RPC       | GetBlock                          |
| ------------------- | ---------------- | --------------------------------- |
| Rate limits         | Heavy throttling | Up to 500 RPS                     |
| Uptime              | No guarantee     | 99.9%+ SLA                        |
| Trace/Debug methods | Not available    | Available (Starter+)              |
| Archive data        | Limited          | Full history                      |
| Private mempool     | No               | Available (Accelerated Dedicated) |
| MEV protection      | None             | Via BloXroute BDN integration     |
| WebSocket           | Unreliable       | Persistent connections            |

### BSC Advanced Tooling — Exclusive to GetBlock

#### Accelerated Dedicated Node

GetBlock offers BSC-specific infrastructure with an integrated BloXroute BDN (Blockchain Distribution Network):

**Private Mempool Submission**

Submit transactions to a private mempool, bypassing the public mempool entirely:

* **MEV protection** — your transactions aren't visible to sandwich bots
* **Higher landing rate** — direct submission to block producers
* **Priority fee support** — set custom priority fees for faster inclusion

[How to Submit to Private Mempool](https://docs.getblock.io/bsc-advanced-tooling/bsc-accelerated-dedicated-node/how-to-submit-transaction-to-private-mempool)

**Bundle Support (Multicall3)**

Execute multiple transactions atomically:

* All-or-nothing execution
* MEV-resistant operations
* Complex DeFi strategies in a single block

[How to Use Bundles](https://docs.getblock.io/bsc-advanced-tooling/bsc-accelerated-dedicated-node/sending-transactions-to-private-mempool-priority-fee/how-to-use-bundle)

**Stream Subscription**

Subscribe to real-time BSC data streams:

* New pending transactions
* New blocks
* Transaction receipts

[How to Subscribe to Streams ](https://docs.getblock.io/bsc-advanced-tooling/bsc-chain-accelerated-dedicated-node/how-to-subscribe-to-stream)

### Choosing Your Plan

| Use Case              | Plan                               | Key Benefit                |
| --------------------- | ---------------------------------- | -------------------------- |
| Development & testing | **Free**                           | 50K CU/day                 |
| Production dApp       | **Starter** ($49/mo)               | 100 RPS, trace/debug       |
| DeFi protocol         | **Advanced** ($199/mo)             | 300 RPS, archive           |
| Trading bot / DEX     | **Dedicated** (from $1,000/mo)     | Unlimited, private mempool |
| HFT / MEV             | **Accelerated Dedicated** (custom) | BloXroute BDN, bundles     |

### What's Next?

* [Full BSC API Reference](https://docs.getblock.io/api-reference/bnb-smart-chain-bsc)
* [BSC Private Mempool Guide](https://docs.getblock.io/bsc-advanced-tooling/bsc-accelerated-dedicated-node/how-to-submit-transaction-to-private-mempool)
* [Configure a Dedicated BSC Node](https://getblock.io/dedicated-nodes/)
* [Using Web3.js with GetBlock](https://docs.getblock.io/guides/using-web3-libraries/web3.js-integration)
* [Configure Dedicated Node](https://getblock.io/dedicated-nodes/)
* [Learn more about our pricing](https://getblock.io/pricing/)

*Need high-performance BSC infrastructure for trading or DeFi?* [*Contact us*](https://getblock.io/contact/) *to discuss Accelerated Dedicated Nodes with private mempool and bundle support.*


# How to Get an Optimism RPC Endpoint

Step-by-step guide to getting a fast, reliable Optimism RPC endpoint

Optimism (OP Mainnet) is a leading Ethereum L2 and the foundation of the Superchain ecosystem. With sub-dollar transaction costs and full EVM compatibility, it hosts major protocols like Velodrome, Synthetix, and Aave. Here's how to get a reliable OP Mainnet RPC endpoint.

### Features

* Archive data access (all plans)
* Trace & Debug methods (Starter+)
* WebSocket support
* Multi-region (Frankfurt, New York, Singapore)
* Dedicated Nodes available

### Step-by-Step: Get Your Optimism RPC Endpoint

{% stepper %}
{% step %}

#### Create a GetBlock Account

Go to [GetBlock Dashboard](https://account.getblock.io) and sign up. You can register with email or via Google/GitHub OAuth.&#x20;
{% endstep %}

{% step %}

#### Create an Optimism Endpoint

Once logged in:

1. Click **"Shared Nodes"** in the left sidebar
2. Click **"Create New Endpoint"** or the **"+"** button

<figure><img src="/files/y9oTEPlbkrRH0ws32yUK" alt=""><figcaption></figcaption></figure>

3. Select:

   * **Protocol:** Optimism
   * **Network:** Mainnet or Sepolia
   * **API Interface:** JSON-RPC or Websocket or GraphQL&#x20;
   * **Region:** Frankfurt (EU)

   <figure><img src="/files/gf38qnQ2P3dR745atiCG" alt=""><figcaption></figcaption></figure>

4. Click **"Create":** Your endpoint URL will be generated immediately.
   {% endstep %}

{% step %}

#### Copy Your Endpoint URL

Your endpoint URL looks like this:

{% code overflow="wrap" %}

```bash
https://go.getblock.io/a1b2c3d4e5f6789012345678abcdef01/
```

{% endcode %}

{% hint style="warning" %}
The long string after `go.getblock.io/` is your **access token** — keep it private.
{% endhint %}
{% endstep %}

{% step %}

#### Test the Connection

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl -X POST https://go.getblock.io/<YOUR-ACCESS-TOKEN>/ \
  -H "Content-Type: application/json" \
  -d '{
  "jsonrpc":"2.0",
  "method":"eth_chainId",
  "params":[],
  "id":1
  }'

```

{% endcode %}
{% endtab %}

{% tab title="Response" %}
{% code overflow="wrap" %}

```bash
{
   "jsonrpc":"2.0",
    "id":1,
    "result": "0xa"
 }
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

#### Code Sample

{% tabs %}
{% tab title="ethers.js" %}
{% code overflow="wrap" %}

```javascript
import { JsonRpcProvider } from "ethers";
const provider = new JsonRpcProvider("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/");
console.log("Block:", await provider.getBlockNumber());
```

{% endcode %}
{% endtab %}

{% tab title="Viem" %}
{% code overflow="wrap" %}

```typescript
import { createPublicClient, http } from "viem";
import { optimism } from "viem/chains";
const client = createPublicClient({
  chain: optimism,
  transport: http("https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"),
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

### What's Next?

* [Full OP API Reference](https://docs.getblock.io/api-reference/optimism-op)
* [Dedicated Nodes](https://getblock.io/dedicated-nodes/)
* [Learn more about our pricing](https://getblock.io/pricing/)

*Need Superchain infrastructure?* [*Contact us*](https://getblock.io/contact/)*.*


# How to Get a TRON RPC Endpoint

Step-by-step guide to getting a fast, reliable TRON RPC endpoint

TRON processes more USDT transfers than any other blockchain. If you're building payment systems, wallets, trading bots, or any application that touches TRC-20 tokens, you need a reliable TRON RPC endpoint. Here's how to set one up with GetBlock.

### Step-by-Step: Get Your TRON RPC Endpoint

{% stepper %}
{% step %}

#### Create a GetBlock Account

Go to [GetBlock Dashboard](https://account.getblock.io) and sign up. You can register with email or via Google/GitHub OAuth.&#x20;
{% endstep %}

{% step %}

#### Create a TRON Endpoint

Once logged in:

1. Click **"Shared Nodes"** in the left sidebar
2. Click **"Create New Endpoint"** or the **"+"** button

<figure><img src="/files/y9oTEPlbkrRH0ws32yUK" alt=""><figcaption></figcaption></figure>

3. Select:

   * **Protocol:** TRON
   * **Network:** Mainnet or Testnet
   * **API Interface:** gRPC (Fullnode) or JSON-RPC (Fullnode) or REST (Fullnode) or gRPC (Solidity) or JSON-RPC (Solidity)
   * **Region:** Frankfurt (EU) or New York or Singapore

   <figure><img src="/files/Rk3BKFvlDuZumlgMI8GY" alt=""><figcaption></figcaption></figure>
4. Click **"Create":** Your endpoint URL will be generated immediately.
   {% endstep %}

{% step %}

#### Copy Your Endpoint URL

Your endpoint URL looks like this:

{% code overflow="wrap" %}

```bash
https://go.getblock.io/a1b2c3d4e5f6789012345678abcdef01/
```

{% endcode %}

{% hint style="warning" %}
The long string after `go.getblock.io/` is your **access token** — keep it private.
{% endhint %}
{% endstep %}

{% step %}

#### Test the Connection

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```bash
curl -X POST https://go.getblock.io/4ddcea01626040019722710f54259810/wallet/getaccount \
  -H "Content-Type: application/json" \
  -d '{"address": "TZ4UXDV5ZhNW7fb2AMSbgfAEZ7hWsnYS2g", "visible": true}'
```

{% endcode %}
{% endtab %}

{% tab title="Response" %}
{% code overflow="wrap" %}

```bash
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

### Code Sample

{% tabs %}
{% tab title="TronWeb (JavaScript)" %}
{% code overflow="wrap" %}

```javascript
import TronWeb from "tronweb";

const tronWeb = new TronWeb({
  fullHost: "https://go.getblock.io/<YOUR-ACCESS-TOKEN>/",
});

// Get TRX balance
const balance = await tronWeb.trx.getBalance("TZ4UXDV5ZhNW7fb2AMSbgfAEZ7hWsnYS2g");
console.log(`Balance: ${balance / 1e6} TRX`);

// Get USDT balance (TRC-20)
const contract = await tronWeb.contract().at("TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"); // USDT
const usdtBalance = await contract.balanceOf("TZ4UXDV5ZhNW7fb2AMSbgfAEZ7hWsnYS2g").call();
console.log(`USDT: ${usdtBalance / 1e6}`);
```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
{% code overflow="wrap" %}

```python
import requests

url = "https://go.getblock.io/<YOUR-ACCESS-TOKEN>/"

# Get latest block
response = requests.post(f"{url}wallet/getnowblock")
block = response.json()
print(f"Block: {block['block_header']['raw_data']['number']}")

# Get account info
response = requests.post(f"{url}wallet/getaccount", json={
    "address": "TZ4UXDV5ZhNW7fb2AMSbgfAEZ7hWsnYS2g",
    "visible": True
})
print(f"Balance: {response.json().get('balance', 0) / 1e6} TRX")
```

{% endcode %}
{% endtab %}
{% endtabs %}

### TRON API Interfaces

TRON supports multiple API interfaces. GetBlock offers:

| Interface             | Use Case                                         |
| --------------------- | ------------------------------------------------ |
| **HTTP API**          | Native TRON API — broadest method support        |
| **JSON-RPC**          | EVM-compatible interface for cross-chain tooling |
| **Solidity HTTP API** | Read-only confirmed data queries                 |

Most TRON developers use the HTTP API with TronWeb library.

### What's Next?

* [Full TRON API Reference ](https://docs.getblock.io/api-reference/tron-trx)
* [TronWeb Integration Guide](https://docs.getblock.io/guides/using-web3-libraries/connect-to-getblock-with-tronweb)
* [Dedicated Nodes ](https://getblock.io/dedicated-nodes/)
* [Learn more about our pricing](https://getblock.io/pricing/)

*Processing USDT at scale?* [*Contact us*](https://getblock.io/contact/) *for dedicated TRON infrastructure.*


# 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.


# 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.

### Install Web3.js

Use your preferred package manager:

{% tabs %}
{% tab title="npm" %}

```bash
npm install web3
```

{% endtab %}

{% tab title="yarn" %}

```bash
yarn add web3
```

{% endtab %}

{% tab title="Pure js link" %}

```bash
dist/web3.min.js
```

{% endtab %}
{% endtabs %}

### Set up your connection to GetBlock

```javascript
// 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);
```

For additional methods and options, refer to the official [Web3.js documentation](https://web3js.readthedocs.io/en/v1.10.0/index.html).


# 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.

### Creating accounts

First, initialize the Web3.js library and set up the connection to a blockchain node:

```javascript
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>/');
```

Next, we can create an account on the [BNB Smart Chain](https://getblock.io/nodes/bsc/) testnet:

```javascript
// Generate new address and private key
const accountTo = web3.eth.accounts.create();
console.log('Generated account:', accountTo);
```

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

```javascript
// Restore account from private key
const privateKey = process.env['privateKey'];
const accountFrom = web3.eth.accounts.privateKeyToAccount(privateKey);
```

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.

### 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.

```javascript
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
```

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

```javascript
const rawTx = {
to: accountTo.address,
value: web3.utils.toWei(amountTo, 'ether'),
chainId: chainId
};

createSignedTx(rawTx).then(sendSignedTx)
```

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


# 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.

### Install Ethers.js

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

* npm

```bash
npm install ethers
```

* yarn

```bash
yarn add ethers
```

### Set GetBlock as a provider

```javascript
// 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();
```

For further details and advanced usage, explore the [Ethers.js documentation](https://docs.ethers.org/v6/getting-started/).


# 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:

```bash
npm install tronweb
```

* Yarn:

```bash
yarn add tronweb
```

In your javascript file, define TronWeb:

```javascript
const TronWeb = require('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:

```javascript
const tronWeb = new TronWeb({
fullHost: "https://go.getblock.io/<ACCESS-TOKEN>/"
})
```

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):

```javascript
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)
```

After this you can call any TronWeb method:

<pre class="language-javascript"><code class="lang-javascript"><strong>tronWeb.trx.getBlock('latest').then(result => {console.log(result)});
</strong></code></pre>

All API references can be found in the project documentation at <https://developers.tron.network/reference>

## Method response:

![tronWeb.trx.getBlock(blockNumberOrBlockId) method response](https://storage.getblock.io/web/docs/guides/how-to-connect-to-getblock-with-tronweb/tronweb_screenshot_1.webp)


# 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:&#x20;

* Create a Telegram bot using [Botfather](https://telegram.me/BotFather)
* Get a GetBlock API access token
* Build the Hyperliquid whale tracker bot that:&#x20;
  * 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

### Prerequisites

1. Basic knowledge of JavaScript
2. Must have installed [Node](https://nodejs.org/en/download/current) and [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm/)
3. A [GetBlock account](https://account.getblock.io/)
4. A [Telegram account](#id-2.-configuration-settings)

### 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`&#x20;
   * Copy your user ID

### Step 2. Set up Development Environment

Before you begin, you need to set up your development environment:

```bash
mkdir hyperliquid-whale-alert-bot
cd hyperliquid-whale-alert-bot
npm init -y
npm i dotenv ws
npm i -D nodemon
```

### Step 3. Getting your HyperEVM Websocket Token

1. Log in to your [GetBlock account](https://account.getblock.io/)
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

{% hint style="warning" %}
Keep your endpoint safe, as it contains an access token
{% endhint %}

#### Project Structure

Create the following files to have a basic structure for your project:

```bash
├── index.js            // Main apllication
└── .env                // Environment variables
└── .gitignore          // Git ignore file
```

### Step 4. Set up Environment Variables

Update the `.env` file in the root of your project and add the following variables:

<pre class="language-bash"><code class="lang-bash"><strong># Telegram Configuration (Get from @BotFather and @userinfobot)
</strong>TELEGRAM_BOT_TOKEN=your-telegram-bot-token
TELEGRAM_CHAT_ID=your-ID

<strong># Whale Detection Thresholds
</strong>WHALE_THRESHOLD_USD=100000
WHALE_THRESHOLD_SIZE=50

<strong># Telegram Settings
</strong>TELEGRAM_BATCH_ALERTS=true
TELEGRAM_BATCH_INTERVAL=10000

<strong># Markets to Track (comma-separated)
</strong>TRACKED_SYMBOLS=BTC,ETH,SOL,ARB,AVAX,HYPE

<strong># Optional: HyperEVM WebSocket from GetBlock
</strong>HYPEREVM_WSS=wss://go.getblock.io/&#x3C;ACCESS_TOKEN>
</code></pre>

### Step 5. Build Whale Tracker Bot

#### 1. Import dependencies:

Import the dependencies and load the environment variables from `.env` file

```javascript
// dependencies
import WebSocket from 'ws';
import { config } from 'dotenv';

// Load environment variables from .env file
config();
```

#### 2. Set up configuration settings:

Set up configuration settings for your application, including environment variables and other constants.

```javascript
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(','),
};
```

#### 3. Create the Main Class with Private Fields:

```javascript
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';
  }
}
```

**Why private fields?**

* `#` prefix makes fields private (ES2022 feature)
* Prevents external code from modifying internal state
* Better encapsulation and code organization

#### 4. Connect to Hyperliquid WebSocket:

```javascript
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'));
}
```

**Event handlers:**

* `open` - Triggered when the connection is established
* `message` - Receives data from the server
* `error` - Handles connection errors
* `close` - Handles disconnection

#### 5. Subscribe to Data Streams:

```javascript
#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');
}
```

**Subscription types:**

* `allMids` - Current market prices for all symbols
* `trades` - Real-time trade executions
* `l2Book` - Level 2 orderbook (buy/sell walls)

#### 6. Handle Incoming Messages:

```java
#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);
  }
}
```

**Message routing:**

* Parse JSON data from WebSocket
* Route to the appropriate handler based on `channel` type
* Graceful error handling with try-catch

#### 7. Update Price Cache

```javascript
#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));
  }
}
```

**Why cache prices?**

* Used for calculating USD value of trades
* Avoids repeated API calls
* Provides a fallback when price data is missing

#### 8. Analyze Trades for Whales

```javascript
#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);
  }
}
```

**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

#### 9. Track Whale Addresses

```javascript
#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])
    });
  }
}
```

**Whale profile includes:**

* Total trading volume (cumulative)
* Number of trades executed
* First and last seen timestamps
* Set of markets they trade in

#### 10. Analyze Orderbook for Whale Walls

```javascript
#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);
  }
}
```

**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

#### 11. Send Trade Notifications

```javascript
#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);
    }
  }
}
```

**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

#### 12. Implement Telegram Batching

```javascript
#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;
}
```

**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)

#### 13. Implement Telegram Queue System

```javascript
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);
}
```

**Queue system benefits:**

* Messages are queued and processed sequentially
* Respects Telegram's rate limits
* Automatic retry on 429 errors
* Non-blocking (uses async/await)

#### 14. Test Telegram Connection

```javascript
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');
  }
}
```

**Connection test:**

* Validates bot token on startup
* Shows bot username
* Sends test message
* Provides helpful error messages

#### 15. Implement Auto-Reconnection

```javascript
#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);
}
```

**Reconnection strategy:**

* Exponential backoff (delays increase)
* Maximum 5 attempts
* Caps at 30 seconds between tries
* Separate handling for different connections

#### 16. Generate Statistics Dashboard

```javascript
#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');
}
```

**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

#### 17. Create the Start Method

```javascript
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');
}
```

**Startup sequence:**

1. Display configuration
2. Test Telegram connection
3. Connect to Hyperliquid WebSocket
4. Optionally connect to HyperEVM
5. Start periodic statistics reporting

#### 18. Initialize and Run the Bot

```javascript
// 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);
});
```

**Proper shutdown:**

* Closes WebSocket connections properly
* Prevents data loss or hanging connections

#### Running and Testing the Application

1. Open your terminal and run the following command:

```bash
node index.js
```

2. Expected result in console:

```
🐋 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
```

3. Expected result in Telegram:

<figure><img src="/files/aQC8ZZ7ZVfJDwjIgQ24i" alt=""><figcaption></figcaption></figure>

### Troubleshooting

You may run into a **WebSocket 503** Error:

```
Connecting to GetBlock WebSocket...
WebSocket error: Error: Unexpected server response: 503
WebSocket connection closed
Reconnecting in 16 seconds... (Attempt 4)
```

* This means that your WebSocket endpoint is incorrect.  Check your `.env` file and ensure it's in this pattern:

```bash
# correct format
HYPEREVM_WSS=wss://go.getblock.io/<ACCESS_TOKEN>
```

Then, restart the server.&#x20;

```bash
node index.js
```

### 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.


# 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.

### 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.&#x20;

GetBlock's Yellowstone gRPC service solves this by streaming data from Solana validators in real time.&#x20;

Here is a comparison:

| Traditional RPC Polling                                       | Websocket                                               | Yellowstone gRPC                                                      |
| ------------------------------------------------------------- | ------------------------------------------------------- | --------------------------------------------------------------------- |
| 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 |

#### 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
* **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.

In this guide, you will learn how to:&#x20;

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
4. Parses instruction data to extract token metadata
5. Extracts account addresses (mint, creator, bonding curve)
6. Displays formatted output with Solscan explorer links
7. Tracks statistics and auto-reconnects on errors

### Prerequisites

Before you begin, ensure you have:

* [Node.js ](https://nodejs.org/en) and npm installed
* Basic knowledge of JavaScript&#x20;
* A [GetBlock’s account](https://account.getblock.io/)
* A Dedicated Solana Node subscription on GetBlock - Required for Yellowstone gRPC access

#### Technology Stack:

* Node.js
* [@triton-one/yellowstone-grpc](https://www.npmjs.com/package/@triton-one/yellowstone-grpc) - Official Yellowstone gRPC client
* [bs58](https://www.npmjs.com/package/bs58) - Base58 encoding for Solana addresses
* GetBlock’s Dedicated Solana Node with Yellowstone add-on

### Step 1: Set Up Your GetBlock’s Yellowstone Endpoint

#### 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](https://getblock.io/)
* 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"**
* Under "**Protocol**", select Solana
* Set the network to **Mainnet**
* Click **Get**

![](/files/cTtrISzdVeccQYu8n2lS)

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

![](/files/MRCJ5VpViJWCxjlcjQG0)

#### 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".**&#x20;
* Select **Yellowstone gRPC**
* Click on **Add** to generate an access token

![](/files/evmzHmnqlt6YFvST6aIz)

2\. **Your endpoint URL**

You'll receive an HTTPS-style gRPC endpoint URL based on your chosen region:

{% tabs %}
{% tab title="Europe (Frankfurt)" %}

```bash
https://go.getblock.io/YOUR_ACCESS_TOKEN/
```

{% endtab %}

{% tab title="USA (New York)" %}

```bash
https://go.getblock.us/YOUR_ACCESS_TOKEN/
```

{% endtab %}

{% tab title="Asia (Singapore)" %}

```bash
https://go.getblock.asia/YOUR_ACCESS_TOKEN/
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
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.
{% endhint %}

{% hint style="info" %}
GetBlock provides a single TLS endpoint - you don't need to configure different ports or protocols. Everything works over standard HTTPS (`port 443`).
{% endhint %}

### Step 2: Set up Development Environment

1. Create a directory for your project

```
mkdir pumpfun-monitor
cd pumpfun-monitor
npm init-y
```

2. Install Dependencies:

```bash
npm install @triton-one/yellowstone-grpc bs58@5.0.0
```

What these packages do:

* [@triton-one/yellowstone-grpc](https://www.npmjs.com/package/@triton-one/yellowstone-grpc) - Official client for connecting to Yellowstone gRPC services (works with GetBlock)
* [bs58@5.0.0 ](https://www.npmjs.com/package/bs58)- Encodes binary data to base58 format (Solana's address format). Version 5.0.0 supports vanilla js.

{% hint style="info" %}
`bs58@5.0.0`  because version 6.x + uses ES modules only, which don't work with vanilla js - `require()` statements.
{% endhint %}

#### Project Structure

Create the following files to have a basic structure for your project:

```bash
├── pumpfun-monitor.js          // Main apllication
└── .env                // Environment variables
└── .gitignore          // Git ignore file
```

### Step 3: Start Building Your Monitor

1. Import dependencies into `pumpfun-monitor.js` :

```javascript
const Client = require("@triton-one/yellowstone-grpc").default;
const { CommitmentLevel } = require("@triton-one/yellowstone-grpc");
const bs58 = require("bs58");
```

**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.

2. Add your GetBlock configuration:&#x20;

```javascript
// GetBlock Configuration
const ENDPOINT = "https://go.getblock.io";  // Your region's endpoint
const TOKEN = "YOUR_ACCESS_TOKEN";           // Your generated token
```

**What this does:**&#x20;

* Stores your GetBlock credentials.&#x20;

{% hint style="danger" %}
Replace **YOUR\_ACCESS\_TOKEN** with the actual token you generated in Step 1. &#x20;

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>`.
{% endhint %}

3. Add Pump.fun constants:

```javascript
// Pump.fun Program Constants
const PUMPFUN_PROGRAM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";
const CREATE_DISCRIMINATOR = Buffer.from([24, 30, 200, 40, 5, 28, 7, 119]);
```

**What this does:**

* &#x20;`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")

4. Add statistics tracker:

```javascript
// Statistics Tracking
let stats = {
  startTime: Date.now(),
  totalMints: 0,
  lastMintTime: null
};
What this does: 
```

* This creates an object to track how many tokens you've detected and when the last one appeared.

#### Step 4: Build Data Parser Functions

Now, you'll add a function to decode the binary data from Pump.fun's instruction format.&#x20;

1. Add string decoder:&#x20;

```javascript
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 };
}
```

**What this does:**&#x20;

* 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.

2. Add Instruction Parser: <br>

   ```javascript
   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;
     }
   }

   ```

   \
   **What this does:**&#x20;

* 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")
  * **Token symbol** (e.g., "SDOGE")
  * **Metadata URI** (link to token image and details)

{% hint style="success" %}
The function starts at byte 8 (after the discriminator) and reads each string one by one using the decodeString helper function.
{% endhint %}

### 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.

<pre class="language-javascript"><code class="lang-javascript">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 {
<strong>      mint: accounts[0],
</strong><strong>      bondingCurve: accounts[2],
</strong><strong>      creator: accounts[7]
</strong>    };
  } catch (error) {
    return null;
  }
}
</code></pre>

**What this does:**&#x20;

* Extracts three key addresses from the instruction:
  * accounts\[0] - The newly created token's mint address
  * accounts\[2] - The bonding curve pool address
  * accounts\[7] - The creator's wallet address

{% hint style="success" %}
These are defined by Pump.fun's program structure.
{% endhint %}

### Step 6: Add Instruction Verifier

The next step is to verify the instruction:&#x20;

```javascript
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);
}
```

**What this does:**&#x20;

* Verifies two things:
  * The instruction calling Pump.fun's program
  * The first 8 bytes which match the create discriminator

{% hint style="success" %}
Only instructions passing both checks are token creations.
{% endhint %}

### Step 7: Add Display Function

The next step is to add a function that displays the data in a readable format:&#x20;

```javascript
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");
}
```

\
**What this does:**&#x20;

* Formats and displays all token information in a readable format
* Updates statistics
* Includes Solscan link to the token, transaction hash and creator.

### Step 8: Build the Main Monitor Function

Now you'll create the core function that connects to GetBlock and processes blockchain data.&#x20;

{% hint style="warning" %}
This section is broken into smaller parts for clarity.&#x20;
{% endhint %}

#### Part A: Start the Function and Connect

```javascript
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();
```

**What this does:**&#x20;

* Creates a client connection to GetBlock using your credentials and opens a bi-directional streaming connection.

#### Part B: Configure Subscription

```javascript
 const request = {
        accounts: {},
        slots: {},
        transactions: {
          pumpfun: {
            accountInclude: [PUMPFUN_PROGRAM],
            accountExclude: [],
            accountRequired: []
          }
        },
        transactionsStatus: {},
        entry: {},
        blocks: {},
        blocksMeta: {},
        commitment: CommitmentLevel.CONFIRMED,
        accountsDataSlice: [],
        ping: undefined
      };

```

**What this does:**&#x20;

* Tells GetBlock you only want transactions involving Pump.fun's program, with CONFIRMED commitment level (\~2-3 seconds, balanced speed/reliability).

#### Part C: Handle Incoming Data

```javascript
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;
```

\
What this does:&#x20;

* Processes each message from GetBlock - responds to keep-alive pings and extracts transaction data.

#### Part D: Process Instructions

```javascript
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}`);
        }
      });

```

&#x20;What this does:&#x20;

* For each instruction, it checks if it's a create, parses metadata, extracts addresses, and displays results.

#### Part E: Handle Errors

```javascript
    stream.on("error", (error) => {
        console.error(`Stream error: ${error.message}`);
        reject(error);
      });
      
      stream.on("end", () => resolve());
      stream.on("close", () => resolve());
```

What this does:&#x20;

* It handles stream errors and connection closures.

#### Part F: Send Request

```javascript
stream.write(request, (err) => {
        if (err) {
          reject(err);
        } else {
          console.log("✅ Subscription active - monitoring blockchain...\n");
        }
      });
      
    } catch (error) {
      reject(error);
    }
  });
}

```

What this does:&#x20;

* Sends your subscription request to GetBlock and confirms the connection is active.&#x20;

{% hint style="warning" %}
This completes the `monitorPumpfunMints()` function - everything above is part of this one function in your `pumpfun-monitor.js` file.
{% endhint %}

### Step 9: Add Execution Code

Finally, add the code to run your monitor:

```javascript
async function main() {
  try {
    await monitorPumpfunMints();
  } catch (error) {
    console.error("Monitor crashed:", error.message);
    console.log("Restarting in 5 seconds...");
    setTimeout(main, 5000);
  }
}
```

What this does:&#x20;

* Runs your monitor and automatically restarts it if it crashes.

```javascript
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();
```

What this does:&#x20;

* Handles `Ctrl+C`  to show final statistics before shutdown.

### Step 10: Run Your Monitor

Run the following command in your terminal to start the server:

```bash
node pumpfun-monitor.js
```

#### Expected Output

You'll see:

```bash
🚀 Starting Pump.fun Token Mint Monitor
🎯 Watching program: 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P
Waiting for new token mints...
✅ Subscription active - monitoring blockchain...
```

This means you're connected to GetBlock and monitoring is active.&#x20;

#### When a Token Appears

When a new token appears, it displays like this:

```bash
================================================================================
🎉 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...

================================================================================

```

Congratulations 🎉, you've successfully created an application that tracks Pump.fun token minted.&#x20;

### Troubleshooting

1. **Connection issues:**&#x20;

```
Connection refused
```

This means there is a connection glitch:&#x20;

* Verify your **ENDPOINT** and **TOKEN** in `pumpfun-monitor.js`
* Check your GetBlock dashboard to confirm if the node is active
* Test your internet connection

2. **Tokens not showing:**

* Be patient - Pump.fun typically has 50-200 tokens per day
* Visit[ pump.fun](https://pump.fun/) to verify tokens are being created
* Try `CommitmentLevel.PROCESSED` for faster updates

3. **Parser Errors:**

```bash
Failed to extract accounts
```

&#x20;These warnings are normal. This means some transactions aren't structured.&#x20;

### 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:

```javascript
GETBLOCK_TOKEN=your_token node pumpfun-monitor.js
```

and reference it in your `pumpfun-monitor.js` like this:

```javascript
//use dotenv
const TOKEN = process.env.GETBLOCK_TOKEN;
```

{% hint style="warning" %}
Remember to add the `.env` file in your `.gitignore` file.
{% endhint %}

### 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.&#x20;

It also explains how to troubleshoot some errors you may encounter and possible ways to enhance the security and maintainability of your applications.&#x20;

#### Additional Resources

* [GetBlock Dashboard](https://getblock.io/dashboard/)
* [GetBlock Yellowstone gRPC API](/add-ons/yellowstone-grpc-api)
* [Yellowstone gRPC GitHub](https://github.com/rpcpool/yellowstone-grpc)
* [Pump.fun on Solscan](https://solscan.io/account/6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P)


# 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 [Anthropic](https://www.anthropic.com/news/model-context-protocol) that provides a universal way for AI assistants to connect to external data sources and tools.&#x20;

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.&#x20;

In this guide, you will learn how to:&#x20;

* 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
  * Get current gas prices
  * Retrieve the latest block number
* Claude configuration and deployment

#### Prerequisites

1. Basic understanding of JavaScript
2. Must have installed [Node](https://nodejs.org/en/download/current) and [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm/)
3. A GetBlock [account](https://account.getblock.io/sign-up)
4. [Claude Desktop](https://claude.ai/download)

#### Technology Stack:

* Node.js: JavaScript runtime environment that lets developers create servers, web apps, command line tools and scripts.
* [Model Context Protocol SDK:](https://www.npmjs.com/package/@modelcontextprotocol/sdk) This allows applications to provide the context for LLMs in a standardized way.
* [Zod](https://www.npmjs.com/package/zod): TypeScript-first validation library.
* [Ethers](mailto:undefined): A library for interacting with the Ethereum blockchain and its ecosystem.

### Step 1: Project Initialization

1. Set up your project directory using this command:

```bash
# create project folder
mkdir basic-ethereum-mcp
# navigate through the folder
cd basic-ethereum-mcp
# initialise npm
npm init -y
```

2. Install Dependencies:

```bash
npm install @modelcontextprotocol/sdk zod ethers
```

* `@modelcontextprotocol/sdk`: Core MCP server functionality that provides `McpServer` class and transport mechanisms.
* `ethers`: Js library for interacting with Blockchain e.g Ethereum.
* `zod`: a schema that validates user inputs before processing.

3. Configure `Package.json`

<pre class="language-json"><code class="lang-json">{
  "name": "basic-ethereum-mcp",
  "version": "1.0.0",
<strong>  "type": "module",
</strong>  "description": "MCP server with GetBlock API integration",
  "main": "server.js",
  "bin": {
<strong>    "mcp-ethereum": "./server.js"
</strong>  },
  "scripts": {
<strong>    "start": "node server.js"
</strong>  },
  "keywords": ["mcp", "blockchain", "ethereum", "getblock"],
  "author": "Your Name",
  "license": "MIT",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.22.0",
    "ethers": "^6.15.0",
    "zod": "^3.25.76"
  }
}
</code></pre>

* `"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` command
* `"scripts"` - Defines shortcuts like `npm start`

4. Get GetBlock's API Access Token

   1. Log in to your [GetBlock account](https://account.getblock.io/)
   2. On your dashboard, scroll and click on **Get Endpoint**
   3. Select the Ethereum **Mainnet** network
   4. Under **API Interface,** select JSON-RPC
   5. Click on **Create** to get your endpoint

   &#x20;    Your endpoint will look like:

   ```json
   https://go.getblock.us/{YOUR-ACCESS-TOKEN}/
   ```

   f. Save the token in `.env` file in this format:

   ```javascript
   GETBLOCK_TOKEN=your_token
   ```

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p>Keep your endpoint safe, as it contains an access token</p></div>
5. Project Structure

Create the following files to have a basic structure for your project:

```bash
├── server.js            // Main application
└── .env                // Environment variables
└── .gitignore          // Git ignore file
```

### Step 2: Server File Setup

#### 1. Import dependencies

{% hint style="success" %}
Your script will be written inside `server.js`
{% endhint %}

```javascript
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}/`
);
```

**What this does:**

* Reads API token from environment variable
* Creates Ethers provider pointing to GetBlock endpoint
* All blockchain queries route through GetBlock's infrastructure

#### 3. Create MCP server instance

```javascript
// Create MCP server with modern API
const server = new McpServer({
  name: "ethereum-mcp-server",
  version: "1.0.0",
});

console.error("✅ Ethereum MCP Server initialized");
```

**Configuration:**

* `name` - Unique identifier for your server
* `version` - Semantic version for tracking updates
* `console.error()` - Logs to stderr (separate from data output)

#### 4.  Implement Blockchain Query Tools

**Tool 1: Get ETH Balance**

This tool fetches the ETH balance for any Ethereum address:

<pre class="language-javascript"><code class="lang-javascript">server.tool(
<strong>  "get_eth_balance",
</strong>  {
    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,
      };
    }
  }
);
</code></pre>

**What this does:**&#x20;

* Register the tool
* Validates Ethereum address format
* Queries Ethereum blockchain through GetBlock
* 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

**Tool 2: Get Gas Price**

This tool retrieves current Ethereum gas prices:&#x20;

<pre class="language-javascript"><code class="lang-javascript"><strong>server.tool("get_gas_price", {}, async () => {
</strong>  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,
    };
  }
});
</code></pre>

**What it does:**&#x20;

* 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.

```javascript
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,
    };
  }
});
```

**What this does:**

* Get the latest block
* Includes server timestamp for correlation

#### **5: Server Startup and Connection**

1. **Create a Server connection with Claude desktop**

```javascript
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);
  }
}
```

What this does:&#x20;

* `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
* Starts listening for incoming requests

2. Start the server and shut down:

```javascript
// 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);
});
```

**What this does:**&#x20;

* `SIGINT` - Handles Ctrl+C interrupts
* When the user runs `npm run start` , this will start the server.

### Step 3: Configuration and Deployment

1. Open your Claude Desktop
2. Click on **Settings**
3. Scroll down and Click on **Developer**
4. Under **Local MCP Server**, click on `Edit Config`

<figure><img src="/files/TVvbGHqff5xNtQFzAMSQ" alt=""><figcaption></figcaption></figure>

5. Add the following **configuration**:

{% tabs %}
{% tab title="macOS" %}
**Config Location:**

```bash
~/Library/Application Support/Claude/claude_desktop_config.json
```

**Edit Configuration:**

```bash
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
```

**Add the following configuration:**

```json
{
  "mcpServers": {
    "ethereum": {
      "command": "node",
      "args": [
        "/Users/YOUR_USERNAME/basic-ethereum-mcp/server.js"
      ],
      "env": {
        "GETBLOCK_TOKEN": "your-actual-getblock-token-here"
      }
    }
  }
}
```

{% endtab %}

{% tab title="windows" %}
**Config Location:**

```
%APPDATA%\Claude\claude_desktop_config.json
```

**Add the following configuration:**

```json
{
  "mcpServers": {
    "ethereum": {
      "command": "node",
      "args": [
        "C:\\Users\\YOUR_USERNAME\\basic-ethereum-mcp/\\server.js"
      ],
      "env": {
        "GETBLOCK_TOKEN": "your-actual-getblock-token-here"
      }
    }
  }
}
```

{% endtab %}

{% tab title="linux" %}
**Config Location:**

```
~/.config/Claude/claude_desktop_config.json
```

**Add the following configuration:**

```json
{
  "mcpServers": {
    "ethereum": {
      "command": "node",
      "args": [
        "/home/YOUR_USERNAME/basic-ethereum-mcp//server.js"
      ],
      "env": {
        "GETBLOCK_TOKEN": "your-actual-getblock-token-here"
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### Step 4: Testing Your Server

**Test 1: Check ETH Balance**

```
What's the ETH balance of 0xd1af2dac4e0a9d1f58b99e2f42bc0320ed74a7cd?
```

{% hint style="success" %}
Permit Claude to query the data
{% endhint %}

**Expected:** Claude calls `get_eth_balance` tool and shows balance e.g&#x20;

> **The ETH balance for address 0xd1af2dac4e0a9d1f58b99e2f42bc0320ed74a7cd is 0.000104792219532 ETH (approximately 104,792,219,532,000 wei).**

**Test 2: Gas Price**

```
What's the current Ethereum gas price?
```

**Expected:** Claude calls `get_gas_price` tool and shows price in Gwei e.g&#x20;

> 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**

```
What's the latest Ethereum block number?
```

**Expected:** Claude calls `get_block_number` tool and shows block e.g&#x20;

> The latest Ethereum block number is **23,811,857** on the Ethereum Mainnet, as of 2025-11-16 at 12:50:34 UTC.

#### Step 4: Advanced Tests

**Test 4: Multiple Queries**

```
Check the balance for 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 
and tell me if the current gas price is high or low
```

**Expected:** Claude calls both tools and provides analysis e.g&#x20;

> **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:
>
> * **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.

**Test 5: Natural Language**

```
Is now a good time to send an Ethereum transaction?
```

**Expected:** Claude checks gas price and provides a recommendation e.g&#x20;

> 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!

### Troubleshooting

If you experience this error:&#x20;

<figure><img src="/files/zV8mMifU2riJNME4igHl" alt=""><figcaption></figcaption></figure>

This means that:

1. Your GetBlock token is missing or incorrect
2. The base URL is not correct.&#x20;

{% hint style="warning" %}
Each location has a unique URL
{% endhint %}

{% tabs %}
{% tab title="New  York" %}

```bash
https://go.getblock.us/7hys368hus...
```

{% endtab %}

{% tab title="Signapore" %}

```bash
https://go.getblock.asia/f782e8ec54....
```

{% endtab %}

{% tab title="Frankfurt" %}

```bash
https://go.getblock.io/d4067b3cc......
```

{% endtab %}
{% endtabs %}

### 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.&#x20;

#### Additional Resources

* [MCP docs](https://modelcontextprotocol.io/)
* [MCP SDK](#id-5-server-startup-and-connection)
* [Basic Ethereum MCP repo](https://github.com/GetBlock-io/guides/tree/main/basic-ethereum-mcp)


# 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.&#x20;

&#x20;GetBlock's Yellowstone gRPC service allows developers to fetch data directly from Solana validators easily with low latency - appropriately \~400ms latency.&#x20;

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

### Prerequisites

Before you begin, ensure you have:

* [Node.js ](https://nodejs.org/en) and npm installed
* Basic knowledge of JavaScript&#x20;
* A [GetBlock’s account](https://account.getblock.io/)
* A Dedicated Solana Node subscription on GetBlock - Required for Yellowstone gRPC access

#### Technology Stack:

* Node.js
* [@triton-one/yellowstone-grpc](https://www.npmjs.com/package/@triton-one/yellowstone-grpc) - Official Yellowstone gRPC client
* [bs58](https://www.npmjs.com/package/bs58) - Base58 encoding for Solana addresses
* GetBlock’s Dedicated Solana Node with Yellowstone gRPC add-on

### Step 1: Set Up Your GetBlock’s Yellowstone Endpoint

#### 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](https://getblock.io/)
* 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"**
* Under "**Protocol**", select Solana
* Set the network to **Mainnet**
* Click **Get**

![](/files/cTtrISzdVeccQYu8n2lS)

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

![](/files/MRCJ5VpViJWCxjlcjQG0)

#### 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".**&#x20;
* Select **Yellowstone gRPC**
* Click on **Add** to generate an access token

![](/files/evmzHmnqlt6YFvST6aIz)

2\. **Your endpoint URL**

You'll receive an HTTPS-style gRPC endpoint URL based on your chosen region:

{% tabs %}
{% tab title="Frankfurt" %}

```css
https://go.getblock.io/YOUR_ACCESS_TOKEN/
```

{% endtab %}

{% tab title="New York" %}

```css
https://go.getblock.us/YOUR_ACCESS_TOKEN/
```

{% endtab %}

{% tab title="Asia (Singapore)" %}

```css
https://go.getblock.asia/YOUR_ACCESS_TOKEN/
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
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.
{% endhint %}

### Step 2: Set up Development Environment

1. Create a directory for your project

```javascript
mkdir pool-monitor
cd pool-monitor
npm init-y
```

2. Install Dependencies:

```javascript
npm install @triton-one/yellowstone-grpc bs58@5.0.0
```

What these packages do:

* [@triton-one/yellowstone-grpc](https://www.npmjs.com/package/@triton-one/yellowstone-grpc) - Official client for connecting to Yellowstone gRPC services (works with GetBlock)
* [bs58@5.0.0 ](https://www.npmjs.com/package/bs58)- Encodes binary data to base58 format (Solana's address format). Version 5.0.0 supports vanilla js.

{% hint style="info" %}
`bs58@5.0.0`  because version 6.x + uses ES modules only, which don't work with vanilla js - `require()` statements.
{% endhint %}

3. Configure `Package.json`

<pre class="language-json"><code class="lang-json">{
  "name": "pool-monitor",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" &#x26;&#x26; exit 1",
    "start": "node pool-monitor.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "module",
<strong>  "dependencies": {
</strong>    "@triton-one/yellowstone-grpc": "^4.0.2",
    "bs58": "^5.0.0",
    "dotenv": "^17.2.3"
  }
}

</code></pre>

* `"type": "module"` - Enables ES6 import/export syntax&#x20;
* `"scripts"` - Defines shortcuts like `npm start`

#### Project Structure

Create the following files to have a basic structure for your project:

```bash
├── pool-monitor.js.          // Main application
└── .env                // Environment variables
└── .gitignore          // Git ignore file
```

### Step 3: Start Building Your Monitor

{% hint style="success" %}
You'll build everything in a single file called `pool-monitor.js`. Let's start creating it piece by piece.
{% endhint %}

#### Import Dependencies

Create a new file pool-monitor.js and add:

```javascript
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();
```

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` - 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.

#### Add Your GetBlock Configuration

```javascript
// GetBlock Configuration
const ENDPOINT = "https://go.getblock.io";  // Your region's endpoint
const TOKEN = process.env.GETBLOCK_TOKEN; ;           // Your generated token
```

What this does:&#x20;

* Stores your GetBlock credentials that you created in [Step 1.](#step-1-set-up-your-getblocks-yellowstone-endpoint) 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`).

#### Add Pool Configuration

```javascript
// Pool Configuration
const TARGET_POOL = "8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj"; // SOL/USDC CLMM
const POOL_NAME = "SOL/USDC";
```

**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

#### Add DEX Program IDs

```javascript
// Common Solana DEX Program IDs
const RAYDIUM_AMM = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8";
const RAYDIUM_CLMM = "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK";
const JUPITER_V6 = "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4";
```

**What this does:**&#x20;

* 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` - Raydium's concentrated liquidity pools (like Uniswap V3)
  * `JUPITER_V6` - Jupiter's DEX aggregator (finds best prices across multiple DEXes)

#### Add Statistics Tracker

```javascript
// Statistics
let stats = {
  startTime: Date.now(),
  totalSwaps: 0
};
```

**What this does:**&#x20;

* 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`).&#x20;
* This allows you to view cumulative statistics when you stop the program.

### Step 4: Build the Swap Source Identifier

Now you'll add a function to identify which platform initiated each swap.

```javascript
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";
}
```

**What this does:**&#x20;

* 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
* 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.)

{% hint style="success" %}
**Why this matters:**&#x20;

* 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.
  {% endhint %}

### Step 5: Add Display Function

```javascript
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");
}
```

**What this does:**&#x20;

* 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.)
* `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

{% hint style="success" %}
Why formatted output matters:&#x20;

* 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.
  {% endhint %}

### Step 6: Build the Main Monitor Function

Now you'll create the core function that connects to GetBlock and processes blockchain data.&#x20;

{% hint style="warning" %}
This is broken into smaller parts for clarity.
{% endhint %}

#### Part A: Start the Function and Connect

```javascript
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();
```

**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.
* `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

{% hint style="success" %}
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.
{% endhint %}

#### Part B: Configure Subscription

```javascript
const request = {
        accounts: {},
        slots: {},
        transactions: {
          pool_swaps: {
            accountInclude: [TARGET_POOL],
            accountExclude: [],
            accountRequired: []
          }
        },
        transactionsStatus: {},
        entry: {},
        blocks: {},
        blocksMeta: {},
        commitment: CommitmentLevel.CONFIRMED,
        accountsDataSlice: [],
        ping: undefined
      };
```

**What this does:**&#x20;

* Tells GetBlock exactly what data you want to receive

#### Part C: Handle Incoming Data

```javascript
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;
```

**What this does:**&#x20;

* Sets up an event listener that processes each message GetBlock sends you.

#### Part D: Process and Display Swaps

```javascript
// 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}`);
}
});

```

**What this does:**&#x20;

* processes each transaction and:&#x20;
  * 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
  * 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

#### Part E: Handle Stream Events

<pre class="language-javascript"><code class="lang-javascript">stream.on("error", (error) => {
<strong>  console.error(`Stream error: ${error.message}`);
</strong>  reject(error);
});

stream.on("end", () => resolve());
stream.on("close", () => resolve());
</code></pre>

**What this does:**&#x20;

* Handles different connection states such as:&#x20;
  * `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)
  * `close` - The connection closed (either normally or due to an error)

Both `end` and `close` resolve the Promise, which allows the program to shut down cleanly or restart if needed.

#### Part F: Send Subscription Request

```javascript
stream.write(request, (err) => {
        if (err) {
          reject(err);
        } else {
          console.log("✅ Subscription active - monitoring pool swaps...\n");
        }
      });
      
    } catch (error) {
      reject(error);
    }
  });
}
```

**What this does:**&#x20;

* Sends your subscription configuration to GetBlock and confirms the connection is active.

{% hint style="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.
{% endhint %}

### Step 7: Add Auto-Restart Functionality

Add the code to run your monitor with automatic restart on errors:

```javascript
async function main() {
  try {
    await monitorPoolSwaps();
  } catch (error) {
    console.error("Monitor crashed:", error.message);
    console.log("Restarting in 5 seconds...");
    setTimeout(main, 5000);
  }
}
```

**What this does:**&#x20;

* Provides resilience by automatically restarting if something goes wrong.

{% hint style="success" %}
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.
{% endhint %}

### Step 8: Add Shutdown

Finally, add the code to handle Ctrl+C successfully:

```javascript
process.on('SIGINT', () => {
  console.log("\n\n🛑 Shutting down...");
  console.log(`Total swaps detected: ${stats.totalSwaps}\n`);
  process.exit(0);
});


main();
```

#### Step 9: Test Your Monitor

1. Run  the Monitor

```javascript
node pool-monitor.js
```

2. Expected output:&#x20;

You'll see:

```javascript
🚀 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
================================================================================
```

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)
* `SLOT` - Happened at blockchain slot 376,205,017
* `TIME`- Your local time when you received this notification

The **SOL/USDC** pool typically has 140,000+ swaps per day, so you should see activity within seconds of starting the monitor.&#x20;

### Troubleshooting

1. Connection Issues:

```javascript
"Connection refused"
```

* Verify your ENDPOINT and TOKEN in pool-monitor.js
* Check your GetBlock dashboard, confirm the node is active
* Test your internet connection

2. 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[ the pool on Solscan](https://solscan.io/account/8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj) to verify it's active
* Check that your subscription was successful (you should see "✅ Subscription active")
* Try `CommitmentLevel.PROCESSED` for faster updates

3. Processing Errors:&#x20;

```javascript
Error processing transaction warnings
```

* These are normal. Occasionally, some transactions have non-standard formats
* Your monitor will skip these and continue running
* Failed transactions are automatically filtered out

### 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.&#x20;

#### Resources:

1. [Pool monitor repo](https://github.com/GetBlock-io/guides/tree/main/pool-monitor)
2. [GetBlock Yellowstone gRPC](/add-ons/yellowstone-grpc-api)<br>


# 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.fun](https://pump.fun/) is a Solana-based memecoin launchpad that uses a [bonding curve mechanism](https://www.coinbase.com/en-gb/learn/advanced-trading/what-is-a-bonding-curve) 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 ](https://raydium.io/swap/)or [PumpSwap](https://swap.pump.fun/) (Pump.fun's native DEX). This migration creates immediate trading opportunities for developers and traders who can detect these events in real-time.

{% hint style="info" %}
March 2025, Pump.fun introduced [PumpSwap](https://swap.pump.fun/), 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.
{% endhint %}

#### 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.

#### 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
4. **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

<figure><img src="/files/UiXnzkvqzM2GK48xC9R0" alt=""><figcaption></figcaption></figure>

#### Key Addresses

| Program                       | Address                                        |
| ----------------------------- | ---------------------------------------------- |
| **Pump.fun Program**          | `6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P`  |
| Pump.fun Migration Account    | `39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg` |
| **Raydium Liquidity Pool V4** | `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8` |

{% hint style="info" %}
The Pump.fun migration account manages both types of migrations.&#x20;

* For PumpSwap migrations, it calls `migrate` instruction on the Pump.fun program.&#x20;
* For Raydium migrations, it calls the `initialize2` instruction on Raydium's Liquidity Pool V4 program.
  {% endhint %}

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
* Distinguish between PumpSwap and Raydium migrations
* Handle reconnections and error scenarios
* Display migration data in a user-friendly format

### Prerequisites

* Basic understanding of JavaScript
* A GetBlock [account](https://account.getblock.io/sign-up)
* Node.js installed (v18 or higher)

### Technology Stack

* **Node.js**: JavaScript runtime environment for building server applications
* [**@solana/web3.js**:](https://npmjs.com/package/@solana/web3.js) Official Solana JavaScript SDK for blockchain interactions
* [**ws**](https://npmjs.com/package/ws): WebSocket client library for real-time connections
* [**dotenv**](https://npmjs.com/package/dotenv): Environment variable management for secure configuration

### Step 1: Project Initialization

1. Set up your project directory using this command:

```bash
# Create project folder
mkdir pumpfun-migrations-listener
cd pumpfun-migrations-listener

# Initialize npm
npm init -y
```

2. Install Dependencies:

```bash
npm install @solana/web3.js ws dotenv
```

3. Configure `package.json`:

```json
{
  "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"
}
}
```

* `"type": "module"` - Enables ES6 import/export syntax (required for modern JavaScript)
* `"main": "server.js"` - Specifies entry point of your application
* `"scripts"` - Defines shortcuts like `npm start`

### Get GetBlock's API Access Token

1. Log in to your [GetBlock account](https://account.getblock.io/)
2. On your dashboard, scroll and click on **Get Endpoint**
3. Select the **Solana Mainnet** network
4. Under API Interface, select **WebSocket (wss\://)**
5. Click on **Create** to get your endpoint

Your WebSocket endpoint will look like:

```bash
wss://go.getblock.us/<ACCESS_TOKEN>
```

6. Also get the HTTP endpoint for transaction fetching:
   * Return to the dashboard
   * Select **JSON-RPC (https\://)** under API Interface
   * Click **Create**

Your HTTP endpoint will look like:

```bash
https://go.getblock.us/<ACCESS_TOKEN>
```

7. Save both endpoints in a `.env` file in your project root:

```bash
GETBLOCK_WS_ENDPOINT=wss://go.getblock.us/<ACCESS_TOKEN>
GETBLOCK_HTTP_ENDPOINT=https://go.getblock.us/<ACCESS_TOKEN>
```

{% hint style="warning" %}
Keep your endpoints safe, as they contain your access token
{% endhint %}

### Project Structure

1. Create the following files to have a basic structure for your project:

```bash
pumpfun-migrations-listener/
├── server.js          # Main application logic
├── .env              # Environment variables (add to .gitignore)
├── .gitignore        # Git ignore file
└── package.json      # Project configuration
```

2. Create a `.gitignore` file:

```bash
node_modules/
.env
*.log
```

### Step 2: Server File Setup

{% hint style="success" %}
Your script will be written inside `server.js`
{% endhint %}

#### 1. Import Dependencies and Configuration

```javascript
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');
```

**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
* 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.&#x20;
  * `PUMPFUN_PROGRAM` - The Pump.fun program ID to detect PumpSwap migrations.

#### 2. Create the Migration Listener Class

```javascript
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;
  }
```

**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
* `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)

#### 3. Create an Interval check

```javascript
  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);
  }
```

**What this does:**

* The `start()` method kicks everything off. It checks if the Websocket is connected or not.&#x20;
* 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
  2. It provides statistics: runtime, total logs received, and migrations detected by type

{% hint style="success" %}
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.
{% endhint %}

#### 4. Create GetBlock Websocket Connection

```javascript
  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();
  }
```

**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` - 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.

#### 5. Subscribe to Migration Events

```javascript
  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));
  }
```

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)

#### 6. Handle Incoming Messages

```javascript
  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);
    }
  }
```

What this does:

* Parses incoming WebSocket messages
* Handles subscription confirmation and stores subscription ID
* Processes log notifications for migration detection

#### 7. Process Transaction Logs

```javascript
  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");
    }
  }
```

What this does:

* Checks transaction logs for migration keywords like: \
  ![](/files/YToOiFBGKpdf3TGSan5O)
* Skips failed transactions
* Fetches full transaction details when migration is detected

#### 8. Fetch Full Transaction Details

```javascript
  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);
    }
  }
```

What this does:

* Waits 1 second for the transaction to propagate
* Fetches complete transaction from Solana via HTTP
* Extracts and displays migration data

#### 9. Extract Migration Data

```javascript
  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;
  }
```

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
* Extracts relevant addresses (token, pool, LP mint)

#### 10. Display Migration Results

```javascript
  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');
    }
  }
```

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

#### 11. Handle Reconnections

```javascript
  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();
    }
  }
}
```

What this does:

* Implements exponential backoff for reconnections (2s, 4s, 8s, etc.)
* Caps reconnection delay at 30 seconds
* Exits after 10 failed reconnection attempts

#### 12. Initialize and Run

```javascript

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

What this does:

* Handles graceful shutdown on Ctrl+C
* Catches uncaught errors

### Step 4: Testing Your Listener

Start your migration listener:

```bash
npm start
```

Expected Output:

```
✅ 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...
```

#### Test 1: Real-time PumpSwap Migration

When a token migrates to PumpSwap:

```bash
📨 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
```

#### Test 2: Real-time Raydium Migration

When a token migrates to Raydium (rare):

```
📨 Log #7 - TX: 5yK8TqPAL2kNXj9bVZmF...
   ↳ 🎯 MIGRATION DETECTED!

🚀 ═══════════════════════════════════════════════════
   NEW PUMP.FUN → RAYDIUM MIGRATION DETECTED!
═══════════════════════════════════════════════════

Migration #1 (Raydium)

📊 Token Address:  8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj
...
```

#### Test 3: Check if alive

Every minute:

```
💓 Alive | Runtime: 0h 15m 30s | Logs: 23 | Raydium: 1 | PumpSwap: 18
```

### Troubleshooting

1\. Missing access token or Connection error

```javascript
//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
```

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.

3. 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 [Solscan](https://solscan.io/account/39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg)

### 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
* How to extract token addresses and pool information from transactions
* How to handle versioned Solana transactions
* How to implement robust reconnection logic

### Additional Resources

* [Solana Web3.js Documentation](https://solana-foundation.github.io/solana-web3.js/)
* [Raydium SDK](https://github.com/raydium-io/raydium-sdk)
* [Pump.fun Platform](https://pump.fun/)


# 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

#### Technology Stack:

* Node.js&#x20;
* [@triton-one/yellowstone-grpc](https://www.npmjs.com/package/@triton-one/yellowstone-grpc) - Official Yellowstone gRPC client
* [bs58](https://www.npmjs.com/package/bs58) - Base58 encoding for Solana addresses
* GetBlock's Dedicated Solana Node with Yellowstone add-on

### 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
* A Dedicated Solana Node subscription on GetBlock - Required for Yellowstone gRPC access

### Step 1: Set Up Your GetBlock Yellowstone Endpoint

#### 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.**"
* Under "Protocol", select Solana
* Set the network to Mainnet
* Click Get

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

#### 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:

{% tabs %}
{% tab title="Singapore" %}

```bash
https://go.getblock.asia/YOUR_ACCESS_TOKEN/
```

{% endtab %}

{% tab title="New York" %}

```bash
https://go.getblock.us/YOUR_ACCESS_TOKEN/
```

{% endtab %}

{% tab title="Frankfurt" %}

```bash
https://go.getblock.io/YOUR_ACCESS_TOKEN/
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
Save both pieces of information:

* Base Endpoint: <https://go.getblock.io> (or your region)
* Access Token: The alphanumeric token generated

You'll use these in your code to authenticate with GetBlock's Yellowstone service.
{% endhint %}

### Step 2: Initialize Your Project

1. Open your terminal and create a new directory:

```bash
mkdir sol-transfer-monitor
cd sol-transfer-monitor
```

2. Initialize Node.js Project

```bash
npm init -y
```

3. Install the required packages:

```bash
npm install @triton-one/yellowstone-grpc bs58@5.0.0 dotenv
```

3. Create a new file:

```bash
touch sol-transfer-monitor.js
```

3. Configure `package.json`:

```json
{
  "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"
  }
}

```

* `"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 `npm start`

### Project Structure

1. Create the following files to have a basic structure for your project:

```bash
pumpfun-migrations-listener/
├── sol-transfer-monitor.js          # Main application logic
├── .env              # Environment variables (add to .gitignore)
├── .gitignore        # Git ignore file
└── package.json      # Project configuration
```

2. Create a `.gitignore` file:

```bash
node_modules/
.env
*.log
```

### Step 3: Start Building Your Monitor

{% hint style="info" %}
You'll build everything in a single file called `sol-transfer-monitor.js.`
{% endhint %}

#### Import Dependencies

```bash
import Client from "@triton-one/yellowstone-grpc";
import { CommitmentLevel } from "@triton-one/yellowstone-grpc";
import bs58 from "bs58";
import { config } from "dotenv";
config();

```

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` - 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

#### Add Your GetBlock Configuration

```javascript
const ENDPOINT = "https://go.getblock.io";  // Your region's endpoint
const TOKEN = process.env.GETBLOCK_TOKEN;           // Your generated token
```

What this does: Stores your GetBlock credentials for authenticating your connection.

{% hint style="warning" %}
If you chose a different region during setup, use that base URL instead (e.g., <https://go.getblock.us> or <https://go.getblock.asia>).
{% endhint %}

#### Add Solana System Program Constants

```javascript
// 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
```

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.).

#### Add Statistics Tracker

```js
// Statistics Tracking
let stats = {
  startTime: Date.now(),
  totalTransfers: 0,
  totalVolume: 0,
  largestTransfer: 0,
  largestTransferTx: null
};
```

What this does:&#x20;

* Creates an object to track key metrics about the transfers you're monitoring. It records:&#x20;
  * When the monitor started
  * How many high-value transfers have been detected
  * the cumulative volume of all transfers
  * information about the largest transfer seen so far.

### Step 4: Build Utility Functions

Now you'll add helper functions to format data and display results.

#### Add SOL Formatter

```javascript
function formatSOL(lamports) {
  return (lamports / 1_000_000_000).toFixed(4);
}
```

What this does:&#x20;

* 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".

#### Add Display Function

```javascript
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");
}
```

\
What this does:&#x20;

* 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).&#x20;
* Then it converts the amount from lamports to SOL and prints out all the details, including sender, recipient, transaction signature, and slot number.&#x20;
* Finally, it includes clickable Solscan explorer links so you can investigate the transaction, sender, and recipient in more detail.

### Step 5: Build the Transfer Parser

Now you'll create the function that extracts transfer details from instruction data.

#### Add Transfer Instruction Parser

```javascript
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;
  }
}
```

\
What this does:&#x20;

* Extracts the transfer amount and account addresses from a System Program instruction.

{% hint style="success" %}
If anything goes wrong during parsing (malformed data, missing accounts, etc.), it catches the error and returns null.
{% endhint %}

### Step 6: Build the Main Monitor Function

Now you'll create the core function that connects to GetBlock and processes blockchain data.

#### Part A: Start the Function and Connect

```javascript
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();
```

What this does:&#x20;

* 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.&#x20;
* The `subscribe()` method returns a stream object that handles both sending requests to GetBlock and receiving blockchain data.

#### Part B: Configure Subscription

```javascript
 const request = {
        accounts: {},
        slots: {},
        transactions: {
          sol_transfers: {
            accountInclude: [SYSTEM_PROGRAM],
            accountExclude: [],
            accountRequired: []
          }
        },
        transactionsStatus: {},
        entry: {},
        blocks: {},
        blocksMeta: {},
        commitment: CommitmentLevel.CONFIRMED,
        accountsDataSlice: [],
        ping: undefined
      };

```

What this does:&#x20;

* Builds the subscription request that tells GetBlock exactly what blockchain data you want to receive.   &#x20;
  * It filters sol\_transfers
  * Send transactions that interact with the system
  * Only receive transactions that are CONFIRMED&#x20;

#### Part C: Handle Incoming Data

```javascript
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;

```

\
What this does:&#x20;

* Sets up an event handler that processes every message GetBlock sends through the stream.

#### Part D: Process Instructions

```javascript
// 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}`);
}
});

```

What this does:&#x20;

* Loops through each instruction in the transaction to find and process SOL transfers.

#### Part E: Handle Stream Events

```javascript
stream.on("error", (error) => {
        console.error(`Stream error: ${error.message}`);
        reject(error);
      });
      
      stream.on("end", () => resolve());
      stream.on("close", () => resolve());

```

What this does:&#x20;

* Sets up handlers for stream connection issues.&#x20;
* 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.&#x20;
* The "end" and "close" events indicate the stream has been terminated gracefully, so it resolves the Promise normally.

#### Part F: Send Subscription Request

```javascript
stream.write(request, (err) => {
        if (err) {
          reject(err);
        } else {
          console.log("Subscription active - monitoring blockchain...\n");
        }
      });
      
    } catch (error) {
      reject(error);
    }
  });
}

```

\
What this does:&#x20;

* Send your subscription request to GetBlock to activate the stream.&#x20;
* Once the request is sent successfully, it confirms that monitoring is active.&#x20;
* 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.

### Step 7: Add Execution Code

Finally, add the code to run your monitor and handle shutdown.&#x20;

#### Add Main Execution Function

```javascript
async function main() {
  try {
    await monitorHighValueTransfers();
  } catch (error) {
    console.error("Monitor crashed:", error.message);
    console.log("Restarting in 5 seconds...");
    setTimeout(main, 5000);
  }
}
```

\
What this does:&#x20;

* 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.

#### Add Shutdown Handler

```javascript
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);
});
```

\
What this does:&#x20;

* 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.

#### Start the Monitor

```javascript
main();
```

What this does:&#x20;

* Run everything. This is the last line of your sol-transfer-monitor.js file and triggers the execution of your monitor.

### TestStep 8: Tets Your Monitor

1\. Start the Monitor

```bash
npm start
```

2. Expected Output:

```bash
> sol-transfer-monitor@1.0.0 start
> node sol-transfer-monitor.js

[dotenv@17.2.3] 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
```

### Troubleshooting

1. Permission denied:

```javascript
Stream error: 7 PERMISSION_DENIED: RBAC: access denied
Monitor crashed: 7 PERMISSION_DENIED: RBAC: access denied
```

This means that your access token is missing or incomplete, or you are using the wrong Base URL.&#x20;

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)

### 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
* Parses SOL transfer amounts and addresses
* Filters by minimum transfer threshold
* Displays formatted results with links
* Tracks cumulative statistics
* Handles errors and auto-reconnects

#### Additional Resources

* [SOL Transfer Monitor Repo](https://github.com/GetBlock-io/guides/tree/main/sol-transfer-monitor)
* [GetBlock Solana RPC Node](https://getblock.io/chains/solana)
* [GetBlock Yellowstone gRPC](/add-ons/yellowstone-grpc-api)
* [Yellowstone gRPC GitHub](https://github.com/rpcpool/yellowstone-grpc)

<br>


# 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.

### 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.&#x20;

{% embed url="<https://youtu.be/EZqRjnCKS6o?si=OaWn35nlo0FMm6e8>" %}

The x402 protocol brings the [HTTP 402 "Payment Required" status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/402) 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.

#### How it works

1. Frank adds "payment required" to his API endpoints
2. His client requests a protected resource,&#x20;
3. The server responds with `402 Payment Required` along with payment details.
4. The client signs a payment authorisation
5. He/she retries the request and receives the data.&#x20;

All of this happens in seconds, without traditional payment infrastructure.

| Traditional API monetization requires              | With x402                                                      |
| -------------------------------------------------- | -------------------------------------------------------------- |
| 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          |
| Subscription tiers and billing cycles              | **Instant micropayments** — Charge per request                 |
| <p></p><p>Fraud prevention and rate limiting</p>   | **Built-in rate limiting** — Users only call what they pay for |
| Transaction or gas fee                             | Gasless fee                                                    |

#### Components of x402

The x402 ecosystem consists of three main components, which are:&#x20;

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.

{% hint style="warning" %}
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.
{% endhint %}

2. **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.

{% hint style="warning" %}
Servers do not need to manage client identities or maintain session state. Verification and settlement are handled per request.
{% endhint %}

3. **Facilitators:**&#x20;

The facilitator is an optional but recommended service that verifies and settles payment between clients and servers.&#x20;

#### Architecture Overview

{% @mermaid/diagram content="flowchart TB
subgraph Client\["🖥️ Client (dApp)"]
A\[User connects wallet]
B\[Request API endpoint]
C\[Sign payment with MetaMask]
end

```
subgraph Server["⚙️ Server (Express + x402)"]
    D[Receive request]
    E{Payment header<br/>present?}
    F[Return 402 + payment requirements]
    G[Verify with Facilitator]
    H{Payment<br/>valid?}
    I[Fetch from GetBlock]
    J[Return data]
    K[Return 402 error]
end

subgraph External["🌐 External Services"]
    L[Facilitator<br/>PayAI Network]
    M[GetBlock API]
end

A --> B
B --> D
D --> E
E -->|No| F
F --> C
C --> B
E -->|Yes| G
G --> L
L --> H
H -->|Yes| I
H -->|No| K
I --> M
M --> J
J --> Client" %}
```

**Key Components Explained:**

| Component            | Role                                                                                     | SDK to Use                                                                                                                                                          |
| -------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Client (dApp)**    | Browser app with wallet connection. Uses `@x402/fetch` to handle payments automatically. | <ul><li><a href="https://www.npmjs.com/package/@x402/evm">@x402/evm</a></li><li><a href="https://www.npmjs.com/package/@x402/fetch">@x402/fetch</a></li></ul>       |
| **Server (Express)** | Your API server. Uses `@x402/express` middleware to protect routes and define prices.    | <ul><li><a href="https://www.npmjs.com/package/@x402/core">@x402/core</a></li><li><a href="https://www.npmjs.com/package/@x402/express">@x402/express</a></li></ul> |
| **Facilitator**      | Third-party service that verifies payment signatures and settles USDC transfers.         | <ul><li><https://x402.org/facilitator></li><li><https://facilitator.payai.network></li></ul>                                                                        |

#### 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
* **Data Providers** — Sell real-time data feeds with per-request pricing
* **Blockchain Services** — Offer RPC access, indexing, or analytics with micropayments

#### 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
4. **Premium API Access** — Charge for rate-limited or enhanced API endpoints
5. **Decentralized CDN** — Pay nodes for bandwidth and storage per request

#### 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
* **Payment:** USDC on Base Sepolia testnet

**Endpoints you'll create:**

| Endpoint                    | Price       | Description                          |
| --------------------------- | ----------- | ------------------------------------ |
| `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            |

#### Prerequisites

* Node.js 18+
* MetaMask wallet
* Base Sepolia USDC (from [Circle Faucet](https://faucet.circle.com/))
* [GetBlock API key](https://getblock.io/) (free tier available)
* Basic knowledge of JavaScript/Express

### A. Project Setup

#### Step 1: Create Project Directories

```bash
mkdir getblock-x402-dapp
cd getblock-x402-dapp
mkdir server client
```

#### Step 2: Initialize Server Package

```bash
cd server
npm init -y
```

#### Step 3: Install Dependencies

```bash
npm install express cors axios dotenv @x402/core @x402/evm @x402/express
```

**Dependency Overview:**

| Package                                                        | Purpose                                                   |
| -------------------------------------------------------------- | --------------------------------------------------------- |
| [`express`](https://www.npmjs.com/package/express)             | Web server framework                                      |
| [`cors`](https://www.npmjs.com/package/cors)                   | Cross-origin resource sharing                             |
| [`axios`](https://www.npmjs.com/package/ax)                    | HTTP client for GetBlock API                              |
| [`dotenv`](https://www.npmjs.com/package/dotenv)               | Environment variable management                           |
| [`@x402/core`](https://www.npmjs.com/package/@x402/core)       | x402 core utilities (Resource Server, Facilitator Client) |
| [`@x402/evm`](https://www.npmjs.com/package/@x402/evm)         | EVM blockchain support (Base, Ethereum)                   |
| [`@x402/express`](https://www.npmjs.com/package/@x402/express) | Express middleware for payment protection                 |

#### Step 4: Configure package.json

Update `server/package.json`:

<pre class="language-json"><code class="lang-json">{
  "name": "getblock-x402-server",
  "version": "1.0.0",
  "description": "",
<strong>  "main": "server.js",
</strong>  "scripts": {
    "test": "echo \"Error: no test specified\" &#x26;&#x26; exit 1",
<strong>    "start": "node server.js",
</strong>  },
  "keywords": ["x402", "getblock"]serv,
  "author": "",
  "license": "ISC",
<strong>  "type": "module",
</strong>  "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"
  }
}
</code></pre>

#### Folder Structure

Create the following project structure:

```bash
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)
```

### Backend: Express Server with x402

#### Step 1: Environment Configuration

Create `server/.env`:

```bash
# 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
```

{% hint style="info" %}
Replace `0xYourWalletAddressHere` with your actual MetaMask wallet address. This is where you'll receive USDC payments.
{% endhint %}

#### Step 2: Create the Server

Create `server/server.js` and add the following code:

{% code title="server/server.js" overflow="wrap" %}

```javascript
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`);
  })
});
```

{% endcode %}

### Frontend: Vanilla JS dApp

Create `client/index.html` and add the following code:

{% code title="client/index.html" overflow="wrap" %}

```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/viem@2.21.0";
      import { baseSepolia } from "https://esm.sh/viem@2.21.0/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>
```

{% endcode %}

### Running the Application

#### Step 1: Start the Server

```bash
cd server
npm start
```

You should see:

```
📋 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
```

#### Step 2: Access the Frontend

Open your browser and navigate to:

```bash
http://localhost:4021
```

Your frontend should look like this:<br>

<figure><img src="/files/O1fXrYOaCbrpuw2n8ojb" alt=""><figcaption></figcaption></figure>

1. Connect your wallet
2. Select any of the endpoints you want to access
3. Sign the request

<figure><img src="/files/CJAhHMoPWpCbIgEOtj2v" alt=""><figcaption></figcaption></figure>

4. The payment is then verified, scroll down to see the result

<figure><img src="/files/91DOlXAXE16eva5Oeb3V" alt=""><figcaption><p>Result of the latest block number</p></figcaption></figure>

### 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:

```javascript
userAddress = getAddress(accounts[0]);
```

2. **CORS Errors:** This means the server not configured for x402 headers. Ensure CORS middleware includes x402 headers:

```javascript
allowedHeaders: ["X-PAYMENT", ...],
exposedHeaders: ["X-PAYMENT-REQUIRED", ...],
```

3. **"Facilitator does not support scheme":** This mean the facilitator is unreachable or doesn't support your network. To resolve this:

&#x20;    i. Check internet connection

&#x20;    ii. Try an alternative facilitator: `https://facilitator.payai.network`

&#x20;    iii. Verify you're using the correct network ID: `eip155:84532`

4. "**Facilitator Connectivity Issues**"

If the default facilitator is down, you can try:

```javascript
const facilitatorClient = new HTTPFacilitatorClient({
  url: "https://x402.org/facilitator", // Alternative facilitator
});
```

5. **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

#### 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
* Error details

### Resources

* [x402 Protocol Docs](https://x402.gitbook.io/x402)
* [GetBlock Account Dashboard](https://account.getblock.io)
* [Circle Faucet](https://faucet.circle.com/)
* [Base Sepolia Explorer](https://sepolia.basescan.org/)
* [x402 + GetBlock dApp Repo](https://github.com/GetBlock-io/guides/tree/main/getblock-x402-dapp)

### 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.


# 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.&#x20;

***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.***&#x20;

### 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
* A series of Flashblocks can be combined to recreate a full block

{% hint style="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.
{% endhint %}

### 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
4. **CEX-like experience on DEXs**: Trading feels instant, not sluggish

### 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)
* Displays real-time blockchain activity

This forms the foundation for building trading bots, monitoring tools, or any application that needs ultra-low-latency blockchain data.

## Understanding the Flashblock Data Structure

Before diving into code, let's understand what data you'll receive. Each Flashblock message contains three main components:

### 1. The Root Structure

```go
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
}
```

The `Index` field tells you which of the 10 Flashblocks within a full block you're receiving (0 through 9).

### 2. BlockDiff — The Block Changes

```go
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"`
}
```

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
* **`GasUsed`**: Total gas consumed by transactions in this Flashblock

### 3. Metadata — Balances and Receipts

```go
type Metadata struct {
    BlockNumber        uint64             `json:"block_number"`
    NewAccountBalances map[string]string  `json:"new_account_balances"`
    Receipts           map[string]Receipt `json:"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
* **`Receipts`**: Transaction receipts with execution results and event logs

### 4. Receipts — Transaction Results

```go
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"`
}
```

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.

## Prerequisites

Before we begin, make sure you have:

* **Go 1.21+** installed ([download here](https://go.dev/dl/))
* Basic understanding of WebSockets and blockchain concepts
* A terminal/command line environment

### Dependencies

This application uses two external packages:

1. [WebSocket client library](https://github.com/gorilla/websocket)
2. [Brotli decompression](https://github.com/andybalholm/brotli) (Flashblocks are compressed)

## Project Setup

1. Create a new directory for your project and initialize the Go module:

```bash
mkdir flashblocks-listener
cd flashblocks-listener
go mod init flashblocks-listener
```

2. Install the required dependencies:

```bash
go get github.com/gorilla/websocket
go get github.com/andybalholm/brotli
```

3. Your `go.mod` file should look like this:

```go
module flashblocks-listener

go 1.23.0

require (
    github.com/andybalholm/brotli v1.2.0
    github.com/gorilla/websocket v1.5.3
)
```

## Building the Listener

1. Create `main.go` and start with the package and imports:

```go
package main

import (
    "bytes"
    "encoding/json"
    "flag"
    "fmt"
    "io"
    "log"
    "os"
    "os/signal"
    "syscall"

    "github.com/andybalholm/brotli"
    "github.com/gorilla/websocket"
)
```

This imports standard library packages for JSON handling, logging, and signal management, plus our two external dependencies.

2. Define WebSocket endpoints and the data structures described earlier:

```go
const (
    mainnetWSURL = "wss://mainnet.flashblocks.base.org/ws"
    sepoliaWSURL = "wss://sepolia.flashblocks.base.org/ws"
)
```

Now define all the data structures:

```go
// 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"`
}
```

The `GetData()` and `GetType()` helper methods on `Receipt` let us work with receipts without worrying about whether they're EIP-1559 or Legacy format.

3. Implement the main routine: flag parsing, selecting the endpoint, connecting via WebSocket, and setting up message processing and graceful shutdown.

{% code overflow="wrap" %}

```go
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)
        }
    }
}
```

{% endcode %}

This covers:

* Flag parsing for `-network`
* WebSocket connection via gorilla/websocket
* Signal handling for graceful shutdown
* Message loop reading text or binary (Brotli) messages

4. Flashblock messages are typically Brotli-compressed. Decompress them with:

```go
func decodeBrotli(data []byte) ([]byte, error) {
    reader := brotli.NewReader(bytes.NewReader(data))
    return io.ReadAll(reader)
}
```

5. Unmarshal JSON into structs and print a readable summary.

```go
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)
}
```

Pretty-print the flashblock:

```go
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:]
}
```

This output shows:

* Flashblock index (0-9)
* Block number and hash
* Gas usage and roots
* Transaction list (truncated hashes)
* Balance update count
* Receipt summaries

## Running the Listener

1\. Build and Run

```bash
# Build the application
go build -o flashblocks-listener

# Run on mainnet (default)
./flashblocks-listener

# Run on Sepolia testnet
./flashblocks-listener -network=sepolia
```

2. Expected Output

When running, you'll see Flashblocks streaming in real-time:

{% code overflow="wrap" %}

```bash
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
```

{% endcode %}

You'll see new Flashblocks appear approximately every 200 milliseconds.

3. Shutting Down

Press `Ctrl+C` to stop the listener. It will send a proper WebSocket close message before exiting:

```bash
^C2026/01/23 12:06:59 Received signal interrupt, shutting down...
```

## Extending for Trading Applications

Now that you have the basic listener working, here are some ways to extend it for trading:

### 1. Filter Transactions by Address

Monitor specific addresses (your wallet, a DEX router, etc.):

```go
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...
            }
        }
    }
}
```

### 2. Detect Swap Events

Watch for Uniswap V2/V3 swap events by checking the first topic (event signature):

```go
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)
                }
            }
        }
    }
}
```

### 3. Track Balance Changes

Monitor when specific addresses receive or send ETH:

```go
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)
        }
    }
}
```

## 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

2. **Rate Limits**

The public endpoints (`wss://mainnet.flashblocks.base.org/ws`) are rate-limited. For production applications:

* Use a node provider ([GetBlock](https://account.getblock.io)) with Flashblocks support
* Consider running your own Flashblocks-aware node

3. **Handling Disconnections**

In production, add reconnection logic:

{% code overflow="wrap" %}

```go
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)
}
```

{% endcode %}

## Complete Code

Here's the full `main.go` file:

<details>

<summary>Full Code</summary>

{% code title="main.go" overflow="wrap" %}

```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:]
}
```

{% endcode %}

</details>

## 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

### Resources

* [Base Flashblocks Documentation](https://docs.base.org/chain/flashblocks)
* [Base Blog: Flashblocks Deep Dive](https://blog.base.dev/flashblocks-deep-dive)
* [Base Flashblocks Listener Repo](https://github.com/GetBlock-io/guides/tree/main/base-flashblocks-listener)
* [Flashbots Documentation](https://docs.flashbots.net/)
* [GetBlock Dashboard](https://account.getblock.io/)


# 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.&#x20;

In the blockchain context, AI agents can:

* Execute token swaps when prices hit targets
* Rebalance portfolios across DeFi protocols
* Monitor wallets and automate transfers
* Mint NFTs based on social media triggers

{% embed url="<https://youtu.be/2AQzYFHsZY0?si=xSn4FlRHOrXjua-G>" %}

### 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.

### 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.&#x20;

***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:***

<figure><img src="/files/NYlIw5k14hNwKzsATi28" alt=""><figcaption></figcaption></figure>

### Prerequisites

You must have the following:

1. [Node.js v23+](https://nodejs.org/en/download) is installed on your laptop
2. Solana Wallet, e.g., [Phantom](https://phantom.com/), [Solflare](https://www.solflare.com/), [MetaMask](https://metamask.io/), etc
3. API keys such as [OpenAI](https://platform.openai.com/api-keys) (for the LLM) and Solana Devnet RPC URL (Optional: [GetBlock Solana RPC URL](https://account.getblock.io/))
4. Package manager installed on your laptop(Preferrably [pnpm](https://pnpm.io/installation))

{% hint style="info" %}
Devnet RPC URL is used for this guide. If you want to interact with Mainnet, then make use of [GetBlock Solana RPC URL](https://account.getblock.io/)
{% endhint %}

## Project Setup

{% stepper %}
{% step %}
Create a new project directory

```bash
mkdir solana-ai-agent
cd solana-ai-agent
```

{% endstep %}

{% step %}
Install the dependencies:

{% code overflow="wrap" %}

```bash
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
```

{% endcode %}

<details>

<summary>Packages Description</summary>

| **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  | Lets the agent send, receive, and check balances of SPL tokens (USDC, BONK) |
| @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           |

</details>
{% endstep %}

{% step %}
Create a `.env` file and add the following details:

{% code overflow="wrap" %}

```bash
RPC_URL=https://api.devnet.solana.com
PRIVATE_KEY=your_wallet_private_key
OPENAI_API_KEY=your_openai_secret_key
```

{% endcode %}
{% endstep %}

{% step %}
Create `agent.ts` file, this is where you will be building your AI agent
{% endstep %}

{% step %}
Import your dependencies:

{% code overflow="wrap" %}

```typescript
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();
```

{% endcode %}
{% endstep %}

{% step %}
Initialize your Agent

{% code overflow="wrap" %}

```typescript
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,
  });
}
```

{% endcode %}

This:

* Connect the AI agent to Solana Devnet and access your wallet to perform actions
* Empower the agent with tools for swapping(`jupiter()`), 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.
  {% endstep %}

{% step %}
Create Interface for interaction:&#x20;

{% code overflow="wrap" %}

```typescript
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);
```

{% endcode %}

This defines an interactive CLI chat loop between you and the AI agent and also logs any errors.
{% endstep %}

{% step %}
Run the agent using this command

{% code overflow="wrap" %}

```bash
npx tsx agent.ts
```

{% endcode %}

You can make any request in any language, as seen below:

{% code overflow="wrap" %}

```bash
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. Пожалуйста, проверьте правильность адреса кошелька и попробуйте снова. 

```

{% endcode %}

You can see that it interprets your natural language, uses the tools plugin to get the right response for it&#x20;
{% endstep %}
{% endstepper %}

#### Extend AI Agent capacity

&#x20;Improve the capacity of your agent by adding more tools:

1. Mint NFT:

<pre class="language-typescript" data-overflow="wrap"><code class="lang-typescript"><strong>import { crossmint } from "@goat-sdk/crossmint";
</strong>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(),
<strong>      crossmint()
</strong>    ],
  });
}
/// rest of code (readline interface and agent.invoke loop)

</code></pre>

### 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.

### 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.

### Additional Resources

1. [GOAT Docs](https://github.com/goat-sdk/goat)
2. [Langchain Docs](https://docs.langchain.com/)
3. [OpenAI Platform](https://platform.openai.com/)
4. [GetBlock Account Dashboard](https://account.getblock.io/)
5. [Solana Agent Guide Repo](https://github.com/GetBlock-io/guides/tree/main/Solana-Agent)


# 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.*&#x20;

### What Are Priority Fees?

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:

```bash
Priority Fee = Compute Units × Compute Unit Price
```

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

### 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                        | Extreme priority            |
| Network congestion detected                    | Increase from baseline      |
| Time-sensitive operations                      | High priority minimum       |

{% hint style="info" %}
During normal network conditions, transactions land fine without priority fees. Only add them when speed matters or when the network is congested.
{% endhint %}

### 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

{% hint style="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.
{% endhint %}

Default behavior:

* Without `SetComputeUnitLimit`: Solana defaults to 200,000 CU per instruction
* Without `SetComputeUnitPrice`: No priority fee is charged (only base fee)

### Prerequisites

You must have the following:

1. [Node.js v23+](https://nodejs.org/en/download) is installed on your laptop
2. Solana Wallet, e.g., [Phantom](https://phantom.com/), [Solflare](https://www.solflare.com/), [MetaMask](https://metamask.io/), etc
3. Solana Devnet RPC URL (Optional: [GetBlock Solana RPC URL](https://account.getblock.io/))
4. A package manager installed on your laptop(Preferrably npm)

{% hint style="info" %}
Devnet RPC URL is used for this guide. If you want to interact with the Mainnet, then make use of [GetBlock Solana RPC URL](https://account.getblock.io/)
{% endhint %}

## Project Setup

{% stepper %}
{% step %}
Create a new project directory

{% code overflow="wrap" %}

```bash
mkdir priority-fees
cd priority-fees
```

{% endcode %}
{% endstep %}

{% step %}
Install the dependencies:

```bash
npm install @solana/web3.js dotenv base58
```

<details>

<summary>Package Description</summary>

| Package         | Description                                                       |
| --------------- | ----------------------------------------------------------------- |
| @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        |

</details>
{% endstep %}

{% step %}
Create a `.env` file and add the following details:

{% code overflow="wrap" %}

```typescript
RPC_URL=https://api.devnet.solana.com //GETBLOCK_API_KEY=your_getblock_api
PRIVATE_KEY=your_wallet_private_key
RECIPIENT_WALLET=the_receiver_wallet
```

{% endcode %}
{% endstep %}

{% step %}
Create `index.ts` file, this is where you will be writing your script
{% endstep %}

{% step %}
Import your dependencies and load the `.env` variables:

{% code overflow="wrap" %}

```typescript
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;
```

{% endcode %}
{% endstep %}

{% step %}
Build the Transfer Instruction

{% code overflow="wrap" %}

```typescript
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,
  });
```

{% endcode %}

This creates the instruction to move SOL. `LAMPORTS_PER_SOL` (1,000,000,000) converts from SOL to the smallest unit (lamports).&#x20;
{% endstep %}

{% step %}
&#x20;Simulate to Estimate Compute Units

{% code overflow="wrap" %}

```typescript
 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,
 );
```

{% endcode %}

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.
* 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.
  {% endstep %}

{% step %}
Get a Dynamic Priority Fee and calculate the total cost

{% code overflow="wrap" %}

```typescript
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)`,
);
```

{% endcode %}

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.
{% endstep %}

{% step %}
Build the final transaction

{% code overflow="wrap" %}

```typescript
  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);
```

{% endcode %}

This:&#x20;

* 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.
* Decodes private key, creates wallet keypair, parses recipient address, calls function with `0.001 SOL`.

<details>

<summary>Complete Working Example</summary>

Here's a full example that puts everything together:

{% code title="index.ts" overflow="wrap" %}

```typescript
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);

```

{% endcode %}

</details>
{% endstep %}

{% step %}
Run the code using this command

{% code overflow="wrap" %}

```bash
npx ts-node index.ts
```

{% endcode %}
{% endstep %}

{% step %}
Result

You will get a response like this:\
This should show the estimated CU, the total priority fee used, and the transaction hash

{% code overflow="wrap" %}

```bash
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
```

{% endcode %}
{% endstep %}
{% endstepper %}

## Best Practices

1. Never hardcode compute unit limits. Simulation catches errors before they cost you fees:

```typescript
// 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
```

2. Network conditions change. Fetch recent fees instead of using static values:

```typescript
// 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
```

### 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

#### Additional Resources

* [Solana Core Fees](https://solana.com/docs/core/fees)
* [GetBlock Dashboard](https://account.getblock.io)
* [Solana Devnet Explorer](https://solscan.io/?cluster=devnet)
* [Priority fee Full Code repository](https://github.com/GetBlock-io/guides/blob/main/priority-fees)
* [Solana Compute Budget](https://solana.com/docs/core/fees/compute-budget)


# 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.&#x20;

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.

### 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

### Available Extensions

Token Extensions are divided into two categories:

#### 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                                                                       | [Paxos USDP](https://www.paxos.com/)                  |
| Transfer Fees               | The ability to charge fees at the protocol level; fees are withheld from recipient                                | Permanent royalties, publisher fees, transaction fees                                                                    | [BERN](https://www.bonkcoin.com/) (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)](https://www.wen.tools/)                   |
| Metadata & Metadata Pointer | Establishes verifiable links between tokens and metadata directly on mint accounts                                | Token verification, accounts receivable attribution                                                                      | [WEN (WNS)](https://www.wen.tools/)                   |
| 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 USDP](https://paxos.com/)                      |
| 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)](https://www.wen.tools/)                   |
| Pausable Mint               | Allows pausing all token operations globally                                                                      | Emergency stops, maintenance windows                                                                                     |                                                       |

#### 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                    |
| CPI Guard       | Protects against certain cross-program invocation attacks | Security for high-value accounts                          |

{% hint style="warning" %}

### Extension Compatibility

Not all extensions can be combined. Some conflicts include:<br>

* 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
  {% endhint %}

### Next Steps

* [Learn about how to create and Mint token with Token-2022 and GetBlock Solana RPC](/guides/what-are-token-extensions/how-to-create-tokens-with-metadata-on-solana-using-token-2022)


# 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 [token extension](/guides/what-are-token-extensions), in this guide, you will be learning how to create a simple token with metadata extension

### Prerequistics

Before you begin, ensure you have the following:

1. Node installed on your PC, preferably v20+
2. A package manager such as npm or yarn
3. Solana Wallet, e.g., [Phantom](https://phantom.com/), [Solfare](https://www.solflare.com/), or [Metamask](https://metamask.io/)
4. Solana Access token from [GetBlock](https://account.getblock.io/)&#x20;
5. Basic knowledge of JavaScript and Typescript
6. Basic understanding of Solana (wallets, transactions, lamports)

### Set up your environment&#x20;

{% stepper %}
{% step %}
Create a new project directory:

<pre class="language-bash"><code class="lang-bash">mkdir token-2022-tutorial
<strong>cd token-2022-tutorial
</strong>npm init -y
</code></pre>

{% endstep %}

{% step %}
Install required dependencies:

```bash
npm install @solana/web3.js @solana/spl-token @solana/spl-token-metadata dotenv
```

{% endstep %}

{% step %}
Create a `.env` file and add the following:

{% code title=".env" overflow="wrap" %}

```js
RPC_URL=https://api.devnet.solana.com //or mainnet URL
PRIVATE_KEY=your-wallet-private-key
```

{% endcode %}
{% endstep %}
{% endstepper %}

### Configuration File

Create `config.js` file and add the following:

{% code title="config.js" overflow="wrap" %}

```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};
```

{% endcode %}

### Create a Token with Metadata Extension

{% stepper %}
{% step %}
Create a new file `index.js` . This will serve as your working file
{% endstep %}

{% step %}
Import all the dependencies:

{% code overflow="wrap" %}

```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";
```

{% endcode %}
{% endstep %}

{% step %}
Generate an account for the mint address

{% code overflow="wrap" %}

```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());
```

{% endcode %}
{% endstep %}

{% step %}
Define the token metadata:

{% code overflow="wrap" %}

```js
 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"]],
 };
```

{% endcode %}
{% endstep %}

{% step %}
Calculate the metadata space and rent needed for the mint account:

{% code overflow="wrap" %}

```js
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,
);
```

{% endcode %}

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.
{% endstep %}

{% step %}
Define the structure of the transaction:

{% code overflow="wrap" %}

```js
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);
});
```

{% endcode %}

This creates the mint address, initializes the mint, metadata, points to the mint itself as the metadata account, and sends the transaction.

<details>

<summary>Complete code</summary>

{% code title="index.js" overflow="wrap" %}

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

```

{% endcode %}

</details>
{% endstep %}

{% step %}
Run the code using this command:

{% code overflow="wrap" %}

```bash
node index.js
```

{% endcode %}
{% endstep %}

{% step %}
Result:&#x20;

{% code overflow="wrap" %}

```bash
=== 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/
```

{% endcode %}

Verify on the [Solscan](https://solscan.io/token/BVwyGVpUNUL7eYVqbMtzgbinTiUgd3tNXsgxfxoAQaWe?cluster=devnet):&#x20;

<figure><img src="/files/jFE9162SWwg9uaHbMfaq" alt="Solscan verification"><figcaption></figcaption></figure>
{% endstep %}
{% endstepper %}

### 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.&#x20;

{% hint style="info" %}
This guide uses Solana Devnet. If you want to make use of Mainnet, go to your [account dashboard ](https://account.getblock.io/)and get a Solana mainnet access token.&#x20;
{% endhint %}

#### Additional Resources

1. [Token Metadata Interface](https://github.com/solana-program/token-metadata/tree/main)
2. [Solana Token](https://solana.com/docs/tokens)
3. [What are Token Extensions](/guides/what-are-token-extensions)
4. [Solana program](https://github.com/solana-program)
5. [GetBlock Account Dashboard](https://account.getblock.io/)
6. [Create Token With Metadata Repo](https://github.com/GetBlock-io/guides/blob/main/token-2022-tutorial/create-token-with-metadata.js)


# How To Optimize Solana Transactions With Jito Bundles

Learn how to optimize your Solana transactions with Jito bundles and priority fees

Though Solana is the fastest blockchain at the moment, it is still subject to delays. For example, in Dec, 2024, the day [PENGU (memecoin)](https://www.binance.com/en-NG/square/post/17720434201329) launched, thousands of Superteam members received an airdrop, and there was heavy network congestion. Hence, the transaction was not easy, and the gas fee went up.&#x20;

During this congestion, block production can't always keep up. The network's capacity (measured in Transactions Per Second) can become saturated. This time, transactions with the tips or higher gas prices are usually considered.&#x20;

To address this issue, Jito Labs, a builder of high-performance MEV infrastructure for Solana, operates a Solana validator client that enables a unique feature called [Bundles](https://docs.jito.wtf/lowlatencytxnsend/#what-are-bundles).

*In this guide, you'll learn:*

* *What Jito bundles are,*&#x20;
* *The comparison between normal transactions and using Jito bundles,*&#x20;
* *A walkthrough on how to implement them in your dApp*
* *Best practices.*

### What Are Jito Bundles?

Jito bundles are groups of transactions (up to 5) that are executed **sequentially** and **atomically**. They're submitted directly to Jito's Block Engine, which [auctions](https://docs.jito.wtf/lowlatencytxnsend/#what-is-the-auction) block space to the highest-tipping bundles and forwards winning bundles to Jito-Solana validators.

Key properties:

* **Atomic Execution**: All transactions in the bundle execute together, or none do. No partial failures.
* **Guaranteed Ordering**: Transactions execute in the exact sequence you specify.
* **Private Submission**: Bundles aren't visible in the public mempool until they're included in a block. This prevents MEV attacks.
* **Tip-Based Priority**: Instead of priority fees, you pay a "tip" directly to the validator who includes your bundle.

{% hint style="info" %}
The tip is set as an instruction and add to the last transaction
{% endhint %}

#### How Jito Bundles Work

1. You create signs and bundle all the transactions via dApp
2. Your dApp sends this bundle transaction to the Jito Block engine
3. Jito block engine forwards the bundle to the Jito-Solana validators
4. The Jito-solana  uses BundleStage to position the bundles before executing
5. The bundles is excuted when the **Jito-Solana validators are producing blocks**

#### The Tip Mechanism

Jito tips are **direct SOL transfers** to the validator. This creates a direct incentive for validators to include your bundle.

**How tips work:**

1. You include a tip transaction as the **last transaction** in your bundle
2. The tip is a simple SOL transfer to one of Jito's official tip accounts
3. If your bundle lands, the tip goes to the validator who included it
4. If your bundle doesn't land, **you pay nothing**

**Official Jito Tip Accounts:**

{% code overflow="wrap" %}

```javascript
const JITO_TIP_ACCOUNTS = [
"DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL",
"Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY",
"3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT",
"ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt",
"ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49",
"96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5",
"DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh",
"HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe"
];
```

{% endcode %}

#### Tip Amount Guidelines

| Level       | SOL Amount   | Use Case                                   |
| ----------- | ------------ | ------------------------------------------ |
| Minimum     | 0.0001       | Testing, low-priority operations           |
| Standard    | 0.001        | Normal DeFi operations                     |
| Competitive | 0.005 - 0.01 | Time-sensitive swaps, moderate competition |
| High        | 0.01 - 0.05  | High-value trades, liquidations            |
| Aggressive  | 0.05+        | Arbitrage, high-competition scenarios      |

### Comparison: Normal Transactions vs Jito Bundles

| Feature                 | Normal Transaction | Jito Bundle                  |
| ----------------------- | ------------------ | ---------------------------- |
| **Mempool Visibility**  | Public             | Private until execution      |
| **MEV Protection**      | ❌ None             | ✅ Protected                  |
| **Atomic Execution**    | ❌ Single TX only   | ✅ Up to 5 TXs                |
| **Guaranteed Ordering** | ❌ No               | ✅ Yes                        |
| **Cost on Failure**     | Pay base fee       | ✅ No cost                    |
| **Network**             | Devnet + Mainnet   | ⚠️ Mainnet only              |
| **Best For**            | Simple transfers   | DeFi, arbitrage, complex ops |
| **Complexity**          | Low                | Medium                       |

#### When to Use Jito Bundle

* DeFi trading (swaps, arbitrage, liquidations)
* Multi-step operations that must execute together
* Large trades vulnerable to sandwich attacks
* Any operation where ordering and privacy matter
* Failed transactions would be costly


# Overview

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

## 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:

```python
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())
```

### 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.

#### 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
* L1 and L2 protocols
* EVM and non-EVM networks

See full list: <https://getblock.io/nodes/>\
\
All mainstream RPC interfaces

* WebSockets
* JSON RPC
* GraphQL
* REST API
* And more

Add them in Lego-like manner: <https://account.getblock.io/>

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

* DAS API
* Firehose
* Blockbook
* Yellowstone Geyser

Need more? Don’t hesitate to contact sales: <https://getblock.io/contact/>

## Examples for Console REST API Requests

#### 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:

```json
curl -h
```

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

```json
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

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

```json
python -m pip install requests
```

Example:

```python
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())
```

#### 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:

```
node -v
```

#### Ruby

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

```
ruby -v
```

## Supported networks

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

[Aptos (APT)](https://getblock.io/docs/apt/json-rpc/apt_v1_estimate_gas_price/)

[Arbitrum (ARB)](https://getblock.io/docs/arb/json-rpc/arbitrum_eth_accounts/)

[Avalanche (AVAX)](https://getblock.io/docs/avax/json-rpc/avax_eth_accounts/)

[Bitcoin Cash (BCH)](https://getblock.io/docs/bch/json-rpc/bch_combinepsbt/)

[BNB Smart Chain (BSC)](https://getblock.io/docs/bsc/json-rpc/bsc_debug_tracecall/)

[Bitcoin-SV (BSV)](https://getblock.io/docs/bsv/json-rpc/bsv_analyzepsbt/)

[Bitcoin (BTC)](https://getblock.io/docs/btc/json-rpc/btc_analyzepsbt/)

[Bitcoin Gold (BTG)](https://getblock.io/docs/btg/json-rpc/btg_analyzepsbt/)

[Cronos (CRO)](https://getblock.io/docs/cro/json-rpc/cro_eth_accounts/)

[Dash (DASH)](https://getblock.io/docs/dash/json-rpc/dash_combinerawtransaction/)

[DigiByte (DGB)](https://getblock.io/docs/dgb/json-rpc/dgb_analyzepsbt/)

[Dogeсoin (DOGE)](https://getblock.io/docs/doge/json-rpc/doge_createrawtransaction/)

[Polkadot (DOT)](https://getblock.io/docs/dot/json-rpc/dot_chain_getblock/)

[Ethereum Classic (ETC)](https://getblock.io/docs/etc/json-rpc/etc_eth_accounts/)

[Ethereum (ETH)](https://getblock.io/docs/eth/json-rpc/eth_eth_accounts/)

[Fantom (FTM)](https://getblock.io/docs/ftm/json-rpc/ftm_dag_getevent/)

[Fuse.io (FUSE)](https://getblock.io/docs/fuse/json-rpc/fuse_eth_accounts/)

[Moonbeam (GLMR)](https://getblock.io/docs/glmr/json-rpc/glmr_eth_accounts/)

[Gnosis Chain (GNO)](https://getblock.io/docs/gno/json-rpc/gno_eth_accounts/)

[Huobi ECO Chain (HECO)](https://getblock.io/docs/heco/json-rpc/heco_eth_accounts/)

[KuCoin Community Chain (KCC)](https://getblock.io/docs/kcc/json-rpc/kcc_eth_accounts/)

[Kusama (KSM)](https://getblock.io/docs/ksm/json-rpc/ksm_chain_getblock/)

[Polygon (MATIC)](https://getblock.io/docs/matic/json-rpc/matic_eth_accounts/)

[Moonriver (MOVR)](https://getblock.io/docs/movr/json-rpc/movr_chain_getblock/)

[Near Protocol (NEAR)](https://getblock.io/docs/near/json-rpc/near_block/)

[Harmony (ONE)](https://getblock.io/docs/one/json-rpc/one_eth_accounts/)

[Ontology (ONT)](https://getblock.io/docs/ont/json-rpc/ont_getbalance/)

[Optimism (OP)](https://getblock.io/docs/op/json-rpc/optimism_eth_accounts/)

[Rootstock (RSK)](https://getblock.io/docs/rsk/json-rpc/rsk_eth_accounts/)

[Solana (SOL)](https://getblock.io/docs/sol/json-rpc/sol_getaccountinfo/)

[Theta (THETA)](https://getblock.io/docs/theta/json-rpc/theta_theta.broadcastrawtransaction/)

[TON (TON)](https://getblock.io/docs/ton/json-rpc/ton_detectaddress/)

[Tron (TRX)](https://getblock.io/docs/trx/json-rpc/trx_eth_blocknumber/)

[NEM (XEM)](https://getblock.io/docs/xem/rest/xem_account_get_forwarded_from-public-key/)

[Monero (XMR)](https://getblock.io/docs/xmr/json-rpc/get_alternate_chains/)

[ZCash (ZEC)](https://getblock.io/docs/zec/json-rpc/zec_createrawtransaction/)


# 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.

## Overview of Aptos Network Methods

Aptos is a Layer 1 blockchain built with the [Move programming language](https://move-book.com/), 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
5. Code example
6. Integration

> Note: This API is compatible only with Aptos Mainnet.

## Quickstart

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

* Axios
* Python

### Quickstart with Axios

Before you begin, you must have already installed `npm` or `yarn` on your local machine. If not, check out [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) or [yarn](https://classic.yarnpkg.com/lang/en/docs/install).

1. Set up your project using this command:

   For npm:

   ```bash
   mkdir aptos-api-quickstart
   cd aptos-api-quickstart
   npm init --yes
   ```

Or yarn:

```bash
mkdir aptos-api-quickstart
cd aptos-api-quickstart
yarn init --yes
```

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

2. Install Axios using this command:\
   Using npm:

   ```bash
   npm install axios
   ```

   Using yarn:

   ```bash
   yarn add axios
   ```
3. Create a new file and name it `index.js`. This is where you will make your first call.
4. Set ES module `"type": "module"` in your `package.json`.
5. Add the following code to the file (`index.js`):

   ```js
   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);
   });
   ```

   > Replace `<ACCESS_TOKEN>` with your actual access token from GetBlock.
6. Run the script:

   ```bash
   node index.js
   ```

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

   ```json
   {
     "Sequence_number": "219241",
     "Authentication_key": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f"
   }
   ```

### 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:

   ```bash
   mkdir aptos-api-quickstart
   cd aptos-api-quickstart
   ```
2. Set up a virtual environment to isolate dependencies:

   ```bash
   python -m venv venv
   source venv/bin/activate  
   # On Windows, use venv\Scripts\activate
   ```
3. Install the requests library:

   ```bash
   pip install requests
   ```
4. Create a new file called [`main.py`](http://main.py) and insert the following code:

   ```python
   import requests

   url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f"

   response = requests.get(url)

   print(response.text)
   ```

   > Replace `<ACCESS_TOKEN>` with your actual access token from GetBlock.
5. Run the script:

   ```bash
   python main.py
   ```

### Endpoint Grouping

1. Blockchain Information
   * /v1
2. Account-Related
   * /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
3. Events
   * /v1/accounts/{account\_hash}/events/{creation\_number}
   * /v1/accounts/{account\_hash}/events/{event\_handle}/{field\_name}
4. Blocks
   * /v1/blocks/by\_height/{block\_height}
   * /v1/blocks/by\_version/{version}
5. Transactions
   * /v1/transactions
   * /v1/transactions/by\_hash/{transaction\_hash}
   * /v1/transactions/by\_version/{version}
6. Additional Utility
   * /v1/estimate\_gas\_price


# /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.

## Supported Network

* Mainnet

***

## Parameters

* None

## Request

**URL (endpoint)**

```bash
https://go.getblock.io/
```

**Example (cURL)**

```bash
curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/info'
```

## Response

```json
{
  "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"
}
```

## Response Definition

| Value                   | Data type | Description                                            |
| ----------------------- | --------- | ------------------------------------------------------ |
| `chain_id`              | integer   | ID of the blockchain                                   |
| `epoch`                 | string    | Current epoch number                                   |
| `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                             |

## 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.

## Code Example (Axios)

```js
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);
});
```

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

## 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.

## Integration

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


# /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.

## Supported Networks

* Mainnet

## Parameters

| Parameter      | Data type | Description           | Required | In   |
| -------------- | --------- | --------------------- | -------- | ---- |
| `account_hash` | string    | Aptos account address | Yes      | Path |

***

## Request Example

**URL**

```bash
https://go.getblock.io/<ACCESS-TOKEN>/
```

**Example**

```bash
curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f'
```

## Response

```json
{
  "sequence_number": "234541",
  "authentication_key": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f"
}
```

## 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.          |

## 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.

## Code Examples

### Python (requests)

```python
import requests

url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f"

response = requests.get(url)

print(response.text)
```

### Node.js (Axios)

```js
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);
});
```

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

## Error Handling

You may encounter responses like:

```json
{
  "sequence_number": "0",
  "authentication_key": "0x00000000000000000000000bf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f"
}
```

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.

## 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.


# /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.

## Supported Network

* Mainnet

***

## Parameters

| Parameter         | Data type | Description                                                                                             | Required | In    |
| ----------------- | --------- | ------------------------------------------------------------------------------------------------------- | -------- | ----- |
| `account_hash`    | string    | Aptos account address.                                                                                  | Yes      | Path  |
| `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 |

***

## Request

**Base URL**

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

**Request Example (cURL)**

```bash
curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/events/0'
```

#### Response

```json
[
  {
    "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"
      }
    }
  }
]

```

***

## 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.                           |
| `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). |

## 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.

***

## Code Examples

### Node.js (Axios)

```js
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);
});
```

### Python (Request)

```python
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)
```

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

***

## Error Handling

| Status Code | Error Message           | Cause                                                   |
| ----------- | ----------------------- | ------------------------------------------------------- |
| **400**     | Invalid account address | The provided `account_hash` is invalid.                 |
| **401**     | Unauthorized            | Missing or invalid `<ACCESS_TOKEN>`.                    |
| **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.        |

***

## 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.


# /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.

## Supported Network

```
- Mainnet
```

## Parameters

| Parameter      | Data type | Description                                                                                      | Required | In    |
| -------------- | --------- | ------------------------------------------------------------------------------------------------ | -------- | ----- |
| `account_hash` | string    | Aptos account address                                                                            | Yes      | Path  |
| `event_handle` | 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 |

## Request Example

**Base URL**

```bash
https://go.getblock.io/<ACCESS\_TOKEN>/
```

**Example (cURL)**

```bash
curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/events/0x1::account::Account/coin_register_events'
```

## Response Example

```bash
    [
      {
        "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"
          }
        }
      }
    ]
```

## Response Parameters

| Field                 | Type   | Description                                                             |
| --------------------- | ------ | ----------------------------------------------------------------------- |
| 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.                            |
| sequence\_number      | string | Number of transactions submitted and committed on-chain by the account. |
| type                  | string | Type of event emitted.                                                  |

## 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.

## Code Examples

### Python (requests)

```python
    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)
```

### Node.js (Axios)

```js
    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);
    });
    
```

> Replace `<ACCESS_TOKEN>` with your actual GetBlock API token.

## Error Handling

| Status Code | Error Message         | Cause                                            |
| ----------- | --------------------- | ------------------------------------------------ |
| 403         | Forbidden             | Missing or invalid ACCESS\_TOKEN.                |
| 404         | Resource not found    | Invalid event\_handle or field\_name.            |
| 500         | Internal server error | Node or network issue — retry the request later. |

## 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.
* Enhance analytics dashboards by focusing on targeted on-chain event streams.


# /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.

***

## Supported Network

* Mainnet

***

## Parameters

| Parameter        | Data type | Description                                                          | Required | In    |
| ---------------- | --------- | -------------------------------------------------------------------- | -------- | ----- |
| `account_hash`   | string    | Aptos account address.                                               | Yes      | Path  |
| `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 |

***

## Request

**Base URL**

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

**Example (cURL)**

```bash
curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/module/curves'
```

### Response

```json
{
  "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" }]
      }
    ]
  }
}
```

***

## 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. |
| `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.                           |

***

### 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.

## Code Examples

**Python (requests)**

```python
import requests

url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/module/curves"

response = requests.get(url)

print(response.text)
```

**Node(Axios)**

```js
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);
});
```

***

## Error Handling

| Status Code | Error Message         | Cause                                           |
| ----------- | --------------------- | ----------------------------------------------- |
| **403**     | Forbidden             | Missing or invalid `<ACCESS_TOKEN>`.            |
| **404**     | Resource not found    | The specified module does not exist.            |
| **500**     | Internal server error | Node or network issue. Retry the request later. |

***

## 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.


# /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.

***

## Supported Network

* Mainnet

## Parameters

| Parameter        | Data Type | Description                                  | Required | In    |
| ---------------- | --------- | -------------------------------------------- | -------- | ----- |
| `account_hash`   | string    | Aptos account address                        | Yes      | Path  |
| `ledger_version` | string    | The ledger version to get the account state  | No       | Query |
| `start`          | string    | The starting point for getting the resources | No       | Query |

***

## Request Example

**Base URL**

```bash
https://go.getblock.io/<ACCESS-TOKEN>/
```

**Example(cURL)**

```curl
curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/modules?ledger_version=3362752463&limit=2'
```

***

## Response

```json
[
    {
        "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"
                        }
                    ]
                }
            ]
        }
    }
]
```

## Response Parameter Definition

| Field                 | Description                                                   |
| --------------------- | ------------------------------------------------------------- |
| `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`                | The name of the smart contract                                |
| `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                                                |

***

## 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.

***

## Code Examples

**Python (Requests)**

```python
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)
```

**Node(Axios)**

```js
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);
});
```

***

## 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`, which means the resources were not found. To resolve this, use the right account\_hash, or it is not a smart contract address.

***

## 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.
* dApps can query other on-chain modules to understand what functions are available for reuse.


# /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.

## Supported Networks

* Mainnet

## Parameters

| **Parameter**    | **Data type** | **Description**                                    | **Required** | **In** |
| ---------------- | ------------- | -------------------------------------------------- | ------------ | ------ |
| `account_hash`   | string        | Aptos account address                              | Yes          | Path   |
| `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  |

## Request Example

**Base URL**

```
https://go.getblock.io/<ACCESS-TOKEN>/
```

**Example(cURL)**

```curl
curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/resource/0x1::account::Account'
```

## Response

```json
{
    "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": []
            }
        }
    }
}

```

## 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                         |
| 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              |

## 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.

## Code Examples

**Python (Requests)**

```python
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)

```

**Node(Axios)**

```js
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);
});


```

## 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. |
| 500             | Internal server error | Node or network issue. Retry later.                      |

## 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.


# /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.

## Supported Networks

* Mainnet

## Parameters

| Parameter        | Data type | Description                                 | Required | In    |
| ---------------- | --------- | ------------------------------------------- | -------- | ----- |
| `account_hash`   | string    | Aptos account address                       | Yes      | Path  |
| `ledger_version` | 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 |

## Request Example

**URL**

```bash
https://go.getblock.io//
```

**Example**

```bash

curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/resources?ledger_version=3357308041&limit=10'
```

## Response

```json
[
  {
    "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": [] }
      }
    }
  }
]
```

## Response Definition

| Value                  | Data type | Description                                                              |
| ---------------------- | --------- | ------------------------------------------------------------------------ |
| `type`                 | string    | The type format of the account resource.                                 |
| `data`                 | object    | The additional data or information related to the account resource.      |
| `authentication_key`   | 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.               |

## 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.
* Supporting conditional logic in dApps (e.g., only allow staking if a required resource exists).

## Code Examples

### Python (requests)

```python
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)
```

### Node.js (Axios)

```js
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);
});
```

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

## Error Handling

* **Missing or invalid account hash** → Empty or malformed response.
* **403** → Access token is missing or invalid.

## 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}/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.

## Supported Network

* Mainnet

## Parameters

| **Parameter** | **Data type** | **Description**                                                                                                     | **Required** | **In** |
| ------------- | ------------- | ------------------------------------------------------------------------------------------------------------------- | ------------ | ------ |
| account\_hash | string        | Aptos account address                                                                                               | Yes          | Path   |
| 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  |

## Request

**Base URL**

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

**Example(cURl)**

```
curl -X GET "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f
/transactions?limit=5"
```

## Response

```json
[
    {
        "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"
    }
]
```

### Response Parameter Definition

| **Field**                | **Type** | **Description**                                                             |
| ------------------------ | -------- | --------------------------------------------------------------------------- |
| version                  | String   | The transaction version (ledger sequence number).                           |
| hash                     | String   | Unique hash of the transaction.                                             |
| 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). |

## 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.

## Code Example

**Python Request**

```python
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)


```

**Node(axios)**

```js
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);
});

```

## 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. |
| 500             | Internal server error | Node or network issue. Retry later.                      |

## 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.
* **a**nalyse user behaviour, token transfers, and contract interactions for dApps.


# /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.

## Supported Networks

* Mainnet

## Parameter

| **Parameter**       | **Type** | **In** | **Required** | **Description**                                                      |
| ------------------- | -------- | ------ | ------------ | -------------------------------------------------------------------- |
| `block_height`      | Integer  | Path   | Yes          | Height (number) of the block to fetch.                               |
| `with_transactions` | Boolean  | Query  | No           | If true, returns full transactions inside the block. Default: false. |

## Request

**Base URL**

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

**Example(cURL)**

```curl
curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/blocks/by_height/425737645?with_transactions=false'
```

## Response Example

```json

{
    "block_height": "445814139",
    "block_hash": "0x0ac6b36f89b6a3fc9b7c2cabcb1f29cc624e609ed0978dd2a757b048196cb3bc",
    "block_timestamp": "1759349325550593",
    "first_version": "3492983944",
    "last_version": "3492983948",
    "transactions": null
}
```

## 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              | 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                       |

## 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.

## Code Example

**Python(Request)**

```python
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)
```

**Node(Axios)**

```js
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);
});
```

## 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. |
| **500**         | Internal server error | Node or network issue; retry later.                 |

## 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.


# /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.

## Supported Network

* Mainnet

## Parameter

| **Parameter**      | **Data type** | **Description**                         | **Required** | **In** |
| ------------------ | ------------- | --------------------------------------- | ------------ | ------ |
| version            | integer       | The ledger version                      | Yes          | Path   |
| with\_transactions | boolean       | To contain transactions' details or not | no           | Query  |

## Request

**Base URL**

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

**Example(cURL)**

```curl
curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_version/3556737308?with_transactions=false'
```

## Response Example

```json
{
    "block_height": "456015808",
    "block_hash": "0xdbe2cbd48ec3b897fa5f6b1ff51bd8eef280e300e12b6ff153b3959a7440a268",
    "block_timestamp": "1760341227055115",
    "first_version": "3556737303",
    "last_version": "3556737309",
    "transactions": null
}

```

## Response Parameter Definition

| Field                                        | Type    | Description                                                                       |
| -------------------------------------------- | ------- | --------------------------------------------------------------------------------- |
| **block\_height**                            | string  | Height of the block in the blockchain.                                            |
| **block\_hash**                              | string  | Unique hash identifying the block.                                                |
| **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.                               |

## 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.

## Code Example

**Node(Axios)**

```js
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);
});
```

**Python(Request)**

```python
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)
```

## 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 |
| **500**         | Internal server error          | Node or network issue; retry later.      |

## 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.


# /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.

## Supported Network

* Mainnet

## Parameter

None

## Request

**Base URL**

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

**Example(cURL)**\*

```curl
curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/estimate_gas_price'
```

## Response Example

```json
{
    "deprioritized_gas_estimate": 100,
    "gas_estimate": 100,
    "prioritized_gas_estimate": 150
}

```

## 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).                          |
| prioritized\_gas\_estimate   | String   | Higher gas price estimate — ensures faster transaction processing.         |

## 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.

## Code example

**Node(axios)**

```js
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);
});


```

**Python(Request)**

```python
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 handling

| **Status Code** | **Error Message**     | **Cause**                                    |
| --------------- | --------------------- | -------------------------------------------- |
| **403**         | Forbidden             | Missing or invalid \<ACCESS\_TOKEN>.         |
| **500**         | Internal server error | Node or network failure when estimating gas. |

## 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.


# /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.

## Supported Network

* Mainnet

## Parameter

| **Parameter** | **Type** | **In** | **Required** | **Description**                                              |
| ------------- | -------- | ------ | ------------ | ------------------------------------------------------------ |
| start         | Integer  | Query  | No           | Starting transaction version for pagination.                 |
| limit         | Integer  | Query  | No           | Number of transactions to return. Default: 25. Maximum: 100. |

## Request

**Base URL**

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

**Example(cURL)**

```curl
curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions?limit=1'
```

## Response Example

```json
[
    {
        "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"
    }
]

```

## Response Parameter Definition

| **Field**                                            | **Type** | **Description**                                                                                   |
| ---------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------- |
| version                                              | String   | Global transaction version (unique ID in Aptos ledger).                                           |
| hash                                                 | String   | Transaction hash.                                                                                 |
| 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). |

## 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.

## Code Example

**Node(Axios)**

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


```

**Python(Request)**

```python
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)


```

## Error handling

| **Status Code** | **Error Message**     | **Cause**                           |
| --------------- | --------------------- | ----------------------------------- |
| **403**         | Forbidden             | Missing or invalid ACCESS\_TOKEN.   |
| **500**         | Internal server error | Node or network issue; retry later. |

## 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.


# /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.

## Supported network

* Mainnet

## Parameter

| **Parameter**     | **Type** | **In** | **Required** | **Description**         |
| ----------------- | -------- | ------ | ------------ | ----------------------- |
| transaction\_hash | String   | Path   | Yes          | Hash of the transaction |

## Request

**Base URL**

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

**Example(cURL)**

```curl
curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_hash/0xd797b944ed8657406a1b09a5928048093399fc0a2f576d3e57c0f9cedbf95c4a'
```

## Response Example

```json
{
    "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"
}

```

## Response parameter Definition

| **Field**               | **Type** | **Description**                                                           |
| ----------------------- | -------- | ------------------------------------------------------------------------- |
| version                 | String   | Global transaction version number.                                        |
| hash                    | String   | Transaction hash used for lookup.                                         |
| 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). |

## 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.

## Code example

**Node(axios)**

```js
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);
});


```

**Python(Request)**

```python
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)
```

## 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>.           |
| **500**         | Internal server error    | Node or network issue; retry later.            |

## 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.


# /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.

## supported Network

* Mainnet

## Parameter

| **Parameter** | **Data type** | **Description**    | **Required** | **In** |
| ------------- | ------------- | ------------------ | ------------ | ------ |
| `version`     | integer       | The ledger version | Yes          | Path   |

## Request

**Base URL**

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

**Example(cURL)**

```curl
curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_version/3363904007'
```

## Response Example

```json
{
    "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"
}

```

## Response Parameter Definition

| **Field**                                            | **Type** | **Description**                                                           |
| ---------------------------------------------------- | -------- | ------------------------------------------------------------------------- |
| version                                              | String   | Global transaction version number.                                        |
| hash                                                 | String   | Hash of the transaction.                                                  |
| 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). |

## 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.

## Code Example

**Node(axios)**

```js
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);
});
```

**Python(Request)**

```python
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)
```

## 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 |
| **500**         | Internal server error          | Node or network issue; retry later.      |

## 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.


# ARC

GetBlock provides fast and reliable access to Arc nodes via JSON-RPC API. Connect to the ARC network without running your own infrastructure.

Arc is an open Layer 1 blockchain built by Circle (the company behind USDC), purpose-built for stablecoin finance, payments, and institutional use cases. Launched on public testnet in late 2025 with participation from 100+ institutions, including BlackRock, Visa, and HSBC, Arc takes a fundamentally different approach to gas economics: instead of a volatile native token, **USDC is the network's native gas token**, making transaction fees predictable and dollar-denominated.&#x20;

Arc is fully EVM-compatible, runs on Circle's Malachite consensus engine for deterministic sub-second finality, and ships with a built-in FX engine for 24/7 PvP stablecoin settlement plus opt-in compliance-friendly privacy. The result is a chain optimized for real-world financial activity — cross-border payments, capital markets, eCommerce checkout, and tokenized credit — that retains the developer experience of Ethereum.

## Key Features

* **USDC as Native Gas**: Transaction fees paid in USDC (6 decimals, not 18) — eliminates crypto-volatility from fee budgets and enables dollar-denominated cost predictability
* **Malachite Consensus**: Deterministic sub-second finality engineered for financial infrastructure standards — no probabilistic settlement windows
* **Full EVM Compatibility**: Standard Ethereum JSON-RPC method set; deploy Solidity / Vyper contracts and use Hardhat, Foundry, ethers.js, viem, and web3.py without modification
* **Built-in FX Engine**: Native on-chain currency exchange with 24/7 PvP (Payment versus Payment) settlement for stablecoin pairs
* **Opt-In Privacy**: Compliance-friendly privacy primitives that institutions can selectively enable for confidential financial operations
* **Circle Ecosystem Integration**: First-class support for CCTP (Cross-Chain Transfer Protocol), Paymaster, and Circle's broader stablecoin tooling
* **Sub-Second Block Times**: \~2 second block production tuned for high-throughput payments and order-flow workloads
* **Institutional Backing**: Designed with input from 100+ financial institutions — BlackRock, Visa, HSBC, and others
* **ERC-4337 & EIP-7702 Native**: Account abstraction support built into the network for gas sponsorship, batched transactions, and smart accounts
* **AI Agent Primitives**: Native support for AI agent registration and ERC-8183 job markets, enabling the agentic economy

{% hint style="info" %}
***TECHNICAL DISCLAIMER: AUTHORITATIVE JSON-RPC SPECIFICATION***

*GetBlock’s Arc API reference documentation is provided exclusively for informational purposes and to optimize the developer experience. The canonical and normative specification for the Ethereum JSON-RPC API is maintained by the Ethereum community and published at* [*ethereum.org/en/developers/docs/apis/json-rpc/*](https://ethereum.org/en/developers/docs/apis/json-rpc/)*. For Arc-specific protocol details, consensus parameters, the FX engine, and the privacy layer, consult the official documentation at* [*docs.arc.io*](https://docs.arc.io/)*.*
{% endhint %}

{% hint style="warning" %}
**USDC-DENOMINATED GAS — IMPORTANT**

Arc uses USDC as its native gas token, with **6 decimals** (not 18 like most EVM chains). When working with `eth_getBalance`, `eth_gasPrice`, `eth_maxPriorityFeePerGas`, `eth_feeHistory`, and transaction `value` fields, divide raw wei values by 10⁶ — not 10¹⁸ — to obtain USDC. This is the single most common integration mistake when porting an existing EVM dApp to Arc.
{% endhint %}

## Network Information

| Property          | Value                                               |
| ----------------- | --------------------------------------------------- |
| Network Name      | Arc Testnet                                         |
| Stage             | Public testnet (mainnet not yet launched)           |
| Chain ID          | 5042002 (`0x4cef52`)                                |
| Native Currency   | USDC                                                |
| Decimals          | 6 (not 18 — see warning above)                      |
| Block Time        | \~2 seconds                                         |
| Consensus         | Malachite (deterministic sub-second finality)       |
| Smart Contract VM | EVM (Ethereum Virtual Machine)                      |
| EVM Compatible    | Yes (fully compatible)                              |
| Address Format    | Ethereum-style (`0x…`, 20 bytes)                    |
| Block Explorer    | [testnet.arcscan.app](https://testnet.arcscan.app/) |
| Faucet            | [faucet.circle.com](https://faucet.circle.com/)     |

## Base URL

{% tabs %}
{% tab title="Frankfurt, Germany" %}

```bash
https://go.getblock.io/<ACCESS-TOKEN>/
```

{% endtab %}

{% tab title="New York, USA" %}

```bash
https://go.getblock.us/<ACCESS-TOKEN>/
```

{% endtab %}

{% tab title="Singapore, Singapore" %}

```bash
https://go.getblock.asia/<ACCESS-TOKEN>/
```

{% endtab %}
{% endtabs %}

All Arc JSON-RPC methods are called by sending a `POST` request to the base URL with a standard JSON-RPC 2.0 body. For real-time subscriptions (new blocks, finalized heads, logs) use the WebSocket scheme: `wss://go.getblock.io/<ACCESS-TOKEN>/`.

## Supported Networks

| Network | JSON-RPC | WSS | Frankfurt, Germany | New York, USA | Singapore, Singapore |
| ------- | -------- | --- | ------------------ | ------------- | -------------------- |
| Testnet | ✅        | ✅   | ✅                  | ✅             | ✅                    |

Arc mainnet has not yet launched. This documentation targets the **public testnet** (Chain ID `5042002`), which is the current stable development environment.

## Quickstart

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

* **Axios** (JavaScript / Node.js)
* **Python** (Requests library)

Before you begin, you must have already installed [`npm`](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) or [`yarn`](https://classic.yarnpkg.com/lang/en/docs/install) on your local machine (for the Axios example) or Python and pip (for the Python example).

{% tabs %}
{% tab title="JavaScript (Axios)" %}
{% stepper %}
{% step %}

#### Setup project

Create and initialize a new project:

```bash
mkdir arc-api-quickstart
cd arc-api-quickstart
npm init --yes
```

{% endstep %}

{% step %}

#### Install Axios

```bash
npm install axios
```

{% endstep %}

{% step %}

#### Create file

Create a new file named `index.js`. This is where you will make your first call.
{% endstep %}

{% step %}

#### Set ES module type

Set the ES module `"type": "module"` in your `package.json`.
{% endstep %}

{% step %}

#### Add code

Add the following code to `index.js`:

{% code title="index.js" %}

```javascript
import axios from 'axios';

const data = JSON.stringify({
    "jsonrpc": "2.0",
    "method": "eth_chainId",
    "params": [],
    "id": "getblock.io"
});

const config = {
    method: 'post',
    url: 'https://go.getblock.io/<ACCESS-TOKEN>/',
    headers: {
        'Content-Type': 'application/json'
    },
    data: data
};

axios(config)
    .then(response => console.log(JSON.stringify(response.data, null, 2)))
    .catch(error => console.log(error));
```

{% endcode %}

Replace `<ACCESS-TOKEN>` with your actual access token from GetBlock.
{% endstep %}

{% step %}

#### Run the script

```bash
node index.js
```

Expected output:

```json
{
    "jsonrpc": "2.0",
    "id": "getblock.io",
    "result": "0x4cef52"
}
```

The `result` field is the Arc testnet chain ID (`0x4cef52` = 5042002 in decimal). This confirms you are connected to the correct network.
{% endstep %}
{% endstepper %}
{% endtab %}

{% tab title="Python (Requests)" %}
{% stepper %}
{% step %}

#### Setup the project directory

```bash
mkdir arc-api-quickstart
cd arc-api-quickstart
```

{% endstep %}

{% step %}

#### Create and activate a virtual environment

```bash
python -m venv venv
source venv/bin/activate

# On Windows, use venv\Scripts\activate
```

{% endstep %}

{% step %}

#### Install requests

```bash
pip install requests
```

{% endstep %}

{% step %}

#### Create script

Create a file called `main.py` with the following content:

{% code title="main.py" %}

```python
import requests
import json

url = "https://go.getblock.io/<ACCESS-TOKEN>/"

payload = json.dumps({
    "jsonrpc": "2.0",
    "method": "eth_chainId",
    "params": [],
    "id": "getblock.io"
})

headers = {
    'Content-Type': 'application/json'
}

response = requests.post(url, headers=headers, data=payload)
print(response.text)
```

{% endcode %}

Replace `<ACCESS-TOKEN>` with your actual access token from GetBlock.
{% endstep %}

{% step %}

#### Run the script

```bash
python main.py
```

{% endstep %}
{% endstepper %}
{% endtab %}
{% endtabs %}

## Available API Methods

Arc exposes the full standard Ethereum JSON-RPC method set. All methods are POST-only and called against the base URL above.

### Block & Chain Information

| Method                                | Description                                                   |
| ------------------------------------- | ------------------------------------------------------------- |
| eth\_blockNumber                      | Returns the current latest block number                       |
| eth\_chainId                          | Returns the chain ID (`0x4cef52` = 5042002 for Arc testnet)   |
| eth\_getBlockByNumber                 | Returns block information by block number                     |
| eth\_getBlockByHash                   | Returns block information by block hash                       |
| eth\_getBlockTransactionCountByNumber | Returns the number of transactions in a block by block number |
| eth\_getBlockTransactionCountByHash   | Returns the number of transactions in a block by block hash   |
| eth\_getBlockReceipts                 | Returns all transaction receipts for a given block            |
| eth\_syncing                          | Returns sync status or `false` if node is fully synced        |

### Account & State

| Method                   | Description                                                       |
| ------------------------ | ----------------------------------------------------------------- |
| eth\_getBalance          | Returns the USDC balance of an account (in 6-decimal base units)  |
| eth\_getCode             | Returns the contract bytecode at a given address                  |
| eth\_getStorageAt        | Returns the value at a specific storage slot                      |
| eth\_getProof            | Returns the Merkle proof for an account and optional storage keys |
| eth\_getTransactionCount | Returns the transaction count (nonce) for an account              |

### Transactions

| Method                                   | Description                                                               |
| ---------------------------------------- | ------------------------------------------------------------------------- |
| eth\_sendRawTransaction                  | Broadcasts a signed transaction                                           |
| eth\_getTransactionByHash                | Returns a transaction by its hash                                         |
| eth\_getTransactionByBlockHashAndIndex   | Returns a transaction by block hash and index                             |
| eth\_getTransactionByBlockNumberAndIndex | Returns a transaction by block number and index                           |
| eth\_getTransactionReceipt               | Returns the receipt for a transaction by hash                             |
| eth\_call                                | Executes a read-only call against contract state                          |
| eth\_estimateGas                         | Estimates gas required for a transaction (denominated in USDC base units) |

### Gas & Fee Market

| Method                    | Description                                                                   |
| ------------------------- | ----------------------------------------------------------------------------- |
| eth\_gasPrice             | Returns the current gas price in USDC base units                              |
| eth\_maxPriorityFeePerGas | Returns the suggested max priority fee per gas (EIP-1559, in USDC base units) |
| eth\_feeHistory           | Returns historical base fees and priority fees                                |

### Logs & Filters

| Method                           | Description                                             |
| -------------------------------- | ------------------------------------------------------- |
| eth\_getLogs                     | Returns logs matching a given filter                    |
| eth\_newFilter                   | Creates a new log filter                                |
| eth\_newBlockFilter              | Creates a filter that fires on new blocks               |
| eth\_newPendingTransactionFilter | Creates a filter that fires on new pending transactions |
| eth\_getFilterChanges            | Polls a filter for new events since the last poll       |
| eth\_getFilterLogs               | Returns all logs matching a filter                      |
| eth\_uninstallFilter             | Uninstalls a filter                                     |

### WebSocket Subscriptions

| Method           | Description                                                         |
| ---------------- | ------------------------------------------------------------------- |
| eth\_subscribe   | Subscribes to events (`newHeads`, `logs`, `newPendingTransactions`) |
| eth\_unsubscribe | Cancels an existing subscription                                    |

### Network & Client Info

| Method              | Description                                                        |
| ------------------- | ------------------------------------------------------------------ |
| net\_version        | Returns the network ID (`5042002` for Arc testnet)                 |
| net\_listening      | Returns `true` if the client is actively listening for connections |
| net\_peerCount      | Returns the number of peers connected to the node                  |
| web3\_clientVersion | Returns the client software version                                |
| web3\_sha3          | Returns the Keccak-256 hash of the given data                      |

## Support

For technical support and questions:

* **Support Email**: <support@getblock.io>

## See Also

* [Official Arc Documentation](https://docs.arc.io/)
* [Arc Homepage](https://arc.io/)
* [Ethereum JSON-RPC Specification](https://ethereum.org/en/developers/docs/apis/json-rpc/)
* [arc-node on GitHub (Circle)](https://github.com/circlefin/arc-node)
* [Arc Testnet Explorer (arcscan)](https://testnet.arcscan.app/)
* [Circle USDC Faucet](https://faucet.circle.com/)
* [Arc on Chainlist](https://chainlist.org/chain/5042002)
* [Ethers.js Documentation](https://docs.ethers.org/)
* [Viem Documentation](https://viem.sh/)
* [Circle CCTP (Cross-Chain Transfer Protocol)](https://www.circle.com/cross-chain-transfer-protocol)




---

[Next Page](/llms-full.txt/1)

