Contas históricas
getHistoricalTokenAccountsByOwner
Liste as contas SPL Token e Token-2022 que pertenciam a uma carteira Solana em um slot anterior ou logo após uma transação específica, com filtros de mint e paginação.
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": "Parâmetros inválidos"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32001,
"message": "Não autorizado"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32005,
"message": "Muitas solicitações"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32603,
"message": "Erro interno"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32002,
"message": "Serviço indisponível"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32003,
"message": "Tempo limite do gateway"
},
"id": "1"
}getHistoricalTokenAccountsByOwner está em Beta. Os parâmetros, preços, formatos de resposta e cobertura de dados podem mudar.Visão geral
getHistoricalTokenAccountsByOwner retorna as contas SPL Token e Token-2022 que pertenciam a uma carteira em um slot anterior ou imediatamente após uma transação específica nesse slot. É um método RPC exclusivo da Helius. O método getTokenAccountsByOwner padrão retorna apenas o estado atual.
Com a codificação jsonParsed, os valores dos tokens usam as casas decimais de cada mint na posição solicitada. Assim, os saldos refletem o que a carteira mantinha naquele momento.
O histórico está disponível a partir do slot 444.959.999 (7 de setembro de 2026), que corresponde ao estado no início da época 1030.
getHistoricalTokenAccountsByOwner está disponível na mainnet para planos Business ou superiores e custa 0 créditos por chamada durante o período beta. Os preços estão sujeitos a alterações.
Diferenças em relação a getTokenAccountsByOwner
- O filtro de mint ou programa é opcional. Sem um filtro, você recebe todas as contas de token que pertenciam à carteira. Para restringir os resultados, defina
mintouprogramIdno objeto de configuração (o terceiro parâmetro), mas não ambos. - O segundo parâmetro é o objeto de consulta que seleciona a posição no histórico, e não um filtro de mint ou programa.
result.valueé um objeto comaccountsepaginationKey, e não um array.
Escolha uma posição no histórico
O segundo parâmetro é um objeto de consulta:- Omitido ou
{}: o slot indexado mais recente, limitado pelo nível de confirmação solicitado. { "slot": 445000000 }: o final do slot 445.000.000.{ "slot": 445000000, "transactionIndex": 10 }: imediatamente após a execução da transação no índice 10 desse slot.
Exemplo de solicitação
Esta solicitação retorna as contas de token USDC da carteira no final do 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" }
]
}'
Percorra todas as contas de token com paginação
Os resultados são ordenados primeiro por mint e depois pelo endereço da conta de token. Cada resposta retornavalue.accounts e value.paginationKey, um cursor no formato <mint>:<tokenAccount>. Envie-o novamente na próxima solicitação até que seja null.
Uma página pode ter poucos resultados ou até estar vazia e ainda incluir um
paginationKey. Somente um paginationKey com valor null significa que você chegou ao fim.slot explícito ao paginar. Se você o omitir, cada página lerá o slot indexado mais recente. Portanto, as páginas poderão vir de momentos diferentes.
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);
Leia a resposta
Cada entrada emvalue.accounts contém o pubkey da conta de token e um objeto account. O objeto da conta tem os mesmos campos que getAccountInfo, além de lastUpdatedAt:
lastUpdatedAt.slotelastUpdatedAt.transactionIndexidentificam a gravação que produziu esse estado.- Um
lastUpdatedAt.slotde 444.959.999 com umtransactionIndexde valornullsignifica que a conta de token não mudou desde o início da cobertura do histórico. context.sloté o slot mais recente que a Helius havia indexado quando processou a solicitação, e não o slot consultado.
Erros
| Código | Significado |
|---|---|
-32018 | O slot é anterior ao início da cobertura do histórico (slot 444.959.999) |
-32004 | O slot é mais recente do que o nível de confirmação solicitado permite. Use confirmed ou consulte um slot mais antigo |
-32602 | Parâmetros inválidos, como usar mint e programId ao mesmo tempo, informar um programId que não seja um programa de token ou usar um paginationKey cujo mint não corresponda a mint |
-32601 | Método não encontrado. Chame seu endpoint da Helius na mainnet ou do Gatekeeper; o método não está disponível na devnet |
Métodos relacionados
Historical Accounts Guide
Entenda como posições, cobertura e lastUpdatedAt funcionam nos métodos de contas históricas
getHistoricalAccountInfo
Leia uma única conta em um slot anterior
getTransactionsForAddress
Encontre o slot e o transactionIndex das transações que você deseja inspecionar
getTokenAccountsByOwnerV2
Percorra as contas de token atuais de uma carteira com paginação
Parâmetros da solicitação
Endereço codificado em Base-58 da carteira à qual pertenciam as contas de token. Informe a carteira do proprietário, e não uma conta de token.
Slot no qual o estado deve ser lido. Retorna a conta como estava no final desse slot. O primeiro slot compatível é 444959999, que corresponde ao estado no início da época 1030. Quando omitido, lê o slot indexado mais recente, limitado pelo nível de confirmação solicitado.
Posição de uma transação dentro do slot. Retorna o estado da conta imediatamente após a execução dessa transação, em vez do estado no final do slot. Requer slot.
Retorna apenas contas de token pertencentes a este programa de token. Não pode ser combinado com mint.
TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DATokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
Formato de codificação dos dados da conta. Com jsonParsed, os valores dos tokens usam as casas decimais do mint na posição solicitada. base58 e binary não são compatíveis.
base64base64+zstdjsonParsed
Retorna apenas uma parte dos dados de cada conta. Aplica-se às codificações base64 e base64+zstd.
Cursor do paginationKey da resposta anterior, no formato
<mint>:<tokenAccount>. Quando você também define mint, o mint do cursor deve corresponder a ele.Autorizações
Sua chave de API da Helius. Você pode obter uma gratuitamente no painel.
Corpo
application/json
Matriz que contém o endereço da carteira proprietária, um objeto de consulta opcional que seleciona a posição no histórico e um objeto de configuração opcional.
Required array length:
1 - 3 elementsEndereço codificado em base 58 da carteira que possuía as contas de token. Informe a carteira proprietária, não uma conta de token.
Exemplo:
"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY"
Esta página foi útil?
⌘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": "Parâmetros inválidos"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32001,
"message": "Não autorizado"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32005,
"message": "Muitas solicitações"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32603,
"message": "Erro interno"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32002,
"message": "Serviço indisponível"
},
"id": "1"
}{
"jsonrpc": "2.0",
"error": {
"code": -32003,
"message": "Tempo limite do gateway"
},
"id": "1"
}