> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Solana DAS API Paginação: Consulta Eficiente de Grandes Conjuntos de Dados

> Paginação baseada em páginas e keyset para a Solana DAS API. Itere grandes conjuntos de dados de forma eficiente com estratégias baseadas em cursor e intervalo e consultas paralelas.

## Visão Geral

Os métodos da DAS API retornam até 1.000 registros por chamada. Para recuperar mais, você usa paginação — fazendo várias chamadas e percorrendo páginas de dados. A Helius suporta dois mecanismos: paginação baseada em páginas e em keyset.

A paginação baseada em páginas é a maneira mais simples de começar. A paginação por keyset é para usuários avançados que desejam consultar grandes conjuntos de dados (500k+) de forma eficiente.

## Quando usar isto

* **Baseada em páginas** — visualizações estáticas, painéis e a maioria das consultas diárias. Fácil e intuitiva.
* **Keyset (cursor ou intervalo)** — grandes conjuntos de dados (coleções inteiras, 500k+ ativos) onde a navegação baseada em páginas se torna lenta.
* **Keyset paralelo** — a opção mais rápida para escanear uma coleção inteira, particionando o intervalo de endereços.

## Opções de ordenação

Você pode ordenar os resultados por diferentes campos usando o campo `sortBy`:

| Valor           | Ordena por                          | Recomendado? |
| --------------- | ----------------------------------- | ------------ |
| `id`            | ID do ativo em binário (padrão)     | Sim          |
| `created`       | Data de criação do ativo            | Sim          |
| `recent_action` | Data da última atualização do ativo | Não          |
| `none`          | Sem ordenação                       | Não          |

Desativar a ordenação gera os resultados mais rápidos, mas como os dados estão desordenados, você pode obter resultados inconsistentes ao paginar.

## Paginação baseada em páginas

Você especifica o número da página e o número de itens por página. Para avançar para a próxima página, incremente o número da página. Isso é fácil, intuitivo e rápido para a maioria dos casos de uso.

<Accordion title="Exemplo">
  ```javascript theme={"system"}
  const url = `https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY`

  const example = async () => {
      let page = 1;
      let items = [];
      while (true) {
          const response = await fetch(url, {
              method: 'POST',
              headers: {
                  'Content-Type': 'application/json',
              },
              body: JSON.stringify({
                  jsonrpc: '2.0',
                  id: 'my-id',
                  method: 'searchAssets',
                  params: {
                      grouping: ['collection', '5PA96eCFHJSFPY9SWFeRJUHrpoNF5XZL6RrE1JADXhxf'],
                      page: page,
                      limit: 1000,
                      sortBy: { sortBy: 'id', sortDirection: 'asc' },
                  },
              }),
          });
          const { result } = await response.json();
          if (result.items.length == 0) {
              console.log('No items remaining');
              break;
          } else {
              console.log(`Processing results from page ${page}`);
              items.push(...result.items);
              page += 1;
          }
      }
      console.log(`Got ${items.length} total items`);
  };
  example();
  ```
</Accordion>

Usar páginas requer que o banco de dados percorra todos os itens até atingir a próxima página. Por exemplo, se você solicitar a página 100 com tamanho de página de 1.000, o banco de dados deve percorrer os primeiros 1M de registros antes de retornar seus dados. Por isso, a paginação baseada em páginas não é recomendada para grandes conjuntos de dados — a paginação por keyset é muito mais adequada para esses workloads.

## Paginação por keyset

Você define as páginas fornecendo condições que filtram o conjunto de dados. Por exemplo, "me forneça todos os ativos com ID > X, mas com ID \< Y." Você percorre todo o conjunto de dados modificando X ou Y a cada chamada. Há dois métodos de paginação por keyset:

1. **Baseado em cursor** — mais fácil de usar, mas menos flexível.
2. **Baseado em intervalo** — mais complexo, mas muito flexível.

A paginação por keyset é suportada apenas quando a ordenação é feita por `id`.

### Baseado em cursor

Uma consulta DAS sem nenhum parâmetro de paginação retorna um cursor. Passe o cursor de volta para a DAS API para continuar de onde parou.

<Accordion title="Exemplo">
  ```typescript theme={"system"}
  const url = `https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY`

  const example = async () => {
      let items = [];
      let cursor;
      while (true) {
          let params = {
              grouping: ['collection', '5PA96eCFHJSFPY9SWFeRJUHrpoNF5XZL6RrE1JADXhxf'],
              limit: 1000,
              sortBy: { sortBy: 'id', sortDirection: 'asc' },
          } as any;
          if (cursor != undefined) {
              params.cursor = cursor;
          }
          const response = await fetch(url, {
              method: 'POST',
              headers: {
                  'Content-Type': 'application/json',
              },
              body: JSON.stringify({
                  jsonrpc: '2.0',
                  id: 'my-id',
                  method: 'searchAssets',
                  params: params,
              }),
          });
          const { result } = await response.json();
          if (result.items.length == 0) {
              console.log('No items remaining');
              break;
          } else {
              console.log(`Processing results for cursor ${cursor}`);
              cursor = result.cursor;
              items.push(...result.items);
          }
      }
      console.log(`Got ${items.length} total items`);
  };
  example();
  ```
</Accordion>

No momento da escrita, o cursor é o último ID de ativo da resposta; no entanto, o design do cursor é flexível e pode suportar qualquer string.

### Baseado em intervalo

Para consultar em um intervalo, especifique `before` e/ou `after`. A consulta é essencialmente "me forneça todos os ativos após X, mas antes de Y." Você percorre o conjunto de dados atualizando o parâmetro `before` ou `after` em cada chamada.

