Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
This section provides simple examples to help you test your connection to the blockchain, using Ethereum API as a reference.
Learn how to interact with blockchain networks through GetBlock’s node infrastructure using popular web3 libraries.
Configure and manage blockchain node endpoints through GetBlock, offering easy creation of shared nodes
GetBlock offers scalable plans tailored to developers and businesses, providing flexible solutions for both small projects and high-traffic platforms.


Download the Postman GetBlock’s collection to test our service. It includes all the accessible endpoints of our nodes and ready-to-go examples.
curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/'
--header 'Content-Type: application/json'
--data-raw '{"jsonrpc": "2.0", "method": "db_getHex", "params": [null, null], "id": "getblock.io"}'{
"result": "null",
"id": "getblock.io",
"status_code": 405,
"message": "Method not allowed"
}curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/'
--header 'Content-Type: application/json'
--data-raw '{"jsonrpc": "2.0", "method": "db_putString", "params": [null, null, null], "id": "getblock.io"}'curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/'
--header 'Content-Type: application/json'
--data-raw '{"jsonrpc": "2.0", "method": "eth_coinbase", "params": [], "id": "getblock.io"}'{
"result": "null",
"id": "getblock.io",
"status_code": 405,
"message": "Method not allowed"
}curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/'
--header 'Content-Type: application/json'
--data-raw '{"jsonrpc": "2.0", "method": "db_getString", "params": [null, null], "id": "getblock.io"}'{
"result": "null",
"id": "getblock.io",
"status_code": 405,
"message": "Method not allowed"
}curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/'
--header 'Content-Type: application/json'
--data-raw '{"jsonrpc": "2.0", "method": "db_putHex", "params": [null, null, null], "id": "getblock.io"}'{
"result": "null",
"id": "getblock.io",
"status_code": 405,
"message": "Method not allowed"
}{
"result": "null",
"id": "getblock.io",
"status_code": 405,
"message": "Method not allowed"
}{YOUR_ACCESS_TOKEN}.https://go.getblock.io/<ACCESS_TOKEN>/curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": "getblock.io"
}'{"jsonrpc":"2.0","id":"getblock.io","result":"0x1449641"}npm install tronwebyarn add tronweb


npm install ethersyarn add ethersdist/web3.min.jsconst Web3 = require('web3');
//Set up the provider (replace ACCESS-TOKEN with your actual token)
const web3 = new Web3('https://go.getblock.io/<ACCESS-TOKEN>/');curl --location --request POST 'https://go.getblock.io/<ACCESS_TOKEN>/' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": "getblock.io"
}'{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": "0x1449641"
}curl --location --request POST 'https://go.getblock.io/<ACCESS_TOKEN>/' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"method": "eth_chainId",
"params": [],
"id": "getblock.io"
}'{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": "0x1"
}curl --location --request POST 'https://go.getblock.io/<ACCESS_TOKEN>/' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"params": ["<ACCOUNT_ADDRESS>", "latest"],
"id": "getblock.io"
}'{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": "0x5a70dac3910910"
}// Import the Ethers library
const { ethers } = require('ethers');
// Set up the provider (replace ACCESS_TOKEN with your actual token)
const provider = new ethers.JsonRpcProvider('https://go.getblock.io/ACCESS_TOKEN');
//Call a method using the provider
const main = async () => {
const blockNumber = await provider.getBlockNumber();
console.log("Latest Block Number:", blockNumber);
};
// Call the main function
main();// Import the Web3 library
const Web3 = require('web3');
// Set GetBlock as the provider (replace ACCESS_TOKEN with your actual token)
var web3 = new Web3('https://go.getblock.io/ACCESS_TOKEN');
// Initialize web3 method
web3.eth.getBlockNumber().then(console.log);// Generate new address and private key
const accountTo = web3.eth.accounts.create();
console.log('Generated account:', accountTo);// Restore account from private key
const privateKey = process.env['privateKey'];
const accountFrom = web3.eth.accounts.privateKeyToAccount(privateKey);const createSignedTx = async (rawTx) => {
rawTx.gas = await web3.eth.estimateGas(rawTx);
return await accountFrom.signTransaction(rawTx);
}
const sendSignedTx = async (signedTx) => {
// You can use signedTx.rawTransaction as params for
// calling eth_sendRawTransaction JSON-RPC method
web3.eth.sendSignedTransaction(signedTx.rawTransaction).then(
console.log
);
}
const amountTo = "0.01" // etherconst rawTx = {
to: accountTo.address,
value: web3.utils.toWei(amountTo, 'ether'),
chainId: chainId
};
createSignedTx(rawTx).then(sendSignedTx)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
An infrastructure that combines other GetBlock and external infrastructures, specifically designed for high-frequency traders (HFT) on Solana.
const TronWeb = require('tronweb');const tronWeb = new TronWeb({
fullHost: "https://go.getblock.io/<ACCESS-TOKEN>/"
})const fullNode = new TronWeb.providers.HttpProvider("https://go.getblock.io/<ACCESS-TOKEN>/")
const solidityNode = new TronWeb.providers.HttpProvider("https://go.getblock.io/<ACCESS-TOKEN>/")
const eventServer = new TronWeb.providers.HttpProvider("https://go.getblock.io/<ACCESS-TOKEN>/")
const tronWeb = new TronWeb(fullNode, solidityNode, eventServer)tronWeb.trx.getBlock('latest').then(result => {console.log(result)});





getblock.config.json file from your GetBlock account;curl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"method": "eth_chainId",
"params": [],
"id": "getblock.io"
}'curl -X GET https://go.getblock.io/"$(jq -r '.shared.btc.mainnet.rest[0]' getblock.config.json)"/rest/chaininfo.jsonconst { getblock } = require('./getblock.config.js');const { getblock } = require('./getblock.config.js');
var Web3 = require('web3');
// Create the JSON-RPC provider
var web3Rpc = new Web3(new Web3.providers.HttpProvider(
getblock.shared.eth.mainnet.rpc[0].go()
));
// Create the WebSocket provider
var web3Ws = new Web3.providers.WebsocketProvider(
`wss://go.getblock.io/${getblock.shared.eth.mainnet.ws[0].token()}`
));npm install --save-dev hardhatconst { getblock } = require('./getblock.config.js');const { getblock } = require('./getblock.config.js');
module.exports = {
defaultNetwork: "sepolia",
networks: {
hardhat: {
},
sepolia: {
url: getblock.shared.eth.sepolia.rpc[0].go() // https://go.getblock.io/<ACCESS-TOKEN>/
},
goerli: {
url: `https://go.getblock.io/${getblock.shared.eth.goerli.rpc[0].token()}` // <ACCESS-TOKEN>
},
},
solidity: {
version: "0.8.19",
settings: {
optimizer: {
enabled: true,
runs: 200
}
}
},
paths: {
sources: "./contracts",
tests: "./test",
cache: "./cache",
artifacts: "./artifacts"
},
mocha: {
timeout: 40000
}
}https://go.getblock.io/<ACCESS-TOKEN>/curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f'{
"sequence_number": "234541",
"authentication_key": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f"
}import requests
url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f"
response = requests.get(url)
print(response.text)import axios from 'axios';
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f',
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});{
"sequence_number": "0",
"authentication_key": "0x00000000000000000000000bf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f"
}An infrastructure for fast transaction delivery in Solana through its own intelligent routing mechanism.
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.
Set up your team account on GetBlock, invite and onboard team members with this step-by-step guide.
EU (Frankfurt): https://go.getblock.io/<ACCESS_TOKEN>/
US (New York): https://go.getblock.us/<ACCESS_TOKEN>/
Asia (Singapore): https://go.getblock.asia/<ACCESS_TOKEN>/https://go.getblock.io/curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/info'{
"block_height": "58851650",
"chain_id": 1,
"epoch": "2796",
"git_hash": "6568c5ee6a58b4f96c0780d4f66d7e573e61c418",
"ledger_timestamp": "1685696086534090",
"ledger_version": "152087593",
"node_role": "full_node",
"oldest_block_height": "1101178",
"oldest_ledger_version": "2287593"
}import axios from 'axios'
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/info',
headers: {}
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});https://go.getblock.io/<ACCESS_TOKEN>curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/estimate_gas_price'{
"deprioritized_gas_estimate": 100,
"gas_estimate": 100,
"prioritized_gas_estimate": 150
}
const axios = require('axios');
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/estimate_gas_price',
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import requests
url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/estimate_gas_price"
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)


