Akun Historis
getHistoricalTokenAccountsByOwner
Cantumkan akun SPL Token dan Token-2022 yang dimiliki dompet Solana pada slot sebelumnya atau tepat setelah transaksi tertentu, dengan filter mint dan paginasi.
POST
/
getHistoricalTokenAccountsByOwner
curl --request POST \
--url 'https://mainnet.helius-rpc.com/?api-key=' \
--header 'Content-Type: application/json' \
--data '
{
"jsonrpc": "2.0",
"id": "1",
"method": "getHistoricalTokenAccountsByOwner",
"params": [
"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
{
"slot": 445000000
},
{
"encoding": "jsonParsed",
"limit": 2
}
]
}
'import requests
url = "https://mainnet.helius-rpc.com/?api-key="
payload = {
"jsonrpc": "2.0",
"id": "1",
"method": "getHistoricalTokenAccountsByOwner",
"params": [
"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
{ "slot": 445000000 },
{
"encoding": "jsonParsed",
"limit": 2
}
]
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
jsonrpc: '2.0',
id: '1',
method: 'getHistoricalTokenAccountsByOwner',
params: [
'86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY',
{slot: 445000000},
{encoding: 'jsonParsed', limit: 2}
]
})
};
fetch('https://mainnet.helius-rpc.com/?api-key=', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://mainnet.helius-rpc.com/?api-key=",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'jsonrpc' => '2.0',
'id' => '1',
'method' => 'getHistoricalTokenAccountsByOwner',
'params' => [
'86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY',
[
'slot' => 445000000
],
[
'encoding' => 'jsonParsed',
'limit' => 2
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://mainnet.helius-rpc.com/?api-key="
payload := strings.NewReader("{\n \"jsonrpc\": \"2.0\",\n \"id\": \"1\",\n \"method\": \"getHistoricalTokenAccountsByOwner\",\n \"params\": [\n \"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY\",\n {\n \"slot\": 445000000\n },\n {\n \"encoding\": \"jsonParsed\",\n \"limit\": 2\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://mainnet.helius-rpc.com/?api-key=")
.header("Content-Type", "application/json")
.body("{\n \"jsonrpc\": \"2.0\",\n \"id\": \"1\",\n \"method\": \"getHistoricalTokenAccountsByOwner\",\n \"params\": [\n \"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY\",\n {\n \"slot\": 445000000\n },\n {\n \"encoding\": \"jsonParsed\",\n \"limit\": 2\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://mainnet.helius-rpc.com/?api-key=")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"jsonrpc\": \"2.0\",\n \"id\": \"1\",\n \"method\": \"getHistoricalTokenAccountsByOwner\",\n \"params\": [\n \"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY\",\n {\n \"slot\": 445000000\n },\n {\n \"encoding\": \"jsonParsed\",\n \"limit\": 2\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"jsonrpc": "2.0",
"id": "1",
"result": {
"context": {
"slot": 468129571
},
"value": {
"accounts": [
{
"pubkey": "EKyGnXReqmmXyqBHmMjV2CKCLafJS47xyhXXZ5WuFMxD",
"account": {
"lamports": 531589475273,
"owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"data": [
"<string>"
],
"executable": false,
"rentEpoch": 123,
"space": 82,
"lastUpdatedAt": {
"slot": 444999837,
"transactionIndex": 700
}
}
}
],
"paginationKey": "11112zAgXhc6hGfdfr5anSY91mq7Cs4HHpSVEQc4ASG:EKyGnXReqmmXyqBHmMjV2CKCLafJS47xyhXXZ5WuFMxD"
}
}
}{
"jsonrpc": "2.0",
"error": {
"code": -32602,
"message": "Parameter tidak valid"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32001,
"message": "Tidak sah"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32005,
"message": "Terlalu banyak permintaan"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32603,
"message": "Kesalahan internal"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32002,
"message": "Layanan tidak tersedia"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32003,
"message": "Waktu tunggu gateway habis"
},
"id": "1"
}getHistoricalTokenAccountsByOwner masih dalam versi Beta. Parameter, harga, format respons, dan cakupan data dapat berubah.Ikhtisar
getHistoricalTokenAccountsByOwner mengembalikan akun SPL Token dan Token-2022 yang dimiliki dompet pada slot sebelumnya, atau tepat setelah transaksi tertentu dalam slot tersebut. Ini adalah metode RPC eksklusif Helius. getTokenAccountsByOwner standar hanya mengembalikan status saat ini.
Dengan pengodean jsonParsed, jumlah token menggunakan nilai desimal setiap mint pada posisi yang diminta sehingga saldo mencerminkan jumlah yang dimiliki dompet pada saat tersebut.
Riwayat tersedia mulai slot 444,959,999 (7 September 2026), yaitu status pada awal epoch 1030.
getHistoricalTokenAccountsByOwner tersedia di mainnet untuk paket Business dan yang lebih tinggi, serta dikenai biaya 0 kredit per panggilan selama periode beta. Harga dapat berubah.
Perbedaannya dari getTokenAccountsByOwner
- Filter mint atau program bersifat opsional. Tanpa filter, Anda mendapatkan setiap akun token yang dimiliki dompet. Untuk mempersempit hasil, tetapkan
mintatauprogramIddalam objek konfigurasi (parameter ketiga), bukan keduanya. - Parameter kedua adalah objek kueri yang memilih posisi dalam riwayat, bukan filter mint atau program.
result.valueadalah objek denganaccountsdanpaginationKey, bukan array.
Pilih posisi dalam riwayat
Parameter kedua adalah objek kueri:- Dihilangkan atau
{}: slot terindeks terbaru, dibatasi pada tingkat komitmen yang diminta. { "slot": 445000000 }: akhir slot 445,000,000.{ "slot": 445000000, "transactionIndex": 10 }: tepat setelah transaksi pada indeks 10 dalam slot tersebut dieksekusi.
Contoh permintaan
Permintaan ini mengembalikan akun token USDC milik dompet pada akhir slot 445,000,000:curl https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "getHistoricalTokenAccountsByOwner",
"params": [
"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
{ "slot": 445000000 },
{ "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "encoding": "jsonParsed" }
]
}'
Lakukan paginasi pada semua akun token
Hasil diurutkan berdasarkan mint, lalu berdasarkan alamat akun token. Setiap respons mengembalikanvalue.accounts dan value.paginationKey, yaitu kursor dalam format <mint>:<tokenAccount>. Teruskan kembali dalam permintaan berikutnya hingga nilainya menjadi null.
Sebuah halaman dapat berisi sedikit data, atau bahkan kosong, tetapi tetap menyertakan
paginationKey. Hanya paginationKey dengan nilai null yang berarti Anda telah mencapai akhir.slot secara eksplisit saat Anda melakukan paginasi. Jika Anda menghilangkannya, setiap halaman membaca slot terindeks terbaru sehingga halaman dapat berasal dari waktu yang berbeda.
const url = `https://mainnet.helius-rpc.com/?api-key=${process.env.HELIUS_API_KEY}`;
async function getTokenAccountsAt(owner: string, slot: number) {
const accounts = [];
let paginationKey: string | null = null;
do {
const response = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: "1",
method: "getHistoricalTokenAccountsByOwner",
params: [
owner,
{ slot },
{ encoding: "jsonParsed", limit: 1000, ...(paginationKey && { paginationKey }) },
],
}),
});
const { result, error } = await response.json();
if (error) throw new Error(`${error.code}: ${error.message}`);
accounts.push(...result.value.accounts);
paginationKey = result.value.paginationKey;
} while (paginationKey);
return accounts;
}
const tokenAccounts = await getTokenAccountsAt("86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY", 445000000);
Baca respons
Setiap entri dalamvalue.accounts memiliki pubkey milik akun token dan objek account. Objek akun memiliki bidang yang sama seperti getAccountInfo, ditambah lastUpdatedAt:
lastUpdatedAt.slotdanlastUpdatedAt.transactionIndexmengidentifikasi penulisan yang menghasilkan status ini.lastUpdatedAt.slotsebesar 444,959,999 dengantransactionIndexbernilainullberarti akun token belum berubah sejak cakupan riwayat dimulai.context.slotadalah slot terbaru yang telah diindeks Helius saat melayani permintaan, bukan slot yang Anda kueri.
Kesalahan
| Kode | Arti |
|---|---|
-32018 | Slot berada sebelum cakupan riwayat dimulai (slot 444,959,999) |
-32004 | Slot lebih baru daripada yang diizinkan oleh tingkat komitmen yang diminta. Gunakan confirmed atau kueri slot yang lebih lama |
-32602 | Parameter tidak valid, seperti menggunakan mint dan programId sekaligus, programId yang bukan program token, atau paginationKey dengan mint yang tidak cocok dengan mint |
-32601 | Metode tidak ditemukan. Panggil endpoint mainnet Helius atau Gatekeeper Anda; metode ini tidak tersedia di devnet |
Metode terkait
Historical Accounts Guide
Cara kerja posisi, cakupan, dan lastUpdatedAt untuk metode akun historis
getHistoricalAccountInfo
Baca satu akun pada slot sebelumnya
getTransactionsForAddress
Temukan slot dan transactionIndex dari transaksi yang ingin Anda periksa
getTokenAccountsByOwnerV2
Lakukan paginasi pada akun token dompet saat ini
Parameter Permintaan
Alamat dompet yang memiliki akun token, dengan pengodean Base-58. Teruskan dompet pemilik, bukan akun token.
Slot tempat status akan dibaca. Mengembalikan akun sebagaimana keadaannya pada akhir slot ini. Slot paling awal yang didukung adalah 444959999, yaitu status pada awal epoch 1030. Jika dihilangkan, membaca slot terindeks terbaru yang dibatasi pada tingkat komitmen yang diminta.
Posisi transaksi dalam slot. Mengembalikan status akun tepat setelah transaksi tersebut dieksekusi, bukan pada akhir slot. Memerlukan slot.
Hanya kembalikan akun token yang dimiliki oleh program token ini. Tidak dapat digabungkan dengan mint.
TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DATokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
Format pengodean untuk data akun. Dengan jsonParsed, jumlah token menggunakan nilai desimal mint pada posisi yang diminta. base58 dan biner tidak didukung.
base64base64+zstdjsonParsed
Kursor dari paginationKey respons sebelumnya, dalam format
<mint>:<tokenAccount>. Jika Anda juga menetapkan mint, mint kursor harus cocok dengannya.Otorisasi
Kunci API Helius Anda. Anda bisa mendapatkannya secara gratis di dasbor.
Body
application/json
Larik yang berisi alamat dompet pemilik, objek kueri opsional yang memilih posisi dalam riwayat, dan objek konfigurasi opsional.
Required array length:
1 - 3 elementsAlamat dompet dengan pengodean base-58 yang memiliki akun token. Masukkan dompet pemilik, bukan akun token.
Contoh:
"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY"
Apakah halaman ini membantu?
⌘I
getHistoricalTokenAccountsByOwner
curl --request POST \
--url 'https://mainnet.helius-rpc.com/?api-key=' \
--header 'Content-Type: application/json' \
--data '
{
"jsonrpc": "2.0",
"id": "1",
"method": "getHistoricalTokenAccountsByOwner",
"params": [
"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
{
"slot": 445000000
},
{
"encoding": "jsonParsed",
"limit": 2
}
]
}
'import requests
url = "https://mainnet.helius-rpc.com/?api-key="
payload = {
"jsonrpc": "2.0",
"id": "1",
"method": "getHistoricalTokenAccountsByOwner",
"params": [
"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
{ "slot": 445000000 },
{
"encoding": "jsonParsed",
"limit": 2
}
]
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
jsonrpc: '2.0',
id: '1',
method: 'getHistoricalTokenAccountsByOwner',
params: [
'86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY',
{slot: 445000000},
{encoding: 'jsonParsed', limit: 2}
]
})
};
fetch('https://mainnet.helius-rpc.com/?api-key=', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://mainnet.helius-rpc.com/?api-key=",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'jsonrpc' => '2.0',
'id' => '1',
'method' => 'getHistoricalTokenAccountsByOwner',
'params' => [
'86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY',
[
'slot' => 445000000
],
[
'encoding' => 'jsonParsed',
'limit' => 2
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://mainnet.helius-rpc.com/?api-key="
payload := strings.NewReader("{\n \"jsonrpc\": \"2.0\",\n \"id\": \"1\",\n \"method\": \"getHistoricalTokenAccountsByOwner\",\n \"params\": [\n \"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY\",\n {\n \"slot\": 445000000\n },\n {\n \"encoding\": \"jsonParsed\",\n \"limit\": 2\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://mainnet.helius-rpc.com/?api-key=")
.header("Content-Type", "application/json")
.body("{\n \"jsonrpc\": \"2.0\",\n \"id\": \"1\",\n \"method\": \"getHistoricalTokenAccountsByOwner\",\n \"params\": [\n \"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY\",\n {\n \"slot\": 445000000\n },\n {\n \"encoding\": \"jsonParsed\",\n \"limit\": 2\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://mainnet.helius-rpc.com/?api-key=")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"jsonrpc\": \"2.0\",\n \"id\": \"1\",\n \"method\": \"getHistoricalTokenAccountsByOwner\",\n \"params\": [\n \"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY\",\n {\n \"slot\": 445000000\n },\n {\n \"encoding\": \"jsonParsed\",\n \"limit\": 2\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"jsonrpc": "2.0",
"id": "1",
"result": {
"context": {
"slot": 468129571
},
"value": {
"accounts": [
{
"pubkey": "EKyGnXReqmmXyqBHmMjV2CKCLafJS47xyhXXZ5WuFMxD",
"account": {
"lamports": 531589475273,
"owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"data": [
"<string>"
],
"executable": false,
"rentEpoch": 123,
"space": 82,
"lastUpdatedAt": {
"slot": 444999837,
"transactionIndex": 700
}
}
}
],
"paginationKey": "11112zAgXhc6hGfdfr5anSY91mq7Cs4HHpSVEQc4ASG:EKyGnXReqmmXyqBHmMjV2CKCLafJS47xyhXXZ5WuFMxD"
}
}
}{
"jsonrpc": "2.0",
"error": {
"code": -32602,
"message": "Parameter tidak valid"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32001,
"message": "Tidak sah"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32005,
"message": "Terlalu banyak permintaan"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32603,
"message": "Kesalahan internal"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32002,
"message": "Layanan tidak tersedia"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32003,
"message": "Waktu tunggu gateway habis"
},
"id": "1"
}