<Accordion title="Exemplo">
  ```javascript theme={"system"}
  const url = `https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY`

  const example = async () => {
      // Two NFTs from the Tensorian collection.
      // The "start" item has a lower asset ID (in binary) than the "end" item.
      // We will traverse in ascending order.
      let start = '6CeKtAYX5USSvPCQicwFsvN4jQSHNxQuFrX2bimWrNey';
      let end = 'CzTP4fUbdfgKzwE6T94hsYV7NWf1SzuCCsmJ6RP1xsDw';
      let sortDirection = 'asc';
      let after = start;
      let before = end;
      let items = [];

      while (true) {
          const response = await fetch(url, {
              method: 'POST',
              headers: {
                  'Content-Type': 'application/json',
              },
              body: JSON.stringify({
                  jsonrpc: '2.0',
                  id: 'my-id',
                  method: 'searchAssets',
                  params: {
                      grouping: ['collection', '5PA96eCFHJSFPY9SWFeRJUHrpoNF5XZL6RrE1JADXhxf'],
                      limit: 1000,
                      after: after,
                      before: before,
                      sortBy: { sortBy: 'id', sortDirection: sortDirection },
                  },
              }),
          });
          const { result } = await response.json();
          if (result.items.length == 0) {
              console.log('No items remaining');
              break;
          } else {
              console.log(`Processing results with (after: ${after}, before: ${before})`);
              after = result.items[result.items.length - 1].id;
              items.push(...result.items);
          }
      }
      console.log(`Got ${items.length} total items`);
  };
  example();
  ```
</Accordion>

## Consulta paralela com keysets (avançado)

Usuários avançados que consultam grandes conjuntos de dados (por exemplo, coleções inteiras de NFTs comprimidas) devem usar a paginação baseada em keyset para desempenho. O exemplo a seguir mostra como consultar em paralelo, particionando o intervalo de endereços Solana e usando os parâmetros `before`/`after`. Este método é rápido, eficiente e seguro.

<Accordion title="Exemplo">
  No exemplo abaixo, escaneamos toda a coleção Tensorian (\~10k registros). Ele particiona o espaço de endereços Solana em 8 intervalos e escaneia esses intervalos simultaneamente. Isso é muito mais rápido do que as outras abordagens.

  ```typescript theme={"system"}
  import base58 from 'bs58';

  const url = `https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY`

  const main = async () => {
      let numParitions = 8;
      let partitons = partitionAddressRange(numParitions);
      let promises = [];
      for (const [i, partition] of partitons.entries()) {
          let [s, e] = partition;
          let start = bs58.encode(s);
          let end = bs58.encode(e);
          console.log(`Parition: ${i}, Start: ${start}, End: ${end}`);

          let promise: Promise<number> = new Promise(async (resolve, reject) => {
              let current = start;
              let totalForPartition = 0;
              while (true) {
                  const response = await fetch(url, {
                      method: 'POST',
                      headers: {
                          'Content-Type': 'application/json',
                      },
                      body: JSON.stringify({
                          jsonrpc: '2.0',
                          id: 'my-id',
                          method: 'searchAssets',
                          params: {
                              grouping: ['collection', '5PA96eCFHJSFPY9SWFeRJUHrpoNF5XZL6RrE1JADXhxf'],
                              limit: 1000,
                              after: current,
                              before: end,
                              sortBy: { sortBy: 'id', sortDirection: 'asc' },
                          },
                      }),
                  });
                  const { result } = await response.json();
                  totalForPartition += result.items.length;
                  console.log(`Found ${totalForPartition} total items in parition ${i}`);
                  if (result.items.length == 0) {
                      break;
                  } else {
                      current = result.items[result.items.length - 1].id;
                  }
              }
              resolve(totalForPartition);
          });
          promises.push(promise);
      }
      let results = await Promise.all(promises);
      let total = results.reduce((a, b) => a + b, 0);
      console.log(`Got ${total} total items`);
  };

  // Function to convert a BigInt to a byte array
  function bigIntToByteArray(bigInt: bigint): Uint8Array {
      const bytes = [];
      let remainder = bigInt;
      while (remainder > 0n) {
          // use 0n for bigint literal
          bytes.unshift(Number(remainder & 0xffn));
          remainder >>= 8n;
      }
      while (bytes.length < 32) bytes.unshift(0); // pad with zeros to get 32 bytes
      return new Uint8Array(bytes);
  }

  function partitionAddressRange(numPartitions: number) {
      let N = BigInt(numPartitions);

      // Largest and smallest Solana addresses in integer form.
      // Solana addresses are 32 byte arrays.
      const start = 0n;
      const end = 2n ** 256n - 1n;

      // Calculate the number of partitions and partition size
      const range = end - start;
      const partitionSize = range / N;

      // Calculate partition ranges
      const partitions: Uint8Array[][] = [];
      for (let i = 0n; i < N; i++) {
          const s = start + i * partitionSize;
          const e = i === N - 1n ? end : s + partitionSize;
          partitions.push([bigIntToByteArray(s), bigIntToByteArray(e)]);
      }

      return partitions;
  }

  main();
  ```
</Accordion>

## Próximos passos

<CardGroup cols={3}>
  <Card title="Procurar Ativos" icon="magnifying-glass" href="/docs/pt-BR/das/search">
    Filtre ativos por proprietário, coleção e tipo de token.
  </Card>

  <Card title="Obter Ativos (NFTs)" icon="image" href="/docs/pt-BR/das/get-nfts">
    Recupere NFTs, coleções, edições e provas.
  </Card>

  <Card title="Referência da DAS API" icon="code" href="/docs/pt-BR/api-reference/das">
    Esquemas completos para cada método DAS.
  </Card>
</CardGroup>
