Cüzdan token bakiyeleri API'si: ERC-20 varlıkları ve transfer geçmişi

Sıfır olmayan ERC-20 token bakiyeleri, token transfer geçmişi ve toplu meta verilerle bir cüzdan varlıkları sayfası oluşturun. Zincir kapsamını kontrol edin, sonuçları sayfalandırın ve tam sayı tutarları decimals değerine göre ölçekleyin.

Blokzincir cüzdan veri API'si ile bir cüzdan varlıkları sayfası oluşturun: sıfır olmayan ERC-20 varlıkları için Token Bakiyeleri API'sini ve cüzdan geçmişi için Token Transferleri API'sini kullanın. Geliştiriciler ve AI Agent'lar aynı kimliği doğrulanmış istekleri kullanır. Sorgulamadan önce GET /v1/status yanıtını okuyun ve seçilen zincirin data_features ile data_status alanlarını kontrol edin; bakiye kapsamı zincire göre değişir. İstek parametreleri ve yanıt şemaları Data API referansında yer almaktadır.

Bu rehberin tamamlamanıza yardımcı olduğu görevler

Bir cüzdan varlıkları sayfasının ihtiyaç duyduğu üç tür veri

Bir cüzdan varlıkları sayfası bir adresin ERC-20 token bakiyelerini, token transfer geçmişini ve token meta verilerini gösterebilir. Data API her biri için ayrı bir uç nokta sunar:

  • Bakiyeler: GET /{chain}/addresses/{address}/balances, adresin sıfır olmayan ERC-20 bakiyelerini token adresine göre artan sırada döndürür; mevcut olduğunda token symbol ve decimals bilgileri eklenir. Bakiyesi olmayan bir adres data: [] ile 200 döndürür.
  • Transferler: GET /{chain}/addresses/{address}/transfers, zorunlu bir blok penceresi içinde adresle ilişkili token transferlerini (block_number, log_index) azalan sırasında döndürür.
  • Token meta verileri: GET /{chain}/tokens/{token}, sözleşme adresine göre tek bir token'ın adını, sembolünü, ondalık basamaklarını (decimals) ve toplam arzını okur; POST /{chain}/tokens:batch, tek bir istekte 100 adrese kadar aynı meta verileri okur.

Her üçü de temel URL olarak https://api.blockvectra.com/v1/data adresini ve x-api-key istek başlığını kullanır; örnek zincir olarak robinhood_mainnet kullanılır. Sırasıyla balances, transfers ve token_metadata yeteneklerine aittirler; her yeteneği sunan zincirler için Desteklenen Zincirler sayfasına bakın. Bu yeteneğe sahip olmayan bir zincirde uç nokta 422 no_coverage döndürür.

İstek 1: adres bakiyeleri

Bu uç nokta daha az parametre alır, bu da onu bir sayfa için iyi bir ilk istek yapar:

  • {chain} (yol parametresi, zorunlu): zincir tanımlayıcısı, GET /chains içindeki bir girdinin chain değeri (örneğin robinhood_mainnet). Eşleme tam ve büyük/küçük harfe duyarlıdır; takma adlar ve sayısal Chain ID'ler kabul edilmez.
  • {address} (yol parametresi, zorunlu): 20 baytlık adres; 0x öneki isteğe bağlıdır ve her iki harf durumu da kabul edilir.
  • limit (sorgu parametresi, isteğe bağlı): sayfa boyutu. Varsayılan değer 50'dir; 500'ün üzerindeki değerler 500'e kırpılır; 0 veya tam sayı olmayan bir değer 400 bad_request döndürür.
  • cursor (sorgu parametresi, isteğe bağlı): sonraki sayfayı getirmek için değiştirilmeden geri iletilen, önceki yanıtın next_cursor değeri. Bir imleç yalnızca onu oluşturan zincir, uç nokta ve sorgu parametreleri için geçerlidir; başka bir yerde yeniden kullanılması 400 bad_request döndürür.

Keyset sayfalandırmalıdır: next_cursor yalnızca başka bir sayfa olduğunda görünür. Son sayfada anahtar hiçbir zaman null olmaz, tamamen mevcut değildir.

export BLOCKVECTRA_API_KEY=rgw_your_api_key

