Стартовий посібник Robinhood Chain Testnet RPC: читання без ключа, журнали WebSocket, потім mainnet
Почніть роботу з Robinhood Chain Testnet RPC: публічний RPC URL, читання без ключа, журнали WebSocket з API ключем, доступ до крана та перехід із тим самим ключем на mainnet.
BlockVectra надає доступ до Robinhood Chain Testnet (chain ID 46630) через JSON-RPC та WebSocket, і той самий API ключ також працює в Robinhood Chain mainnet. Цей посібник використовує шаблон Robinhood Chain Testnet starter і складається з трьох кроків: читання testnet без ключа, програмне відкриття акаунта та потокове отримання журналів, а потім перенесення того самого ключа на mainnet. Параметри ендпоінтів, політику методів та дані токенізованих акцій див. у посібнику з Robinhood Chain.
Запуск шаблону
git clone https://github.com/blockvectra/robinhood-testnet-starter
cd robinhood-testnet-starter
npm install
npm run typecheckПотрібен Node.js 18 або новішої версії. Три скрипти: npm run step1, npm run step2 та npm run step3. Необов'язкові змінні (BLOCKVECTRA_API_KEY, WALLET_PRIVATE_KEY) зчитуються з командного процесора; жоден компонент не завантажує .env автоматично.
Крок 1: читання testnet без ключа
Публічний ендпоінт https://api.blockvectra.com/v1/robinhood_testnet/public обслуговує гаманцеві методи JSON-RPC без акаунта та без API ключа. Запитуйте EIP-155 chain ID напряму:
curl -s "https://api.blockvectra.com/v1/robinhood_testnet/public" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'Відповідь має вигляд {"jsonrpc":"2.0","id":1,"result":"0xb626"}; 0xb626 — це шістнадцятковий chain ID, що відповідає числу 46630 у десятковій системі.
Шаблон читає запис мережі з GET /v1/chains і створює клієнт viem на його основі, тому назва мережі та chain ID не зашиті в коді. Із src/shared.ts:
import { createPublicClient, defineChain, http, webSocket } from "viem";
export const API_BASE = "https://api.blockvectra.com/v1";
export interface ChainEntry {
chain: string;
name: string;
chain_id: number;
data: boolean;
ws: boolean;
subscriptions: string[];
public?: { url: string };
}
export async function getChain(slug: string): Promise<ChainEntry> {
const res = await fetch(`${API_BASE}/chains`);
if (!res.ok) throw new Error(`GET /v1/chains failed: ${res.status}`);
const { chains } = (await res.json()) as { chains: ChainEntry[] };
const entry = chains.find((c) => c.chain === slug);
if (!entry) throw new Error(`${slug} not found in /v1/chains`);
return entry;
}
export function toViemChain(entry: ChainEntry, rpcUrl: string) {
return defineChain({
id: entry.chain_id,
name: entry.name,
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
rpcUrls: { default: { http: [rpcUrl] } },
});
}
export function httpClient(entry: ChainEntry, url: string, apiKey?: string) {
return createPublicClient({
chain: toViemChain(entry, url),
transport: http(url, apiKey ? { fetchOptions: { headers: { "x-api-key": apiKey } } } : undefined),
});
}
export function wsClient(entry: ChainEntry, apiKey: string) {
const base = "wss://api.blockvectra.com/v1";
const url = `${base}/${entry.chain}/${apiKey}`;
return createPublicClient({ chain: toViemChain(entry, url), transport: webSocket(url) });
}За допомогою цього модуля src/step1-public-read.ts читає chain ID, останній блок та баланс адреси:
import { formatEther, type Address } from "viem";
import { API_BASE, getChain, httpClient } from "./shared.js";
const SLUG = "robinhood_testnet";
// Any address works; override with the first CLI argument.
const address = (process.argv[2] ?? "0x0000000000000000000000000000000000000000") as Address;
const chain = await getChain(SLUG);
const client = httpClient(chain, `${API_BASE}/${SLUG}/public`);
const [chainId, blockNumber, balance] = await Promise.all([
client.getChainId(),
client.getBlockNumber(),
client.getBalance({ address }),
]);
console.log(`chain : ${chain.name} (${SLUG})`);
console.log(`eth_chainId : ${chainId} (0x${chainId.toString(16)})`);
console.log(`block : ${blockNumber}`);
console.log(`balance : ${formatEther(balance)} ETH (${address})`);Крок 2: програмне відкриття акаунта та підписка на журнали
src/step2-key-and-logs.ts виконує вхід за допомогою гаманця (SIWE, EIP-191) за адресою https://console-api.blockvectra.com/v1. Перший вхід створює акаунт; після цього клієнт створює API ключ. Нові акаунти отримують 30,000,000 CU під час реєстрації — без кредитної картки.
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
import type { Hex } from "viem";
const CONSOLE_API = "https://console-api.blockvectra.com/v1";
const REF = "gh-robinhood-testnet-starter";
async function post<T>(path: string, body: unknown, token?: string): Promise<T> {
const res = await fetch(`${CONSOLE_API}${path}`, {
method: "POST",
headers: { "Content-Type": "application/json", ...(token ? { Authorization: `Bearer ${token}` } : {}) },
body: JSON.stringify(body),
});
if (!res.ok) throw new Error(`${path} failed: ${res.status} ${await res.text()}`);
return (await res.json()) as T;
}
async function provisionKey(): Promise<string> {
const pk = (process.env.WALLET_PRIVATE_KEY as Hex | undefined) ?? generatePrivateKey();
const account = privateKeyToAccount(pk);
console.log(`wallet: ${account.address}`);
// SIWE: ask for a challenge, sign it verbatim (EIP-191), log in. A first sign-in creates the account.
const { message } = await post<{ message: string }>("/auth/siwe/challenge", {
address: account.address,
purpose: "login",
});
const signature = await account.signMessage({ message });
const login = await post<{ session: { token: string }; account_created: boolean }>("/auth/siwe/login", {
message,
signature,
ref: REF,
});
console.log(`account_created: ${login.account_created}`);
const created = await post<{ api_key: string }>("/keys", { label: "robinhood-testnet-starter" }, login.session.token);
return created.api_key;
}
const apiKey = process.env.BLOCKVECTRA_API_KEY?.trim() || (await provisionKey());Якщо у вас уже є ключ, export BLOCKVECTRA_API_KEY=... пропускає реєстрацію. Без WALLET_PRIVATE_KEY скрипт генерує одноразовий гаманець у пам'яті та видаляє його після завершення виконання; встановіть WALLET_PRIVATE_KEY у своєму локальному середовищі, якщо хочете увійти до того самого акаунта знову.
URL WebSocket містить ключ у шляху: wss://api.blockvectra.com/v1/robinhood_testnet/{api_key}. Шаблон перевіряє актуальний прапорець ws та список subscriptions із GET /v1/chains перед оформленням підписки:
const chain = await getChain("robinhood_testnet");
if (!chain.ws || !chain.subscriptions.includes("logs")) {
throw new Error(`robinhood_testnet does not offer a logs subscription in /v1/chains`);
}
console.log(`subscriptions (from /v1/chains): ${chain.subscriptions.join(", ")}`);
const client = wsClient(chain, apiKey);
const stop = client.watchEvent({
address: "0x1234567890123456789012345678901234567890",
onLogs: (logs) => {
for (const l of logs) console.log(`block ${l.blockNumber} ${l.address} topic0=${l.topics[0]}`);
},
onError: (e) => console.error("subscription error:", e.message),
});Кожен фільтр підписки на logs повинен містити address або topic0; замініть приклад адреси на контракт, який ви бажаєте відстежувати. Правила фільтрації, коди закриття та повторне підключення див. у посібнику з підписок WebSocket.
Крок 3: перемикання того самого ключа на mainnet
Перехід на mainnet — це зміна одного слова: використайте слаг robinhood_mainnet та той самий API ключ. src/step3-mainnet.ts читає номер блоку mainnet та викликає Data API для токенів акцій Robinhood:
const apiKey = process.env.BLOCKVECTRA_API_KEY?.trim();
if (!apiKey) throw new Error("Set BLOCKVECTRA_API_KEY (run step 2 first, or create a key in the console).");
const mainnet = await getChain("robinhood_mainnet");
// JSON-RPC with the key: the chain slug changes.
const client = httpClient(mainnet, `${API_BASE}/${mainnet.chain}`, apiKey);
console.log(`mainnet block: ${await client.getBlockNumber()}`);
// Data API: Robinhood stock-token leaderboard (see the Robinhood Chain guide).
const res = await fetch(`${API_BASE}/data/${mainnet.chain}/stocks`, { headers: { "x-api-key": apiKey } });
if (!res.ok) throw new Error(`Data API failed: ${res.status} ${await res.text()}`);
console.log(JSON.stringify(await res.json(), null, 2).slice(0, 2000));Той самий ендпоінт таблиці лідерів за допомогою curl:
curl -s -H "x-api-key: $BLOCKVECTRA_API_KEY" \
"https://api.blockvectra.com/v1/data/robinhood_mainnet/stocks"Data API доступний лише в mainnet: GET /v1/chains повертає data: false для robinhood_testnet та data: true для robinhood_mainnet. Параметри запиту та конверти відповідей див. у посібнику з токенізованих акцій.
Визначення лімітів та можливостей через API
Звертайтеся до GET /v1/chains, щоб отримати актуальні прапорці jsonrpc, data, ws та subscriptions, дозволені методи JSON-RPC, діапазони блоків журналів, збереження стану та публічний ендпоінт кожної мережі. Звертайтеся до GET /v1/plans для перегляду актуальних цін та лімітів планів.
curl -s "https://api.blockvectra.com/v1/chains"Пов'язані посібники
- Знайдіть RPC URL для testnet та ліміти.
- Отримайте тестовий ETH із крана testnet перед надсиланням транзакцій.
Наступні кроки
- Перегляньте каталог датасетів, щоб побачити всі набори даних, які індексує BlockVectra.
- Перегляньте безкоштовний план та ціни, щоб перевірити, що включено у ваш акаунт.
- Увійдіть до консолі, щоб створити API ключ.
Востаннє оновлено:
Robinhood Chain
Підключайтеся до Robinhood Chain за допомогою viem або ethers, розгортайте за допомогою Foundry або Hardhat, слухайте журнали WebSocket або події webhook та запитуйте активність токенізованих акцій.
Кран testnet
Отримуйте тестовий ETH за допомогою власного API ключа: вимоги до акаунта, ліміти запитів, прийняті транзакції та обробка помилок.