package.jsonimport Client, {
SubscribeRequest,
CommitmentLevel
} from "@triton-one/yellowstone-grpc";
const client = new Client("https://go.getblock.io/", "YOUR_ACCESS_TOKEN");
const stream = await client.subscribe();
stream.write({
accounts: ["YourWalletPubkeyHere"],
commitment: CommitmentLevel.PROCESSED,
} as SubscribeRequest);
stream.on("data", (msg) => {
if (msg.accountChange) {
console.log(`Account updated: ${msg.accountChange.pubkey}`);
}
});import axios from 'axios'
let account = {
method: 'get',
url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f',
};
axios.request(account)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});node index.js{
"Sequence_number": "219241",
"Authentication_key": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f"
}python main.pymkdir aptos-api-quickstart
cd aptos-api-quickstart
npm init --yesmkdir aptos-api-quickstart
cd aptos-api-quickstart
yarn init --yesnpm install axiosyarn add axiosmkdir aptos-api-quickstart
cd aptos-api-quickstartpython -m venv venv
source venv/bin/activate
# On Windows, use venv\Scripts\activatepip install requestsimport requests
url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f"
response = requests.get(url)
print(response.text)curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header '
import axios from 'axios'
let
curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header '
import axios from 'axios'
let
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.
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
GetBlock API docs: RPC endpoints, SDK guides, and developer tools. Everything you need to connect and build on 100+ blockchain networks
Example code for the eth_getBlockTransactionCountByNumber JSON RPC method. Сomplete guide on how to use eth_getBlockTransactionCountByNumber JSON RPC in GetBlock Web3 documentation.
Example code for the eth_getBalance JSON RPC method. Сomplete guide on how to use eth_getBalance JSON RPC in GetBlock Web3 documentation.
Arbitrum Network API Reference for efficient interaction with ARB nodes, enabling fast, low-cost Layer 2 scaling solutions for Ethereum with high throughput and secure smart contracts.
Example code for the eth_gasPrice JSON RPC method. Сomplete guide on how to use eth_gasPrice JSON RPC in GetBlock Web3 documentation.
import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_accounts",
"params": [],
"id": "getblock.io"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_accounts",
"params": [],
"id": "getblock.io"
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}const { ethers } = require('ethers');
// Initialize Ethers provider with GetBlock
const provider = new ethers.JsonRpcProvider(
'https://go.getblock.us/<ACCESS-TOKEN>/'
);
// Using the method through Ethers
async function useEthersMethod() {
try {
// Method-specific Ethers implementation
const result = await provider.send('eth_accounts', []);
console.log('Result:', result);
return result;
} catch (error) {
console.error('Ethers Error:', error);
throw error;
}
}{
"jsonrpc": "2.0",
"id": "1",
"result": [
"0xd1f5279be4b4dd94133a23dee1b23f5bfe436tf3r"
]
}import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": "getblock.io"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": "getblock.io"
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function fetchBlockNumberFromProvider() {
try {
// Call the method — this will resolve to a number (promise resolves to number)
const result = await provider.send("eth_blockNumber", []);
console.log("Block number result:", result);
return result;
} catch (error) {
console.error("Ethers Error fetching block number:", error);
throw error;
}
}import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
// Create Viem client with GetBlock
const client = createPublicClient({
chain: arbitrum,
transport: http("https://go.getblock.us/<ACCESS_TOKEN>"),
});
// Using the method through Viem
async function fetchAccountViem() {
try {
// Method-specific Viem implementation
const result = await client.request({
method: 'eth_blockNumber',
});
console.log('Result:', result);
return result;
} catch (error) {
console.error('Viem Error:', error);
throw error;
}
}{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": "0x183037af"
}- Mainnetcurl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"method": "eth_getBlockTransactionCountByNumber ",
"params": [
"latest"
],
"id": "getblock.io"
}'import axios from 'axios'
let data = JSON.stringify({
"jsonrpc": "2.0",
"method": "eth_getBlockTransactionCountByNumber",
"params": [
"latest"
],
"id": "getblock.io"
};
let config = {
method: "post",
maxBodyLength: Infinity,
url: "https://go.getblock.us/<ACCESS_TOKEN>",
headers: {
"Content-Type": "application/json",
},
data: data,
};
axios
.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"id": "getblock.io",
"params": [
"0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
"latest"
]
}'import axios from 'axios'
let data = JSON.stringify({
"jsonrpc": "2.0",
"method": "eth_getBalance",
"id": "getblock.io",
"params": [
"0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
"latest"
],
};
let config = {
method: "post",
maxBodyLength: Infinity,
url: "https://go.getblock.us/<ACCESS_TOKEN>",
headers: {
"Content-Type": "application/json",
},
data: data,
};
axios
.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"method": "eth_gasPrice",
"id": "getblock.io",
"params": [],
}'import axios from 'axios'
let data = JSON.stringify({
"jsonrpc": "2.0",
"method": "eth_gasPrice",
"id": "getblock.io",
"params": [],
};
let config = {
method: "post",
maxBodyLength: Infinity,
url: "https://go.getblock.us/<ACCESS_TOKEN>",
headers: {
"Content-Type": "application/json",
},
data: data,
};
axios
.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
index.jshttps://go.getblock.io//
curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/resources?ledger_version=3357308041&limit=10'[
{
"type": "0x1::account::Account",
"data": {
"authentication_key": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
"coin_register_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
"creation_num": "0"
}
}
},
"guid_creation_num": "2",
"key_rotation_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
"creation_num": "1"
}
}
},
"rotation_capability_offer": {
"for": { "vec": [] }
},
"sequence_number": "234285",
"signer_capability_offer": {
"for": { "vec": [] }
}
}
}
]import requests
url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/resources?ledger_version=3357308041&limit=10"
response = requests.get(url)
print(response.text)import axios from 'axios';
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/resources?ledger_version=3357308041&limit=10',
headers: {}
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});https://go.getblock.io/<ACCESS\_TOKEN>/curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/events/0x1::account::Account/coin_register_events' [
{
"version": "2304959",
"guid": {
"creation_number": "0",
"account_address": "0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12"
},
"sequence_number": "0",
"type": "0x1::account::CoinRegisterEvent",
"data": {
"type_info": {
"account_address": "0x1",
"module_name": "0x6170746f735f636f696e",
"struct_name": "0x4170746f73436f696e"
}
}
},
{
"version": "2665347733",
"guid": {
"creation_number": "0",
"account_address": "0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12"
},
"sequence_number": "1",
"type": "0x1::account::CoinRegisterEvent",
"data": {
"type_info": {
"account_address": "0xec42a352cc65eca17a9fa85d0fc602295897ed6b8b8af6a6c79ef490eb8f9eba",
"module_name": "0x616d6d5f73776170",
"struct_name": "0x506f6f6c4c6971756964697479436f696e3c3078313a3a6170746f735f636f696e3a3a4170746f73436f696e2c203078663232626564653233376130376531323162353664393161343931656237626364666431663539303739323661396535383333386639363461303162313766613a3a61737365743a3a555344543e"
}
}
}
] import requests
url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/events/0x1::account::Account/coin_register_events"
response = requests.get(url)
print(response.text) import axios from 'axios';
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/events/0x1::account::Account/coin_register_events'
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import requests
url = "https://go.getblock.io/<ACCESS-TOKEN>/"
headers = { "Content-Type": "application/json" }
payload = { "jsonrpc": "2.0", "method": "eth_blockNumber", "params": [], "id": "getblock.io" }
response = requests.post(url, headers=headers, json=payload)
print(response.json())curl -hcurl --location --request POST 'https://go.getblock.io/<ACCESS-TOKEN>/' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": "getblock.io"
}'python -m pip install requestsimport requests
url = "https://go.getblock.io/<ACCESS-TOKEN>/"
headers = { "Content-Type": "application/json" }
payload = { "jsonrpc": "2.0", "method": "eth_blockNumber", "params": [], "id": "getblock.io" }
response = requests.post(url, headers=headers, json=payload)
print(response.json())node -vruby -vimport requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_getBlockTransactionCountByNumber",
"params": [
"latest"
],
"id": "getblock.io"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_getBlockTransactionCountByNumber",
"params": [
"latest"
],
"id": "getblock.io"
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": "0x8"
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function Call() {
try {
const result = await provider.send("eth_getBlockTransactionCountByNumber",
["latest"]);
console.log("The result:", result);
return result;
} catch (error) {
console.error("The error:", error);
throw error;
}
}import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
// Create Viem client with GetBlock
const client = createPublicClient({
chain: arbitrum,
transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
});
// Using the method through Viem
async function Call() {
try {
// Method-specific Viem implementation
const result = await client.request({
method: "eth_getBlockTransactionCountByNumber",
params: ["latest"]
});
console.log('Result:', result);
return result;
} catch (error) {
console.error('Viem Error:', error);
throw error;
}
}
import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_getBalance",
"id": "getblock.io",
"params": [
"0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
"latest"
],
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"id": "getblock.io",
"params": [
"0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
"latest"
],
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": "0x20a2c3a842980"
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function Call() {
try {
const result = await provider.send("eth_getBalance", ["0xb8b2522480f850eb198ada5c3f31ac528538d2f5", "latest"]);
console.log("The result:", result);
return result;
} catch (error) {
console.error("The error:", error);
throw error;
}
}import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
// Create Viem client with GetBlock
const client = createPublicClient({
chain: arbitrum,
transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
});
// Using the method through Viem
async function Call() {
try {
// Method-specific Viem implementation
const result = await client.request({
method: 'eth_getBalance',
params: ["0xb8b2522480f850eb198ada5c3f31ac528538d2f5", "latest"],
});
console.log('Result:', result);
return result;
} catch (error) {
console.error('Viem Error:', error);
throw error;
}
}
import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_gasPrice",
"id": "getblock.io",
"params": [],
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_gasPrice",
"id": "getblock.io",
"params": [],
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": "0x989680"
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function Call() {
try {
const result = await provider.send("eth_gasPrice", []);
console.log("The result:", result);
return result;
} catch (error) {
console.error("The error:", error);
throw error;
}
}import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
// Create Viem client with GetBlock
const client = createPublicClient({
chain: arbitrum,
transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
});
// Using the method through Viem
async function Call() {
try {
// Method-specific Viem implementation
const result = await client.request({
method: 'eth_gasPrice',
});
console.log('Result:', result);
return result;
} catch (error) {
console.error('Viem Error:', error);
throw error;
}
}
RBAC: access deniednode index.js{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": "0x183037af"
}python main.pyhttps://go.getblock.us/https://go.getblock.iomkdir arbitrum-api-quickstart
cd arbitrum-api-quickstart
npm init --yesmkdir arbitrum-api-quickstart
cd arbitrum-api-quickstart
yarn init --yesnpm install axiosyarn add axiosmkdir arbitrum-api-quickstart
cd arbitrum-api-quickstartpython -m venv venv
source venv/bin/activate
# On Windows, use venv\Scripts\activatepip install requestsimport axios from 'axios'
let data = JSON.stringify({
jsonrpc: "2.0",
method: "eth_blockNumber",
params: [],
id: "getblock.io",
});
let config = {
method: "post",
maxBodyLength: Infinity,
url: "https://go.getblock.us/<ACCESS_TOKEN>",
headers: {
"Content-Type": "application/json",
},
data: data,
};
axios
.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import requests
import json
url = "https://go.getblock.us/<ACCESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": "getblock.io"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header '
import axios from 'axios'
let
curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header '
import axios from 'axios'
let
curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header '
import axios from 'axios'
let
Example code for the eth_getStorageAt JSON RPC method. Сomplete guide on how to use eth_getStorageAt JSON RPC in GetBlock Web3 documentation.
Example code for the eth_getTransactionCount JSON RPC method. Сomplete guide on how to use eth_getTransactionCount JSON RPC in GetBlock Web3 documentation.
https://go.getblock.io/<ACCESS_TOKEN>/curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/module/curves'{
"bytecode": "0xa11ceb0b050000000b01000402040c03101e042e0c053a0f07497e08c701400687020a109102300ac1020a0ccb023e00000101000200000003000001090700000400000100000500010100000600010100000700010100010a000301000302040204040405020201020001010109000108020108000108010663757276657309747970655f696e666f06537461626c650c556e636f7272656c61746564126173736572745f76616c69645f63757276650969735f737461626c650f69735f756e636f7272656c617465640e69735f76616c69645f63757276650b64756d6d795f6669656c640854797065496e666f07747970655f6f66190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12000000000000000000000000000000000000000000000000000000000000000103081127000000000000126170746f733a3a6d657461646174615f76301c011127000000000000114552525f494e56414c49445f43555256450000020108010102010801000100000005380003040700270201010000000438013802210202010000000438013803210203010000010a380403030506080c00050838050c000b000200",
"abi": {
"address": "0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12",
"name": "curves",
"friends": [],
"exposed_functions": [
{
"name": "assert_valid_curve",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [{ "constraints": [] }],
"params": [],
"return": []
},
{
"name": "is_stable",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [{ "constraints": [] }],
"params": [],
"return": ["bool"]
},
{
"name": "is_uncorrelated",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [{ "constraints": [] }],
"params": [],
"return": ["bool"]
},
{
"name": "is_valid_curve",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [{ "constraints": [] }],
"params": [],
"return": ["bool"]
}
],
"structs": [
{
"name": "Stable",
"is_native": false,
"is_event": false,
"abilities": [],
"generic_type_params": [],
"fields": [{ "name": "dummy_field", "type": "bool" }]
},
{
"name": "Uncorrelated",
"is_native": false,
"is_event": false,
"abilities": [],
"generic_type_params": [],
"fields": [{ "name": "dummy_field", "type": "bool" }]
}
]
}
}import requests
url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/module/curves"
response = requests.get(url)
print(response.text)import axios from 'axios';
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/module/curves'
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});https://go.getblock.io/<ACCESS_TOKEN>curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions?limit=1'[
{
"version": "3556744764",
"hash": "0x1cd28f386d48edfaf30c822117bd0b971e349c59f5fdd08f284558b33ac1715f",
"state_change_hash": "0xafb6e14fe47d850fd0a7395bcfb997ffacf4715e0f895cc162c218e4a7564bc6",
"event_root_hash": "0x414343554d554c41544f525f504c414345484f4c4445525f4841534800000000",
"state_checkpoint_hash": "0xe8daf9e9f3986dc69e0247b5638af4f55a6e5912da8a2c71e1fa537009a59964",
"gas_used": "0",
"success": true,
"vm_status": "Executed successfully",
"accumulator_root_hash": "0x6a006a1a2d4d22b7fdf4ca27a31aac610c3911429d8e5f925e31016738b225e2",
"changes": [],
"timestamp": "1760341338522220",
"block_end_info": {
"block_gas_limit_reached": false,
"block_output_limit_reached": false,
"block_effective_block_gas_units": 71,
"block_approx_output_size": 7846
},
"type": "block_epilogue_transaction"
}
]
const axios = require('axios');
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions?limit=1',
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import requests
url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions?limit=1"
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)
https://go.getblock.io/<ACCESS_TOKEN>curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/blocks/by_height/425737645?with_transactions=false'
{
"block_height": "445814139",
"block_hash": "0x0ac6b36f89b6a3fc9b7c2cabcb1f29cc624e609ed0978dd2a757b048196cb3bc",
"block_timestamp": "1759349325550593",
"first_version": "3492983944",
"last_version": "3492983948",
"transactions": null
}import requests
url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/blocks/by_height/425737645?with_transactions=false"
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)import axios from ‘axios’
let config = {
method: 'get',
maxBodyLength: Infinity,
url: "https://go.getblock.io/<ACCESS_TOKEN>/v1/blocks/by_height/425737645?with_transactions=false"
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});https://go.getblock.io/<ACCESS_TOKEN>curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_version/3363904007'{
"version": "3363904007",
"hash": "0xd797b944ed8657406a1b09a5928048093399fc0a2f576d3e57c0f9cedbf95c4a",
"state_change_hash": "0xafb6e14fe47d850fd0a7395bcfb997ffacf4715e0f895cc162c218e4a7564bc6",
"event_root_hash": "0x414343554d554c41544f525f504c414345484f4c4445525f4841534800000000",
"state_checkpoint_hash": "0xbf257d934f991d1e7d74079cc9060d3ac005aaa208d93a1fd4928dfc224bba53",
"gas_used": "0",
"success": true,
"vm_status": "Executed successfully",
"accumulator_root_hash": "0xc985314d5c118899c649b772c237178c63f328e7d286aceea01a30373d491d95",
"changes": [],
"timestamp": "1757261767411156",
"block_end_info": {
"block_gas_limit_reached": false,
"block_output_limit_reached": false,
"block_effective_block_gas_units": 500,
"block_approx_output_size": 21541
},
"type": "block_epilogue_transaction"
}
const axios = require('axios');
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_version/3541136893',
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});import requests
url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_version/3541136893"
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)https://go.getblock.io/<ACCESS-TOKEN>/curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/resource/0x1::account::Account'{
"type": "0x1::account::Account",
"data": {
"authentication_key": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
"coin_register_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
"creation_num": "0"
}
}
},
"guid_creation_num": "2",
"key_rotation_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
"creation_num": "1"
}
}
},
"rotation_capability_offer": {
"for": {
"vec": []
}
},
"sequence_number": "250163",
"signer_capability_offer": {
"for": {
"vec": []
}
}
}
}
import requests
url = "https://go.getblock.io/b293629b1b3a4e188efb3c4e94d133b6/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/resource/0x1::account::Account"
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)
import axios from 'axios'
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://go.getblock.io/b293629b1b3a4e188efb3c4e94d133b6/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/resource/0x1::account::Account',
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
https://go.getblock.io/
<ACCESS_TOKEN>curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f/events/0'[
{
"version": "2665347733",
"guid": {
"creation_number": "0",
"account_address": "0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12"
},
"sequence_number": "1",
"type": "0x1::account::CoinRegisterEvent",
"data": {
"type_info": {
"account_address": "0xec42a352cc65eca17a9fa85d0fc602295897ed6b8b8af6a6c79ef490eb8f9eba",
"module_name": "0x616d6d5f73776170",
"struct_name": "0x506f6f6c4c6971756964697479436f696e3c3078313a3a6170746f735f636f696e3a3a4170746f73436f696e2c203078663232626564653233376130376531323162353664393161343931656237626364666431663539303739323661396535383333386639363461303162313766613a3a61737365743a3a555344543e"
}
}
}
]
import axios from 'axios';
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xc32f662cd9718f02d8a8e5628f8f642fa27cd9b5f457b406ed734901a4939e34/events/0?limit=1&start=1'
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});import requests
url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xc32f662cd9718f02d8a8e5628f8f642fa27cd9b5f457b406ed734901a4939e34/events/0?limit=1&start=1"
response = requests.get(url)
print(response.text)import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_call",
"id": "getblock.io",
"params": [
{
"to": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
"data": "0x8da5cb5b"
},
"latest"
]
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{{
"jsonrpc": "2.0",
"method": "eth_call",
"id": "getblock.io",
"params": [
{
"to": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
"data": "0x8da5cb5b"
},
"latest"
]
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/24915a36b17143a891d3b10447615258";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function Call() {
try {
// Call the method — this will resolve to a number (promise resolves to number)
const result = await provider.send("eth_call", [
{
to: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
data: "0x8da5cb5b",
},
"latest",
]);
console.log("The result:", result);
return result;
} catch (error) {
console.error("Ethers Error fetching block number:", error);
throw error;
}
}
{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": "0x0000000000000000000000002bad8182c09f50c8318d769245bea52c32be46cd"
}import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_getCode",
"params": [
"0x9b956e3d318625be2686ae7268d81777c462d41f",
"latest"
],
"id": "getblock.io"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_getCode",
"params": [
"0x9b956e3d318625be2686ae7268d81777c462d41f",
"latest"
],
"id": "getblock.io"
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function Call() {
try {
const result = await provider.send("eth_getCode",
[
"0x9b956e3d318625be2686ae7268d81777c462d41f",
"latest"
],);
console.log("The result:", result);
return result;
} catch (error) {
console.error("The error:", error);
throw error;
}
}import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
// Create Viem client with GetBlock
const client = createPublicClient({
chain: arbitrum,
transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
});
// Using the method through Viem
async function Call() {
try {
// Method-specific Viem implementation
const result = await client.request({
"method": "eth_getCode",
"params": [
"0x9b956e3d318625be2686ae7268d81777c462d41f",
"latest"
]
});
console.log('Result:', result);
return result;
} catch (error) {
console.error('Viem Error:', error);
throw error;
}
}
{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": "0x"
}import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_getBlockTransactionCountByHash",
"params": [
"0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a"
],
"id": "getblock.io"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_getBlockTransactionCountByHash",
"params": [
"0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a"
],
"id": "getblock.io"
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function Call() {
try {
const result = await provider.send("eth_getBlockTransactionCountByHash",
["0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a"]);
console.log("The result:", result);
return result;
} catch (error) {
console.error("The error:", error);
throw error;
}
}import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
// Create Viem client with GetBlock
const client = createPublicClient({
chain: arbitrum,
transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
});
// Using the method through Viem
async function Call() {
try {
// Method-specific Viem implementation
const result = await client.request({
method: "eth_getBlockTransactionCountByHash",
params: ["0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a"]
});
console.log('Result:', result);
return result;
} catch (error) {
console.error('Viem Error:', error);
throw error;
}
}
{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": "0x5"
}curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"method": "eth_getStorageAt",
"params": [
"0x80d40e32FAD8bE8da5C6A42B8aF1E181984D137c",
"0x0",
"latest"
],
"id": "getblock.io"
}'import axios from 'axios'
let data = JSON.stringify({
"jsonrpc": "2.0",
"method": "eth_getStorageAt",
"params": [
"0x80d40e32FAD8bE8da5C6A42B8aF1E181984D137c",
"0x0",
"latest"
],
"id": "getblock.io"
};
let config = {
method: "post",
maxBodyLength: Infinity,
url: "https://go.getblock.us/<ACCESS_TOKEN>",
headers: {
"Content-Type": "application/json",
},
data: data,
};
axios
.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"method": "eth_getTransactionCount",
"params": [
"0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
"latest"
],
"id": "getblock.io"
}'import axios from 'axios'
let data = JSON.stringify({
"jsonrpc": "2.0",
"method": "eth_getTransactionCount",
"params": [
"0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
"latest"
],
"id": "getblock.io"
};
let config = {
method: "post",
maxBodyLength: Infinity,
url: "https://go.getblock.us/<ACCESS_TOKEN>",
headers: {
"Content-Type": "application/json",
},
data: data,
};
axios
.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_getStorageAt",
"params": [
"0x80d40e32FAD8bE8da5C6A42B8aF1E181984D137c",
"0x0",
"latest"
],
"id": "getblock.io"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_getStorageAt",
"params": [
"0x80d40e32FAD8bE8da5C6A42B8aF1E181984D137c",
"0x0",
"latest"
],
"id": "getblock.io"
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": "0x000000000000000000000000aadc76c6e4abeeb52d764443357f6e75db28f0e1"
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function Call() {
try {
const result = await provider.send("eth_getStorageAt",
[
"0x80d40e32FAD8bE8da5C6A42B8aF1E181984D137c",
"0x0",
"latest"
],);
console.log("The result:", result);
return result;
} catch (error) {
console.error("The error:", error);
throw error;
}
}import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
// Create Viem client with GetBlock
const client = createPublicClient({
chain: arbitrum,
transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
});
// Using the method through Viem
async function Call() {
try {
// Method-specific Viem implementation
const result = await client.request({
method: "eth_getStorageAt",
params: [
"0x80d40e32FAD8bE8da5C6A42B8aF1E181984D137c",
"0x0",
"latest"
]
});
console.log('Result:', result);
return result;
} catch (error) {
console.error('Viem Error:', error);
throw error;
}
}
import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_getTransactionCount",
"params": [
"0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
"latest"
],
"id": "getblock.io"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_getTransactionCount",
"params": [
"0xb8b2522480f850eb198ada5c3f31ac528538d2f5",
"latest"
],
"id": "getblock.io"
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": "0x50"
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function Call() {
try {
const result = await provider.send("eth_getTransactionByHash",
[
"0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181"
]);
console.log("The result:", result);
return result;
} catch (error) {
console.error("The error:", error);
throw error;
}
}import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
// Create Viem client with GetBlock
const client = createPublicClient({
chain: arbitrum,
transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
});
// Using the method through Viem
async function Call() {
try {
// Method-specific Viem implementation
const result = await client.request({
method: "eth_getTransactionCount",
params: ["0xb8b2522480f850eb198ada5c3f31ac528538d2f5", "latest"]});
console.log('Result:', result);
return result;
} catch (error) {
console.error('Viem Error:', error);
throw error;
}
}
mkdir multicall3-example
cd multicall3-example
npm init
mkdir multicall3-example
cd multicall3-example
yarn init
curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header '
import axios from 'axios'
let
Example code for the eth_getTransactionByBlockHashAndIndex JSON RPC method. Сomplete guide on how to use eth_getTransactionByBlockHashAndIndex JSON RPC in GetBlock Web3 documentation.
Example code for the eth_getTransactionByHash JSON RPC method. Сomplete guide on how to use eth_getTransactionByHash JSON RPC in GetBlock Web3 documentation.
Example code for the eth_getTransactionByBlockNumberAndIndex JSON RPC method. Сomplete guide on how to use eth_getTransactionByBlockNumberAndIndex JSON RPC in GetBlock Web3 documentation.
Learn how to build an AI agent that swap token, checks balance and transfers on Solana
const PANCAKE_ROUTER = '0x10ED43C718714eb63d5aA57B78B54704E256024E';
const WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
const TOKEN_ADDRESS = '0xYOUR_TOKEN_ADDRESS';
// Build the swap calldata
const routerABI = [
'function swapExactETHForTokens(uint256 amountOutMin, address[] path, address to, uint256 deadline)'
];
const router = new ethers.Contract(PANCAKE_ROUTER, routerABI, wallet);
const deadline = Math.floor(Date.now() / 1000) + 300; // 5 minutes from now
const swapData = router.interface.encodeFunctionData('swapExactETHForTokens', [
minAmountOut,
[WBNB, TOKEN_ADDRESS],
wallet.address,
deadline
]);
// Construct the Multicall3 calls
const calls = [
{
target: BLOXROUTE_FEE,
allowFailure: false,
value: ethers.parseEther('0.0005'), // Priority fee
callData: '0x'
},
{
target: PANCAKE_ROUTER,
allowFailure: false,
value: ethers.parseEther('1.0'), // Swap amount
callData: swapData
}
];https://go.getblock.io/<ACCESS_TOKEN>curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_version/3556737308?with_transactions=false'{
"block_height": "456015808",
"block_hash": "0xdbe2cbd48ec3b897fa5f6b1ff51bd8eef280e300e12b6ff153b3959a7440a268",
"block_timestamp": "1760341227055115",
"first_version": "3556737303",
"last_version": "3556737309",
"transactions": null
}
const axios = require('axios');
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_version/3363904007',
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});import requests
url = 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_version/3363904007'
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_estimateGas",
"id": "getblock.io",
"params": [
{
"from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"to": "0x44aa93095d6749a706051658b970b941c72c1d53",
"value": "0x1"
}
],
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_estimateGas",
"id": "getblock.io",
"params": [
{
"from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"to": "0x44aa93095d6749a706051658b970b941c72c1d53",
"value": "0x1"
}
],
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function Call() {
try {
const result = await provider.send("eth_estimateGas", [
{
from: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
to: "0x44aa93095d6749a706051658b970b941c72c1d53",
value: "0x1",
},
]);
console.log("The result:", result);
return result;
} catch (error) {
console.error("The error:", error);
throw error;
}
}import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
// Create Viem client with GetBlock
const client = createPublicClient({
chain: arbitrum,
transport: http("https://go.getblock.us/<ACCESS_TOKEN>");
// Using the method through Viem
async function Call() {
try {
// Method-specific Viem implementation
const result = await client.request({
method: "eth_estimateGas",
params: [
{
from: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
to: "0x44aa93095d6749a706051658b970b941c72c1d53",
value: "0x1",
},
]
});
console.log('Result:', result);
return result;
} catch (error) {
console.error('Viem Error:', error);
throw error;
}
}{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": "0x5208"
}curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"method": "eth_getTransactionByBlockHashAndIndex",
"params": [
"0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
"0x0"
],
"id": "getblock.io"
}'import axios from 'axios'
let data = JSON.stringify({
"jsonrpc": "2.0",
"method": "eth_getTransactionByBlockHashAndIndex",
"params": [
"0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
"0x0"
],
"id": "getblock.io"
};
let config = {
method: "post",
maxBodyLength: Infinity,
url: "https://go.getblock.us/<ACCESS_TOKEN>",
headers: {
"Content-Type": "application/json",
},
data: data,
};
axios
.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"method": "eth_getTransactionByHash",
"params": [
"0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181"
],
"id": "getblock.io"
}'import axios from 'axios'
let data = JSON.stringify({
"jsonrpc": "2.0",
"method": "eth_getTransactionByHash",
"params": [
"0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181"
],
"id": "getblock.io"
};
let config = {
method: "post",
maxBodyLength: Infinity,
url: "https://go.getblock.us/<ACCESS_TOKEN>",
headers: {
"Content-Type": "application/json",
},
data: data,
};
axios
.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"method": "eth_getTransactionByBlockNumberAndIndex",
"params": ["latest", "0x0"],
"id": "getblock.io"
}'import axios from 'axios'
let data = JSON.stringify({
"jsonrpc": "2.0",
"method": "eth_getTransactionByBlockNumberAndIndex",
"params": ["latest", "0x0"],
"id": "getblock.io"
};
let config = {
method: "post",
maxBodyLength: Infinity,
url: "https://go.getblock.us/<ACCESS_TOKEN>",
headers: {
"Content-Type": "application/json",
},
data: data,
};
axios
.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_getTransactionByBlockHashAndIndex",
"params": [
"0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
"0x0"
],
"id": "getblock.io"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_getTransactionByBlockHashAndIndex",
"params": [
"0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
"0x0"
],
"id": "getblock.io"
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": {
"blockHash": "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
"blockNumber": "0x5206d53",
"from": "0x00000000000000000000000000000000000a4b05",
"gas": "0x0",
"gasPrice": "0x0",
"hash": "0xaf256a9ce8839489dcaa4f9a2740bcd5865b3db34a15434cce29e6bdcf043bc7",
"input": "0x6bf6a42d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105e0460000000000000000000000000000000000000000000000000000000005206d530000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0",
"to": "0x00000000000000000000000000000000000a4b05",
"transactionIndex": "0x0",
"value": "0x0",
"type": "0x6a",
"chainId": "0xa4b1",
"v": "0x0",
"r": "0x0",
"s": "0x0"
}
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function Call() {
try {
const result = await provider.send("eth_getTransactionByBlockHashAndIndex",
[
"0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
"0x0"
]);
console.log("The result:", result);
return result;
} catch (error) {
console.error("The error:", error);
throw error;
}
}import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
// Create Viem client with GetBlock
const client = createPublicClient({
chain: arbitrum,
transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
});
// Using the method through Viem
async function Call() {
try {
// Method-specific Viem implementation
const result = await client.request({
method: "eth_getTransactionByBlockHashAndIndex",
params: [
"0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
"0x0"
]
});
console.log('Result:', result);
return result;
} catch (error) {
console.error('Viem Error:', error);
throw error;
}
}
import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_getTransactionByHash",
"params": [
"0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181"
],
"id": "getblock.io"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_getTransactionByHash",
"params": [
"0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181"
],
"id": "getblock.io"
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": {
"blockHash": "0xd8fe755134d44967f0c919084d3e0ec9b875c476c924f37bff17e5ef37d10d47",
"blockNumber": "0x5911313",
"from": "0xe911f7f98ac57cf0c1cc71519d3ba720089381c4",
"gas": "0x1a02b0",
"gasPrice": "0x1dcd6500",
"hash": "0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181",
"input": "0x1801fbe5d5843b1d8c7345812c7ba7257e927b0c5e000000a6ca46b71aa1cdb6545660ad000000004f62e6aa5433274e333035ca261c12397df9febee0782f42749b8e0b",
"nonce": "0x3c",
"to": "0xae56c981f9bb8b07e380b209fcd1498c5876fd4c",
"transactionIndex": "0x1",
"value": "0x0",
"type": "0x0",
"chainId": "0xa4b1",
"v": "0x14986",
"r": "0x87ac24f33be39a0bd27fe84a8934aa957610872606e5dbc46d296843a57930df",
"s": "0x6ad9aba71382c20a528f3310c369b095e15991b352aea3261e2683c2b1288964"
}
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function Call() {
try {
const result = await provider.send("eth_getTransactionByHash",
[
"0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181"
]);
console.log("The result:", result);
return result;
} catch (error) {
console.error("The error:", error);
throw error;
}
}import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
// Create Viem client with GetBlock
const client = createPublicClient({
chain: arbitrum,
transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
});
// Using the method through Viem
async function Call() {
try {
// Method-specific Viem implementation
const result = await client.request({
method: "eth_getTransactionByHash",
params: [
"0xfd11ef35c7179439723e026cb7857ea5a2e48a19257bec00b0ed26672f632181"
],
});
console.log('Result:', result);
return result;
} catch (error) {
console.error('Viem Error:', error);
throw error;
}
}
import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_getTransactionByBlockNumberAndIndex",
"params": ["latest", "0x0"],
"id": "getblock.io"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_getTransactionByBlockNumberAndIndex",
"params": ["latest", "0x0"],
"id": "getblock.io"
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": {
"blockHash": "0xbb465c64e929a4700a6c5cfc3355e651e0f558134e09e06b4c65657f24499cec",
"blockNumber": "0x185f29e6",
"from": "0x00000000000000000000000000000000000a4b05",
"gas": "0x0",
"gasPrice": "0x0",
"hash": "0x61d48ab94f7fccf48f4baa3903781053f932feb466474c037736e910d7ca2afe",
"input": "0x6bf6a42d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016ddb2700000000000000000000000000000000000000000000000000000000185f29e60000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0",
"to": "0x00000000000000000000000000000000000a4b05",
"transactionIndex": "0x0",
"value": "0x0",
"type": "0x6a",
"chainId": "0xa4b1",
"v": "0x0",
"r": "0x0",
"s": "0x0"
}
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function Call() {
try {
const result = await provider.send( "eth_getTransactionByBlockNumberAndIndex",
["latest", "0x0"]);
console.log("The result:", result);
return result;
} catch (error) {
console.error("The error:", error);
throw error;
}
}import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
// Create Viem client with GetBlock
const client = createPublicClient({
chain: arbitrum,
transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
});
// Using the method through Viem
async function Call() {
try {
// Method-specific Viem implementation
const result = await client.request({
method: "eth_getTransactionByBlockNumberAndIndex",
params: ["latest", "0x0"]
});
console.log('Result:', result);
return result;
} catch (error) {
console.error('Viem Error:', error);
throw error;
}
}
Example code for the eth_getBlockByHash JSON RPC method. Сomplete guide on how to use eth_getBlockByHash JSON RPC in GetBlock Web3 documentation.
Example code for the eth_getBlockByNumber JSON RPC method. Сomplete guide on how to use eth_getBlockByNumber JSON RPC in GetBlock Web3 documentation.
Learn how to submit transaction to private mempool directly to block builders, protecting you from MEV extraction until it's included in a block.
ACCESS_TOKEN=your-accelerated-node-endpoint
RPC_URL=your-normal-bsc-node-endppoint //e.g https
PRIVATE_KEY=your-wallet-private-keyimport WebSocket from "ws";
import { ethers } from "ethers";
import "dotenv/config";
const PRIVATE_KEY = process.env.PRIVATE_KEY
const RPC_URL = process.env.RPC_URL;
// Constants
const MULTICALL3 = "0xcA11bde05977b3631167028862bE2a173976CA11";
const BLOXROUTE_FEE = "0x6374Ca2da5646C73Eb444aB99780495d61035f9b";
const MULTICALL_ABI = [
"function aggregate3Value(tuple(address target, bool allowFailure, uint256 value, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[])",
];
async function sendPrivateTxWithTip() {
const provider = new ethers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
console.log("Wallet:", wallet.address);
// Define amounts
const tipAmount = ethers.parseEther("0.0001"); // 0.0001 BNB tip
const transferAmount = ethers.parseEther("0.001"); // Your actual transfer
const totalValue = tipAmount + transferAmount;
// Build Multicall3 calls
const calls = [
{
target: BLOXROUTE_FEE, // Tip payment FIRST
allowFailure: false,
value: tipAmount,
callData: "0x", // Empty = simple transfer
},
{
target: process.env.TO_ADDRESS, // Your actual transaction
allowFailure: false,
value: transferAmount,
callData: "0x", // Or your contract calldata
},
];
// Encode Multicall3 call
const multicall = new ethers.Contract(MULTICALL3, MULTICALL_ABI, wallet);
const data = multicall.interface.encodeFunctionData("aggregate3Value", [
calls,
]);
// Get nonce
const nonce = await provider.getTransactionCount(wallet.address);
// Sign transaction
const signedTx = await wallet.signTransaction({
nonce: nonce,
to: MULTICALL3,
value: totalValue,
data: data,
gasPrice: ethers.parseUnits("3", "gwei"),
gasLimit: 150000, // Higher for Multicall3
chainId: 56,
});
const signedTxNoPrefix = signedTx.startsWith("0x")
? signedTx.slice(2)
: signedTx;
console.log("Transaction built:");
console.log(" Tip:", ethers.formatEther(tipAmount), "BNB");
console.log(" Transfer:", ethers.formatEther(transferAmount), "BNB");
console.log(" Total:", ethers.formatEther(totalValue), "BNB");
// Send via bsc_private_tx
const ws = new WebSocket(process.env.ACCESS_TOKEN);
ws.on("open", () => {
const request = {
jsonrpc: "2.0",
id: 1,
method: "bsc_private_tx",
params: {
transaction: signedTxNoPrefix,
mev_builders: ["all"],
},
};
console.log("\nSending private TX with tip...");
ws.send(JSON.stringify(request));
});
ws.on("message", (data) => {
const response = JSON.parse(data);
if (response.result) {
console.log("\n✅ Transaction submitted!");
console.log("TX Hash:", response.result.txHash);
console.log(
"BSCScan:",
`https://bscscan.com/tx/${response.result.txHash}`,
);
} else {
console.error("\n❌ Error:", response.error);
}
ws.close();
});
}
sendPrivateTxWithTip().catch(console.error);
node index.jsWallet: 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/61bd625be986bb45e9fb495a5dba7bf39e00fd6871176971663436465311c970mkdir token-2022-tutorial
cd token-2022-tutorial
npm init -ynpm install @solana/web3.js @solana/spl-token @solana/spl-token-metadata dotenvimport {
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";import { Connection, Keypair } from "@solana/web3.js";
import bs58 from "bs58";
import 'dotenv/config'
// Replace with your GetBlock endpoint
const GETBLOCK_RPC_URL = process.env.RPC_URL;
// Create connection to Solana via GetBlock
const connection = new Connection(GETBLOCK_RPC_URL, "confirmed");
// Load keypair from private key in .env
const payer = Keypair.fromSecretKey(bs58.decode(process.env.PRIVATE_KEY));
export { connection, payer};mkdir solana-ai-agent
cd solana-ai-agentpnpm 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 dotenvimport { crossmint } from "@goat-sdk/crossmint";
import { Connection, Keypair } from "@solana/web3.js";
import { solana } from "@goat-sdk/wallet-solana";
import { jupiter } from "@goat-sdk/plugin-jupiter";
import { splToken } from "@goat-sdk/plugin-spl-token";
import { getOnChainTools } from "@goat-sdk/adapter-langchain";
import { ChatOpenAI } from "@langchain/openai";
import { pumpfun } from "@goat-sdk/plugin-pumpfun";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { MemorySaver } from "@langchain/langgraph";
import * as dotenv from "dotenv";
import bs58 from "bs58";
import * as readline from "readline";
async function initializeAgent() { .....
// continuation
const tools = await getOnChainTools({
wallet: solana({
keypair,
connection,
}),
plugins: [
splToken(),
pumpfun(),
jupiter(),
crossmint()
],
});
}
/// rest of code (readline interface and agent.invoke loop)
https://go.getblock.io/<ACCESS_TOKEN>curl -X GET "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f
/transactions?limit=5"[
{
"version": "3574927316",
"hash": "0x01ef3543f79823b3a9fbc8acac9fba4bb25c7c1abb65f533caff2d9bcc0678f6",
"state_change_hash": "0x5cfb448ecb226172f3f5279d02658a645afdacf88a1ce308bf5b0717eca0c99e",
"event_root_hash": "0x63937d2f2e996f5c9e6cd669e518fdf7e474af4902a11501ec15dbb8d53e5ce9",
"state_checkpoint_hash": null,
"gas_used": "82",
"success": true,
"vm_status": "Executed successfully",
"accumulator_root_hash": "0x3d25cf24e802a777497da7f76fdeb05a472b30586f2171b82fbb72e1e3504609",
"changes": [
{
"address": "0xa",
"state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
"data": {
"type": "0x1::coin::PairedCoinType",
"data": {
"type": {
"account_address": "0x1",
"module_name": "0x6170746f735f636f696e",
"struct_name": "0x4170746f73436f696e"
}
}
},
"type": "write_resource"
}
],
"sender": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
"sequence_number": "871700",
"max_gas_amount": "200000",
"gas_unit_price": "100",
"expiration_timestamp_secs": "1760643271",
"payload": {
"function": "0x487e905f899ccb6d46fdaec56ba1e0c4cf119862a16c409904b8c78fab1f5e8a::router::swap",
"type_arguments": [],
"arguments": [
"0x82e0b52f95ae57b35220726a32c3415919389aa5b8baa33a058d7125797535cc01000000000000000000000000000000683e030100000000000000000000000000000000000000000000000000000000d093f60000000000000000000000000000000000000000000000000000000000"
],
"type": "entry_function_payload"
},
"signature": {
"public_key": "0x7df17b23676ef29e040847e64ae2a8351819d4bfaf64f3bfe2124d92156c1c02",
"signature": "0x8001b27ddb488c1ad5f4f6ed7fe4886b42528b0646a05685469b524b67cc6298192fa42d9af5ff2df1791c88f2f16dfdc22c8c1d5060795c68161a25ef335d01",
"type": "ed25519_signature"
},
"replay_protection_nonce": null,
"events": [
{
"guid": {
"creation_number": "0",
"account_address": "0x0"
},
"sequence_number": "0",
"type": "0xa611a8ba7261ed1f4d3afe4ac2166fc9f3180103e3296772d593a1e2720c7405::stable::IncentiveSynced",
"data": {
"accumulated_rewards_per_share": "33902212381193",
"campaign_idx": "15",
"last_accumulation_time": "1760643255",
"last_total_shares": "4992836695498717952869616",
"pool_addr": "0x82e0b52f95ae57b35220726a32c3415919389aa5b8baa33a058d7125797535cc",
"total_distributed": "25151305402",
"ts": "1760643255618178"
}
},
{
"guid": {
"creation_number": "0",
"account_address": "0x0"
},
"sequence_number": "0",
"type": "0xa611a8ba7261ed1f4d3afe4ac2166fc9f3180103e3296772d593a1e2720c7405::stable::Swapped",
"data": {
"bought_id": "0",
"buyer": "0xbf9239be9eb7e7a3d8e4c1f36083464fd47e6bd1f82a43b7c0f7ee958705a52f",
"pool_addr": "0x82e0b52f95ae57b35220726a32c3415919389aa5b8baa33a058d7125797535cc",
"sold_id": "1",
"stored_balances": [
"1990058935750",
"3042379974793"
],
"tokens_bought": "16980317",
"tokens_sold": "16989240",
"ts": "1760643255618178"
}
},
"timestamp": "1760643255618178",
"type": "user_transaction"
}
]import requests
url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xc20ea5a196c81d8d7aff814aa37f8a5823acffbc4193efd3b2aafc9ef2803255/transactions"
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)
import axios from 'axios';
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0xc20ea5a196c81d8d7aff814aa37f8a5823acffbc4193efd3b2aafc9ef2803255/transactions',
headers: { }
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});

curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"method": "eth_getBlockByHash",
"params": [
"0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
false
],
"id": "getblock.io"
}'import axios from 'axios'
let data = JSON.stringify({
"jsonrpc": "2.0",
"method": "eth_getBlockByHash",
"params": [
"0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
false
],
"id": "getblock.io"
};
let config = {
method: "post",
maxBodyLength: Infinity,
url: "https://go.getblock.us/<ACCESS_TOKEN>",
headers: {
"Content-Type": "application/json",
},
data: data,
};
axios
.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
curl --location 'https://go.getblock.us/<ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"method": "eth_getBlockByNumber",
"params": [
"latest",
false
],
"id": "getblock.io"
}'import axios from 'axios'
let data = JSON.stringify({
"jsonrpc": "2.0",
"method": "eth_getBlockByNumber",
"params": [
"latest",
false
],
"id": "getblock.io"
};
let config = {
method: "post",
maxBodyLength: Infinity,
url: "https://go.getblock.us/<ACCESS_TOKEN>",
headers: {
"Content-Type": "application/json",
},
data: data,
};
axios
.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
RPC_URL=https://api.devnet.solana.com //or mainnet URL
PRIVATE_KEY=your-wallet-private-keyasync function createTokenWithMetadata() {
console.log("=== Creating Token with Metadata Extension ===\n");
console.log("Payer address:", payer.publicKey.toBase58());
const mintKeypair = Keypair.generate();
const mint = mintKeypair.publicKey;
console.log("\nMint address:", mint.toBase58()); const metadata = {
updateAuthority: payer.publicKey,
mint: mint,
name: "GetBlock Tutorial Token",
symbol: "GBT",
uri: "https://getblock.io/",
additionalMetadata: [["description", "A test token created with GetBlock"]],
};const decimals = 9;
const mintLen = getMintLen([ExtensionType.MetadataPointer]);
const metadataLen =
TYPE_SIZE + // 2 bytes for type
LENGTH_SIZE + // 2 bytes for length
pack(metadata).length; // Actual metadata size
const lamports = await connection.getMinimumBalanceForRentExemp
mintLen + metadataLen,
);const transaction = new Transaction().add(
SystemProgram.createAccount({
fromPubkey: payer.publicKey,
newAccountPubkey: mint,
space: mintLen, // ← Just the mint size
lamports: lamports, // ← But funded for full size
programId: TOKEN_2022_PROGRAM_ID,
}),
createInitializeMetadataPointerInstruction(
mint, // mint
payer.publicKey, // authority
mint, // metadata address (pointing to itself)
TOKEN_2022_PROGRAM_ID,
),
createInitializeMintInstruction(
mint, // mint
decimals, // decimals
payer.publicKey, // mint authority
null, // freeze authority (optional)
TOKEN_2022_PROGRAM_ID,
),
createInitializeInstruction({
programId: TOKEN_2022_PROGRAM_ID,
mint: mint,
metadata: mint,
name: metadata.name,
symbol: metadata.symbol,
uri: metadata.uri,
mintAuthority: payer.publicKey,
updateAuthority: payer.publicKey,
}),
);
console.log("\nSending transaction...");
const signature = await sendAndConfirmTransaction(
connection,
transaction,
[payer, mintKeypair], // Signers
{ commitment: "confirmed" },
);
console.log("\Token created successfully!");
console.log("Transaction signature:", signature);
console.log("Mint address:", mint.toBase58());
console.log("\nToken details:");
console.log(" Name:", metadata.name);
console.log(" Symbol:", metadata.symbol);
console.log(" Decimals:", decimals);
console.log(" URI:", metadata.uri);
return mint;
}
ceateTokenWithMetadata()
.then(() => process.exit(0))
.catch((error) => {
console.error("Error:", error);
process.exit(1);
});import { Keypair, SystemProgram, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
import { TOKEN_2022_PROGRAM_ID, ExtensionType, createInitializeMintInstruction, createInitializeMetadataPointerInstruction, getMintLen, TYPE_SIZE, LENGTH_SIZE } from "@solana/spl-token";
import { createInitializeInstruction, pack } from "@solana/spl-token-metadata";
import { connection, payer } from "./config.js";
async function createTokenWithMetadata() {
console.log("=== Creating Token with Metadata Extension ===\n");
console.log("Payer address:", payer.publicKey.toBase58());
const mintKeypair = Keypair.generate();
const mint = mintKeypair.publicKey;
console.log("\nMint address:", mint.toBase58());
const metadata = {
updateAuthority: payer.publicKey,
mint: mint,
name: "GetBlock Tutorial Token",
symbol: "GBT",
uri: "https://getblock.io/",
additionalMetadata: [["description", "A test token created with GetBlock"]],
};
const decimals = 9;
const mintLen = getMintLen([ExtensionType.MetadataPointer]);
const metadataLen =
TYPE_SIZE + // 2 bytes for type
LENGTH_SIZE + // 2 bytes for length
pack(metadata).length; // Actual metadata size
const lamports = await connection.getMinimumBalanceForRentExemption(
mintLen + metadataLen,
);
const transaction = new Transaction().add(
SystemProgram.createAccount({
fromPubkey: payer.publicKey,
newAccountPubkey: mint,
space: mintLen, // ← Just the mint size
lamports: lamports, // ← But funded for full size
programId: TOKEN_2022_PROGRAM_ID,
}),
createInitializeMetadataPointerInstruction(
mint, // mint
payer.publicKey, // authority
mint, // metadata address (pointing to itself)
TOKEN_2022_PROGRAM_ID,
),
createInitializeMintInstruction(
mint, // mint
decimals, // decimals
payer.publicKey, // mint authority
null, // freeze authority (optional)
TOKEN_2022_PROGRAM_ID,
),
createInitializeInstruction({
programId: TOKEN_2022_PROGRAM_ID,
mint: mint,
metadata: mint,
name: metadata.name,
symbol: metadata.symbol,
uri: metadata.uri,
mintAuthority: payer.publicKey,
updateAuthority: payer.publicKey,
}),
);
console.log("\nSending transaction...");
const signature = await sendAndConfirmTransaction(
connection,
transaction,
[payer, mintKeypair], // Signers
{ commitment: "confirmed" },
);
console.log("\Token created successfully!");
console.log("Transaction signature:", signature);
console.log("Mint address:", mint.toBase58());
console.log("\nToken details:");
console.log(" Name:", metadata.name);
console.log(" Symbol:", metadata.symbol);
console.log(" Decimals:", decimals);
console.log(" URI:", metadata.uri);
return mint;
}
createTokenWithMetadata()
.then(() => process.exit(0))
.catch((error) => {
console.error("Error:", error);
process.exit(1);
});
node index.js=== Creating Token with Metadata Extension ===
Payer address: 5C7dUe5ZDWBCYQ5eqtGPRyz7CQYk2aK4FhZTDYQeji7r
Mint address: BVwyGVpUNUL7eYVqbMtzgbinTiUgd3tNXsgxfxoAQaWe
Sending transaction...
Token created successfully!
Transaction signature: N9DHUYdNRUc9RC2H6LMtiSPpY2UW1aVmFZsK7b8KG3xpTUWiVDrj79EkxHTh74T5QmbMR3CbprYif3jNveAnQBJ
Mint address: BVwyGVpUNUL7eYVqbMtzgbinTiUgd3tNXsgxfxoAQaWe
Token details:
Name: GetBlock Tutorial Token
Symbol: GBT
Decimals: 9
URI: https://getblock.io/import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_getBlockByHash",
"params": [
"0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
false
],
"id": "getblock.io"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_getBlockByHash",
"params": [
"0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
false
],
"id": "getblock.io"
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": {
"baseFeePerGas": "0x5f5e100",
"difficulty": "0x1",
"extraData": "0xe31298ca6df96cb00d355ca9554878c19d39292b6a26eb9fc54b5df482851ef7",
"gasLimit": "0x4000000000000",
"gasUsed": "0x229dd8",
"hash": "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
"l1BlockNumber": "0x105e046",
"logsBloom": "0x00000100000000020000100000000000080000000000000000000000001000001000000000000000000000000101000000000000000000000001010000000000000010000000000000001008000120000100000000001000800100008000000000000000000000000000000000000000021000200000400000000010000000001000000000000000000000000008000000000001000000000008000000000010000000000000000000000000000000000000000000000000000000000000000000008002000048000000000000000000200800000000000010000000000000000000000040000000000000008000000010000000004010400000000000000040",
"miner": "0xa4b000000000000000000073657175656e636572",
"mixHash": "0x0000000000012069000000000105e046000000000000000a0000000000000000",
"nonce": "0x00000000000c7662",
"number": "0x5206d53",
"parentHash": "0xb458d44871af788992e51a89661eb28a6539cf9f33c0e9a30d0aab5f2e50e974",
"receiptsRoot": "0x184ea05480454e4c4fcf6406106a4cb13477af97d45752a126ee84de88695c7c",
"sendCount": "0x12069",
"sendRoot": "0xe31298ca6df96cb00d355ca9554878c19d39292b6a26eb9fc54b5df482851ef7",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x579",
"stateRoot": "0xea41be04084dc613cfbf8d1fef75d9a097fad2b222373669e42e2aa173175649",
"timestamp": "0x644f0242",
"transactions": [
"0xaf256a9ce8839489dcaa4f9a2740bcd5865b3db34a15434cce29e6bdcf043bc7",
"0xfd7e27e19777598be2536bc6e4a5e89cc8a386eca46374333b1fba22641ed255",
"0x98b2f04b2eb747e685c7db6f97ef2aaca236e146afb310ed039d56ab8599eb0e",
"0x23c566cf1c2f208a74ef2e585b5bfe7fcffab6445027f06b4207ec43968cf71e",
"0x9febdfb50d48f1891b6660379dcea3d0060808538a102d589e7ea3b7aa6d787d"
],
"transactionsRoot": "0x22ef4159c9394a555af55a3ae5719bf15c1ff296838dd920f1566eeecb15aa1f",
"uncles": []
}
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function Call() {
try {
const result = await provider.send("eth_getBlockByHash", [
"0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
false,
]); console.log("The result:", result);
return result;
} catch (error) {
console.error("The error:", error);
throw error;
}
}import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
// Create Viem client with GetBlock
const client = createPublicClient({
chain: arbitrum,
transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
});
// Using the method through Viem
async function Call() {
try {
// Method-specific Viem implementation
const result = await client.request({
method: 'eth_getBlockByHash',
params: [ "0xf5524f0cf99ac6bc5905e95294ebed9007e2d978155f3457118eb7a26d97503a",
false],
});
console.log('Result:', result);
return result;
} catch (error) {
console.error('Viem Error:', error);
throw error;
}
}
import requests
import json
url = "https://go.getblock.us/<ACESS_TOKEN>"
payload = json.dumps({
"jsonrpc": "2.0",
"method": "eth_getBlockByNumber",
"params": [
"latest",
false
],
"id": "getblock.io"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
let data = r#"{
"jsonrpc": "2.0",
"method": "eth_getBlockByNumber",
"params": [
"latest",
false
],
"id": "getblock.io"
}"#;
let json: serde_json::Value = serde_json::from_str(&data)?;
let request = client.request(reqwest::Method::POST, "https://go.getblock.us/<ACCESS_TOKEN>")
.headers(headers)
.json(&json);
let response = request.send().await?;
let body = response.text().await?;
println!("{}", body);
Ok(())
}{
"jsonrpc": "2.0",
"id": "getblock.io",
"result": {
"baseFeePerGas": "0x7cf30f8",
"difficulty": "0x1",
"extraData": "0x539464419cc7e1235fba3837a56b348ecb8ae3a3ed2f1c8839012038bbb59e32",
"gasLimit": "0x4000000000000",
"gasUsed": "0x1560d7",
"hash": "0x1d77c0b85c1d0a75c19c94dc05868c936dc6d6b537c1846613e97110c90b3f48",
"l1BlockNumber": "0x16dd9f1",
"logsBloom": "0x000100c2000c0008800000044000200000000000000000180000010401000800000408020108000800800000000000000100400108082210006000000028000000000001000200080014040800002004000000040280000008004020000020412000000c0002040000001824000000000000040000000000004000100008000a0020800080004010000001000000000800000000000001000080000000000000020000200001000000000020800000000000080000000000000000080000001000402002000000200000000000010008040082001000882042200200008000080210040000200000000020000000200000000000080040000000000000400400",
"miner": "0xa4b000000000000000000073657175656e636572",
"mixHash": "0x0000000000025f6000000000016dd9f100000000000000280000000000000000",
"nonce": "0x0000000000221739",
"number": "0x185eef3d",
"parentHash": "0x9c39e9f3fbc4b716cc974f5bec6766c95d23caf0dd89c97da33bc39656643437",
"receiptsRoot": "0xb51b31ab3fccbb7423ae394c8d5e2039b55476d9df233e8031bf1c7d5620e489",
"sendCount": "0x25f60",
"sendRoot": "0x539464419cc7e1235fba3837a56b348ecb8ae3a3ed2f1c8839012038bbb59e32",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0xed9",
"stateRoot": "0x764448b4dcde129e0630c8f010e8a7c6ebcc446ec4cb2c2bea87d8f3ff8d86d8",
"timestamp": "0x69384f78",
"transactions": [
"0xd31a43fdc91c3aaa6b00537d8788b06b28833ea14d237488ac35d5993ed8634c",
"0xdf1df3a844340e0ae82485f78754818d8d628ac7236b6bcdbe3946c219301a45",
"0x4c02aa4e537ff54dbfda1b3ef528bd611cfe88225d071fda4fa57a12801a2c88",
"0x5c4f37fdf581342bb1e0eed9522feb69e988b5270945ce6128d55914b0a76c8f",
"0x795fdc0ab98a9ec4f651779dfc055677f7a35596dda5292ab966b4c35c935231",
"0x93e9d4fd77c2a9f34f80b328cbbe0613d943d376277a3758c0023c9e349becaf",
"0xe05ee8bbc3a0db68529271b76ddcca2e5ac3c52263d57268293c09606d1bcaa6",
"0x5f9fe747df5850d935f769be1a3e91102cd5ab73750b14b82f7e0afbba7cb30f",
"0x7ee97b9dfa06eeec0bfac8bdcfb320888092a735174b5b7b15f0d066b6b85ecf",
"0x8357a5f4721cec2e7d27caa0c0ae909e4db26f0e001888651f6213430e3489fe",
"0xbc740ac9a94989b232c9445e475eb1cc94c3ed858a869ce0c43029cb9ed9d836",
"0x89203f417d97ae57eaa1f73f1e08a11a9ffd73936744233555152d37d38cdb6e"
],
"transactionsRoot": "0xacd0886f4df73a6d36dcbe36a854a162d25d2e2b81d6362b174d01582aeae562",
"uncles": []
}
}import { ethers } from "ethers";
const RPC_URL = "https://go.getblock.us/<ACCESS_TOKEN>";
const provider = new ethers.JsonRpcProvider(RPC_URL);
async function Call() {
try {
const result = await provider.send("eth_getBlockByNumber", ["latest", false],); console.log("The result:", result);
return result;
} catch (error) {
console.error("The error:", error);
throw error;
}
}import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
// Create Viem client with GetBlock
const client = createPublicClient({
chain: arbitrum,
transport: http('https://go.getblock.us/<ACCESS_TOKEN>'),
});
// Using the method through Viem
async function Call() {
try {
// Method-specific Viem implementation
const result = await client.request({
method: 'eth_getBlockByNumber',
params: ["latest", false],
});
console.log('Result:', result);
return result;
} catch (error) {
console.error('Viem Error:', error);
throw error;
}
}
pumpfun()splToken()
wss://go.getblock.io/<ACCESS_TOKEN>blxr_txmkdir transaction-public-mempool
cd transaction-public-mempool
npm init
mkdir transaction-public-mempool
cd transaction-public-mempool
yarn init
This guide explains how to submit transaction bundles on BNB Smart Chain using GetBlock's MEV endpoint.
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.
RPC_URL=https://api.devnet.solana.com
PRIVATE_KEY=your_wallet_private_key
OPENAI_API_KEY=your_openai_secret_keyimport { Connection, Keypair } from "@solana/web3.js";
import { solana } from "@goat-sdk/wallet-solana";
import { jupiter } from "@goat-sdk/plugin-jupiter";
import { splToken } from "@goat-sdk/plugin-spl-token";
import { getOnChainTools } from "@goat-sdk/adapter-langchain";
import { ChatOpenAI } from "@langchain/openai";
import { pumpfun } from "@goat-sdk/plugin-pumpfun";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { MemorySaver } from "@langchain/langgraph";
import * as dotenv from "dotenv";
import bs58 from "bs58";
import * as readline from "readline";
dotenv.config();async function initializeAgent() {
const connection = new Connection(process.env.RPC_URL!, "confirmed");
const privateKey = process.env.SOLANA_PRIVATE_KEY!;
const keypair = Keypair.fromSecretKey(bs58.decode(privateKey));
const tools = await getOnChainTools({
wallet: solana({
keypair,
connection,
}),
plugins: [
splToken(),
pumpfun(),
jupiter(),
],
});
const llm = new ChatOpenAI({
modelName: "gpt-4o",
temperature: 0, // Lower temperature is better for tool calling
});
const memory = new MemorySaver();
return createReactAgent({
llm,
tools,
checkpointSaver: memory,
});
}async function run() {
const agent = await initializeAgent();
const config = { configurable: { thread_id: "goat-session-1" } };
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const ask = (prompt: string) => new Promise<string>((resolve) => rl.question(prompt, resolve)
console.log('Solana AI Agent ready. Type "exit" to quit.\n');
while (true) {
const input = await ask("You: ");
if (input.trim().toLowerCase() === "exit") {
rl.close();
break;
}
const response = await agent.invoke(
{ messages: [{ role: "user", content: input }] },
config,
);
const lastMessage = response.messages[response.messages.length - 1];
console.log("Agent:", lastMessage.content, "\n");
}
}
run().catch(console.error);npx tsx agent.tsYou: What is my wallet address and how much sol do i have left
Agent: Your wallet address is `5C7dUe5ZDWBCYQ5eqtGPRyz7CQYk2aK4FhZTDYQeji7r`, and you have approximately 7.94991 SOL left in your wallet.
You: Send 0.05 sol to 3xk5f92EhRfDSD29W9ZWKmX2x7DXkc6TpMW8TpX5eFU8
Agent: The transaction to send 0.05 SOL to the address `3xk5f92EhRfDSD29W9ZWKmX2x7DXkc6TpMW8TpX5eFU8` has been successfully completed. You can view the transaction details with the hash: [2ZK5U6pJ7i6j8nDRvdidgEyPnRPivzyBddUrJGebnefApFFXcvmomYNGZVC85XNjnAG5PTnuUyCwFYtjp55HNfLX](https://explorer.solana.com/tx/2ZK5U6pJ7i6j8nDRvdidgEyPnRPivzyBddUrJGebnefApFFXcvmomYNGZVC85XNjnAG5PTnuUyCwFYtjp55HNfLX).
You: Если вы обращаетесь в поддержку, можно сказать: "Подскажите, пожалуйста, мой адрес кошелька и баланс SOL"
Agent: Ваш адрес кошелька: `5C7dUe5ZDWBCYQ5eqtGPRyz7CQYk2aK4FhZTDYQeji7r`.
К сожалению, возникла ошибка при попытке получить баланс SOL. Пожалуйста, проверьте правильность адреса кошелька и попробуйте снова.
wss://go.getblock.io/<ACCESS_TOKEN>bsc_private_txmkdir transaction-private-mempool
cd transaction-private-mempool
npm init -y
npm install ws ethers dotenvmkdir transaction-private-mempool
cd transaction-private-mempool
yarn init -y
yarn ws ethersimport WebSocket from "ws";
import { ethers } from "ethers";
import "dotenv/config";
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const RPC_URL = process.env.RPC_URL;
async function sendPrivateTransaction(recipient, amountBNB) {
const provider = new ethers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
console.log("Wallet:", wallet.address);
console.log("Recipient:", recipient);
console.log("Amount:", amountBNB, "BNB");
console.log("Mode: Private (MEV Protected)");
// Get nonce
const nonce = await provider.getTransactionCount(wallet.address);
// Build transaction
const signedTx = await wallet.signTransaction({
nonce: nonce,
to: recipient,
value: ethers.parseEther(amountBNB),
gasPrice: ethers.parseUnits("3", "gwei"),
gasLimit: 21000,
chainId: 56,
});
const signedTxNoPrefix = signedTx.startsWith("0x")
? signedTx.slice(2)
: signedTx;
// Submit privately
const ws = new WebSocket(process.env.ACCESS_TOKEN);
return new Promise((resolve, reject) => {
ws.on("open", () => {
console.log("\nSubmitting private transaction...");
ws.send(
JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "bsc_private_tx",
params: {
transaction: signedTxNoPrefix,
mev_builders: ["all"],
},
}),
);
});
ws.on("message", (data) => {
const response = JSON.parse(data);
ws.close();
if (response.result) {
console.log("\n✅ Private transaction submitted!");
console.log("TX Hash:", response.result.txHash);
console.log(
"BSCScan:",
`https://bscscan.com/tx/${response.result.txHash}`,
);
resolve(response.result.txHash);
} else {
console.error("\n❌ Error:", response.error);
reject(response.error);
}
});
ws.on("error", reject);
});
}
// Usage
sendPrivateTransaction(process.env.TO_ADDRESS, "0.001").catch(console.error);
import WebSocket from 'ws';
import { ethers } from 'ethers';
import 'dotenv/config';
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const RPC_URL = process.env.RPC_URL;
const PANCAKE_ROUTER = '0x10ED43C718714eb63d5aA57B78B54704E256024E';
const WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
async function privateSwap(tokenAddress, amountBNB, minAmountOut) {
const provider = new ethers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
// Router ABI
const routerABI = [
'function swapExactETHForTokens(uint256 amountOutMin, address[] path, address to, uint256 deadline) payable'
];
const router = new ethers.Contract(PANCAKE_ROUTER, routerABI, wallet);
// Build swap calldata
const deadline = Math.floor(Date.now() / 1000) + 300;
const swapData = router.interface.encodeFunctionData('swapExactETHForTokens', [
minAmountOut,
[WBNB, tokenAddress],
wallet.address,
deadline
]);
// Get nonce
const nonce = await provider.getTransactionCount(wallet.address);
// Sign transaction
const signedTx = await wallet.signTransaction({
nonce: nonce,
to: PANCAKE_ROUTER,
value: ethers.parseEther(amountBNB),
data: swapData,
gasPrice: ethers.parseUnits('3', 'gwei'),
gasLimit: 300000,
chainId: 56
});
console.log('Swap details:');
console.log(' Amount:', amountBNB, 'BNB');
console.log(' Token:', tokenAddress);
console.log(' Min out:', ethers.formatEther(minAmountOut));
console.log(' Mode: Private (MEV Protected)');
// Submit privately
const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
return new Promise((resolve, reject) => {
ws.on('open', () => {
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'bsc_private_tx',
params: {
transaction: signedTx,
mev_builders: ['all']
}
}));
});
ws.on('message', (data) => {
const response = JSON.parse(data);
ws.close();
if (response.result) {
console.log('\n✅ Private swap submitted!');
console.log('TX Hash:', response.result.txHash);
console.log('BSCScan:', `https://bscscan.com/tx/${response.result.txHash}`);
resolve(response.result.txHash);
} else {
console.error('\n❌ Error:', response.error);
reject(response.error);
}
});
});
}
// Usage: Swap 1 BNB for BUSD (MEV protected)
privateSwap(
'0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56', // BUSD
'1.0', // 1 BNB
ethers.parseEther('200') // Min 200 BUSD
).catch(console.error);params: {
transaction: signedTx,
mev_builders: ['48club', 'bloxroute'] // Specific builders only
}import WebSocket from 'ws';
import { ethers } from 'ethers';
import 'dotenv/config';
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const RPC_URL = process.env.RPC_URL;
const PANCAKE_ROUTER = '0x10ED43C718714eb63d5aA57B78B54704E256024E';
const WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
async function swapBNBForToken(tokenAddress, amountBNB, minAmountOut) {
const provider = new ethers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
// Router ABI
const routerABI = [
'function swapExactETHForTokens(uint256 amountOutMin, address[] path, address to, uint256 deadline) payable'
];
const router = new ethers.Contract(PANCAKE_ROUTER, routerABI, wallet);
// Build swap calldata
const deadline = Math.floor(Date.now() / 1000) + 300; // 5 minutes
const swapData = router.interface.encodeFunctionData('swapExactETHForTokens', [
minAmountOut,
[WBNB, tokenAddress],
wallet.address,
deadline
]);
// Get nonce
const nonce = await provider.getTransactionCount(wallet.address);
// Build transaction
const tx = {
nonce: nonce,
to: PANCAKE_ROUTER,
value: ethers.parseEther(amountBNB),
data: swapData,
gasPrice: ethers.parseUnits('3', 'gwei'),
gasLimit: 300000, // Higher gas limit for swaps
chainId: 56
};
// Sign transaction
const signedTx = await wallet.signTransaction(tx);
const signedTxNoPrefix = signedTx.startsWith("0x")
? signedTx.slice(2)
: signedTx;
console.log('Swap details:');
console.log(' Amount:', amountBNB, 'BNB');
console.log(' Token:', tokenAddress);
console.log(' Min out:', ethers.formatEther(minAmountOut));
// Submit via BDN
const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
return new Promise((resolve, reject) => {
ws.on('open', () => {
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: "blxr_tx",
params: {"transaction": signedTxNoPrefix},
}));
});
ws.on('message', (data) => {
const response = JSON.parse(data);
ws.close();
if (response.result) {
console.log('\n✅ Swap submitted!');
console.log('TX Hash:', response.result);
resolve(response.result);
} else {
console.error('\n❌ Error:', response.error);
reject(response.error);
}
});
});
}
// Usage: Swap 0.001 BNB for BUSD
swapBNBForToken(
'0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56', // BUSD
'0.001', // 0.001 BNB
ethers.parseEther('50') // Min 50 BUSD
).catch(console.error);const nonce = await provider.getTransactionCount(wallet.address, 'pending');Required = value + (gasPrice × gasLimit)const newGasPrice = existingGasPrice * 110n / 100n;
{
"jsonrpc": "2.0",
"id": 1,
"method": "blxr_tx",
"params": ["0x<signed_transaction_hex>"]
}{
"jsonrpc": "2.0",
"id": 1,
"result": "0x<transaction_hash>"
}{
"jsonrpc": "2.0",
"id": 1,
"method": "bsc_private_tx",
"params": {
"transaction": "0xf86c...",
"mev_builders": ["all"]
}
}{
"jsonrpc": "2.0",
"id": 1,
"result": {
"txHash": "0x..."
}
}ACCESS_TOKEN=your-accelerated-node-endpoint
RPC_URL=your-normal-bsc-node-endppoint //e.g https
PRIVATE_KEY=your-wallet-private-keyimport WebSocket from 'ws';
import { ethers } from 'ethers';
import 'dotenv/config';
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const RPC_URL = process.env.RPC_URLconst provider = new ethers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
// Get current nonce
const nonce = await provider.getTransactionCount(wallet.address);
// Build transaction
const tx = {
nonce: nonce,
to: '0xRECIPIENT_ADDRESS',
value: ethers.parseEther('0.1'),
gasPrice: ethers.parseUnits('3', 'gwei'),
gasLimit: 21000,
chainId: 56
};
// Sign transaction
const signedTx = await wallet.signTransaction(tx);const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
ws.on('open', () => {
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'bsc_private_tx',
params: {
transaction: signedTx,
mev_builders: ['all']
}
}));
});
ws.on('message', (data) => {
const response = JSON.parse(data);
if (response.result) {
console.log('✅ Private TX submitted!');
console.log('TX Hash:', response.result.txHash);
} else {
console.error('❌ Error:', response.error);
}
ws.close();
});Wallet: 0xD1AF2dAc4e0a....
Recipient: 0xd26ea.....
Amount: 0.001 BNB
Mode: Private (MEV Protected)
Submitting private transaction...
✅ Private transaction submitted!
TX Hash: 14223ac9adf33b77e4b52e8612dd351517b1bbc5b771567089994a6183f46df2
BSCScan: https://bscscan.com/tx/14223ac9adf33b77e4b52e8612dd351517b1bbc5b771567089994a6183f46df2ACCESS_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-addressimport WebSocket from "ws";
import { ethers } from "ethers";
import "dotenv/config";const PRIVATE_KEY = process.env.PRIVATE_KEY;
const RPC_URL = process.env.RPC_URL;
const provider = new ethers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
// Get current nonce
const nonce = await provider.getTransactionCount(wallet.address);
// Build transaction
const tx = {
nonce: nonce,
to: process.env.TO_ADDRESS,
value: ethers.parseEther("0.001"),
gasPrice: ethers.parseUnits("3", "gwei"), // Minimum 3 gwei for BSC
gasLimit: 21000,
chainId: 56, // BSC Mainnet
};
// Sign transaction
const signedTx = await wallet.signTransaction(tx);
const signedTxNoPrefix = signedTx.startsWith("0x")
? signedTx.slice(2)
: signedTx;const ws = new WebSocket(process.env.ACCESS_TOKEN);
ws.on("open", () => {
ws.send(
JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "blxr_tx",
params: {"transaction": signedTxNoPrefix},
}),
);
});
ws.on("message", (data) => {
const response = JSON.parse(data);
if (response.result?.txHash) {
const hash = response.result.txHash;
console.log("TX Hash:", hash);
console.log(`https://bscscan.com/tx/${hash}`);
} else if (response.error) {
console.error("❌ Error:", response.error.message);
}
ws.close();
});01f86c380384b2d05e0082520894d26ea0f03100358b2ebd4c9638f042aada9a1bcf87038d7ea4c6800080c001a04647f98754480337ae409bcc225f2d62b706b47f31385221421cea20e41080b0a03ae32f07bb7110c4153c2ab121c152db7d3030d54cc0c5341f0b75b20e3d439d
TX Hash: 00d4fe2db5c667ce549318cf621913af1bcb130022ec51020cbb6cae2b7eedce
https://bscscan.com/tx/00d4fe2db5c667ce549318cf621913af1bcb130022ec51020cbb6cae2b7eedcehttps://go.getblock.io/<ACCESS-TOKEN>/curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/modules?ledger_version=3362752463&limit=2'[
{
"bytecode": "0xa11ceb0b050000000801000203022305251d0742470889012006a9012e10d7014f0ca602c703000000010001000002020100000303010000040004000005050400000606010000070401000203030103030303030304040401040204040102000202030403030404046d617468076d696e5f753634076d756c5f6469760c6d756c5f6469765f753132380b6d756c5f746f5f753132380c6f766572666c6f775f61646406706f775f31300473717274190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e120308d0070000000000000410ffffffffffffffffffffffffffffffff0410ffffffffffffffff0000000000000000126170746f733a3a6d657461646174615f76303b01d007000000000000124552525f4449564944455f42595f5a45524f1e5768656e20747279696e6720746f20646976696465206279207a65726f2e00010000010c0a000a0123030505080b000c02050a0b010c020b02020101000004120a020600000000000000002203060700270b00350b0135180b02351a0c030b03340202010000040f0a0232000000000000000000000000000000002203060700270b000b01180b021a0c030b0334020301000007060b00350b0135180204010000042207010a01170c020a020a00230309050f0b000b02173201000000000000000000000000000000170207010a00170c020a020a01230318051e0b010b0217320100000000000000000000000000000017020b000b0116020501000008150601000000000000000c0231000c01280a010a0023030a05130b02060a00000000000000180c020b013101160c0105040b020206010000092f0a00320400000000000000000000000000000023030505120b00320000000000000000000000000000000021030a050d0600000000000000000c01050f0601000000000000000c010b010c02052d0a000c040a0032020000000000000000000000000000001a3201000000000000000000000000000000160c030a030a0423031f052a0a030c040a000a031a0b031632020000000000000000000000000000001a0c03051a0b04340c020b020200",
"abi": {
"address": "0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12",
"name": "math",
"friends": [],
"exposed_functions": [
{
"name": "min_u64",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [],
"params": [
"u64",
"u64"
],
"return": [
"u64"
]
},
{
"name": "mul_div",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [],
"params": [
"u64",
"u64",
"u64"
],
"return": [
"u64"
]
},
{
"name": "mul_div_u128",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [],
"params": [
"u128",
"u128",
"u128"
],
"return": [
"u64"
]
},
{
"name": "mul_to_u128",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [],
"params": [
"u64",
"u64"
],
"return": [
"u128"
]
},
{
"name": "overflow_add",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [],
"params": [
"u128",
"u128"
],
"return": [
"u128"
]
},
{
"name": "pow_10",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [],
"params": [
"u8"
],
"return": [
"u64"
]
},
{
"name": "sqrt",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [],
"params": [
"u128"
],
"return": [
"u64"
]
}
],
"structs": []
}
},
{
"bytecode": "0xa11ceb0b050000000b01000402040c03101e042e0c053a0f07497e08c701400687020a109102300ac1020a0ccb023e00000101000200000003000001090700000400000100000500010100000600010100000700010100010a000301000302040204040405020201020001010109000108020108000108010663757276657309747970655f696e666f06537461626c650c556e636f7272656c61746564126173736572745f76616c69645f63757276650969735f737461626c650f69735f756e636f7272656c617465640e69735f76616c69645f63757276650b64756d6d795f6669656c640854797065496e666f07747970655f6f66190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12000000000000000000000000000000000000000000000000000000000000000103081127000000000000126170746f733a3a6d657461646174615f76301c011127000000000000114552525f494e56414c49445f43555256450000020108010102010801000100000005380003040700270201010000000438013802210202010000000438013803210203010000010a380403030506080c00050838050c000b000200",
"abi": {
"address": "0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12",
"name": "curves",
"friends": [],
"exposed_functions": [
{
"name": "assert_valid_curve",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [
{
"constraints": []
}
],
"params": [],
"return": []
},
{
"name": "is_stable",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [
{
"constraints": []
}
],
"params": [],
"return": [
"bool"
]
},
{
"name": "is_uncorrelated",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [
{
"constraints": []
}
],
"params": [],
"return": [
"bool"
]
},
{
"name": "is_valid_curve",
"visibility": "public",
"is_entry": false,
"is_view": false,
"generic_type_params": [
{
"constraints": []
}
],
"params": [],
"return": [
"bool"
]
}
],
"structs": [
{
"name": "Stable",
"is_native": false,
"is_event": false,
"abilities": [],
"generic_type_params": [],
"fields": [
{
"name": "dummy_field",
"type": "bool"
}
]
},
{
"name": "Uncorrelated",
"is_native": false,
"is_event": false,
"abilities": [],
"generic_type_params": [],
"fields": [
{
"name": "dummy_field",
"type": "bool"
}
]
}
]
}
}
]import requests
url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/modules?ledger_version=3362752463&limit=2"
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)import axios from ‘axios’;
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/accounts/0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12/modules?ledger_version=3362752463&limit=2',
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});{
"jsonrpc": "2.0",
{
"jsonrpc": "2.0",
wss://go.getblock.io/<ACCESS_TOKEN>mkdir bundle-example
cd bundle-example
npm init -y
npm install ws ethers dotenvmkdir bundle-example
cd bundle-example
yarn init -y
yarn ws ethers dotenvACCESS_TOKEN=your-accelerated-node-endpoint
RPC_URL=your-normal-bsc-node-endppoint //e.g https
PRIVATE_KEY=your-wallet-private-keyimport WebSocket from "ws";
import { ethers } from "ethers";
import "dotenv/config";
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const RPC_URL = process.env.RPC_URL;
async function submitBundle() {
const provider = new ethers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
// Get the current nonce for your wallet
const nonce = await provider.getTransactionCount(wallet.address);
// Transaction 1: First operation
const tx1 = await wallet.signTransaction({
nonce: nonce,
to: DEX_A,
value: ethers.parseEther("0.001"),
data: buyCalldata,
gasPrice: ethers.parseUnits("3", "gwei"),
gasLimit: 300000,
chainId: 56,
});
// Transaction 2: Second operation (must use nonce + 1)
const tx2 = await wallet.signTransaction({
nonce: nonce + 1,
to: DEX_B,
value: 0,
data: sellCalldata,
gasPrice: ethers.parseUnits("3", "gwei"),
gasLimit: 300000,
chainId: 56,
});
// Connect to the MEV endpoint
const ws = new WebSocket(process.env.ACCESS_TOKEN);
ws.on("open", () => {
ws.send(
JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "mev_sendBundle",
params: {
transactions: [tx1.slice(2), tx2.slice(2)],
mev_builders: { all: "" },
blocks_count: 5,
},
}),
);
});
ws.on("message", (data) => {
const response = JSON.parse(data);
if (response.result) {
console.log("Bundle submitted successfully");
console.log("Bundle Hash:", response.result.bundleHash);
} else {
console.error("Submission failed:", response.error);
}
ws.close();
});
}
submitBundle();node index.jsconst nonce = await provider.getTransactionCount(wallet.address);
// Transaction 1: nonce
// Transaction 2: nonce + 1
// Transaction 3: nonce + 2const feeTx = await wallet.signTransaction({
nonce: lastNonce,
to: '0x6374Ca2da5646C73Eb444aB99780495d61035f9b',
value: ethers.parseEther('0.001'),
gasPrice: ethers.parseUnits('3', 'gwei'),
gasLimit: 21000,
chainId: 56
});await provider.call({
to: tx1.to,
data: tx1.data,
value: tx1.value
});const WebSocket = require('ws');
const { ethers } = require('ethers');
import 'dotenv/config';
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const RPC_URL= process.env.RPC_URL
// Contract addresses
const PANCAKE_V2_ROUTER = '0x10ED43C718714eb63d5aA57B78B54704E256024E';
const PANCAKE_V3_ROUTER = '0x13f4EA83D0bd40E75C8222255bc855a974568Dd4';
const FEE_ADDRESS = '0x6374Ca2da5646C73Eb444aB99780495d61035f9b';
const WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
const TOKEN = '0xYOUR_TOKEN';
async function arbitrage() {
const provider = new ethers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
const nonce = await provider.getTransactionCount(wallet.address);
const deadline = Math.floor(Date.now() / 1000) + 300;
// Encode the V2 swap
const v2ABI = [
'function swapExactETHForTokens(uint256 amountOutMin, address[] path, address to, uint256 deadline) payable'
];
const v2Router = new ethers.Contract(PANCAKE_V2_ROUTER, v2ABI, wallet);
const buyData = v2Router.interface.encodeFunctionData('swapExactETHForTokens', [
0, // amountOutMin (set appropriately in production)
[WBNB, TOKEN],
wallet.address,
deadline
]);
// Transaction 1: Buy on PancakeSwap V2
const tx1 = await wallet.signTransaction({
nonce: nonce,
to: PANCAKE_V2_ROUTER,
value: ethers.parseEther('1.0'),
data: buyData,
gasPrice: ethers.parseUnits('3', 'gwei'),
gasLimit: 300000,
chainId: 56
});
// Transaction 2: Sell on PancakeSwap V3
// Note: V3 uses a different interface; replace with your actual V3 swap calldata
const tx2 = await wallet.signTransaction({
nonce: nonce + 1,
to: PANCAKE_V3_ROUTER,
value: 0,
data: '0x...', // Your V3 swap calldata
gasPrice: ethers.parseUnits('3', 'gwei'),
gasLimit: 300000,
chainId: 56
});
// Transaction 3: Priority fee (optional but recommended)
const tx3 = await wallet.signTransaction({
nonce: nonce + 2,
to: FEE_ADDRESS,
value: ethers.parseEther('0.001'),
gasPrice: ethers.parseUnits('3', 'gwei'),
gasLimit: 21000,
chainId: 56
});
// Submit the bundle
const ws = new WebSocket(process.env.ACCESS_TOKEN);
return new Promise((resolve, reject) => {
ws.on('open', () => {
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'mev_sendBundle',
params: {
transactions: [tx1, tx2, tx3],
mev_builders: { all: '' },
blocks_count: 3 // Short validity for time-sensitive arbitrage
}
}));
});
ws.on('message', (data) => {
const response = JSON.parse(data);
ws.close();
if (response.result) {
console.log('Bundle submitted successfully');
console.log('Bundle Hash:', response.result.bundleHash);
resolve(response.result.bundleHash);
} else {
console.error('Submission failed:', response.error);
reject(response.error);
}
});
});
}
arbitrage();mkdir priority-fees
cd priority-feesnpm install @solana/web3.js dotenv base58Priority Fee = Compute Units × Compute Unit Price// Good: Simulate and use actual consumption + buffer
const simulation = await connection.simulateTransaction(tx);
const estimatedCU = Math.ceil(simulation.value.unitsConsumed * 1.1);
// Bad: Hardcoded value wastes money or fails
const estimatedCU = 1_400_000; // Don't do this// Good: Adapt to current network conditions
const fees = await connection.getRecentPrioritizationFees();
const dynamicFee = calculatePercentile(fees, 75);
// Bad: Static fee may be too low or waste money
const staticFee = 50_000; // Don't do thiscd go-client
go mod tidy
go run main.gogo get github.com/rpcpool/yellowstone-grpc/examples/golang@latest
go get google.golang.org/grpc@latestimport (
"context"
"fmt"
"log"
"time"
ygrpc "github.com/rpcpool/yellowstone-grpc/examples/golang/pkg/grpc"
pb "github.com/rpcpool/yellowstone-grpc/examples/golang/pkg/proto"
"google.golang.org/grpc/metadata"
)
func main() {
endpoint := "go.getblock.io:443"
token := "YOUR_GETBLOCK_TOKEN"
client, err := ygrpc.NewGrpcConnection(context.Background(), endpoint)
if err != nil {
log.Fatalf("Connection error: %v", err)
}
defer client.Close()
ctx := metadata.AppendToOutgoingContext(context.Background(), "x-token", token)
stream, err := client.Subscribe(ctx)
if err != nil {
log.Fatalf("Subscription error: %v", err)
}
req := &pb.SubscribeRequest{
Accounts: map[string]*pb.SubscribeRequestFilterAccounts{
"example": {
Account: []string{"YOUR_WATCHED_ACCOUNT"},
},
},
Commitment: pb.CommitmentLevel_CONFIRMED,
}
if err := stream.Send(req); err != nil {
log.Fatalf("Send error: %v", err)
}
fmt.Println("Streaming...")
for {
res, err := stream.Recv()
if err != nil {
log.Printf("Stream error: %v", err)
time.Sleep(time.Second)
continue
}
fmt.Printf("Update at slot %d for %s\n", res.GetSlot(), res.GetAccount().GetAccount().GetPubkey())
}
}git clone https://github.com/rpcpool/yellowstone-grpc
export PYTHONPATH=$PYTHONPATH:$(pwd)/yellowstone-grpc/examples/pythonfrom examples.grpc import new_client
import time
from google.protobuf.json_format import MessageToDict
endpoint = "go.getblock.io:443"
token = "YOUR_GETBLOCK_TOKEN"
channel, client = new_client(endpoint, token)
req = {
"accounts": {
"example": {
"account": ["YOUR_WATCHED_ACCOUNT"]
}
},
"commitment": "CONFIRMED"
}
stream = client.Subscribe(iter([req]))
for update in stream:
print("Update:", MessageToDict(update))
time.sleep(0.5)// Europe (Frankfurt)
https://go.getblock.io/<YOUR_ACCESS_TOKEN>/
// USA (New York)
https://go.getblock.us/<YOUR_ACCESS_TOKEN>/
// Asia (Singapore)
https://go.getblock.asia/<YOUR_ACCESS_TOKEN>/
ENDPOINT = 'https://go.getblock.io';
TOKEN = 'YOUR_GETBLOCK_ACCESS_TOKEN';# 1) List services and methods
grpcurl \
-insecure \
-authority go.getblock.io \
-H "x-access-token: YOUR_ACCESS_TOKEN" \
go.getblock.io:443 \
list
# 2) Subscribe to slots
grpcurl \
-insecure \
-authority go.getblock.io \
-H "x-access-token: YOUR_ACCESS_TOKEN" \
go.getblock.io:443 \
geyser.Geyser/Subscribe \
-d '{ "slots": { "slots": []{} } }'
npm install @triton-one/yellowstone-grpc
# or
yarn add @triton-one/yellowstone-grpcimport 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);
import {
Connection,
Keypair,
Transaction,
TransactionMessage,
VersionedTransaction,
SystemProgram,
PublicKey,
ComputeBudgetProgram,
sendAndConfirmTransaction,
LAMPORTS_PER_SOL,
TransactionInstruction,
} from "@solana/web3.js";
import "dotenv/config";
import bs58 from "bs58";
const SOLANA_RPC = process.env.GETBLOCK_API_KEY;
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const RECIPIENT_WALLET = process.env.RECIPIENT_WALLET;
if (!SOLANA_RPC || !PRIVATE_KEY || !RECIPIENT_WALLET) {
throw new Error("Missing required environment variables: GETBLOCK_API_KEY, PRIVATE_KEY, or RECIPIENT_WALLET");
}
async function sendWithPriorityFee(
wallet: Keypair,
recipient: PublicKey,
amountSol: number,
): Promise<string> {
const connection = new Connection(SOLANA_RPC!);
// 1. Create the transfer instruction
const transferIx = SystemProgram.transfer({
fromPubkey: wallet.publicKey,
toPubkey: recipient,
lamports: amountSol * LAMPORTS_PER_SOL,
});
// 2. Simulate to estimate compute units
const { blockhash: simBlockhash } = await connection.getLatestBlockhash();
const simMessage = new TransactionMessage({
payerKey: wallet.publicKey,
recentBlockhash: simBlockhash,
instructions: [transferIx],
}).compileToV0Message();
const simTx = new VersionedTransaction(simMessage);
const simulation = await connection.simulateTransaction(simTx);
// Add 600 CU overhead to account for the two ComputeBudget instructions
// (each ~150 CU), which are not included in the simulation
const estimatedCU = Math.max(
Math.ceil((simulation.value.unitsConsumed || 200_000) * 1.1) + 600,
600,
);
console.log(`Estimated CU: ${estimatedCU}`);
// 3. Get dynamic priority fee from network
const recentFees = await connection.getRecentPrioritizationFees();
const sortedFees = recentFees
.map((f) => f.prioritizationFee)
.filter((f) => f > 0)
.sort((a, b) => a - b);
const dynamicFee =
sortedFees.length > 0
? sortedFees[Math.floor(sortedFees.length * 0.75)]
: 10_000;
console.log(`Priority fee: ${dynamicFee} microLamports/CU`);
// 4. Calculate total cost
const totalPriorityFee = Math.ceil((estimatedCU * dynamicFee) / 1_000_000);
console.log(
`Total priority fee: ${totalPriorityFee} lamports (${totalPriorityFee / LAMPORTS_PER_SOL} SOL)`,
);
// 5. Build final transaction
const { blockhash } = await connection.getLatestBlockhash("confirmed");
const finalTx = new Transaction();
finalTx.add(ComputeBudgetProgram.setComputeUnitLimit({ units: estimatedCU }));
finalTx.add(
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: dynamicFee }),
);
finalTx.add(transferIx);
finalTx.recentBlockhash = blockhash;
finalTx.feePayer = wallet.publicKey;
// 6. Sign and send
finalTx.sign(wallet);
const signature = await sendAndConfirmTransaction(
connection,
finalTx,
[wallet],
{ skipPreflight: false, preflightCommitment: "confirmed" },
);
console.log(
`Transaction confirmed: https://solscan.io/tx/${signature}?cluster=devnet`,
);
return signature;
}
// Main entry point
const privateKeyBytes = bs58.decode(PRIVATE_KEY!);
const wallet = Keypair.fromSecretKey(privateKeyBytes);
const recipient = new PublicKey(RECIPIENT_WALLET!);
const amountSol = 0.001; // Amount in SOL to send
sendWithPriorityFee(wallet, recipient, amountSol).catch(console.error);
RPC_URL=https://api.devnet.solana.com //GETBLOCK_API_KEY=your_getblock_api
PRIVATE_KEY=your_wallet_private_key
RECIPIENT_WALLET=the_receiver_walletimport {
Connection,
Keypair,
Transaction,
TransactionMessage,
VersionedTransaction,
SystemProgram,
PublicKey,
ComputeBudgetProgram,
sendAndConfirmTransact
LAMPORTS_PER_SOL,
TransactionInstruction
} from "@solana/web3.js"
import "dotenv/config";
import bs58 from "bs58";
const SOLANA_RPC = process.env.RPC_URL; //replace with GETBLOCK_API_KEY if you are interacting with Mainnet
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const RECIPIENT_WALLET = process.env.RECIPIENT_WALLET;async function sendWithPriorityFee(
wallet: Keypair,
recipient: PublicKey,
amountSol: number,
): Promise<string> {
const connection = new Connection(SOLANA_RPC!);
// 1. Create the transfer instruction
const transferIx = SystemProgram.transfer({
fromPubkey: wallet.publicKey,
toPubkey: recipient,
lamports: amountSol * LAMPORTS_PER_SOL,
}); const { blockhash: simBlockhash } = await connection.getLatestBlockhash();
const simMessage = new TransactionMessage({
payerKey: wallet.publicKey,
recentBlockhash: simBlockhash,
instructions: [transferIx],
}).compileToV0Message();
const simTx = new VersionedTransaction(simMessage);
const simulation = await connection.simulateTransaction(simTx);
// Add 600 CU overhead to account for the two ComputeBudget instructions
// (each ~150 CU), which are not included in the simulation
const estimatedCU = Math.max(
Math.ceil((simulation.value.unitsConsumed || 200_000) * 1.1) + 600,
600,
);const recentFees = await connection.getRecentPrioritizationFees();
const sortedFees = recentFees
.map((f) => f.prioritizationFee)
.filter((f) => f > 0)
.sort((a, b) => a - b);
const dynamicFee =
sortedFees.length > 0
? sortedFees[Math.floor(sortedFees.length * 0.75)]
: 10_000;
console.log(`Priority fee: ${dynamicFee} microLamports/CU`);
const totalPriorityFee = Math.ceil((estimatedCU * dynamicFee) / 1_000_000);
console.log(
`Total priority fee: ${totalPriorityFee} lamports (${totalPriorityFee / LAMPORTS_PER_SOL} SOL)`,
); const { blockhash } = await connection.getLatestBlockhash("confirmed");
const finalTx = new Transaction();
finalTx.add(ComputeBudgetProgram.setComputeUnitLimit({ units: estimatedCU }));
finalTx.add(
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: dynamicFee }),
);
finalTx.add(transferIx);
finalTx.recentBlockhash = blockhash;
finalTx.feePayer = wallet.publicKey;
finalTx.sign(wallet);
const signature = await sendAndConfirmTransaction(
connection,
finalTx,
[wallet],
{ skipPreflight: false, preflightCommitment: "confirmed" },
);
console.log(
`Transaction confirmed: https://solscan.io/tx/${signature}?cluster=devnet`,
);
return signature;
}
const privateKeyBytes = bs58.decode(PRIVATE_KEY!);
const wallet = Keypair.fromSecretKey(privateKeyBytes);
const recipient = new PublicKey(RECIPIENT_WALLET!);
const amountSol = 0.001; // Amount in SOL to send
sendWithPriorityFee(wallet, recipient, amountSol).catch(console.error);npx ts-node index.tsEstimated CU: 765
Priority fee: 10000 microLamports/CU
Total priority fee: 8 lamports (8e-9 SOL)
Transaction confirmed: https://solscan.io/tx/2xaGFBomVphZWDBwiT4KeyqwHrDkgsoLdhFawbXotAam43yziCwUdSqQCGiXtoHF2h8gAAEnZ4GjNi3tQ8QX3RSp?cluster=devnetcd rust-client
cargo build
cargo run[dependencies]
yellowstone-grpc = { git = "https://github.com/rpcpool/yellowstone-grpc", branch = "main" }
tonic = "0.9"
tokio = { version = "1", features = ["full"] }use tonic::metadata::MetadataValue;
use yellowstone_grpc::client::{subscribe_with_token, SubscribeRequest};
#[tokio::main]
async fn main() {
let endpoint = "https://go.getblock.io";
let token = "YOUR_GETBLOCK_TOKEN";
let mut stream = subscribe_with_token(endpoint, token, SubscribeRequest {
accounts: Some({
let mut m = std::collections::HashMap::new();
m.insert("example".to_string(), vec!["YOUR_WATCHED_ACCOUNT".to_string()]);
m
}),
commitment: Some("confirmed".into()),
..Default::default()
}).await.expect("stream failed");
println!("Streaming...");
while let Some(Ok(update)) = stream.message().await {
println!("Update: {:?}", update);
}
}Learn how to direct real-time access to transaction and block streams sourced from the BDN, bypassing RPC node-level execution and processing entirely.
https://go.getblock.io/<ACCESS_TOKEN>curl --location 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_hash/0xd797b944ed8657406a1b09a5928048093399fc0a2f576d3e57c0f9cedbf95c4a'{
"version": "3556737308",
"hash": "0x4c3248d4c2f3a5ca1617e43e69332c66586478871ee44634cdb4554fe537dff6",
"state_change_hash": "0x50148eff819eeb093efbe1cb56936ba02b3169db3343f5df0cb47aba016ea227",
"event_root_hash": "0x1c432ce28a587287ef8abf14f025b78f5e288e886f16f217919cd2e35274f5f3",
"state_checkpoint_hash": null,
"gas_used": "195",
"success": false,
"vm_status": "Move abort in 0x31deb490728ae8e1a89675ee4c1877af8e5849c526d2c9a64238c49d8ece08a0::fa: E_NO_PROFIT(0x385): ",
"accumulator_root_hash": "0xdc354eb8f4a96e9267bab2727240965becd154e35a21fede212af96f56333955",
"changes": [
{
"address": "0xa",
"state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
"data": {
"type": "0x1::coin::PairedCoinType",
"data": {
"type": {
"account_address": "0x1",
"module_name": "0x6170746f735f636f696e",
"struct_name": "0x4170746f73436f696e"
}
}
},
"type": "write_resource"
},
{
"address": "0xa",
"state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
"data": {
"type": "0x1::coin::PairedFungibleAssetRefs",
"data": {
"burn_ref_opt": {
"vec": [
{
"metadata": {
"inner": "0xa"
}
}
]
},
"mint_ref_opt": {
"vec": [
{
"metadata": {
"inner": "0xa"
}
}
]
},
"transfer_ref_opt": {
"vec": [
{
"metadata": {
"inner": "0xa"
}
}
]
}
}
},
"type": "write_resource"
},
{
"address": "0xa",
"state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
"data": {
"type": "0x1::fungible_asset::ConcurrentSupply",
"data": {
"current": {
"max_value": "340282366920938463463374607431768211455",
"value": "25726501655234340"
}
}
},
"type": "write_resource"
},
{
"address": "0xa",
"state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
"data": {
"type": "0x1::fungible_asset::Metadata",
"data": {
"decimals": 8,
"icon_uri": "",
"name": "Aptos Coin",
"project_uri": "",
"symbol": "APT"
}
},
"type": "write_resource"
},
{
"address": "0xa",
"state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
"data": {
"type": "0x1::object::ObjectCore",
"data": {
"allow_ungated_transfer": true,
"guid_creation_num": "1125899906842625",
"owner": "0x1",
"transfer_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0xa",
"creation_num": "1125899906842624"
}
}
}
}
},
"type": "write_resource"
},
{
"address": "0xa",
"state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
"data": {
"type": "0x1::primary_fungible_store::DeriveRefPod",
"data": {
"metadata_derive_ref": {
"self": "0xa"
}
}
},
"type": "write_resource"
},
{
"address": "0x60d8ef2e962b1d1b4f602c72e23eed6fbba86eefb41853a7688073fc918d912",
"state_key_hash": "0x222b15ff81f90d75937ef6012807f0de0e0d488ccb5a229e55a954bc7870c75d",
"data": {
"type": "0x1::fungible_asset::FungibleStore",
"data": {
"balance": "566263899",
"frozen": false,
"metadata": {
"inner": "0xa"
}
}
},
"type": "write_resource"
},
{
"address": "0x60d8ef2e962b1d1b4f602c72e23eed6fbba86eefb41853a7688073fc918d912",
"state_key_hash": "0x222b15ff81f90d75937ef6012807f0de0e0d488ccb5a229e55a954bc7870c75d",
"data": {
"type": "0x1::object::ObjectCore",
"data": {
"allow_ungated_transfer": false,
"guid_creation_num": "1125899906842625",
"owner": "0x31deb490728ae8e1a89675ee4c1877af8e5849c526d2c9a64238c49d8ece08a0",
"transfer_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0x60d8ef2e962b1d1b4f602c72e23eed6fbba86eefb41853a7688073fc918d912",
"creation_num": "1125899906842624"
}
}
}
}
},
"type": "write_resource"
},
{
"address": "0x95a0fd88b11286d4790c253b39c6678b798c54b54b63bfd2bfe042411ee2e3e8",
"state_key_hash": "0xf389cd5138744eb2c2c40a6b708ff717cb7a04bec7c9c1b9b8847857eaf617cd",
"data": {
"type": "0x1::account::Account",
"data": {
"authentication_key": "0x95a0fd88b11286d4790c253b39c6678b798c54b54b63bfd2bfe042411ee2e3e8",
"coin_register_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0x95a0fd88b11286d4790c253b39c6678b798c54b54b63bfd2bfe042411ee2e3e8",
"creation_num": "0"
}
}
},
"guid_creation_num": "2",
"key_rotation_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0x95a0fd88b11286d4790c253b39c6678b798c54b54b63bfd2bfe042411ee2e3e8",
"creation_num": "1"
}
}
},
"rotation_capability_offer": {
"for": {
"vec": []
}
},
"sequence_number": "1680",
"signer_capability_offer": {
"for": {
"vec": []
}
}
}
},
"type": "write_resource"
}
],
"sender": "0x95a0fd88b11286d4790c253b39c6678b798c54b54b63bfd2bfe042411ee2e3e8",
"sequence_number": "1679",
"max_gas_amount": "5000",
"gas_unit_price": "100",
"expiration_timestamp_secs": "1760341246",
"payload": {
"function": "0x31deb490728ae8e1a89675ee4c1877af8e5849c526d2c9a64238c49d8ece08a0::lesserafim_3::crazy",
"type_arguments": [
"0x1::aptos_coin::AptosCoin",
"0x111ae3e5bc816a5e63c2da97d0aa3886519e0cd5e4b046659fa35796bd11542a::stapt_token::StakedApt",
"0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDC",
"0x159df6b7689437016108a019fd5bef736bac692b6d4a1f10c941f6fbb9a74ca6::oft::CakeOFT",
"0x8d87a65ba30e09357fa2edea2c80dbac296e5dec2b18287113500b902942929d::celer_coin_manager::UsdcCoin",
"0x1::aptos_coin::AptosCoin",
"u64",
"u64",
"u64",
"u64",
"u64"
],
"arguments": [
"0x010f0a0101",
"0x01010101010000",
[
"25",
"10",
"30",
"25",
"25"
],
[
{
"inner": "0xa"
},
{
"inner": "0xa"
},
{
"inner": "0xa"
},
{
"inner": "0xa"
},
{
"inner": "0xa"
},
{
"inner": "0xa"
}
],
[
"0x1",
"0x5669f388059383ab806e0dfce92196304205059874fd845944137d96bbdfc8de",
"0x1",
"0x1",
"0x1"
],
[
false,
true,
false,
true,
false
],
"28452012"
],
"type": "entry_function_payload"
},
"signature": {
"sender": {
"public_key": "0x1e9d94603ebd6b4a1d38e760be2b0523f09fb1f59e1e43c657f0ab3ef6205427",
"signature": "0x05f71501658fdc40b6f42f71d6c298a378434a5825af5bc0efcc15aba2aa38625064612139299f43ae40e710bad18ce0b9935dee00b705285a8f73318f06a301",
"type": "ed25519_signature"
},
"secondary_signer_addresses": [],
"secondary_signers": [],
"fee_payer_address": "0x31deb490728ae8e1a89675ee4c1877af8e5849c526d2c9a64238c49d8ece08a0",
"fee_payer_signer": {
"public_key": "0x17dfb6544cf49621c75af067528755a38061bdd210342f8bdf565bcdf561f056",
"signature": "0x7866a52d642e7442671d0614cf7b201a29bdbd8b709ea59462d32917c368f596d771ab6592d1659952970cb277a35d536d0966a754c2cd610858f8c04eb93e08",
"type": "ed25519_signature"
},
"type": "fee_payer_signature"
},
"replay_protection_nonce": null,
"events": [
{
"guid": {
"creation_number": "0",
"account_address": "0x0"
},
"sequence_number": "0",
"type": "0x1::transaction_fee::FeeStatement",
"data": {
"execution_gas_units": "130",
"io_gas_units": "65",
"storage_fee_octas": "0",
"storage_fee_refund_octas": "0",
"total_charge_gas_units": "195"
}
}
],
"timestamp": "1760341227055115",
"type": "user_transaction"
}
const axios = require('axios');
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_hash/0xd797b944ed8657406a1b09a5928048093399fc0a2f576d3e57c0f9cedbf95c4a',
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import requests
url = "https://go.getblock.io/<ACCESS_TOKEN>/v1/transactions/by_hash/0xd797b944ed8657406a1b09a5928048093399fc0a2f576d3e57c0f9cedbf95c4a"
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)wss://go.getblock.io/<ACCESS_TOKEN>//npm install ws dotenv
import WebSocket from "ws";
import "dotenv/config";
const ws = new WebSocket(
`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`,
);
ws.on("open", () => {
console.log("Connected to BSC streams");
});
ws.on("error", (err) => {
console.error("WebSocket error:", err.message);
});> [email protected] start
> node index.js
Connected to BSC streamsimport WebSocket from "ws";
import "dotenv/config";
const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
ws.on("open", () => {
console.log("Connected");
// Subscribe to new blocks
ws.send(
JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "subscribe",
params: ["bdnBlocks", { include: ["header", "transactions", "hash"] }],
}),
);
});
ws.on("message", (data) => {
const message = JSON.parse(data);
// Subscription confirmation
if (message.id === 1 && message.result) {
console.log("Subscribed! ID:", parseInt(message.result));
return;
}
// Block notification
if (message.params?.result) {
const block = message.params.result;
console.log("New block:", {
number: parseInt(block.header.number, 16),
hash: block.header.hash,
txCount: block.transactions?.length || 0,
});
}
});
Connected
Subscribed! ID: 9
New block: { number: 84411561, hash: undefined, txCount: 86 }
New block: { number: 84411562, hash: undefined, txCount: 105 }
New block: { number: 84411563, hash: undefined, txCount: 66 }
New block: { number: 84411564, hash: undefined, txCount: 66 }
New block: { number: 84411565, hash: undefined, txCount: 78 }
New block: { number: 84411566, hash: undefined, txCount: 93 }
New block: { number: 84411567, hash: undefined, txCount: 63 }import WebSocket from "ws";
import { ethers } from "ethers";
import "dotenv/config";
const PANCAKE_ROUTER = "0x10ED43C718714eb63d5aA57B78B54704E256024E";
const SWAP_METHODS = {
"0x38ed1739": "swapExactTokensForTokens",
"0x7ff36ab5": "swapExactETHForTokens",
"0x18cbafe5": "swapExactTokensForETH",
"0xfb3bdb41": "swapETHForExactTokens",
"0x5c11d795": "swapExactTokensForTokensSupportingFeeOnTransferTokens",
"0xb6f9de95": "swapExactETHForTokensSupportingFeeOnTransferTokens",
};
function monitorPancakeSwap() {
const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
ws.on("open", () => {
console.log("🔌 Connected to BSC stream");
console.log("📊 Monitoring PancakeSwap...\n");
ws.send(
JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "subscribe",
params: [
"pendingTxs",
{
include: ["tx_hash", "from", "to", "value", "input", "gas_price"],
filters: {
to: [PANCAKE_ROUTER],
},
},
],
}),
);
});
ws.on("message", (data) => {
const msg = JSON.parse(data);
// Subscription confirmed
if (msg.id === 1) {
console.log("✅ Subscribed to PancakeSwap transactions\n");
return;
}
// New transaction
if (msg.params?.result) {
const tx = msg.params.result;
const methodId = tx.input?.slice(0, 10);
const methodName = SWAP_METHODS[methodId] || "unknown";
if (SWAP_METHODS[methodId]) {
const value = ethers.formatEther(tx.value || "0");
const gasPrice = ethers.formatUnits(tx.gas_price || "0", "gwei");
console.log("🔄 Swap detected:");
console.log(` Hash: ${tx.tx_hash.slice(0, 18)}...`);
console.log(` Method: ${methodName}`);
console.log(` From: ${tx.from.slice(0, 10)}...`);
console.log(` Value: ${value} BNB`);
console.log(` Gas: ${gasPrice} gwei`);
console.log("");
}
}
});
ws.on("close", () => {
console.log("Disconnected, reconnecting in 5s...");
setTimeout(monitorPancakeSwap, 5000);
});
ws.on("error", (err) => {
console.error("WebSocket error:", err.message);
});
}
monitorPancakeSwap();
{
"tx_hash": "0xdef456...",
"from": "0xabc...",
"to": "0x10ED43C718714eb63d5aA57B78B54704E256024E",
"value": "0x16345785d8a0000",
"gas_price": "0xb2d05e00",
"input": "0x38ed1739..."
}import WebSocket from 'ws';
import 'dotenv/config';
const PANCAKE_ROUTER = '0x10ED43C718714eb63d5aA57B78B54704E256024E';
const SWAP_METHODS = {
'0x38ed1739': 'swapExactTokensForTokens',
'0x7ff36ab5': 'swapExactETHForTokens',
'0x18cbafe5': 'swapExactTokensForETH',
'0xfb3bdb41': 'swapETHForExactTokens',
};
function monitorNewTxs() {
const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
ws.on('open', () => {
console.log('Connected to BSC stream');
console.log('Monitoring confirmed PancakeSwap swaps...\n');
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'subscribe',
params: ['newTxs', {
include: ['tx_hash', 'from', 'to', 'value', 'input'],
filters: {
to: [PANCAKE_ROUTER],
method_id: Object.keys(SWAP_METHODS)
}
}]
}));
});
ws.on('message', (data) => {
const msg = JSON.parse(data);
if (msg.id === 1) {
console.log('Subscribed to confirmed PancakeSwap transactions\n');
return;
}
if (msg.params?.result) {
const tx = msg.params.result;
const methodId = tx.input?.slice(0, 10);
const methodName = SWAP_METHODS[methodId] || 'unknown';
console.log('Confirmed swap:');
console.log(` Hash: ${tx.tx_hash}`);
console.log(` Method: ${methodName}`);
console.log(` From: ${tx.from}`);
console.log(` To: ${tx.to}`);
console.log(` Value: ${tx.value}`);
console.log('');
}
});
ws.on('close', () => {
console.log('Disconnected, reconnecting in 5s...');
setTimeout(monitorNewTxs, 5000);
});
ws.on('error', (err) => {
console.error('WebSocket error:', err.message);
});
}
monitorNewTxs();
{
"jsonrpc":"2.0",
"id":1,
"result":"0x11"
}import WebSocket from 'ws';
import 'dotenv/config';
const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
ws.on("open", () => {
console.log("Connected");
// Subscribe to new blocks
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'subscribe',
params: ['txReceipts', {
include: ['receipt', 'logs']
}]
}));
});
ws.on("message", (data) => {
const message = JSON.parse(data);
console.log(message)}){
jsonrpc: '2.0',
id: 1,
result: '0x10'
}import WebSocket from "ws";
import "dotenv/config";
const ws = new WebSocket(`wss://go.getblock.io/${process.env.ACCESS_TOKEN}`);
ws.on("open", () => {
console.log("Connected");
ws.send(
JSON.stringify({
jsonrpc: "2.0",
id: 10,
method: "unsubscribe",
params: ["23"], // Subscription ID
}),
);})
ws.on("message", (data) => {
const message = JSON.parse(data);
console.log(JSON.stringify(message, null, 2));
});{
jsonrpc: '2.0',
id: 10,
result: true
}// ❌ Bad: Request everything
include: ['tx_contents'] // Large payloads, high bandwidth// ✅ Good: Request specific fields
include: ['tx_hash', 'from', 'to', 'value'] // Small payloads// ❌ Bad: Filter client-side
params: ['newTxs', { include: ['tx_contents'] }]
// Then filter in your code... wasteful!// ✅ Good: Filter server-side
params: ['newTxs', {
include: ['tx_hash', 'to', 'input'],
filters: { to: ['0xTargetContract'] }
}]function createConnection() {
const ws = new WebSocket(`wss://bsc.getblock.io/mev/ws?api_key=${API_KEY}`);
ws.on('close', () => {
console.log('Disconnected, reconnecting...');
setTimeout(createConnection, 5000);
});
ws.on('open', () => {
// Re-subscribe after reconnect
subscribeToFeeds(ws);
});
return ws;
}ws.on('message', async (data) => {
// Don't block the message loop
setImmediate(() => {
processMessage(JSON.parse(data));
});
});A step-by-step guide on how to build MCP with GetBlock API
zodEdit Config