curl -s "https://api.blockvectra.com/v1/data/robinhood_mainnet/addresses/0x1111111111111111111111111111111111111111/balances?limit=50" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"

Yanıt zarfı (envelope), data ve meta içeren AddressBalanceListEnvelope biçimindedir. data içindeki her öğe bir AddressBalance nesnesidir:

AlanTürAçıklama
tokenstring (address)Token sözleşme adresi; kanonik biçim 0x ve ardından 40 küçük harfli onaltılık basamaktır.
balancestring (decimal)2^53 değerini aşabilen ham tam sayı bakiye, düz bir ondalık dize olarak döndürülür — hiçbir zaman bir JSON sayısı, bilimsel gösterim veya onaltılık değildir.
symbolstring veya nullToken sembolü veya mevcut olmadığında null.
decimalsinteger veya nullToken ondalık basamak sayısı, 0–255 veya mevcut olmadığında null.

İstek 2: adres transferleri

Transferler uç noktası açık bir blok penceresi gerektirir: from_block ve to_block zorunludur ve from_block <= to_block koşulunu sağlamalıdır. Birkaç parametre daha alır:

  • standard (sorgu parametresi, zorunlu): erc20 veya erc721. Adres kapsamlı sorgular erc1155 standardını kapsamaz; bunun iletilmesi 422 no_coverage döndürür.
  • direction (sorgu parametresi, isteğe bağlı): in, out veya any; varsayılan any değeridir ve adrese göre yöne göre filtreler.
  • token (sorgu parametresi, isteğe bağlı): sonuçları tek bir token sözleşmesiyle sınırlandırır.
  • clamp (sorgu parametresi, isteğe bağlı): yalnızca "true" dize sabiti etkinleştirir; diğer tüm değerler false olarak değerlendirilir.

Pencere sınırları ve kesinlik (finality): as_of_block üzerinde açık bir to_block belirtilmesi, clamp=true değeri onu as_of_block seviyesine kırpmadığı sürece 409 not_indexed_yet döndürür; zincirin sınırından (GET /chains üzerinden limits.max_window_blocks) daha geniş bir pencere, clamp=true değeri eski uçtan kırpmadığı sürece (from_block yükseltilir ve to_block sabit tutulur) 409 window_too_large döndürür. from_block değerinin kendisi zaten as_of_block değerini geçmişse, clamp=true olsa bile kesin 409 olarak kalır. Pencere kırpıldığında veya kısmen kapsandığında, yanıttaki meta.coverage değeri "partial" olur; aksi takdirde "full" değeridir.

Transfer kayıtlarında ERC-20 öğelerine amount; ERC-721 öğelerine ise token_id eklenir. Her ikisi de token, standard, from, to, block_number, block_timestamp, tx_hash, tx_index ve log_index alanlarını içerir.

export BLOCKVECTRA_API_KEY=rgw_your_api_key

