OHLC dan VWAP DEX harian untuk token dengan pecahan eksak
Kueri harga OHLC dan VWAP DEX harian dari Data API, tangani pecahan rasional eksak di TypeScript dan Python, serta lakukan backfill data historis secara efisien.
Apa itu dataset harga DEX harian
Dataset DEX BlockVectra mengindeks aktivitas perdagangan bursa terdesentralisasi dan menghitung metrik harga harian agregat. Endpoint harga DEX harian (getDexPrices) menyediakan harga rata-rata tertimbang volume (VWAP) harian, indikator harga (bidang first_price, last_price, min_price, dan max_price), serta metrik volume untuk token tertentu selama rentang tanggal yang ditentukan.
Ketersediaan dataset ini berbeda antarjaringan; rantai yang menyediakan dataset ini mengikuti halaman Rantai yang Didukung.
Endpoint ini tidak menggunakan paginasi: semua baris harian yang cocok dalam rentang tanggal permintaan dikembalikan langsung dalam data, dan next_cursor tidak pernah disertakan. Jika aplikasi Anda memerlukan transaksi swap individual alih-alih agregat harian, gunakan GET /{chain}/dex/swaps (lihat Referensi Data API).
Parameter permintaan dan batas
Rute endpoint adalah GET https://api.blockvectra.com/v1/data/{chain}/dex/prices. Semua permintaan memerlukan autentikasi dengan menyertakan API key Anda pada header x-api-key.
Endpoint ini menerima parameter kueri berikut:
| Parameter | Lokasi | Tipe | Wajib | Deskripsi |
|---|---|---|---|---|
chain | path | string | Ya | Identitas rantai, misalnya robinhood_mainnet |
token | query | string | Ya | Alamat token dasar 20 byte, 0x opsional, huruf besar atau kecil |
quote | query | string | Tidak | Alamat token kuotasi 20 byte opsional untuk membatasi ke satu pasangan dasar/kuotasi |
from | query | date string | Ya | Tanggal mulai UTC, inklusif, YYYY-MM-DD |
to | query | date string | Ya | Tanggal akhir UTC, inklusif, YYYY-MM-DD. to - from harus <= 90 hari |
Batasan dan kode error
Jika permintaan melanggar batasan, API mengembalikan body error terstruktur {"error":{"code","message"}}:
- HTTP 400 (
bad_request): Parameter kueri wajib (token,from, atauto) tidak disertakan, sintaks alamattoken/quotetidak valid, tanggal kalenderYYYY-MM-DDtidak valid, ataufromberada setelahto. - HTTP 409 (
span_exceeded):to - fromlebih dari 90 hari. - HTTP 404 (
unknown_chain):{chain}bukan rantai yang tercantum dalamGET /chains. - HTTP 422 (
no_coverage): Rantai tidak mendukung kapabilitas datasetdex_prices. - HTTP 503 (
unavailable): Layanan sementara tidak tersedia; coba lagi sesuai headerRetry-After.
Contoh permintaan
Contoh berikut mengueri harga DEX harian untuk token dasar sepanjang September 2026:
curl -s "https://api.blockvectra.com/v1/data/robinhood_mainnet/dex/prices?token=0x1Cdad396DB64BDa184d5182A97Dd9B3C62100b7D&from=2026-09-01&to=2026-09-30" \
-H "x-api-key: $BLOCKVECTRA_API_KEY"Referensi bidang terperinci
Setiap entri dalam data mewakili metrik DEX harian agregat untuk pasangan token pada tanggal UTC tersebut:
Token dan aset kuotasi
day(string): Tanggal UTC dalam formatYYYY-MM-DD.token(string): Alamat token dasar 20 byte dalam heksadesimal huruf kecil dengan awalan0x.token_symbol(string ataunull): Simbol token dasar.token_name(string ataunull): Nama tampilan token dasar.quote_token(string): Alamat aset kuotasi. Alamat yang seluruhnya nol (0x0000000000000000000000000000000000000000) mewakili ETH native sebagai aset kuotasi.quote_symbol(string ataunull): Simbol aset kuotasi ("ETH"jikaquote_tokenadalah alamat yang seluruhnya nol).quote_name(string ataunull): Nama tampilan aset kuotasi ("Ether"jikaquote_tokenadalah alamat yang seluruhnya nol).base_decimals(integer ataunull): Jumlah desimal token dasar (0–255).quote_decimals(integer ataunull): Jumlah desimal aset kuotasi (18jikaquote_tokenadalah alamat yang seluruhnya nol).
Volume dan jumlah perdagangan
swap_count(integer): Jumlah swap untuk baris ini.base_volume_raw(string): Volume dasar dalam unit atomik sebagai string desimal integer tanpa tanda (UInt256String).quote_volume_raw(string): Volume kuotasi dalam unit atomik sebagai string desimal integer tanpa tanda (UInt256String).base_volume(string ataunull): Volume token dasar yang dapat dibaca manusia, diskalakan menurutbase_decimalssebagaiDecimalString;nulljikabase_decimalstidak diketahui.quote_volume(string ataunull): Volume kuotasi yang diskalakan menurut jumlah desimal kuotasi sebagaiDecimalString, ataunull.
Indikator harga dan VWAP
vwap(string ataunull): Harga rata-rata tertimbang volume sebagaiDecimalString, ataunull.first_price(string ataunull): Indikator harga pertama sebagaiDecimalString, ataunull.last_price(string ataunull): Indikator harga terakhir sebagaiDecimalString, ataunull.min_price(string ataunull): Indikator harga minimum sebagaiDecimalString, ataunull.max_price(string ataunull): Indikator harga maksimum sebagaiDecimalString, ataunull.
Bidang pecahan eksak
first_price_numerator/first_price_denominator(string): Pembilang dan penyebut integer eksak untukfirst_price(UInt256String).last_price_numerator/last_price_denominator(string): Pembilang dan penyebut integer eksak untuklast_price(UInt256String).min_price_numerator/min_price_denominator(string): Pembilang dan penyebut integer eksak untukmin_price(UInt256String).max_price_numerator/max_price_denominator(string): Pembilang dan penyebut integer eksak untukmax_price(UInt256String).refreshed_at(string): Timestamp pembaruan untuk baris ini (timestamp UTC ISO-8601).
Metadata struktur respons (meta)
chain: Identitas rantai.chain_slug: Slug rantai kanonis dalam huruf besar.chain_external_id: Identitas rantai dalam format CAIP-2.as_of_block: Blok terbaru rantai yang sudah ditulis sepenuhnya (dilaporkan oleh dataset ini, tidak diperiksa terhadap parameter permintaan).coverage: Klasifikasi cakupan (melaporkan"full"untuk endpoint ini).refreshed_at: Timestamp pembaruan metadata. Dapat bernilainull:nullberarti waktu pembaruan data ini tidak diketahui dan data harus dianggap usang; endpoint berbasis blok selalu mengembalikan nilai.
Mengapa harga menggunakan pembilang dan penyebut eksak
Angka JSON standar menggunakan floating-point presisi ganda IEEE-754, yang memiliki keterbatasan presisi:
- Pemotongan dan penyimpangan floating-point: Nilai Float64 hanya menyediakan presisi 53 bit, dan pembagian jumlah token menghasilkan penyimpangan pembulatan yang terakumulasi dalam perhitungan.
- Keamanan transmisi: Memformat nilai sebagai string desimal (
UInt256String) memastikan angka dikirim melalui HTTP tanpa kehilangan presisi di parser JSON.
Dengan menyediakan pembilang dan penyebut integer eksak untuk indikator harga, BlockVectra memungkinkan perhitungan matematika eksak tanpa konversi floating-point.
Menangani pecahan eksak di TypeScript (BigInt)
Di TypeScript, Anda dapat menggunakan BigInt native untuk perbandingan dengan perkalian silang dan konversi fixed-point tanpa konversi floating-point:
interface DexDailyPrice {
first_price_numerator: string;
first_price_denominator: string;
last_price_numerator: string;
last_price_denominator: string;
}
// 1. Ratio comparison without floating-point conversion: check if close price is higher than open price
// a / b > c / d is equivalent to a * d > c * b
export function isPriceUp(row: DexDailyPrice): boolean {
const openNum = BigInt(row.first_price_numerator);
const openDen = BigInt(row.first_price_denominator);
const closeNum = BigInt(row.last_price_numerator);
const closeDen = BigInt(row.last_price_denominator);
return closeNum * openDen > openNum * closeDen;
}
// 2. Convert fraction to a fixed-point decimal string with arbitrary scale (without floating-point loss)
export function fractionToFixedString(
numeratorStr: string,
denominatorStr: string,
decimals = 18
): string {
const num = BigInt(numeratorStr);
const den = BigInt(denominatorStr);
if (decimals === 0) {
return (num / den).toString();
}
const scaleFactor = 10n ** BigInt(decimals);
const scaled = (num * scaleFactor) / den;
const intPart = scaled / scaleFactor;
const remainder = scaled % scaleFactor;
const fracPart = remainder.toString().padStart(decimals, "0");
return `${intPart}.${fracPart}`;
}Menangani pecahan eksak di Python
Python menyediakan modul pustaka standar yang khusus dibuat untuk perhitungan rasional dan desimal: fractions.Fraction dan decimal.Decimal.
from decimal import Decimal, getcontext
from fractions import Fraction
# 1. Exact rational calculations with fractions.Fraction
open_price = Fraction(
int(row["first_price_numerator"]),
int(row["first_price_denominator"])
)
close_price = Fraction(
int(row["last_price_numerator"]),
int(row["last_price_denominator"])
)
# Exact price delta without floating-point rounding error
price_delta = close_price - open_price
print(f"Price delta (fraction): {price_delta}")
if open_price != 0:
percentage_change = (price_delta / open_price) * 100
print(f"Percentage change: {float(percentage_change):.4f}%")
# 2. Arbitrary-precision decimal arithmetic with decimal.Decimal
getcontext().prec = 50
if int(row["first_price_denominator"]) != 0:
open_decimal = Decimal(row["first_price_numerator"]) / Decimal(row["first_price_denominator"])
print(f"High-precision open: {open_decimal}")Backfill harga harian selama satu tahun
Untuk melakukan backfill data satu tahun (365 hari) dalam batas rentang 90 hari, bagi seluruh rentang tanggal menjadi jendela berurutan yang masing-masing paling lama 90 hari dan kirim permintaan secara bertahap:
interface DateSpan {
from: string;
to: string;
}
/**
* Split a large date range into consecutive spans of at most maxDays (default: 90)
*/
export function splitDateRange(startDateStr: string, endDateStr: string, maxDays = 90): DateSpan[] {
const spans: DateSpan[] = [];
let currentStart = new Date(startDateStr);
const end = new Date(endDateStr);
while (currentStart <= end) {
const chunkEnd = new Date(currentStart);
chunkEnd.setUTCDate(chunkEnd.getUTCDate() + (maxDays - 1));
const effectiveEnd = chunkEnd < end ? chunkEnd : end;
spans.push({
from: currentStart.toISOString().slice(0, 10),
to: effectiveEnd.toISOString().slice(0, 10),
});
const nextStart = new Date(effectiveEnd);
nextStart.setUTCDate(nextStart.getUTCDate() + 1);
currentStart = nextStart;
}
return spans;
}
/**
* Backfill token daily prices across multiple 90-day chunks
*/
export async function backfillTokenDailyPrices(
chain: string,
token: string,
startDate: string,
endDate: string,
apiKey: string
) {
const chunks = splitDateRange(startDate, endDate, 90);
const allDailyPrices = [];
for (const chunk of chunks) {
const url = new URL(`https://api.blockvectra.com/v1/data/${chain}/dex/prices`);
url.searchParams.set("token", token);
url.searchParams.set("from", chunk.from);
url.searchParams.set("to", chunk.to);
const res = await fetch(url, {
headers: { "x-api-key": apiKey },
});
if (!res.ok) {
throw new Error(`Failed to fetch span ${chunk.from}..${chunk.to}: HTTP ${res.status}`);
}
const json = await res.json();
allDailyPrices.push(...json.data);
}
return allDailyPrices;
}Perhitungan kapasitas dan penggunaan CU
Setiap endpoint Data API mengukur konsumsi dalam Compute Units (CU). Bobot CU per panggilan untuk data.dex_prices dan perkiraan konsumsi untuk backfill token dihitung di bawah:
data.dex_prices: 15 CU / call- Pengisian riwayat harga harian 1 tahun untuk 200 token: dengan rentang maksimum 90 hari per permintaan, mencakup 365 hari memerlukan 5 bagian per token, dengan total 1,000 panggilan. Konsumsi total adalah 15,000 CU (sekitar <0.1% dari kuota siklus paket gratis), sekitar <$0.01 dengan harga terdaftar.
- Pemeliharaan harian (menyegarkan 200 token sekali sehari): 200 panggilan/hari (3,000 CU/hari), dengan total sekitar 6,000 panggilan per siklus 30 hari (90,000 CU, sekitar 0.3% dari kuota gratis), sekitar <$0.01/bulan dengan harga terdaftar.
Saat meningkatkan volume backfill atau memerlukan konkurensi permintaan yang lebih tinggi, lakukan top up on-chain pada halaman Penagihan di konsol untuk meningkatkan akun ke akun berbayar. Untuk tarif dan konversi unit terkini, lihat halaman Harga.
Langkah selanjutnya
- Telusuri direktori dataset untuk melihat setiap dataset yang diindeks oleh BlockVectra.
- Lihat paket gratis dan harga untuk memeriksa apa yang termasuk dalam akun Anda.
- Masuk ke konsol untuk membuat API key.
Terakhir diperbarui:
Deployment kontrak
Deploy Hello.sol di jaringan EVM dengan Foundry atau Hardhat 2, verifikasi chain ID, lalu periksa receipt transaksi dan respons kontrak.
State EVM historis
Bedakan jendela state terautentikasi, riwayat tanpa API key, dan rentang log. Pilih blok tetap untuk eth_call dan diagnosis error state_window.