A complete guide on how to track Pump.fun token launches on Solana in real-time using GetBlock’s Yellowstone gRPC service.
How to Build an App to Track Large Solana Transactions with GetBlock Yellowstone Geyer gRPC
Step-by-step guide for building a Node.js app to track real-time swaps on Solana using GetBlock's Yellowstone gRPC
# create project folder
mkdir basic-ethereum-mcp
# navigate through the folder
cd basic-ethereum-mcp
# initialise npm
npm init -ynpm install @modelcontextprotocol/sdk zod ethers{
"name": "basic-ethereum-mcp",
"version": "1.0.0",
"type": "module",
"description": "MCP server with GetBlock API integration",
"main": "server.js",
"bin": {
"mcp-ethereum": "./server.js"
},
"scripts": {
"start": "node server.js"
},
"keywords": ["mcp", "blockchain", "ethereum", "getblock"],
"author": "Your Name",
"license": "MIT",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.22.0",
"ethers": "^6.15.0",
"zod": "^3.25.76"
}
}├── server.js // Main application
└── .env // Environment variables
└── .gitignore // Git ignore fileimport { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { ethers } from "ethers";
import { z } from "zod";
// Validate environment
const GETBLOCK_TOKEN = process.env.GETBLOCK_TOKEN;
// Initialise Ethers provider with GetBlock
const provider = new ethers.JsonRpcProvider(
`https://go.getblock.us/${GETBLOCK_TOKEN}/`
);// Create MCP server with modern API
const server = new McpServer({
name: "ethereum-mcp-server",
version: "1.0.0",
});
console.error("✅ Ethereum MCP Server initialized");server.tool(
"get_eth_balance",
{
address: z
.string()
.regex(/^0x[a-fA-F0-9]{40}$/)
.describe("Ethereum address (0x followed by 40 hex characters)"),
},
async ({ address }) => {
try {
// Fetch balance from blockchain
const balanceWei = await provider.getBalance(address);
// Convert Wei to ETH
const balanceEth = ethers.formatEther(balanceWei);
// Return structured response
return {
content: [
{
type: "text",
text: JSON.stringify(
{
address: address,
balance: balanceEth,
unit: "ETH",
balanceWei: balanceWei.toString(),
},
null,
2
),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: JSON.stringify({
error: error.message,
address: address,
}),
},
],
isError: true,
};
}
}
);server.tool("get_gas_price", {}, async () => {
try {
// Fetch current fee data
const feeData = await provider.getFeeData();
// Convert to Gwei
const gasPriceGwei = ethers.formatUnits(feeData.gasPrice, "gwei");
return {
content: [
{
type: "text",
text: JSON.stringify(
{
gasPrice: gasPriceGwei,
unit: "Gwei",
gasPriceWei: feeData.gasPrice.toString(),
maxFeePerGas: feeData.maxFeePerGas
? ethers.formatUnits(feeData.maxFeePerGas, "gwei")
: null,
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas
? ethers.formatUnits(feeData.maxPriorityFeePerGas, "gwei")
: null,
},
null,
2
),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: JSON.stringify({ error: error.message }),
},
],
isError: true,
};
}
});server.tool("get_block_number", {}, async () => {
try {
// Fetch latest block number
const blockNumber = await provider.getBlockNumber();
return {
content: [
{
type: "text",
text: JSON.stringify(
{
blockNumber: blockNumber,
timestamp: new Date().toISOString(),
network: "Ethereum Mainnet",
},
null,
2
),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: JSON.stringify({ error: error.message }),
},
],
isError: true,
};
}
});async function main() {
try {
// Create stdio transport for Claude Desktop
const transport = new StdioServerTransport();
// Connect server to transport
await server.connect(transport);
console.error("🚀 Ethereum MCP Server is running!");
console.error("📡 Connected via stdio transport");
console.error("⏳ Waiting for tool calls...");
} catch (error) {
console.error("❌ Failed to start server:", error);
process.exit(1);
}
}// Handle graceful shutdown
process.on("SIGINT", () => {
console.error("\n👋 Shutting down...");
process.exit(0);
});
// Start the server
main().catch((error) => {
console.error("💥 Fatal error:", error);
process.exit(1);
});~/Library/Application Support/Claude/claude_desktop_config.jsoncode ~/Library/Application\ Support/Claude/claude_desktop_config.json{
"mcpServers": {
"ethereum": {
"command": "node",
"args": [
"/Users/YOUR_USERNAME/basic-ethereum-mcp/server.js"
],
"env": {
"GETBLOCK_TOKEN": "your-actual-getblock-token-here"
}
}
}
}%APPDATA%\Claude\claude_desktop_config.json{
"mcpServers": {
"ethereum": {
"command": "node",
"args": [
"C:\\Users\\YOUR_USERNAME\\basic-ethereum-mcp/\\server.js"
],
"env": {
"GETBLOCK_TOKEN": "your-actual-getblock-token-here"
}
}
}
}What's the ETH balance of 0xd1af2dac4e0a9d1f58b99e2f42bc0320ed74a7cd?What's the current Ethereum gas price?What's the latest Ethereum block number?Check the balance for 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
and tell me if the current gas price is high or lowIs now a good time to send an Ethereum transaction?https://go.getblock.us/7hys368hus...https://go.getblock.asia/f782e8ec54....https://go.getblock.io/d4067b3cc......https://go.getblock.us/{YOUR-ACCESS-TOKEN}/GETBLOCK_TOKEN=your_token~/.config/Claude/claude_desktop_config.json{
"mcpServers": {
"ethereum": {
"command": "node",
"args": [
"/home/YOUR_USERNAME/basic-ethereum-mcp//server.js"
],
"env": {
"GETBLOCK_TOKEN": "your-actual-getblock-token-here"
}
}
}
}npm startaccountKeys[programIdx] and convert it from binary to a readable format using bs58.encode()CommitmentLevel.PROCESSED for faster updateshttps://go.getblock.io/YOUR_ACCESS_TOKEN/https://go.getblock.us/YOUR_ACCESS_TOKEN/https://go.getblock.asia/YOUR_ACCESS_TOKEN/mkdir pumpfun-monitor
cd pumpfun-monitor
npm init-ynpm install @triton-one/yellowstone-grpc [email protected]├── pumpfun-monitor.js // Main apllication
└── .env // Environment variables
└── .gitignore // Git ignore fileconst Client = require("@triton-one/yellowstone-grpc").default;
const { CommitmentLevel } = require("@triton-one/yellowstone-grpc");
const bs58 = require("bs58");// GetBlock Configuration
const ENDPOINT = "https://go.getblock.io"; // Your region's endpoint
const TOKEN = "YOUR_ACCESS_TOKEN"; // Your generated token// Pump.fun Program Constants
const PUMPFUN_PROGRAM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";
const CREATE_DISCRIMINATOR = Buffer.from([24, 30, 200, 40, 5, 28, 7, 119]);// Statistics Tracking
let stats = {
startTime: Date.now(),
totalMints: 0,
lastMintTime: null
};
What this does: function decodeString(buffer, offset) {
const length = buffer.readUInt32LE(offset);
const str = buffer.slice(offset + 4, offset + 4 + length).toString('utf8');
return { value: str, bytesRead: 4 + length };
}function parseCreateInstruction(data) {
try {
let offset = 8; // Skip the discriminator
const name = decodeString(data, offset);
offset += name.bytesRead;
const symbol = decodeString(data, offset);
offset += symbol.bytesRead;
const uri = decodeString(data, offset);
return {
name: name.value,
symbol: symbol.value,
uri: uri.value
};
} catch (error) {
return null;
}
}
function extractAccounts(transaction, instructionIndex) {
try {
const message = transaction.transaction.message;
const instruction = message.instructions[instructionIndex];
const accountKeys = message.accountKeys;
const accountIndices = Array.from(instruction.accounts);
const accounts = accountIndices.map(idx => {
const accountKey = accountKeys[idx];
return bs58.encode(Buffer.from(accountKey));
});
return {
mint: accounts[0],
bondingCurve: accounts[2],
creator: accounts[7]
};
} catch (error) {
return null;
}
}function isCreateInstruction(instruction, accountKeys) {
const programIdx = instruction.programIdIndex;
const programId = bs58.encode(accountKeys[programIdx]);
if (programId !== PUMPFUN_PROGRAM) return false;
const data = Buffer.from(instruction.data);
return data.slice(0, 8).equals(CREATE_DISCRIMINATOR);
}function displayTokenMint(tokenData, signature, slot) {
stats.totalMints++;
stats.lastMintTime = new Date();
console.log("\n" + "=".repeat(80));
console.log(`🎉 NEW PUMP.FUN TOKEN MINT #${stats.totalMints}`);
console.log("=".repeat(80));
console.log(`\n📛 NAME: ${tokenData.name}`);
console.log(`🏷️ SYMBOL: $${tokenData.symbol}`);
console.log(`\n🪙 MINT: ${tokenData.mint}`);
console.log(`👤 CREATOR: ${tokenData.creator}`);
console.log(`📊 BONDING: ${tokenData.bondingCurve}`);
console.log(`\n🔗 METADATA: ${tokenData.uri}`);
console.log(`📜 SIGNATURE: ${signature}`);
console.log(`🎰 SLOT: ${slot}`);
console.log(`\n🔍 EXPLORE:`);
console.log(` Token: https://solscan.io/token/${tokenData.mint}`);
console.log(` TX: https://solscan.io/tx/${signature}`);
console.log(` Creator: https://solscan.io/account/${tokenData.creator}`);
console.log("\n" + "=".repeat(80) + "\n");
}async function monitorPumpfunMints() {
console.log("🚀 Starting Pump.fun Token Mint Monitor");
console.log(`🎯 Watching program: ${PUMPFUN_PROGRAM}\n`);
console.log("Waiting for new token mints...\n");
return new Promise(async (resolve, reject) => {
try {
const client = new Client(ENDPOINT, TOKEN, undefined);
const stream = await client.subscribe(); const request = {
accounts: {},
slots: {},
transactions: {
pumpfun: {
accountInclude: [PUMPFUN_PROGRAM],
accountExclude: [],
accountRequired: []
}
},
transactionsStatus: {},
entry: {},
blocks: {},
blocksMeta: {},
commitment: CommitmentLevel.CONFIRMED,
accountsDataSlice: [],
ping: undefined
};
stream.on("data", (message) => {
try {
if (message.pong) {
stream.write({ ping: { id: message.pong.id } });
return;
}
if (message.transaction && message.filters &&
message.filters.includes('pumpfun')) {
const tx = message.transaction.transaction;
const signature = bs58.encode(tx.signature);
const slot = message.transaction.slot.toString();
const txMessage = tx.transaction.message;
const accountKeys = txMessage.accountKeys;
const instructions = txMessage.instructions;for (let i = 0; i < instructions.length; i++) {
const instruction = instructions[i];
if (isCreateInstruction(instruction, accountKeys)) {
const instructionData = Buffer.from(instruction.data);
const tokenMetadata = parseCreateInstruction(instructionData);
if (!tokenMetadata) continue;
const accounts = extractAccounts(
{ transaction: { message: txMessage } },
i
);
if (!accounts) continue;
displayTokenMint(
{ ...tokenMetadata, ...accounts },
signature,
slot
);
}
}
}
} catch (error) {
console.error(`Error: ${error.message}`);
}
});
stream.on("error", (error) => {
console.error(`Stream error: ${error.message}`);
reject(error);
});
stream.on("end", () => resolve());
stream.on("close", () => resolve());stream.write(request, (err) => {
if (err) {
reject(err);
} else {
console.log("✅ Subscription active - monitoring blockchain...\n");
}
});
} catch (error) {
reject(error);
}
});
}
async function main() {
try {
await monitorPumpfunMints();
} catch (error) {
console.error("Monitor crashed:", error.message);
console.log("Restarting in 5 seconds...");
setTimeout(main, 5000);
}
}process.on('SIGINT', () => {
console.log("\n\n🛑 Shutting down...");
console.log(`\nTotal mints detected: ${stats.totalMints}`);
const uptime = Math.floor((Date.now() - stats.startTime) / 1000);
console.log(`Uptime: ${Math.floor(uptime / 60)}m ${uptime % 60}s\n`);
process.exit(0);
});
main();node pumpfun-monitor.js🚀 Starting Pump.fun Token Mint Monitor
🎯 Watching program: 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P
Waiting for new token mints...
✅ Subscription active - monitoring blockchain...================================================================================
🎉 NEW PUMP.FUN TOKEN MINT #1
================================================================================
📛 NAME: Super Doge
🏷️ SYMBOL: $SDOGE
🪙 MINT: 7xKXtG5CJYAuGZ3w8bXRGLynAmj4twABC123def456
👤 CREATOR: 9wFFyRfZBsuAha4YcuxcXLKwMxJR43S7fPfQLusDBzvT
📊 BONDING: HMU77nPMBMZ9Wf9TpvvJtFHkjNLkNeGZ8xzBvakKpump
🔗 METADATA: https://ipfs.io/ipfs/QmYJZ9HGVgYiRGkF...
📜 SIGNATURE: 5TYqzsc8kGY7vMGDZxEbBFWGnEUPTQQMpk9k...
🎰 SLOT: 376205017
🔍 EXPLORE:
Token: https://solscan.io/token/7xKXtG5...
TX: https://solscan.io/tx/5TYqzsc8kGY7v...
Creator: https://solscan.io/account/9wFFyRfZ...
================================================================================
Connection refusedFailed to extract accountsGETBLOCK_TOKEN=your_token node pumpfun-monitor.js//use dotenv
const TOKEN = process.env.GETBLOCK_TOKEN;https://go.getblock.asia/YOUR_ACCESS_TOKEN/https://go.getblock.us/YOUR_ACCESS_TOKEN/https://go.getblock.io/YOUR_ACCESS_TOKEN/mkdir sol-transfer-monitor
cd sol-transfer-monitornpm init -ynpm install @triton-one/yellowstone-grpc [email protected] dotenvtouch sol-transfer-monitor.js{
"name": "sol-transfer-monitor",
"version": "1.0.0",
"description": "A Listener that tracks high-value SOL transactions",
"main": "sol-transfer-monitor.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node sol-transfer-monitor.js"
},
"keywords": [
"Solana",
"Liquidity Monitor",
"Onchain transfer"
],
"author": "",
"license": "ISC",
"type": "module",
"dependencies": {
"@triton-one/yellowstone-grpc": "^4.0.2",
"bs58": "^5.0.0",
"dotenv": "^17.2.3"
}
}
pumpfun-migrations-listener/
├── sol-transfer-monitor.js # Main application logic
├── .env # Environment variables (add to .gitignore)
├── .gitignore # Git ignore file
└── package.json # Project configurationnode_modules/
.env
*.logimport Client from "@triton-one/yellowstone-grpc";
import { CommitmentLevel } from "@triton-one/yellowstone-grpc";
import bs58 from "bs58";
import { config } from "dotenv";
config();
const ENDPOINT = "https://go.getblock.io"; // Your region's endpoint
const TOKEN = process.env.GETBLOCK_TOKEN; // Your generated token// System Program (handles all native SOL transfers)
const SYSTEM_PROGRAM = "11111111111111111111111111111111";
// Minimum transfer amount in SOL to alert on
const MIN_TRANSFER_AMOUNT = 100; // 100 SOL threshold// Statistics Tracking
let stats = {
startTime: Date.now(),
totalTransfers: 0,
totalVolume: 0,
largestTransfer: 0,
largestTransferTx: null
};function formatSOL(lamports) {
return (lamports / 1_000_000_000).toFixed(4);
}function displayTransfer(transferData) {
stats.totalTransfers++;
stats.totalVolume += transferData.amount;
if (transferData.amount > stats.largestTransfer) {
stats.largestTransfer = transferData.amount;
stats.largestTransferTx = transferData.signature;
}
const solAmount = formatSOL(transferData.amount);
console.log("\n" + "=".repeat(80));
console.log(`HIGH VALUE TRANSFER #${stats.totalTransfers}`);
console.log("=".repeat(80));
console.log(`\nAMOUNT: ${solAmount} SOL`);
console.log(`FROM: ${transferData.from}`);
console.log(`TO: ${transferData.to}`);
console.log(`SIGNATURE: ${transferData.signature}`);
console.log(`SLOT: ${transferData.slot}`);
console.log(`\nEXPLORE:`);
console.log(` TX: https://solscan.io/tx/${transferData.signature}`);
console.log(` From: https://solscan.io/account/${transferData.from}`);
console.log(` To: https://solscan.io/account/${transferData.to}`);
console.log("\n" + "=".repeat(80) + "\n");
}function parseTransferInstruction(instruction, accountKeys) {
try {
const data = Buffer.from(instruction.data);
// System program transfer instruction has type 2
// Data format: [4 bytes: instruction type (2)][8 bytes: lamports amount]
if (data.length < 12) return null;
const instructionType = data.readUInt32LE(0);
if (instructionType !== 2) return null; // Not a transfer instruction
const lamports = data.readBigUInt64LE(4);
// Get from and to accounts
const accountIndices = Array.from(instruction.accounts);
if (accountIndices.length < 2) return null;
const fromAccount = bs58.encode(Buffer.from(accountKeys[accountIndices[0]]));
const toAccount = bs58.encode(Buffer.from(accountKeys[accountIndices[1]]));
return {
amount: Number(lamports),
from: fromAccount,
to: toAccount
};
} catch (error) {
return null;
}
}async function monitorHighValueTransfers() {
console.log("Starting High Value SOL Transfer Monitor");
console.log(`Minimum amount: ${MIN_TRANSFER_AMOUNT} SOL`);
console.log(`Watching: Native SOL transfers\n`);
console.log("Waiting for high value transfers...\n");
return new Promise(async (resolve, reject) => {
try {
const client = new Client(ENDPOINT, TOKEN, undefined);
const stream = await client.subscribe(); const request = {
accounts: {},
slots: {},
transactions: {
sol_transfers: {
accountInclude: [SYSTEM_PROGRAM],
accountExclude: [],
accountRequired: []
}
},
transactionsStatus: {},
entry: {},
blocks: {},
blocksMeta: {},
commitment: CommitmentLevel.CONFIRMED,
accountsDataSlice: [],
ping: undefined
};
stream.on("data", (message) => {
try {
if (message.pong) {
stream.write({ ping: { id: message.pong.id } });
return;
}
if (message.transaction && message.filters &&
message.filters.includes('sol_transfers')) {
const tx = message.transaction.transaction;
const signature = bs58.encode(tx.signature);
const slot = message.transaction.slot.toString();
const txMessage = tx.transaction.message;
const accountKeys = txMessage.accountKeys;
const instructions = txMessage.instructions;
// Process each instruction
for (const instruction of instructions) {
const programIdx = instruction.programIdIndex;
const programId = bs58.encode(accountKeys[programIdx]);
// Only process System Program instructions
if (programId !== SYSTEM_PROGRAM) continue;
const transferData = parseTransferInstruction(instruction, accountKeys);
if (!transferData) continue;
// Check if transfer meets minimum threshold
const solAmount = transferData.amount / 1_000_000_000;
if (solAmount >= MIN_TRANSFER_AMOUNT) {
displayTransfer({
...transferData,
signature: signature,
slot: slot
});
}
}
}
} catch (error) {
console.error(`Error processing transaction: ${error.message}`);
}
});
stream.on("error", (error) => {
console.error(`Stream error: ${error.message}`);
reject(error);
});
stream.on("end", () => resolve());
stream.on("close", () => resolve());
stream.write(request, (err) => {
if (err) {
reject(err);
} else {
console.log("Subscription active - monitoring blockchain...\n");
}
});
} catch (error) {
reject(error);
}
});
}
async function main() {
try {
await monitorHighValueTransfers();
} catch (error) {
console.error("Monitor crashed:", error.message);
console.log("Restarting in 5 seconds...");
setTimeout(main, 5000);
}
}process.on('SIGINT', () => {
console.log("\n\nShutting down...");
console.log(`\nTotal high value transfers: ${stats.totalTransfers}`);
console.log(`Total volume: ${formatSOL(stats.totalVolume)} SOL`);
console.log(`Largest transfer: ${formatSOL(stats.largestTransfer)} SOL`);
if (stats.largestTransferTx) {
console.log(`Largest TX: https://solscan.io/tx/${stats.largestTransferTx}`);
}
const uptime = Math.floor((Date.now() - stats.startTime) / 1000);
console.log(`Uptime: ${Math.floor(uptime / 60)}m ${uptime % 60}s\n`);
process.exit(0);
});main();npm start> [email protected] start
> node sol-transfer-monitor.js
[[email protected]] injecting env (1) from .env -- tip: ⚙️ load multiple .env files with { path: ['.env.local', '.env'] }
Starting High Value SOL Transfer Monitor
Minimum amount: 100 SOL
Watching: Native SOL transfers
Waiting for high value transfers...
Subscription active - monitoring blockchain...
================================================================================
HIGH VALUE TRANSFER #1
================================================================================
AMOUNT: 1990.0000 SOL
FROM: 5tzFkiKscXHK5ZXCGbXZxdw7gTjjD1mBwuoFbhUvuAi9
TO: 53AXjkQHZQEbHZvV55VHtcZtFzBzArLZZG5AF4ufkRhv
SIGNATURE: 4uJgnfRohiq6c9CDWUtk3w94ouYGya5dGkx4LSS5tuFGDRypuXtN7cQLLy3eNj5V1b5PwEWccJqLak1Rnd9kRtTB
SLOT: 382899112
EXPLORE:
TX: https://solscan.io/tx/4uJgnfRohiq6c9CDWUtk3w94ouYGya5dGkx4LSS5tuFGDRypuXtN7cQLLy3eNj5V1b5PwEWccJqLak1Rnd9kRtTB
From: https://solscan.io/account/5tzFkiKscXHK5ZXCGbXZxdw7gTjjD1mBwuoFbhUvuAi9
To: https://solscan.io/account/53AXjkQHZQEbHZvV55VHtcZtFzBzArLZZG5AF4ufkRhv
================================================================================
^C
Shutting down...
Total high value transfers: 7
Total volume: 5519.0244 SOL
Largest transfer: 2272.0770 SOL
Largest TX: https://solscan.io/tx/3p92tKFb4AGRUJKA87vJD4fYcb3Z9wKi5AuUskA6TAR5SYciZxL3qmSH88ubQP3g7xSJQjC5kEeMSr7Lhhn8Hkc4
Uptime: 1m 50sStream error: 7 PERMISSION_DENIED: RBAC: access denied
Monitor crashed: 7 PERMISSION_DENIED: RBAC: access deniedhttps://go.getblock.io/YOUR_ACCESS_TOKEN/https://go.getblock.us/YOUR_ACCESS_TOKEN/https://go.getblock.asia/YOUR_ACCESS_TOKEN/mkdir pool-monitor
cd pool-monitor
npm init-ynpm install @triton-one/yellowstone-grpc [email protected]{
"name": "pool-monitor",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node pool-monitor.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module",
"dependencies": {
"@triton-one/yellowstone-grpc": "^4.0.2",
"bs58": "^5.0.0",
"dotenv": "^17.2.3"
}
}
├── pool-monitor.js. // Main application
└── .env // Environment variables
└── .gitignore // Git ignore fileimport Client from "@triton-one/yellowstone-grpc";
import { CommitmentLevel } from "@triton-one/yellowstone-grpc";
import bs58 from "bs58";
import { config } from "dotenv";
// Load environment variables from .env
config();// GetBlock Configuration
const ENDPOINT = "https://go.getblock.io"; // Your region's endpoint
const TOKEN = process.env.GETBLOCK_TOKEN; ; // Your generated token// Pool Configuration
const TARGET_POOL = "8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj"; // SOL/USDC CLMM
const POOL_NAME = "SOL/USDC";// Common Solana DEX Program IDs
const RAYDIUM_AMM = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8";
const RAYDIUM_CLMM = "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK";
const JUPITER_V6 = "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4";// Statistics
let stats = {
startTime: Date.now(),
totalSwaps: 0
};function identifySwapSource(instructions, accountKeys) {
for (const instruction of instructions) {
const programIdx = instruction.programIdIndex;
const programId = bs58.encode(accountKeys[programIdx]);
if (programId === JUPITER_V6) {
return "Jupiter";
} else if (programId === RAYDIUM_CLMM) {
return "Raydium CLMM";
} else if (programId === RAYDIUM_AMM) {
return "Raydium AMM";
}
}
return "Other";
}function displaySwap(swapData) {
stats.totalSwaps++;
console.log("\n" + "=".repeat(80));
console.log(`✅ SWAP #${stats.totalSwaps} on ${POOL_NAME}`);
console.log("=".repeat(80));
console.log(`\n🔀 SOURCE: ${swapData.source}`);
console.log(`👤 TRADER: ${swapData.trader}`);
console.log(`📜 SIGNATURE: ${swapData.signature}`);
console.log(`🎰 SLOT: ${swapData.slot}`);
console.log(`⏰ TIME: ${swapData.time}`);
console.log(`\n🔍 EXPLORE:`);
console.log(` TX: https://solscan.io/tx/${swapData.signature}`);
console.log(` Pool: https://solscan.io/account/${TARGET_POOL}`);
console.log("\n" + "=".repeat(80) + "\n");
}async function monitorPoolSwaps() {
console.log("🚀 Starting Liquidity Pool Swap Monitor");
console.log(`🎯 Pool: ${POOL_NAME}`);
console.log(`📍 Address: ${TARGET_POOL}\n`);
console.log("Waiting for swaps...\n");
return new Promise(async (resolve, reject) => {
try {
const client = new Client(ENDPOINT, TOKEN, undefined);
const stream = await client.subscribe();const request = {
accounts: {},
slots: {},
transactions: {
pool_swaps: {
accountInclude: [TARGET_POOL],
accountExclude: [],
accountRequired: []
}
},
transactionsStatus: {},
entry: {},
blocks: {},
blocksMeta: {},
commitment: CommitmentLevel.CONFIRMED,
accountsDataSlice: [],
ping: undefined
};stream.on("data", (message) => {
try {
if (message.pong) {
stream.write({ ping: { id: message.pong.id } });
return;
}
if (message.transaction && message.filters &&
message.filters.includes('pool_swaps')) {
const tx = message.transaction.transaction;
const signature = bs58.encode(tx.signature);
const slot = message.transaction.slot.toString();
const txMessage = tx.transaction.message;
const accountKeys = txMessage.accountKeys;
const instructions = txMessage.instructions;// Skip failed transactions
const txMeta = message.transaction.meta;
if (txMeta && txMeta.err) return;
// Identify swap source
const source = identifySwapSource(instructions, accountKeys);
// Get trader (signer)
const trader = accountKeys.length > 0
? bs58.encode(Buffer.from(accountKeys[0]))
: "Unknown";
displaySwap({
source: source,
trader: trader,
signature: signature,
slot: slot,
time: new Date().toLocaleTimeString()
});
}
} catch (error) {
console.error(`Error processing transaction: ${error.message}`);
}
});
stream.on("error", (error) => {
console.error(`Stream error: ${error.message}`);
reject(error);
});
stream.on("end", () => resolve());
stream.on("close", () => resolve());stream.write(request, (err) => {
if (err) {
reject(err);
} else {
console.log("✅ Subscription active - monitoring pool swaps...\n");
}
});
} catch (error) {
reject(error);
}
});
}async function main() {
try {
await monitorPoolSwaps();
} catch (error) {
console.error("Monitor crashed:", error.message);
console.log("Restarting in 5 seconds...");
setTimeout(main, 5000);
}
}process.on('SIGINT', () => {
console.log("\n\n🛑 Shutting down...");
console.log(`Total swaps detected: ${stats.totalSwaps}\n`);
process.exit(0);
});
main();node pool-monitor.js🚀 Starting Liquidity Pool Swap Monitor
🎯 Pool: SOL/USDC
📍 Address: 8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj
Waiting for swaps...
✅ Subscription active - monitoring pool swaps...
This means you're connected to GetBlock and monitoring is active!
When a Swap Appears
================================================================================
✅ SWAP #1 on SOL/USDC
================================================================================
🔀 SOURCE: Jupiter
👤 TRADER: 9wFFyRfZBsuAha4YcuxcXLKwMxJR43S7fPfQLusDBzvT
📜 SIGNATURE: 5TYqzsc8kGY7vMGDZxEbBFWGnEUPTQQMpk9kRvx3H8p2
🎰 SLOT: 376205017
⏰ TIME: 14:32:18
🔍 EXPLORE:
TX: https://solscan.io/tx/5TYqzsc8kGY7vMGDZxEbBFWGnEUPTQQMpk9kRvx3H8p2
Pool: https://solscan.io/account/8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj
================================================================================"Connection refused"Error processing transaction warnings





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
initialize2npm start