# 1) balances yanıtından as_of_block değerini okuyun.
AS_OF_BLOCK=$(curl -s "https://api.blockvectra.com/v1/data/robinhood_mainnet/addresses/0x1111111111111111111111111111111111111111/balances" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY" | grep -o '"as_of_block":[0-9]*' | cut -d: -f2)

# 2) clamp=true, 409 döndürmek yerine çok geniş bir pencereyi veya as_of_block üzerindeki bir to_block değerini kırpar.
curl -s "https://api.blockvectra.com/v1/data/robinhood_mainnet/addresses/0x1111111111111111111111111111111111111111/transfers?standard=erc20&from_block=0&to_block=$AS_OF_BLOCK&direction=any&clamp=true" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"

Tüm transferler arasında sayfalandırma yapma

Adres transferleri uç noktasının next_cursor değeri iyimserdir (optimistic): yalnızca sayfa tam olarak limit sayıda satır döndürdüğünde görünür; dolayısıyla bir sayfa next_cursor taşısa bile son sayfa olduğu ortaya çıkabilir. Bir sayfa boş olduğunda durmayın; anahtar mevcut olmayana kadar next_cursor değerini izleyin.

Aşağıdaki kod penceredeki her transferi getirir:

const address = "0x1111111111111111111111111111111111111111";
const head = await fetch(
  `https://api.blockvectra.com/v1/data/robinhood_mainnet/addresses/${address}/balances`,
  { headers: { "x-api-key": process.env.BLOCKVECTRA_API_KEY! } },
).then((r) => r.json());
const asOfBlock = head.meta.as_of_block;
const transfers: unknown[] = [];
let cursor: string | undefined;

do {
  const url = new URL(
    `https://api.blockvectra.com/v1/data/robinhood_mainnet/addresses/${address}/transfers`,
  );
  url.searchParams.set("standard", "erc20");
  url.searchParams.set("from_block", "0");
  url.searchParams.set("to_block", String(asOfBlock));
  url.searchParams.set("limit", "500");
  // clamp daha eski taraftan kırpar
  url.searchParams.set("clamp", "true");
  if (cursor) url.searchParams.set("cursor", cursor);

  const res = await fetch(url, {
    headers: { "x-api-key": process.env.BLOCKVECTRA_API_KEY! },
  });
  const page = await res.json();
  transfers.push(...page.data);
  cursor = page.next_cursor; // son sayfada bulunmaz
} while (cursor);

İstek 3: token meta verileri ve tokens:batch

GET /{chain}/tokens/{token} ile tek bir token okuyun; yol yalnızca {chain} ve {token} alır, sayfalandırma içermez. Yanıt zarfı TokenEnvelope biçimindedir ve data bir Token nesnesidir:

AlanTürAçıklama
addressstring (address)Token sözleşme adresi.
standardstringerc20, erc721 veya unknown.
namestring veya nullToken adı veya mevcut olmadığında null.
symbolstring veya nullToken sembolü veya mevcut olmadığında null.
decimalsinteger veya nullToken ondalık basamak sayısı, 0–255 veya mevcut olmadığında null.
total_supplystring veya nullHam toplam arz; API decimals ölçeklemesi uygulamaz. Mevcut olmadığında null.
first_seen_blockinteger (int64)Token'ın ilk görüldüğü blok yüksekliği.
metadata_updated_atstring (timestamp)Meta verilerin son güncellendiği UTC zamanı.
metadata_blockinteger (int64)Meta verilerin okunduğu blok yüksekliği.
metadata_statusstringok, partial veya unavailable.
metadata_issuesobjectname, symbol, decimals, total_supply anahtarlarıyla alan bazında sorun kayıtları; değerler reverted, no_data, invalid_encoding veya temporarily_unavailable.

Geçerli bir 20 baytlık adres olmayan bir {token} 400 bad_request döndürür; bilinmeyen bir {token} 404 not_found döndürür; bilinmeyen bir {chain} 404 unknown_chain döndürür.

Bakiyeler uç noktası mevcut olduğunda zaten symbol ve decimals içerir, ancak her ikisi de null olabilir. Bir cüzdandaki her token için adı ve ondalık basamakları tamamlamak üzere POST /{chain}/tokens:batch kullanın:

  • İstek gövdesi, istek başına en fazla 100 adres içeren {"addresses": [...]} biçimindedir; 100'den fazla girdi veya geçerli bir 20 baytlık adres olmayan bir girdi 400 bad_request döndürür (karşılaştığı ilk geçersiz adreste başarısız olur).
  • Bulunamayan adresler bir hatayı tetiklemez; data.missing içinde listelenirken, data.tokens yalnızca meta verileri bulunan token'ları içerir.
  • Yinelenen adresler hem tokens hem de missing içinde, her birinde ilk görülme istek sırasına göre tekilleştirilir.
export BLOCKVECTRA_API_KEY=rgw_your_api_key

# Tek token
curl -s "https://api.blockvectra.com/v1/data/robinhood_mainnet/tokens/0x1111111111111111111111111111111111111111" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"

# Batch: istek başına en fazla 100 adres
curl -s -X POST "https://api.blockvectra.com/v1/data/robinhood_mainnet/tokens:batch" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"addresses":["0x1111111111111111111111111111111111111111","0x2222222222222222222222222222222222222222"]}'

Tutarları decimals değerine göre ölçekleme