# Create project folder
mkdir pumpfun-migrations-listener
cd pumpfun-migrations-listener
# Initialize npm
npm init -ynpm install @solana/web3.js ws dotenv{
"name": "pumpfun-migrations-listener",
"version": "1.0.0",
"type": "module",
"description": "Real-time listener for Pump.fun migrations to PumpSwap and Raydium",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"keywords": ["pump.fun", "pumpswap", "raydium", "solana", "getblock"],
"author": "GetBlock",
"license": "MIT",
"dependencies": {
"@solana/web3.js": "^1.98.4",
"dotenv": "^17.2.3",
"ws": "^8.18.3"
}
}wss://go.getblock.us/<ACCESS_TOKEN>https://go.getblock.us/<ACCESS_TOKEN>GETBLOCK_WS_ENDPOINT=wss://go.getblock.us/<ACCESS_TOKEN>
GETBLOCK_HTTP_ENDPOINT=https://go.getblock.us/<ACCESS_TOKEN>pumpfun-migrations-listener/
├── server.js # Main application logic
├── .env # Environment variables (add to .gitignore)
├── .gitignore # Git ignore file
└── package.json # Project configurationnode_modules/
.env
*.logimport { Connection, PublicKey } from '@solana/web3.js';
import WebSocket from 'ws';
import dotenv from 'dotenv';
// Load environment variables
dotenv.config();
// Configuration
const WS_ENDPOINT = process.env.GETBLOCK_WS_ENDPOINT;
const HTTP_ENDPOINT = process.env.GETBLOCK_HTTP_ENDPOINT;
const MIGRATION_ACCOUNT = '39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg';
const RAYDIUM_PROGRAM = '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8';
const PUMPFUN_PROGRAM = '6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P';
// Validate configuration
if (!WS_ENDPOINT || !HTTP_ENDPOINT) {
console.error('❌ Missing required environment variables');
console.error('Please set GETBLOCK_WS_ENDPOINT and GETBLOCK_HTTP_ENDPOINT in .env file');
process.exit(1);
}
console.log('✅ Configuration loaded successfully');class PumpFunMigrationListener {
constructor() {
this.ws = null;
this.connection = new Connection(HTTP_ENDPOINT, 'confirmed');
this.subscriptionId = null;
this.isConnected = false;
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 10;
this.raydiumMigrationCount = 0;
this.pumpswapMigrationCount = 0;
this.migrations = [];
this.startTime = Date.now();
this.totalLogsReceived = 0;
} start() {
console.log('🚀 Starting Pump.fun Migration Listener...');
console.log('📡 Monitoring account:', MIGRATION_ACCOUNT);
console.log('🎯 Tracking: Raydium + PumpSwap migrations');
console.log('');
this.connect();
this.checkRunning();
}
checkRunning() {
setInterval(() => {
const runtime = Math.floor((Date.now() - this.startTime) / 1000);
const hours = Math.floor(runtime / 3600);
const minutes = Math.floor((runtime % 3600) / 60);
const seconds = runtime % 60;
console.log(`💓 Alive | Runtime: ${hours}h ${minutes}m ${seconds}s | Logs: ${this.totalLogsReceived} | Raydium: ${this.raydiumMigrationCount} | PumpSwap: ${this.pumpswapMigrationCount}`);
}, 60000);
} connect() {
console.log('🔌 Connecting to GetBlock WebSocket...');
this.ws = new WebSocket(WS_ENDPOINT);
this.ws.on('open', () => this.handleOpen());
this.ws.on('message', (data) => this.handleMessage(data));
this.ws.on('error', (error) => this.handleError(error));
this.ws.on('close', () => this.handleClose());
}
handleOpen() {
console.log('✅ Connected to GetBlock WebSocket');
this.isConnected = true;
this.reconnectAttempts = 0;
this.subscribeToLogs();
} subscribeToLogs() {
const subscribeRequest = {
jsonrpc: '2.0',
id: 1,
method: 'logsSubscribe',
params: [
{
mentions: [MIGRATION_ACCOUNT]
},
{
commitment: 'confirmed'
}
]
};
console.log('📡 Subscribing to migration events...');
this.ws.send(JSON.stringify(subscribeRequest));
} async handleMessage(data) {
try {
const message = JSON.parse(data.toString());
if (message.result && !message.params) {
this.subscriptionId = message.result;
console.log(`✅ Subscribed with ID: ${this.subscriptionId}`);
console.log('⏳ Listening for migrations...\n');
return;
}
if (message.params && message.params.result) {
await this.processLog(message.params.result);
}
} catch (error) {
console.error('❌ Error handling message:', error.message);
}
} async processLog(result) {
const { value } = result;
this.totalLogsReceived++;
console.log(`📨 Log #${this.totalLogsReceived} - TX: ${value.signature.substring(0, 20)}...`);
if (value.err) {
console.log(' ↳ Skipped (failed transaction)');
return;
}
const hasMigration = value.logs.some(
(log) =>
log.includes("Instruction: Migrate") ||
log.includes("migrate") ||
log.includes("initialize2")
);
if (hasMigration) {
console.log(" ↳ 🎯 MIGRATION DETECTED!");
await this.fetchAndProcessTransaction(value.signature);
} else {
console.log(" ↳ Not a migration");
}
} async fetchAndProcessTransaction(signature) {
try {
await new Promise((resolve) => setTimeout(resolve, 1000));
const tx = await this.connection.getTransaction(signature, {
maxSupportedTransactionVersion: 0,
commitment: 'confirmed'
});
if (!tx) {
console.log('⚠️ Transaction not found, skipping...');
return;
}
const migrationData = this.extractMigrationData(tx, signature);
if (migrationData) {
this.migrations.push(migrationData);
if (migrationData.type === 'raydium') {
this.raydiumMigrationCount++;
} else if (migrationData.type === 'pumpswap') {
this.pumpswapMigrationCount++;
}
this.displayMigration(migrationData);
}
} catch (error) {
console.error('❌ Error fetching transaction:', error.message);
}
} extractMigrationData(tx, signature) {
try {
let accountKeys, instructions;
if (tx.transaction.message.addressTableLookups) {
accountKeys = tx.transaction.message.staticAccountKeys ||
tx.transaction.message.accountKeys;
instructions = tx.transaction.message.compiledInstructions ||
tx.transaction.message.instructions;
} else {
accountKeys = tx.transaction.message.accountKeys;
instructions = tx.transaction.message.instructions;
}
if (!Array.isArray(instructions)) {
instructions = Object.values(instructions);
}
for (const instruction of instructions) {
let programId;
if (instruction.programIdIndex !== undefined) {
programId = accountKeys[instruction.programIdIndex];
} else if (instruction.programId) {
programId = instruction.programId;
}
// Check for Raydium migration
if (programId && programId.toString() === RAYDIUM_PROGRAM) {
const accounts = instruction.accounts;
if (!accounts || accounts.length < 7) continue;
return {
type: 'raydium',
signature: signature,
slot: tx.slot,
blockTime: tx.blockTime,
poolAddress: accountKeys[accounts[1]].toString(),
tokenAddress: accountKeys[accounts[5]].toString(),
quoteMint: accountKeys[accounts[6]].toString(),
lpMint: accountKeys[accounts[4]].toString(),
};
}
// Check for PumpSwap migration
if (programId && programId.toString() === PUMPFUN_PROGRAM) {
return {
type: 'pumpswap',
signature: signature,
slot: tx.slot,
blockTime: tx.blockTime,
tokenAddress: accountKeys[2] ? accountKeys[2].toString() : 'Unknown',
bondingCurve: accountKeys[1] ? accountKeys[1].toString() : 'Unknown',
destination: 'PumpSwap',
};
}
}
} catch (error) {
console.error('❌ Error extracting migration data:', error.message);
}
return null;
} displayMigration(data) {
if (data.type === 'raydium') {
console.log('\n🚀 ═══════════════════════════════════════════════════');
console.log(' NEW PUMP.FUN → RAYDIUM MIGRATION DETECTED!');
console.log('═══════════════════════════════════════════════════\n');
console.log(`Migration #${this.raydiumMigrationCount} (Raydium)\n`);
console.log(`📊 Token Address: ${data.tokenAddress}`);
console.log(`🏊 Pool Address: ${data.poolAddress}`);
console.log(`💧 LP Mint: ${data.lpMint}`);
console.log(`💰 Quote Token: ${data.quoteMint}\n`);
console.log(`📝 Transaction: ${data.signature}`);
console.log(`🔢 Slot: ${data.slot}`);
if (data.blockTime) {
console.log(`⏰ Time: ${new Date(data.blockTime * 1000).toISOString()}`);
}
console.log(`\n🔗 View on Solscan:`);
console.log(` https://solscan.io/tx/${data.signature}\n`);
console.log(`🔗 Trade on Raydium:`);
console.log(` https://raydium.io/swap/?inputMint=sol&outputMint=${data.tokenAddress}\n`);
console.log('═══════════════════════════════════════════════════\n');
} else if (data.type === 'pumpswap') {
console.log('\n💧 ═══════════════════════════════════════════════════');
console.log(' NEW PUMP.FUN → PUMPSWAP MIGRATION DETECTED!');
console.log('═══════════════════════════════════════════════════\n');
console.log(`Migration #${this.pumpswapMigrationCount} (PumpSwap)\n`);
console.log(`📊 Token Address: ${data.tokenAddress}`);
console.log(`🎯 Bonding Curve: ${data.bondingCurve}`);
console.log(`🏪 Destination: ${data.destination}\n`);
console.log(`📝 Transaction: ${data.signature}`);
console.log(`🔢 Slot: ${data.slot}`);
if (data.blockTime) {
console.log(`⏰ Time: ${new Date(data.blockTime * 1000).toISOString()}`);
}
console.log(`\n🔗 View on Solscan:`);
console.log(` https://solscan.io/tx/${data.signature}\n`);
console.log(`🔗 View Token:`);
console.log(` https://pump.fun/${data.tokenAddress}\n`);
console.log('═══════════════════════════════════════════════════\n');
}
} handleError(error) {
console.error('❌ WebSocket error:', error.message);
}
handleClose() {
this.isConnected = false;
console.log('🔌 Connection closed');
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);
console.log(`🔄 Reconnecting in ${delay / 1000}s (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);
setTimeout(() => {
this.connect();
}, delay);
} else {
console.error('❌ Max reconnection attempts reached. Exiting...');
process.exit(1);
}
}
stop() {
console.log('👋 Stopping listener...');
if (this.ws) {
this.ws.close();
}
}
}
const listener = new PumpFunMigrationListener();
listener.start();
process.on('SIGINT', () => {
console.log('\n👋 Shutting down...');
listener.stop();
process.exit(0);
});
process.on('SIGTERM', () => {
listener.stop();
process.exit(0);
});
process.on('uncaughtException', (error) => {
console.error('💥 Uncaught exception:', error);
listener.stop();
process.exit(1);
});
process.on('unhandledRejection', (error) => {
console.error('💥 Unhandled rejection:', error);
listener.stop();
process.exit(1);
});npm start✅ Configuration loaded successfully
🚀 Starting Pump.fun Migration Listener...
📡 Monitoring account: 39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg
🎯 Tracking: Raydium + PumpSwap migrations
🔌 Connecting to GetBlock WebSocket...
✅ Connected to GetBlock WebSocket
📡 Subscribing to migration events...
✅ Subscribed with ID: 17473
⏳ Listening for migrations...📨 Log #4 - TX: 2QAbbdjj8P5qk3gzoey5...
📊 Token Address: 3MSQF3mHFL9CuzKtUg6zp3GDdmGgDpPs7tQ1VPoXabTq
🎯 Bonding Curve: 39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg
🏪 Destination: PumpSwap
📝 Transaction: G6YuhMQtC5vonGFDwGDUsy5Uukb7JvkzQeB91FDfbRCYL8fNzvig4so4ZXVnqWNsNZWjLWf2rs5xf55KDZ7wXTW
🔢 Slot: 382201040
⏰ Time: 2025-11-24T12:30:13.000Z
🔗 View on Solscan:
https://solscan.io/tx/G6YuhMQtC5vonGFDwGDUsy5Uukb7JvkzQeB91FDfbRCYL8fNzvig4so4ZXVnqWNsNZWjLWf2rs5xf55KDZ7wXTW
🔗 View Token:
https://pump.fun/3MSQF3mHFL9CuzKtUg6zp3GDdmGgDpPs7tQ1VPoXabTq📨 Log #7 - TX: 5yK8TqPAL2kNXj9bVZmF...
↳ 🎯 MIGRATION DETECTED!
🚀 ═══════════════════════════════════════════════════
NEW PUMP.FUN → RAYDIUM MIGRATION DETECTED!
═══════════════════════════════════════════════════
Migration #1 (Raydium)
📊 Token Address: 8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj
...💓 Alive | Runtime: 0h 15m 30s | Logs: 23 | Raydium: 1 | PumpSwap: 18//Missing api key or environment variable
❌ Missing required environment variables
Please set GETBLOCK_WS_ENDPOINT and GETBLOCK_HTTP_ENDPOINT in .env file
//Connection error(403)
🔌 Connecting to GetBlock WebSocket...
❌ WebSocket error: Unexpected server response: 403
🔌 Connection closedA step-by-step guide to subscribing to Base Flashblocks and building trading applications around ultra-fast blockchain data.
A step by step guide on how to build an Hyperliquid Whale Tracker Bot using GetBlock API
type Flashblock struct {
Diff BlockDiff `json:"diff"` // Block differences/updates
Index int `json:"index"` // Flashblock index (0-9 within a block)
Metadata Metadata `json:"metadata"` // Block metadata
}type BlockDiff struct {
BlobGasUsed string `json:"blob_gas_used"`
BlockHash string `json:"block_hash"`
GasUsed string `json:"gas_used"`
LogsBloom string `json:"logs_bloom"`
ReceiptsRoot string `json:"receipts_root"`
StateRoot string `json:"state_root"`
Transactions []string `json:"transactions"`
Withdrawals []any `json:"withdrawals"`
WithdrawalsRoot string `json:"withdrawals_root"`
}type Metadata struct {
BlockNumber uint64 `json:"block_number"`
NewAccountBalances map[string]string `json:"new_account_balances"`
Receipts map[string]Receipt `json:"receipts"`
}type Receipt struct {
Eip1559 *ReceiptData `json:"Eip1559,omitempty"`
Legacy *ReceiptData `json:"Legacy,omitempty"`
}
type ReceiptData struct {
CumulativeGasUsed string `json:"cumulativeGasUsed"`
Logs []Log `json:"logs"`
Status string `json:"status"`
}
type Log struct {
Address string `json:"address"`
Data string `json:"data"`
Topics []string `json:"topics"`
}mkdir flashblocks-listener
cd flashblocks-listener
go mod init flashblocks-listenergo get github.com/gorilla/websocket
go get github.com/andybalholm/brotlimodule flashblocks-listener
go 1.23.0
require (
github.com/andybalholm/brotli v1.2.0
github.com/gorilla/websocket v1.5.3
)package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io"
"log"
"os"
"os/signal"
"syscall"
"github.com/andybalholm/brotli"
"github.com/gorilla/websocket"
)const (
mainnetWSURL = "wss://mainnet.flashblocks.base.org/ws"
sepoliaWSURL = "wss://sepolia.flashblocks.base.org/ws"
)// Flashblock represents the root structure of a flashblock message
type Flashblock struct {
Diff BlockDiff `json:"diff"`
Index int `json:"index"`
Metadata Metadata `json:"metadata"`
}
// BlockDiff contains the block differences/updates
type BlockDiff struct {
BlobGasUsed string `json:"blob_gas_used"`
BlockHash string `json:"block_hash"`
GasUsed string `json:"gas_used"`
LogsBloom string `json:"logs_bloom"`
ReceiptsRoot string `json:"receipts_root"`
StateRoot string `json:"state_root"`
Transactions []string `json:"transactions"`
Withdrawals []any `json:"withdrawals"`
WithdrawalsRoot string `json:"withdrawals_root"`
}
// Metadata contains block metadata including balances and receipts
type Metadata struct {
BlockNumber uint64 `json:"block_number"`
NewAccountBalances map[string]string `json:"new_account_balances"`
Receipts map[string]Receipt `json:"receipts"`
}
// Receipt represents a transaction receipt (can be EIP-1559 or Legacy)
type Receipt struct {
Eip1559 *ReceiptData `json:"Eip1559,omitempty"`
Legacy *ReceiptData `json:"Legacy,omitempty"`
}
// GetData returns the receipt data regardless of type
func (r *Receipt) GetData() *ReceiptData {
if r.Eip1559 != nil {
return r.Eip1559
}
return r.Legacy
}
// GetType returns the receipt type as a string
func (r *Receipt) GetType() string {
if r.Eip1559 != nil {
return "EIP-1559"
}
if r.Legacy != nil {
return "Legacy"
}
return "Unknown"
}
// ReceiptData contains the actual receipt information
type ReceiptData struct {
CumulativeGasUsed string `json:"cumulativeGasUsed"`
Logs []Log `json:"logs"`
Status string `json:"status"`
}
// Log represents an event log
type Log struct {
Address string `json:"address"`
Data string `json:"data"`
Topics []string `json:"topics"`
}func main() {
// Parse command-line flags
network := flag.String("network", "mainnet", "Network to connect to: mainnet or sepolia")
flag.Parse()
// Select the appropriate WebSocket URL
var wsURL string
switch *network {
case "mainnet":
wsURL = mainnetWSURL
case "sepolia":
wsURL = sepoliaWSURL
default:
log.Fatalf("Invalid network: %s. Use 'mainnet' or 'sepolia'", *network)
}
log.Printf("Connecting to Base flashblocks on %s: %s", *network, wsURL)
// Establish WebSocket connection
conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
if err != nil {
log.Fatalf("Failed to connect to WebSocket: %v", err)
}
defer conn.Close()
log.Println("Connected! Listening for flashblocks...")
// Set up graceful shutdown
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
done := make(chan struct{})
// Message processing goroutine
go func() {
defer close(done)
for {
messageType, message, err := conn.ReadMessage()
if err != nil {
if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) {
log.Println("WebSocket closed normally")
return
}
log.Printf("Error reading message: %v", err)
return
}
switch messageType {
case websocket.TextMessage:
handleFlashblockJSON(message)
case websocket.BinaryMessage:
decoded, err := decodeBrotli(message)
if err != nil {
log.Printf("Error decoding Brotli: %v", err)
log.Printf("Raw binary message length: %d bytes", len(message))
continue
}
handleFlashblockJSON(decoded)
default:
log.Printf("Received unknown message type: %d", messageType)
}
}
}()
// Wait for shutdown signal or connection close
select {
case <-done:
log.Println("Connection closed")
case sig := <-sigChan:
log.Printf("Received signal %v, shutting down...", sig)
err := conn.WriteMessage(websocket.CloseMessage,
websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil {
log.Printf("Error sending close message: %v", err)
}
}
}func decodeBrotli(data []byte) ([]byte, error) {
reader := brotli.NewReader(bytes.NewReader(data))
return io.ReadAll(reader)
}func handleFlashblockJSON(data []byte) {
var flashblock Flashblock
if err := json.Unmarshal(data, &flashblock); err != nil {
log.Printf("Error parsing flashblock JSON: %v", err)
log.Printf("Raw data: %s", string(data))
return
}
printFlashblock(&flashblock)
}func printFlashblock(fb *Flashblock) {
fmt.Println("═══════════════════════════════════════════════════════════════")
fmt.Printf("FLASHBLOCK #%d | Block: %d | Hash: %s\n",
fb.Index,
fb.Metadata.BlockNumber,
truncateHash(fb.Diff.BlockHash))
fmt.Println("═══════════════════════════════════════════════════════════════")
fmt.Printf(" Gas Used: %s\n", fb.Diff.GasUsed)
fmt.Printf(" Blob Gas Used: %s\n", fb.Diff.BlobGasUsed)
fmt.Printf(" State Root: %s\n", truncateHash(fb.Diff.StateRoot))
fmt.Printf(" Receipts Root: %s\n", truncateHash(fb.Diff.ReceiptsRoot))
fmt.Printf("\n Transactions: %d\n", len(fb.Diff.Transactions))
for i, tx := range fb.Diff.Transactions {
fmt.Printf(" [%d] %s...\n", i, truncateHash(tx))
}
fmt.Printf("\n Account Balance Updates: %d\n", len(fb.Metadata.NewAccountBalances))
fmt.Printf("\n Receipts: %d\n", len(fb.Metadata.Receipts))
receiptCount := 0
for txHash, receipt := range fb.Metadata.Receipts {
if receiptCount >= 3 {
fmt.Printf(" ... and %d more receipts\n", len(fb.Metadata.Receipts)-3)
break
}
data := receipt.GetData()
if data != nil {
fmt.Printf(" [%s] %s - Status: %s, Logs: %d\n",
receipt.GetType(),
truncateHash(txHash),
data.Status,
len(data.Logs))
}
receiptCount++
}
fmt.Println()
}
func truncateHash(hash string) string {
if len(hash) <= 20 {
return hash
}
return hash[:10] + "..." + hash[len(hash)-8:]
}# Build the application
go build -o flashblocks-listener
# Run on mainnet (default)
./flashblocks-listener
# Run on Sepolia testnet
./flashblocks-listener -network=sepolia2026/01/23 12:06:55 Connecting to Base flashblocks on mainnet: wss://mainnet.flashblocks.base.org/ws
2026/01/23 12:06:57 Connected! Listening for flashblocks...
═══════════════════════════════════════════════════════════════
FLASHBLOCK #3 | Block: 41188536 | Hash: 0x1832098f...7ebd4a7f
═══════════════════════════════════════════════════════════════
Gas Used: 0x124f501
Blob Gas Used: 0x22e3d6
State Root: 0x00000000...00000000
Receipts Root: 0xa83fdcff...1e433d49
Transactions: 16
[0] 0x02f90133...60eff264...
[1] 0x02f90133...4732f1c0...
[2] 0x02f90133...01fd3ba7...
[3] 0x02f90133...470392b3...
[4] 0x02f90196...e4134811...
[5] 0x02f901f3...0e62c9ff...
[6] 0x02f90153...b0328e40...
[7] 0x02f90153...f04b2f4f...
[8] 0x02f8c082...7ceecf2b...
[9] 0x02f90153...1f75269c...
[10] 0x02f90151...c9b5718a...
[11] 0xf86c822a...3bd176a3...
[12] 0xf9014183...06eeeac4...
[13] 0x02f88482...1d4b11e4...
[14] 0x02f88482...97783f64...
[15] 0x02f90354...def1bfb6...
Account Balance Updates: 205
Receipts: 16
[EIP-1559] 0x7c69632d...c315f13a - Status: 0x1, Logs: 0
[EIP-1559] 0xda9e6136...1fdde572 - Status: 0x1, Logs: 0
[EIP-1559] 0xe2030a9f...399a02ce - Status: 0x1, Logs: 0
... and 13 more receipts^C2026/01/23 12:06:59 Received signal interrupt, shutting down...func filterByAddress(fb *Flashblock, targetAddress string) {
for txHash, receipt := range fb.Metadata.Receipts {
data := receipt.GetData()
if data == nil {
continue
}
for _, logEntry := range data.Logs {
if strings.EqualFold(logEntry.Address, targetAddress) {
fmt.Printf("Activity detected! TX: %s\n", txHash)
// Process the event...
}
}
}
}const (
// Uniswap V2 Swap event signature
uniswapV2Swap = "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822"
// Uniswap V3 Swap event signature
uniswapV3Swap = "0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67"
)
func detectSwaps(fb *Flashblock) {
for txHash, receipt := range fb.Metadata.Receipts {
data := receipt.GetData()
if data == nil {
continue
}
for _, logEntry := range data.Logs {
if len(logEntry.Topics) > 0 {
switch logEntry.Topics[0] {
case uniswapV2Swap:
fmt.Printf("Uniswap V2 Swap in TX: %s\n", txHash)
case uniswapV3Swap:
fmt.Printf("Uniswap V3 Swap in TX: %s\n", txHash)
}
}
}
}
}func trackBalanceChanges(fb *Flashblock, watchAddresses []string) {
for _, addr := range watchAddresses {
if newBalance, exists := fb.Metadata.NewAccountBalances[addr]; exists {
fmt.Printf("Balance update for %s: %s\n", addr, newBalance)
}
}
}func connectWithRetry(wsURL string, maxRetries int) (*websocket.Conn, error) {
for i := 0; i < maxRetries; i++ {
conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
if err == nil {
return conn, nil
}
log.Printf("Connection attempt %d failed: %v", i+1, err)
time.Sleep(time.Second * time.Duration(i+1))
}
return nil, fmt.Errorf("failed after %d attempts", maxRetries)
}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:]
}mkdir hyperliquid-whale-alert-bot
cd hyperliquid-whale-alert-bot
npm init -y
npm i dotenv ws
npm i -D nodemon├── index.js // Main apllication
└── .env // Environment variables
└── .gitignore // Git ignore file# Telegram Configuration (Get from @BotFather and @userinfobot)
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
TELEGRAM_CHAT_ID=your-ID
# Whale Detection Thresholds
WHALE_THRESHOLD_USD=100000
WHALE_THRESHOLD_SIZE=50
# Telegram Settings
TELEGRAM_BATCH_ALERTS=true
TELEGRAM_BATCH_INTERVAL=10000
# Markets to Track (comma-separated)
TRACKED_SYMBOLS=BTC,ETH,SOL,ARB,AVAX,HYPE
# Optional: HyperEVM WebSocket from GetBlock
HYPEREVM_WSS=wss://go.getblock.io/<ACCESS_TOKEN>// dependencies
import WebSocket from 'ws';
import { config } from 'dotenv';
// Load environment variables from .env file
config();const CONFIG = {
// HyperEVM WebSocket endpoint from GetBlock
HYPEREVM_WSS: process.env.HYPEREVM_WSS,
// Whale thresholds
WHALE_THRESHOLD_USD: Number(process.env.WHALE_THRESHOLD_USD) || 100000,
WHALE_THRESHOLD_SIZE: Number(process.env.WHALE_THRESHOLD_SIZE) || 50,
// Notification settings
TELEGRAM_BOT_TOKEN: process.env.TELEGRAM_BOT_TOKEN || '',
TELEGRAM_CHAT_ID: process.env.TELEGRAM_CHAT_ID || '',
TELEGRAM_BATCH_ALERTS: process.env.TELEGRAM_BATCH_ALERTS !== 'false',
TELEGRAM_BATCH_INTERVAL: Number(process.env.TELEGRAM_BATCH_INTERVAL) || 60 * 10000,
// Tracked markets
TRACKED_SYMBOLS: (process.env.TRACKED_SYMBOLS || 'BTC,ETH,SOL,ARB,AVAX,HYPE').split(','),
};class HyperliquidWhaleTracker {
// Private fields (only accessible within the class)
#ws = null; // Hyperliquid WebSocket connection
#wsHyperEVM = null; // HyperEVM WebSocket connection
#reconnectAttempts = 0; // Track reconnection attempts
#maxReconnectAttempts = 5; // Maximum reconnection tries
#priceCache = new Map(); // Store current prices
#whaleAddresses = new Map(); // Track whale wallet addresses
#tradeCount = 0; // Total whale trades detected
#telegramQueue = []; // Queue for Telegram messages
#isSendingTelegram = false; // Flag for queue processing
#lastTelegramSent = 0; // Timestamp of last message
#TELEGRAM_DELAY = 1500; // Delay between messages (ms)
#pendingAlerts = []; // Batch alerts before sending
#batchTimer = null; // Timer for batching
constructor() {
this.HYPERLIQUID_WS_URL = 'wss://api.hyperliquid.xyz/ws';
}
}async connectHyperliquid() {
console.log('Connecting to Hyperliquid Info WebSocket...');
this.#ws = new WebSocket(this.HYPERLIQUID_WS_URL);
this.#ws.on('open', () => {
console.log('✅ Connected to Hyperliquid Info API');
this.#subscribeToTrades();
this.#subscribeToOrderbook();
});
this.#ws.on('message', (data) => this.#handleHyperliquidMessage(data));
this.#ws.on('error', (error) => console.error('Hyperliquid error:', error.message));
this.#ws.on('close', () => this.#handleReconnect('hyperliquid'));
}#subscribeToTrades() {
// Subscribe to price updates
this.#ws.send(JSON.stringify({
method: 'subscribe',
subscription: { type: 'allMids' }
}));
// Subscribe to trades for each tracked symbol
for (const symbol of CONFIG.TRACKED_SYMBOLS) {
this.#ws.send(JSON.stringify({
method: 'subscribe',
subscription: { type: 'trades', coin: symbol }
}));
}
console.log('📡 Subscribed to Hyperliquid trades');
}
#subscribeToOrderbook() {
// Subscribe to orderbook depth for whale wall detection
for (const symbol of CONFIG.TRACKED_SYMBOLS) {
this.#ws.send(JSON.stringify({
method: 'subscribe',
subscription: { type: 'l2Book', coin: symbol }
}));
}
console.log('📊 Subscribed to orderbook data');
}#handleHyperliquidMessage(data) {
try {
const message = JSON.parse(data.toString());
// Route messages based on channel type
switch (message.channel) {
case 'trades':
message.data?.forEach(trade => this.#analyzeTrade(trade));
break;
case 'allMids':
this.#updatePrices(message.data);
break;
case 'l2Book':
this.#analyzeOrderbook(message.data);
break;
}
} catch (error) {
console.error('Error parsing message:', error.message);
}
}#updatePrices(midsData) {
if (!midsData?.mids) return;
// Store current prices in a Map for quick lookup
for (const [symbol, price] of Object.entries(midsData.mids)) {
this.#priceCache.set(symbol, parseFloat(price));
}
}#analyzeTrade(trade) {
try {
const { coin, side, px, sz, time, user, hash, tid } = trade;
const price = parseFloat(px);
const size = parseFloat(sz);
const value = price * size; // Calculate USD value
// Check if trade meets whale threshold
if (value < CONFIG.WHALE_THRESHOLD_USD && size < CONFIG.WHALE_THRESHOLD_SIZE) {
return; // Not a whale trade, skip
}
// Track the whale's address
if (user) {
this.#trackWhaleAddress(user, value, coin);
}
// Send notification
this.#notifyWhaleTrade({
coin,
side,
price,
size,
value,
time: new Date(time).toLocaleString(),
user: user || 'Unknown',
hash: hash || null,
tradeId: tid || null
});
this.#tradeCount++;
} catch (error) {
console.error('Error analyzing trade:', error.message);
}
}#trackWhaleAddress(address, value, coin) {
const whale = this.#whaleAddresses.get(address);
if (whale) {
// Existing whale - update stats
whale.totalVolume += value;
whale.tradeCount++;
whale.lastSeen = new Date();
whale.coins.add(coin);
} else {
// New whale - create profile
this.#whaleAddresses.set(address, {
address,
totalVolume: value,
tradeCount: 1,
firstSeen: new Date(),
lastSeen: new Date(),
coins: new Set([coin])
});
}
}#analyzeOrderbook(bookData) {
try {
const { coin, levels } = bookData;
if (!Array.isArray(levels)) return;
const largeOrders = [];
// Analyze both bid (buy) and ask (sell) sides
for (const [index, side] of ['BID', 'ASK'].entries()) {
if (!Array.isArray(levels[index])) continue;
for (const level of levels[index]) {
// Handle different data formats
const [price, size] = Array.isArray(level)
? level
: [level.px, level.sz];
if (!price || !size) continue;
const value = parseFloat(price) * parseFloat(size);
// Check if it's a whale-sized order
if (value >= CONFIG.WHALE_THRESHOLD_USD) {
largeOrders.push({
side,
price: parseFloat(price),
size: parseFloat(size),
value
});
}
}
}
if (largeOrders.length > 0) {
this.#notifyWhaleOrder(coin, largeOrders);
}
} catch (error) {
console.error('Error analyzing orderbook:', error.message);
}
}#notifyWhaleTrade(trade) {
const emoji = trade.side === 'B' ? '🟢' : '🔴';
const sideText = trade.side === 'B' ? 'BUY' : 'SELL';
const shortAddress = trade.user !== 'Unknown'
? `${trade.user.slice(0, 6)}...${trade.user.slice(-4)}`
: 'Unknown';
// Get whale statistics if available
let whaleStats = '';
const whale = this.#whaleAddresses.get(trade.user);
if (whale) {
whaleStats = `\n📈 Whale Stats: ${whale.tradeCount} trades | $${whale.totalVolume.toLocaleString()} total volume`;
}
const consoleMessage = `
🐋 WHALE TRADE ALERT! 🐋
${emoji} ${sideText} ${trade.coin}
💰 Size: ${trade.size.toFixed(2)} contracts
💵 Price: $${trade.price.toFixed(2)}
📊 Value: $${trade.value.toLocaleString()}
👤 Trader: ${shortAddress}
${trade.user !== 'Unknown' ? `🔗 Address: ${trade.user}` : ''}${whaleStats}
${trade.hash ? `📝 TX Hash: ${trade.hash}` : ''}
${trade.tradeId ? `🆔 Trade ID: ${trade.tradeId}` : ''}
🕐 Time: ${trade.time}
${trade.value >= 500000 ? '🚨 MEGA WHALE! 🚨' : ''}
`;
console.log(consoleMessage);
// Send to Telegram if configured
if (CONFIG.TELEGRAM_BOT_TOKEN && CONFIG.TELEGRAM_CHAT_ID) {
if (CONFIG.TELEGRAM_BATCH_ALERTS) {
this.#addToBatch({ type: 'trade', emoji, sideText, ...trade });
} else {
this.#sendTelegramMessage(consoleMessage);
}
}
}#addToBatch(alert) {
this.#pendingAlerts.push(alert);
// Start batch timer if not already running
if (!this.#batchTimer) {
this.#batchTimer = setTimeout(() => {
this.#sendBatchedAlerts();
}, CONFIG.TELEGRAM_BATCH_INTERVAL);
}
}
#sendBatchedAlerts() {
console.log(`📦 Sending batched alerts: ${this.#pendingAlerts.length} trades`);
if (this.#pendingAlerts.length === 0) {
this.#batchTimer = null;
return;
}
const totalValue = this.#pendingAlerts.reduce((sum, alert) => sum + alert.value, 0);
const trades = this.#pendingAlerts.length;
// Build compact batch message
const alertsList = this.#pendingAlerts
.map((alert, index) => {
const shortAddr = alert.user !== 'Unknown'
? `${alert.user.slice(0, 6)}...${alert.user.slice(-4)}`
: 'Unknown';
let line = `${index + 1}. ${alert.emoji} ${alert.sideText} ${alert.coin}\n`;
line += ` 💰 $${alert.value.toLocaleString()} | 👤 ${shortAddr}\n`;
if (alert.value >= 500000) line += ` 🚨 MEGA WHALE!\n`;
return line;
})
.join('\n');
const message = `🐋 WHALE ACTIVITY BATCH (${trades} trades, $${totalValue.toLocaleString()} total) 🐋\n\n${alertsList}\n🕐 ${new Date().toLocaleString()}`;
console.log('📤 Adding batch message to Telegram queue...');
this.#sendTelegramMessage(message);
this.#pendingAlerts = [];
this.#batchTimer = null;
}async #sendTelegramMessage(message) {
if (!CONFIG.TELEGRAM_BOT_TOKEN || !CONFIG.TELEGRAM_CHAT_ID) return;
// Add to queue instead of sending immediately
this.#telegramQueue.push(message);
// Start processing if not already running
if (!this.#isSendingTelegram) {
this.#processTelegramQueue();
}
}
async #processTelegramQueue() {
if (this.#telegramQueue.length === 0) {
this.#isSendingTelegram = false;
return;
}
this.#isSendingTelegram = true;
const message = this.#telegramQueue.shift();
try {
// Respect rate limit (1.5 seconds between messages)
const timeSinceLastSend = Date.now() - this.#lastTelegramSent;
if (timeSinceLastSend < this.#TELEGRAM_DELAY) {
await new Promise(resolve =>
setTimeout(resolve, this.#TELEGRAM_DELAY - timeSinceLastSend)
);
}
// Send to Telegram API
const url = `https://api.telegram.org/bot${CONFIG.TELEGRAM_BOT_TOKEN}/sendMessage`;
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chat_id: CONFIG.TELEGRAM_CHAT_ID,
text: message,
parse_mode: 'HTML'
})
});
this.#lastTelegramSent = Date.now();
if (!response.ok) {
const errorData = await response.json();
console.error('❌ Telegram API error:', response.status, errorData.description || '');
// Handle rate limiting
if (response.status === 429) {
const retryAfter = errorData.parameters?.retry_after || 5;
console.log(`⏳ Rate limited. Waiting ${retryAfter}s...`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
this.#telegramQueue.unshift(message); // Re-add to front
}
} else {
console.log('✅ Telegram message sent');
}
} catch (error) {
console.error('❌ Telegram error:', error.message);
}
// Process next message in queue
setTimeout(() => this.#processTelegramQueue(), this.#TELEGRAM_DELAY);
}async #testTelegramConnection() {
try {
const url = `https://api.telegram.org/bot${CONFIG.TELEGRAM_BOT_TOKEN}/getMe`;
const response = await fetch(url);
const data = await response.json();
if (data.ok) {
console.log(`✅ Telegram bot connected: @${data.result.username}`);
await this.#sendTelegramMessage('🤖 Whale Tracker Started!\n\nMonitoring Hyperliquid for whale activity...');
console.log('✅ Test message sent\n');
} else {
console.error('❌ Telegram error:', data.description);
}
} catch (error) {
console.error('❌ Failed to connect to Telegram:', error.message);
console.log('💡 Check your TELEGRAM_BOT_TOKEN\n');
}
}#handleReconnect(connection) {
if (this.#reconnectAttempts >= this.#maxReconnectAttempts) {
console.error(`Max reconnection attempts reached for ${connection}`);
return;
}
this.#reconnectAttempts++;
// Exponential backoff: 2s, 4s, 8s, 16s, 30s (max)
const delay = Math.min(1000 * 2 ** this.#reconnectAttempts, 30000);
console.log(`Reconnecting ${connection} in ${delay/1000}s... (Attempt ${this.#reconnectAttempts})`);
setTimeout(() => {
connection === 'hyperevm' ? this.connectHyperEVM() : this.connectHyperliquid();
}, delay);
}#printWhaleStats() {
console.log('\n' + '='.repeat(60));
console.log('📊 WHALE STATISTICS SUMMARY');
console.log('='.repeat(60));
console.log(`Total Whale Trades: ${this.#tradeCount}`);
console.log(`Unique Whales: ${this.#whaleAddresses.size}\n`);
if (this.#whaleAddresses.size === 0) {
console.log('='.repeat(60) + '\n');
return;
}
console.log('Top 10 Whales by Volume:');
console.log('-'.repeat(60));
// Sort whales by total volume and get top 10
const topWhales = Array.from(this.#whaleAddresses.values())
.sort((a, b) => b.totalVolume - a.totalVolume)
.slice(0, 10);
topWhales.forEach((whale, index) => {
const shortAddr = `${whale.address.slice(0, 8)}...${whale.address.slice(-6)}`;
console.log(`${index + 1}. ${shortAddr}`);
console.log(` Volume: $${whale.totalVolume.toLocaleString()}`);
console.log(` Trades: ${whale.tradeCount}`);
console.log(` Markets: ${Array.from(whale.coins).join(', ')}`);
console.log(` Last Active: ${whale.lastSeen.toLocaleString()}\n`);
});
console.log('='.repeat(60) + '\n');
}async start() {
console.log('🚀 Starting Hyperliquid Whale Tracker...');
console.log(`📊 Tracking: ${CONFIG.TRACKED_SYMBOLS.join(', ')}`);
console.log(`💰 Whale threshold: $${CONFIG.WHALE_THRESHOLD_USD.toLocaleString()}\n`);
// Test Telegram if configured
if (CONFIG.TELEGRAM_BOT_TOKEN && CONFIG.TELEGRAM_CHAT_ID) {
console.log('✅ Telegram notifications: ENABLED');
console.log(`📱 Chat ID: ${CONFIG.TELEGRAM_CHAT_ID}`);
console.log(`📦 Batch mode: ${CONFIG.TELEGRAM_BATCH_ALERTS ? `ON (every ${CONFIG.TELEGRAM_BATCH_INTERVAL/1000}s)` : 'OFF'}\n`);
await this.#testTelegramConnection();
} else {
console.log('⚠️ Telegram notifications: DISABLED\n');
}
// Connect to Hyperliquid
await this.connectHyperliquid();
// Optional: Connect to HyperEVM
if (CONFIG.HYPEREVM_WSS) {
await this.connectHyperEVM();
} else {
console.log('ℹ️ HyperEVM WebSocket not configured (optional)\n');
}
// Print statistics every 5 minutes
setInterval(() => this.#printWhaleStats(), 5 * 60 * 1000);
}
stop() {
this.#ws?.close();
this.#wsHyperEVM?.close();
console.log('Bot stopped');
}// Create bot instance
const bot = new HyperliquidWhaleTracker();
await bot.start();
// Handle graceful shutdown
process.on('SIGINT', () => {
console.log('\n👋 Shutting down...');
bot.stop();
process.exit(0);
});node index.js🐋 WHALE TRADE ALERT! 🐋
🟢 BUY AVAX
💰 Size: 56.00 contracts
💵 Price: 17.88
📊 Value: 1,001.392
👤 Trader: Unknown
📝 TX Hash: 0xc806e65080fb77e5c980042f145c7302024000361bfe96b76bcf91a33fff51d0
🆔 Trade ID: 720410117733902
🕐 Time: 11/8/2025, 12:07:11 PM
🐋 WHALE TRADE ALERT! 🐋
🔴 SELL HYPE
💰 Size: 61.56 contracts
💵 Price: 41.46
📊 Value: 2,552.154
👤 Trader: Unknown
📝 TX Hash: 0x03f399453dfc2d42056d042f145c12020235002ad8ff4c14a7bc4497fcf0072c
🆔 Trade ID: 438223268535475
🕐 Time: 11/8/2025, 12:07:04 PM
🐳 WHALE WALL DETECTED! 🐳
📈 ETH Orderbook
🟢 BID: $3442.20 × 47.29 = $162,787.146
🟢 BID: $3442.10 × 182.11 = $626,825.342
🔴 ASK: $3444.20 × 336.14 = $1,157,739.243
🔴 ASK: $3444.30 × 64.56 = $222,347.131
🔴 ASK: $3444.40 × 119.15 = $410,398.538
🕐 11/8/2025, 12:07:16 PM
^C
👋 Shutting down ...
Bot stoppedConnecting to GetBlock WebSocket...
WebSocket error: Error: Unexpected server response: 503
WebSocket connection closed
Reconnecting in 16 seconds... (Attempt 4)# correct format
HYPEREVM_WSS=wss://go.getblock.io/<ACCESS_TOKEN>node index.js
Build a pay-per-request blockchain data API using the x402 protocol and GetBlock's node infrastructure.



mkdir getblock-x402-dapp
cd getblock-x402-dapp
mkdir server clientcd server
npm init -ynpm install express cors axios dotenv @x402/core @x402/evm @x402/express{
"name": "getblock-x402-server",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js",
},
"keywords": ["x402", "getblock"]serv,
"author": "",
"license": "ISC",
"type": "module",
"dependencies": {
"@x402/core": "^2.2.0",
"@x402/evm": "^2.2.0",
"@x402/express": "^2.2.0",
"axios": "^1.13.2",
"cors": "^2.8.5",
"dotenv": "^17.2.3",
"express": "^5.2.1"
}
}getblock-x402-dapp/
├── server/
│ ├── server.js # Express server with x402 middleware
│ ├── package.json # Server dependencies
│ └── .env # Environment variables (API keys)
└── client/
└── index.html # Frontend dApp (single file)# Your wallet address to receive payments
PAYMENT_WALLET_ADDRESS=0xYourWalletAddressHere
# GetBlock API key (optional - will use mock data if not set)
GETBLOCK_API_KEY=your_getblock_api_key_here
# Server port
PORT=4021import 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`);
})
});<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>GetBlock x402 dApp</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: -apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", sans-serif;
background: rgb(0, 0, 0);
min-height: 100vh;
color: #fff;
padding: 2rem;
}
.container {
max-width: 700px;
margin: 0 auto;
}
header {
text-align: center;
margin-bottom: 2rem;
}
h1 {
font-size: 2.2rem;
margin-bottom: 0.5rem;
background: linear-gradient(90deg, #00d4ff, #7b2cbf);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.subtitle {
color: #888;
margin-bottom: 1.5rem;
}
.wallet-section {
text-align: center;
margin-bottom: 2rem;
}
#connectBtn {
background: #7b2cbf;
color: white;
border: none;
padding: 1rem 2rem;
border-radius: 12px;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
#connectBtn:hover {
opacity: 0.9;
transform: translateY(-2px);
}
#walletInfo {
background: rgba(0, 212, 255, 0.1);
border: 1px solid rgba(0, 212, 255, 0.3);
padding: 1rem;
border-radius: 12px;
display: none;
}
#walletInfo.connected {
display: block;
}
.wallet-address {
font-family: monospace;
color: #00d4ff;
}
.endpoints {
margin-top: 2rem;
}
.endpoints h2 {
font-size: 1.2rem;
color: #888;
margin-bottom: 1rem;
}
.endpoint-card {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.25rem;
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
margin-bottom: 0.75rem;
border: 1px solid rgba(255, 255, 255, 0.1);
transition: all 0.3s ease;
}
.endpoint-card:hover {
background: rgba(255, 255, 255, 0.08);
border-color: rgba(0, 212, 255, 0.3);
}
.endpoint-name {
font-weight: 600;
margin-bottom: 0.25rem;
}
.endpoint-price {
color: #00d4ff;
font-size: 0.9rem;
}
.pay-btn {
background: #7b2cbf;
color: white;
border: none;
padding: 0.6rem 1.2rem;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.pay-btn:hover {
opacity: 0.9;
}
.pay-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
#status {
margin-top: 1.5rem;
padding: 1rem;
border-radius: 12px;
display: none;
}
#status.error {
display: block;
background: rgba(255, 0, 0, 0.1);
border: 1px solid rgba(255, 0, 0, 0.3);
color: #ff6b6b;
}
#status.loading {
display: block;
background: rgba(255, 255, 0, 0.1);
border: 1px solid rgba(255, 255, 0, 0.3);
color: #ffd93d;
}
#status.success {
display: block;
background: rgba(0, 255, 0, 0.1);
border: 1px solid rgba(0, 255, 0, 0.3);
color: #00ff88;
}
#result {
margin-top: 1.5rem;
display: none;
}
#result.show {
display: block;
}
#result h3 {
color: #00ff88;
margin-bottom: 0.75rem;
}
#result pre {
background: rgba(0, 0, 0, 0.4);
padding: 1rem;
border-radius: 8px;
overflow-x: auto;
font-size: 0.9rem;
}
footer {
text-align: center;
margin-top: 3rem;
color: #666;
font-size: 0.85rem;
}
.network-badge {
display: inline-block;
background: rgba(123, 44, 191, 0.2);
color: #b57edc;
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.8rem;
margin-top: 0.5rem;
}
.info-box {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 12px;
padding: 1rem;
margin-bottom: 1.5rem;
font-size: 0.9rem;
color: #aaa;
}
.info-box a {
color: #00d4ff;
text-decoration: none;
}
.info-box a:hover {
text-decoration: underline;
}
.debug-log {
background: rgba(0, 0, 0, 0.3);
padding: 0.5rem;
margin-top: 1rem;
border-radius: 8px;
font-family: monospace;
font-size: 0.75rem;
max-height: 200px;
overflow-y: auto;
display: none;
}
.debug-log.show {
display: block;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>GetBlock x402 dApp</h1>
<p class="subtitle">Pay-per-request blockchain data powered by x402</p>
</header>
<div class="info-box">
<strong>Requirements:</strong> MetaMask wallet with USDC on Base Sepolia testnet.<br />
Get test USDC from <a href="https://faucet.circle.com/" target="_blank">Circle Faucet</a>
</div>
<div class="wallet-section">
<button id="connectBtn">Connect Wallet</button>
<div id="walletInfo">
<p>Connected: <span class="wallet-address" id="walletAddress"></span></p>
<p style="margin-top: 0.5rem; font-size: 0.85rem; color: #888">
USDC Balance: <span id="usdcBalance">Loading...</span>
</p>
<span class="network-badge">Base Sepolia Testnet</span>
</div>
</div>
<div class="endpoints" id="endpoints" style="display: none">
<h2>Available Endpoints</h2>
<div class="endpoint-card">
<div>
<div class="endpoint-name">Latest Block Number</div>
<div class="endpoint-price">$0.001 USDC</div>
</div>
<button class="pay-btn" data-endpoint="/api/eth/block/latest">Pay & Fetch</button>
</div>
<div class="endpoint-card">
<div>
<div class="endpoint-name">Current Gas Price</div>
<div class="endpoint-price">$0.001 USDC</div>
</div>
<button class="pay-btn" data-endpoint="/api/eth/gas">Pay & Fetch</button>
</div>
</div>
<div id="status"></div>
<div id="result">
<h3>✓ Result</h3>
<pre id="resultData"></pre>
</div>
<footer>
<p>Network: Base Sepolia | Powered by GetBlock & x402</p>
<a href="#" id="toggleDebug" style="color: #666; font-size: 0.75rem">Toggle Debug Log</a>
<div class="debug-log" id="debugLog"></div>
</footer>
</div>
<!-- Load dependencies from CDN -->
<script type="module">
// =======================================================================
// Import Dependencies
// =======================================================================
import {
createWalletClient,
custom,
getAddress,
} from "https://esm.sh/[email protected]";
import { baseSepolia } from "https://esm.sh/[email protected]/chains";
import {
x402Client,
wrapFetchWithPayment,
} from "https://esm.sh/@x402/fetch";
import { registerExactEvmScheme } from "https://esm.sh/@x402/evm/exact/client";
// =======================================================================
// Configuration
// =======================================================================
const API_URL = "http://localhost:4021";
const BASE_SEPOLIA_CHAIN_ID = "0x14a34"; // 84532 in hex
const USDC_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e"; // Base Sepolia USDC
// =======================================================================
// State
// =======================================================================
let fetchWithPayment = null;
let userAddress = null;
// =======================================================================
// DOM Elements
// =======================================================================
const connectBtn = document.getElementById("connectBtn");
const walletInfo = document.getElementById("walletInfo");
const walletAddressEl = document.getElementById("walletAddress");
const usdcBalanceEl = document.getElementById("usdcBalance");
const endpointsSection = document.getElementById("endpoints");
const statusEl = document.getElementById("status");
const resultEl = document.getElementById("result");
const resultData = document.getElementById("resultData");
const debugLog = document.getElementById("debugLog");
const toggleDebug = document.getElementById("toggleDebug");
// =======================================================================
// Debug Logging
// =======================================================================
function log(msg, type = "info") {
const time = new Date().toLocaleTimeString();
const color =
type === "error" ? "#ff6b6b" : type === "success" ? "#00ff88" : "#aaa";
debugLog.innerHTML += `<div style="color:${color}">[${time}] ${msg}</div>`;
debugLog.scrollTop = debugLog.scrollHeight;
console.log(`[${type}]`, msg);
}
toggleDebug.addEventListener("click", (e) => {
e.preventDefault();
debugLog.classList.toggle("show");
});
function showStatus(message, type) {
statusEl.textContent = message;
statusEl.className = type || "";
}
// =======================================================================
// USDC Balance Helper
// =======================================================================
async function getUsdcBalance(address) {
try {
// Call balanceOf(address) on USDC contract
const data = "0x70a08231" + address.slice(2).padStart(64, "0");
const result = await window.ethereum.request({
method: "eth_call",
params: [{ to: USDC_ADDRESS, data }, "latest"],
});
const balance = parseInt(result, 16) / 1e6; // USDC has 6 decimals
return balance.toFixed(6);
} catch (e) {
log("Error getting USDC balance: " + e.message, "error");
return "0.000000";
}
}
// =======================================================================
// Create x402-Compatible Signer
// =======================================================================
/**
* Creates a signer object that x402 can use to sign payment authorizations.
* This wraps MetaMask's signing capabilities in the interface x402 expects.
*/
function createMetaMaskSigner(address, walletClient) {
return {
address: address,
async signTypedData(typedData) {
log("Signing payment authorization...");
log("Domain: " + JSON.stringify(typedData.domain));
try {
// Use viem's signTypedData which handles EIP-712 formatting
const signature = await walletClient.signTypedData({
account: address,
domain: typedData.domain,
types: typedData.types,
primaryType: typedData.primaryType,
message: typedData.message,
});
log("Signature obtained: " + signature.substring(0, 20) + "...", "success");
return signature;
} catch (error) {
log("Signing error: " + error.message, "error");
throw error;
}
},
};
}
// =======================================================================
// Connect Wallet Handler
// =======================================================================
connectBtn.addEventListener("click", async () => {
try {
if (!window.ethereum) {
showStatus("Please install MetaMask!", "error");
return;
}
showStatus("Connecting wallet...", "loading");
log("Requesting wallet connection...");
// Request account access
const accounts = await window.ethereum.request({
method: "eth_requestAccounts",
});
userAddress = getAddress(accounts[0]); // Normalize address checksum
log("Connected to: " + userAddress, "success");
// Switch to Base Sepolia network
log("Checking network...");
try {
await window.ethereum.request({
method: "wallet_switchEthereumChain",
params: [{ chainId: BASE_SEPOLIA_CHAIN_ID }],
});
log("On Base Sepolia", "success");
} catch (switchError) {
// Network not added - add it
if (switchError.code === 4902) {
log("Adding Base Sepolia network...");
await window.ethereum.request({
method: "wallet_addEthereumChain",
params: [
{
chainId: BASE_SEPOLIA_CHAIN_ID,
chainName: "Base Sepolia",
nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 },
rpcUrls: ["https://sepolia.base.org"],
blockExplorerUrls: ["https://sepolia.basescan.org"],
},
],
});
} else {
throw switchError;
}
}
// Create viem wallet client
log("Creating wallet client...");
const walletClient = createWalletClient({
account: userAddress,
chain: baseSepolia,
transport: custom(window.ethereum),
});
// Create x402-compatible signer
log("Creating x402 signer...");
const signer = createMetaMaskSigner(userAddress, walletClient);
// Initialize x402 client with EVM scheme
log("Initializing x402 client...");
const x402client = new x402Client();
registerExactEvmScheme(x402client, { signer });
// Wrap fetch with automatic payment handling
fetchWithPayment = wrapFetchWithPayment(fetch, x402client);
log("x402 client ready!", "success");
// Update UI
walletAddressEl.textContent = `${userAddress.slice(0, 6)}...${userAddress.slice(-4)}`;
const balance = await getUsdcBalance(userAddress);
usdcBalanceEl.textContent = balance + " USDC";
log("USDC Balance: " + balance);
walletInfo.classList.add("connected");
connectBtn.style.display = "none";
endpointsSection.style.display = "block";
showStatus("", "");
} catch (error) {
log("Connection error: " + error.message, "error");
showStatus("Connection failed: " + error.message, "error");
}
});
// =======================================================================
// Endpoint Button Click Handlers
// =======================================================================
document.querySelectorAll(".pay-btn").forEach((btn) => {
btn.addEventListener("click", async () => {
if (!fetchWithPayment) {
showStatus("Please connect wallet first", "error");
return;
}
const endpoint = btn.dataset.endpoint;
const fullUrl = API_URL + endpoint;
// Disable buttons during request
document.querySelectorAll(".pay-btn").forEach((b) => (b.disabled = true));
btn.textContent = "Processing...";
showStatus("Making request...", "loading");
resultEl.classList.remove("show");
try {
log("Request: GET " + fullUrl);
// Make the paid request - x402 handles payment automatically
const response = await fetchWithPayment(fullUrl, { method: "GET" });
log("Response status: " + response.status);
if (response.status === 402) {
const text = await response.text();
log("402 response: " + text.substring(0, 200), "error");
try {
const data = JSON.parse(text);
if (data.accepts) {
log("Payment requirements received", "error");
throw new Error("Payment failed - check USDC balance and try again");
}
throw new Error(data.error || "Payment required");
} catch (e) {
if (e.message.includes("Payment") || e.message.includes("USDC")) throw e;
throw new Error("Payment required");
}
}
if (!response.ok) {
const text = await response.text();
log("Error: " + text, "error");
throw new Error(`Failed (${response.status}): ${text}`);
}
// Success! Display the data
const data = await response.json();
log("Success!", "success");
resultData.textContent = JSON.stringify(data, null, 2);
resultEl.classList.add("show");
showStatus("✓ Payment successful!", "success");
// Refresh USDC balance
const newBalance = await getUsdcBalance(userAddress);
usdcBalanceEl.textContent = newBalance + " USDC";
} catch (error) {
log("Error: " + error.message, "error");
showStatus("Error: " + error.message, "error");
} finally {
// Re-enable buttons
document.querySelectorAll(".pay-btn").forEach((b) => {
b.disabled = false;
b.textContent = "Pay & Fetch";
});
}
});
});
// =======================================================================
// Handle Wallet Events
// =======================================================================
if (window.ethereum) {
window.ethereum.on("accountsChanged", () => location.reload());
window.ethereum.on("chainChanged", () => location.reload());
}
// =======================================================================
// Initialize
// =======================================================================
log('Ready. Click "Connect Wallet" to start.');
log("Toggle this debug log with the link below.");
</script>
</body>
</html>cd server
npm start📋 Configuration:
Payment wallet: 0xYourWalletAddress
GetBlock API: Configured
Facilitator: https://facilitator.payai.network
Server running at http://localhost:4021
Protected endpoints:
GET /api/eth/block/latest - $0.001 USDC
GET /api/eth/gas - $0.001 USDChttp://localhost:4021userAddress = getAddress(accounts[0]);allowedHeaders: ["X-PAYMENT", ...],
exposedHeaders: ["X-PAYMENT-REQUIRED", ...],const facilitatorClient = new HTTPFacilitatorClient({
url: "https://x402.org/facilitator", // Alternative facilitator
});