Bakiye alanı balance ve ERC-20 transfer alanı amount, ondalık dize (UInt256String) olarak oluşturulmuş ham tam sayılardır; bir token'ın total_supply değeri de decimals ölçeklemesi uygulanmamış ham bir zincir üstü tam sayıdır. İnsan tarafından okunabilir bir miktar göstermek için, o token'ın decimals değerine bölün.

  • decimals, bakiye öğesinin kendi symbol/decimals değerinden veya GET /{chain}/tokens/{token} ile POST /{chain}/tokens:batch yanıtlarından gelir; null olabilir.
  • Bu değerler 2^53 sınırını aşabilir, bu nedenle aritmetik işlemleri bir JSON sayısı ile yapmayın: duyarlık kaybını önlemek için TypeScript'te BigInt ve Python'da Decimal kullanarak ondalık dizeyi olduğu gibi ayrıştırın.
function toDisplayAmount(raw: string, decimals: number | null): string {
  if (decimals === null) return raw; // decimals meta verisi yok: ham tam sayıyı koru
  const value = BigInt(raw);
  const base = 10n ** BigInt(decimals);
  const whole = value / base;
  const fraction = (value % base)
    .toString()
    .padStart(decimals, "0")
    .replace(/0+$/, "");
  return fraction ? `${whole}.${fraction}` : whole.toString();
}

// balance.balance ham bir ondalık dizedir; decimals aynı öğeden veya tokens:batch'ten gelir.
const display = toDisplayAmount(balance.balance, balance.decimals);

Veri güncelliği

Zincir kapsamındaki her başarılı yanıt meta taşır:

  • as_of_block: zincirin en yeni tamamen yazılmış bloğu. Blok kapsamlı uç noktalar bu yüksekliğe kadar veri sunar.
  • safe_block: düğümün konsensüs safe blok etiketini gösteren bir işaretçi (bilinmediğinde null). Asla finalized_block altında değildir ve yanıtları kırpmaz, reddetmez veya geciktirmez.
  • finalized_block: düğümün konsensüs finalized blok etiketini gösteren bir işaretçi (bilinmediğinde null). Yanıtları kırpmaz, reddetmez veya geciktirmez; istemciler bu işaretçiden ne tür bir güvenliğe ihtiyaç duyduklarına (onay durumu gibi) kendileri karar verir.
  • coverage: "full" veya "partial". Adres transferleri ve benzer uç noktalar, clamp sunulan pencereyi daralttığında veya pencere zincirin ilk indekslenen bloğundan önce başladığında "partial" bildirir.
  • refreshed_at: yanıtın arkasındaki verilerin en son güncellendiği zaman (UTC). null olabilir: null, verilerin güncelleme zamanının bilinmediği ve güncelliğini yitirmiş (stale) olarak değerlendirilmesi gerektiği anlamına gelir; blok tabanlı uç noktalar her zaman bir değer döndürür.
  • Ayrıca chain, chain_slug ve chain_external_id alanlarını yineler.

Yaygın bir model: en yeni indekslenmiş bloğa kadar okumak için herhangi bir ilk yanıttan meta.as_of_block değerini okuyun ve onaylanmış durumu görüntülemek istiyorsanız meta.safe_block / meta.finalized_block değerlerini kontrol edin.

Tek bir sayfa yüklemesi için CU tahmini

Her yöntem, platform planları API'sinden okunan CU ağırlığına göre faturalandırılır:

Çağrı başına CU ağırlığı

YöntemÇağrı başına CU
data.address_balances25
data.address_transfers25
data.tokens_batch10

Bir sayfa yüklemesi (tahmini)

1 balances isteği + 3 transfer sayfası + 1 tokens:batch isteği, toplam 5 çağrı, yaklaşık 110 CU. Gerçek kullanım, sayfa ve token sayısına bağlıdır.

Faturalandırma kararları ve faturalandırılmayan hata yanıtları için faturalandırma kurallarına bakın. İhtiyacınız olan şey indekslenmiş transfer geçmişi değil de en son bloklardaki loglarsa, eth_getLogs yöntemine geçip geçmeyeceğinize karar vermeden önce En son düğüm verileri ve indekslenmiş geçmiş rehberini okuyun.

Sonraki adımlar

Son güncelleme:

Bu sayfada