Ir diretamente para o conteúdo principal

Criar um sistema de acompanhamento de carteiras em tempo real no Hyperliquid

Atualizado em
22 de abril de 2026

17 minutos de leitura

Visão geral

Como trader ativo na Hyperliquid, é essencial dispor de um sistema de acompanhamento de carteira abrangente para monitorizar as suas posições, PnL e utilização de margem em tempo real. Este guia mostra-lhe como criar um poderoso sistema de acompanhamento de carteira que monitoriza qualquer carteira Hyperliquid utilizando o endpoint de informação da Hyperliquid da Quicknode. Para além de criar uma ferramenta de negociação útil, este tutorial irá também esclarecer como os dados do HyperCore são obtidos, estruturados e utilizados para a criação da aplicação. A aplicação apresenta:


  • Acompanhamento de posições em tempo real - Atualizações em tempo real sobre posições perpétuas com PnL
  • Análise da carteira - Valor da conta, utilização da margem e métricas de risco
  • Gestão do cofre - Acompanhar o valor do cofre e os horários de encerramento
  • Spot Holdings - Monitorizar saldos de tokens e valores em USD
  • Pesquisar qualquer carteira - Alternar entre diferentes contas de negociação

Página Principal


Página do Painel de Controlo

O que irá fazer

Crie um sistema completo de acompanhamento de carteiras em 4 fases:


  1. Configurar um ponto de acesso Quicknode e uma conta Supabase
  2. Configurar o esquema da sua base de dados
  3. Criação de um indexador que recupera dados do HyperCore a cada 500 ms
  4. Criação de um painel de controlo com bibliotecas modernas de interface do utilizador que apresente dados de negociação em tempo real

O que vai precisar


  • Quicknode Hyperliquid Endpoint
  • Conta Supabase
  • Node.js v20+, npm e um editor de código
  • Conceitos básicos de React/TypeScript e API REST
  • Conceitos básicos de SQL
  • Opcional: Experiência de negociação contínua com liquidez extrema
Por que escolher um Endpoint da Quicknode?

A Quicknode disponibiliza pontos de acesso dedicados à API do Hyperliquid, que eliminam a necessidade de executar o seu próprio nó:

  • Terminais pré-configurados que não requerem configuração
  • Gere a gestão de ligações e a transição para o sistema de reserva
  • Acesso direto aos dados do HyperCore sem infraestrutura adicional

Visão geral da arquitetura

O sistema de acompanhamento de carteiras é composto por três componentes que comunicam entre si através de uma base de dados PostgreSQL. O indexador obtém dados do Hyperliquid, armazena-os na base de dados e o front-end consulta a base de dados para os apresentar.

Componentes da pilha tecnológica

  • Frontend: React + TypeScript + Tailwind CSS + shadcn/ui e Radix UI

    • Apresenta dados de negociação numa interface adaptável
    • Verifica a base de dados de sondagens a cada 1000 ms para ver se há atualizações
    • Gere a troca de carteiras através de pedidos à base de dados
  • Backend: indexador Node.js com intervalo de sondagem de 500 ms

    • Recolhe dados de 5 pontos de acesso diferentes do Hyperliquid
    • Armazena dados no PostgreSQL com um tratamento adequado da precisão
    • Gere os pedidos de mudança de carteira a partir do front-end
Considerações sobre as sondagens

Este guia utiliza intervalos de sondagem agressivos (500 ms para o indexador, 1000 ms para o front-end) para demonstrar atualizações em tempo real. Pode ajustar estes intervalos, se necessário:

  • Frontend: src/Dashboard.tsx linhas 260-264 - Alterar o 1000 valor em:
    const interval = setInterval(async () => {
    await fetchData(currentWallet);
    }, 1000);
  • Indexador: src/indexer/indexer.ts linhas 623-630 - Alterar o 500 valor em:
    setInterval(async () => {
    await indexer.checkForWalletSwitch();
    await indexer.indexData();
    }, 500);

Acompanhe a utilização do Quicknode e do Supabase para otimizar os custos.

  • Base de dados: Supabase PostgreSQL

    • Armazena os dados comerciais em 6 tabelas com precisão financeira (DECIMAL tipos)
    • Gere a comunicação entre o front-end e o indexador através de pedidos_de_mudança_de_carteira tabela
    • Utiliza restrições únicas para evitar entradas duplicadas
  • Fonte dos dados: Hiperlíquido informações ponto final através do Quicknode

    • Fornece dados da conta, posições, saldos em cofre, saldos à vista e delegações
    • Devolve dados no formato JSON com números representados por cadeias de caracteres para indicar a precisão
    • Acedido através de pedidos HTTP POST com o parâmetro «endereço da carteira»
                    ┌─────────────────┐
│ Perp Trader │
└─────────┬───────┘
│ 1. Introduza o endereço da carteira

┌─────────────────┐
│ Painel do React │◄─────────────────┐
└─────────┬───────┘ │
│ 2. Armazenar pedido │ 6. Ler e apresentar dados
▼ │
┌─────────────────┐ │
│ Supabase │◄─────────────────┤
│ PostgreSQL │ │
└─────────┬───────┘ │
│ 3. Detetar pedido │ 5. Armazenar dados
▼ │
┌─────────────────┐ │
│ Indexador │──────────────────┘
│ (sondagem a cada 500 ms) │
└─────────┬───────┘
│ 4. Obter dados do HyperCore

┌─────────────────┐
│ Quicknode │
│ Hyperliquid │
│ Endpoint │
└─────────────────┘

Fluxo do processo de candidatura

1.ª Pesquisa na carteira:


  1. O utilizador acede à carteira → O front-end valida e armazena o pedido na base de dados
  2. O indexador deteta o pedido (verifica a cada 500 ms) → Muda para a nova carteira
  3. Início da recolha de dados → Recolhe dados de 5 pontos de acesso especificados de forma independente e armazena-os na base de dados
  4. A base de dados de sondagens do front-end (a cada 1000 ms) → A interface do utilizador é atualizada com dados recentes obtidos do indexador

2.ª Pesquisa na carteira e muito mais:


  1. O utilizador introduz uma nova carteira → O frontend executa chamadas para limpar quaisquer dados da carteira anterior e ordena ao indexador que mude para a nova carteira
  2. O indexador deteta um novo pedido → Muda imediatamente para a nova carteira e começa a recolher dados utilizando o endereço da nova carteira
  3. Atualizações de dados em tempo real → O painel começa a recolher as novas posições e métricas da carteira

Estrutura do projeto

O projeto segue uma arquitetura simples e modular que separa as responsabilidades entre a recolha de dados, os componentes da interface do utilizador e a lógica de negócio. Esta estrutura torna a base de código fácil de manter e permite a fácil ampliação das funcionalidades.

Discriminação do diretório

├── src/
│ ├── indexer/
│ │ ├── indexer.ts # Orquestração principal do indexador e gestão da carteira
│ │ └── apicalls.ts # Consultas ao ponto de acesso de informações do Hyperliquid
│ ├── components/
│ │ ├── ui/ # Componentes shadcn/ui (Botão, Campo de entrada, Cartão, etc.)
│ │ └── dashboard/ # Componentes do painel de controlo (WalletHeader, PortfolioMetrics, etc.)
│ ├── shared/
│ │ ├── types.ts # Interfaces e tipos do TypeScript
│ │ ├── utils.ts # Formatação, cálculos e funções utilitárias
│ │ ├── constants.ts # Constantes da interface do utilizador para o painel de controlo
│ │ └── supabase.ts # Instância do cliente Supabase para acesso front-end
│ ├── Dashboard.tsx # Lógica principal do painel de controlo
│ └── main.tsx
├── supabase/
│ └── schema.sql # Esquema completo da base de dados
├── package.json
└── .env

Execução do projeto

Passo 1: Clonar o repositório

Primeiro, clone o repositório do projeto e aceda ao diretório do projeto:

git clone https://github.com/quiknode-labs/qn-guide-examples.git
cd qn-guide-examples/sample-dapps/hyperliquid-portfolio-tracker

Passo 2: Configurar o ficheiro de ambiente

Crie o seu .env ficheiro, executando o comando:

cp .env.example .env

Passo 3: Configuração da base de dados Supabase

Crie uma nova conta Supabase ou inicie sessão na sua conta Supabase existente no site da Supabase.

Crie um novo projeto e, em seguida, clique no botão «Ligar».

DB Connect


Na secção «App Frameworks», selecione «React» e altere o utilizando campo para o Vite. Copie o VITE_SUPABASE_URL e VITE_SUPABASE_ANON_KEY valores e adicione-os ao seu .env ficheiro.

DB selectReact

Por último, aceda ao Editor SQL no canto superior direito e cole o conteúdo do schema.sql ficheiro e, em seguida, clique em «Executar». Isto irá criar todas as tabelas e funções necessárias para armazenar e recuperar os dados para o front-end.

Editor de SQL

Passo 4: Configuração do Quicknode

Crie a sua versão de avaliação gratuita Conta Quicknode, em seguida, crie o seu primeiro ponto de extremidade RPC do Hyperliquid e cole-o no seu .env ficheiro.

informações

Certifique-se de que remove o existente /evm e acrescentar /info no final do URL do seu ponto de extremidade Quicknode para aceder aos pontos de extremidade de informação do Hyperliquid.

Passo 5: Iniciar a aplicação

Assim que as tabelas estiverem criadas e o seu ambiente estiver configurado, pode iniciar o projeto executando os seguintes comandos no diretório raiz:

npm install && npm run dev:both

Isto irá executar tanto a aplicação front-end como o indexador.

Quando o indexador começar a funcionar, ficará à espera que introduza um endereço de carteira válido:

Início do indexador

Abra a sua página front-end na URL do localhost e clique no botão «carteira de demonstração» para obter um endereço de carteira de exemplo:

Revista de carteiras

Após procurar uma carteira, o indexador começará a recolher dados relativos a esse endereço a cada 500 ms:

Indexador em execução

O painel de controlo irá apresentar estatísticas em tempo real relativas à carteira:

Página do Painel de Controlo

Agora tem acesso ao valor da conta, às posições ativas e a outros dados de negociação em tempo real.

Resolução de problemas

Ao trabalhar com o indexador, poderá deparar-se com os seguintes problemas durante a configuração ou em tempo de execução:


  • O Indexer deixa de responder
  • Não aparecem dados após a pesquisa na carteira
  • Parei acidentalmente o indexador

Solução:

Reinicie o indexador executando o seguinte comando:

npm run dev:indexer

Nesse caso, tente pesquisar novamente, introduzindo um endereço de carteira válido.

Análise aprofundada do código-fonte

Agora que já tem o sistema de acompanhamento da carteira a funcionar, vamos explorar como funciona por dentro. Esta secção analisa em pormenor os três componentes principais que tornam possível o acompanhamento da carteira em tempo real:

O Indexador - Compatível com o Hyperliquid informações ponto final através de apicalls.ts, deteta pedidos de mudança de carteira e coordena a recolha de dados de 5 pontos de acesso Hyperliquid diferentes a cada 500 ms.

O Esquema e a Base de Dados - Apresenta as estruturas das tabelas do PostgreSQL que armazenam dados de negociação com precisão financeira, incluindo o mecanismo de coordenação da comunicação entre o front-end e o indexador.

O Painel de Controlo (Frontend) — Abrange a gestão de estado no React, a consulta da base de dados em tempo real, a validação de endereços de carteira e a interface de utilizador que apresenta dados de negociação em tempo real.

O Indexador

O indexador funciona como um processo Node.js independente que consulta o ponto de extremidade do Quicknode a cada 500 ms. Recolhe os dados de transações relativos ao endereço atual da carteira e armazena-os na base de dados. O indexador aguarda os pedidos de mudança de carteira provenientes do front-end e gere o isolamento do processo através de um ficheiro de bloqueio.

Detecção de alterações na carteira

O indexador consulta o pedidos_de_mudança_de_carteira verificar a tabela a cada 500 ms para detetar mudanças de carteira no front-end, utilizando campos de estado para evitar condições de corrida durante o processo de mudança.

Hiperlíquido informações Integração de terminais

O indexador utiliza o HyperliquidAPI aula de apicalls.ts para comunicar com o ponto de extremidade Hyperliquid da Quicknode. Cada método da API segue um padrão consistente para obter diferentes tipos de dados de negociação:

// From apicalls.ts - Main account data fetching
async getClearinghouseState(walletAddress: string): Promise<ClearinghouseStateResponse> {
const payload = {
type: 'clearinghouseState',
user: walletAddress
};

const response = await fetch(QUICKNODE_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});

return await response.json();
}

O getUserVaultEquities() Este método segue a mesma estrutura, mas com tipo: 'userVaultEquities', demonstrando como cada ponto de extremidade requer apenas o endereço da carteira e o tipo de ponto de extremidade. Todos os métodos incluem um tratamento de erros abrangente e registo de eventos para a depuração de problemas relacionados com os dados de negociação.

Uma explicação aprofundada sobre o Indexador

O ciclo principal de indexação chama 5 diferentes informações endpoints e armazena os resultados em tabelas separadas da base de dados:

// From indexer.ts - Core data fetching and storage
const data = await hyperliquidAPI.getClearinghouseState(CURRENT_WALLET_ADDRESS);
const stateId = await this.storeClearinghouseState(data);

// Store positions with atomic replacement to prevent UI flickering
await this.storeAssetPositions(data.assetPositions, data.time);

// Fetch additional data types with error handling
try {
const rateLimitData = await hyperliquidAPI.getUserRateLimit(CURRENT_WALLET_ADDRESS);
await this.storeUserRateLimit(rateLimitData, timestamp);
} catch (error) {
console.log(`No rate limit data available for ${CURRENT_WALLET_ADDRESS}`);
}

O indexador lida com falhas em pontos finais individuais de forma adequada — se uma fonte de dados falhar, as outras continuam a funcionar normalmente.

O indexador utiliza um bloqueio baseado em ficheiros para impedir que várias instâncias sejam executadas em simultâneo:

// From indexer.ts - Lock file creation and process checking
function createLock(): boolean {
if (fs.existsSync(LOCK_FILE)) {
const { pid } = JSON.parse(fs.readFileSync(LOCK_FILE, 'utf8'));
try {
process.kill(pid, 0);
console.error(`❌ Another indexer is already running (PID: ${pid})`);
return false;
} catch (e) {
fs.unlinkSync(LOCK_FILE); // Remove stale lock
}
}

fs.writeFileSync(LOCK_FILE, JSON.stringify({ pid: process.pid }));
return true;
}

O indexador utiliza um ficheiro de bloqueio para impedir que várias instâncias sejam executadas em simultâneo, garantindo a consistência dos dados.

O esquema e a base de dados (Supabase)

Agora que já vimos como o indexador recolhe os dados, vamos analisar como esses dados são armazenados e estruturados. A base de dados PostgreSQL armazena os dados de negociação em 6 tabelas e gere a comunicação entre o frontend e o indexador. Cada tabela utiliza DECIMAL tipos para garantir a precisão financeira e restrições específicas para evitar entradas duplicadas.

Exemplos de estruturas de tabelas

Tabela de Posições de Ativos - Armazena posições de negociação perpétuas com precisão financeira:

-- From schema.sql - Core trading data storage
CREATE TABLE asset_positions (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
wallet_address TEXT NOT NULL,

coin TEXT NOT NULL, -- Asset symbol (e.g., 'BTC', 'ETH', 'SOL')
size DECIMAL(20, 5) NOT NULL, -- Position size: 20 digits total, 5 after decimal
leverage_type TEXT NOT NULL, -- 'cross' or 'isolated' margin mode
leverage_value INTEGER NOT NULL, -- Leverage multiplier (1x, 5x, 10x, etc.)

entry_price DECIMAL(20, 5), -- Average entry price with 5 decimal precision
position_value DECIMAL(20, 5), -- Current USD value of the position
unrealized_pnl DECIMAL(20, 5), -- Profit/loss before closing position
liquidation_price DECIMAL(20, 5), -- Price at which position gets liquidated
margin_used DECIMAL(20, 5), -- Amount of margin allocated to this position

timestamp BIGINT NOT NULL, -- Unix timestamp in milliseconds from HyperCore
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() -- Database insertion time
);

-- Unique constraint prevents duplicate positions per wallet-coin pair
ALTER TABLE asset_positions ADD CONSTRAINT unique_position_per_wallet
UNIQUE (wallet_address, coin);

O DECIMAL(20, 5) Este tipo permite um total de 20 dígitos, com 5 casas decimais.

Tabela de pedidos de mudança de carteira - Coordena a comunicação entre o front-end e o indexador:

-- Do ficheiro schema.sql - Coordenação entre o frontend e o indexador
CREATE TABLE wallet_switch_requests (
id UUID DEFAULT gen_random_uuid() PRIMÁRIO CHAVE,
endereço_da_carteira_solicitado TEXTO NÃO NULO, -- Endereço Ethereum (formato 0x)
estado TEXTO NÃO NULL PADRÃO 'pendente', -- Máquina de estados: pendente → em processamento → concluído
created_at TIMESTAMP WITH TIME ZONE DEFAULT AGORA()
);

-- Índice para consultas eficientes baseadas no estado, por indexador
CREATE INDEX idx_wallet_switch_requests_status ON wallet_switch_requests(status);

Esta tabela funciona como uma fila de mensagens entre o front-end do React e o indexador do Node.js. Quando um utilizador introduz um novo endereço de carteira, o front-end insere um «pendente» pedido. O indexador verifica se há «pendente» solicita a cada 500 ms, atualiza o estado para «processamento» para evitar condições de corrida, e, em seguida, efetua a mudança de carteira. A progressão do estado garante que apenas uma mudança de carteira ocorra de cada vez, mesmo que os utilizadores pesquisem rapidamente endereços diferentes.

O Painel de Controlo (Interface do Utilizador)

Com o indexador a recolher dados e a base de dados a armazená-los, a última peça do quebra-cabeças é a interface do utilizador. O front-end React consulta a base de dados a cada 1000 ms para obter dados de negociação atualizados e apresenta-os utilizando componentes modulares. Gere a alternância entre carteiras inserindo pedidos na base de dados e limpando imediatamente o estado local.

Visão geral

A arquitetura do painel de controlo assenta na gestão centralizada do estado, com uma composição modular de componentes:

// From Dashboard.tsx - Centralized state management
const [latestState, setLatestState] = useState<ClearinghouseState | null>(null);
const [positions, setPositions] = useState<AssetPosition[]>([]);
const [vaultEquities, setVaultEquities] = useState<UserVaultEquity[]>([]);
const [spotBalances, setSpotBalances] = useState<SpotBalance[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [hasInitialData, setHasInitialData] = useState(false);

O Painel de controlo O componente armazena todos os dados de negociação no estado do React e transmite-os aos componentes filhos como props. Este padrão simplifica a gestão do estado e facilita o acompanhamento do fluxo de dados durante a depuração.

Atualização automática por polling

O front-end consulta a base de dados a cada 1000 ms utilizando um setInterval loop com limpeza adequada:

// From Dashboard.tsx - Auto-refresh with cleanup
useEffect(() => {
if (currentWallet && hasStarted && hasInitialData) {
const interval = setInterval(async () => {
await fetchData(currentWallet);
}, 1000);
return () => clearInterval(interval);
}
}, [currentWallet, hasStarted, hasInitialData, fetchData]);

// Data freshness detection provides visual feedback
const isDataStale = latestState && (Date.now() - latestState.timestamp > 3000);

A recolha de dados inicia e termina automaticamente com base nas ações do utilizador, sendo executada apenas quando necessário, para poupar recursos. A interface indica quando os dados estão desatualizados (com mais de 3 segundos) para manter os utilizadores informados sobre a atualidade dos dados.

Padrões de consulta a bases de dados

O front-end utiliza padrões de consulta otimizados para obter dados de negociação do Supabase em tempo real:

// From Dashboard.tsx - Real-time data queries
const { data: latestData, error: latestError } = await supabase
.from('clearinghouse_states')
.select('*')
.eq('wallet_address', walletAddress)
.order('timestamp', { ascending: false })
.limit(1)
.maybeSingle();

// Get all positions for this wallet
const { data: positionsData, error: positionsError } = await supabase
.from('asset_positions')
.select('*')
.eq('wallet_address', walletAddress)
.order('timestamp', { ascending: false });

if (positionsError && positionsError.code !== 'PGRST116') throw positionsError;

As consultas tratam adequadamente os casos em que as carteiras não têm dados de transações, apresentando resultados vazios em vez de erros.

Gestão da mudança de carteira

O frontend valida os endereços das carteiras e limpa o estado imediatamente ao mudar:

// From Dashboard.tsx - Wallet validation and switching
const isValidWalletAddress = (address: string): boolean => {
return /^0x[a-fA-F0-9]{40}$/.test(address);
};

const handleWalletSearch = async () => {
if (!isValidWalletAddress(address)) {
setError('Invalid wallet address format');
return;
}

// Clear ALL old data immediately when switching wallets
setLatestState(null);
setPositions([]);
setVaultEquities([]);
setSpotBalances([]);
setIsSearching(true);

// Signal indexer to switch
await switchIndexerWallet(address);
setCurrentWallet(address);
};

A interface valida os endereços das carteiras e limpa os dados antigos imediatamente ao mudar de endereço, apresentando um indicador de carregamento até que os novos dados sejam carregados.

Apresentação de dados

Os dados de negociação fluem do estado do React para componentes de interface do utilizador especializados, que formatam e apresentam a informação:

// From PortfolioMetrics.tsx - Portfolio overview card component
interface PortfolioMetricsProps {
totalAccountValue: number;
totalUnrealizedPnl: number;
userRateLimit: UserRateLimit | null;
vaultEquities: UserVaultEquity[];
delegations: Delegation[];
formatCurrency: (value: number) => string;
}

export const PortfolioMetrics: React.FC<PortfolioMetricsProps> = ({
totalAccountValue,
totalUnrealizedPnl,
formatCurrency
}) => {
return (
<Card className="bg-slate-900/50 border-slate-700/50 backdrop-blur-sm mb-6">
<CardContent className="p-4">
<div className="text-xs text-slate-400 mb-3 font-medium tracking-wide uppercase">
Perp Account Value
</div>
<div className="text-2xl font-bold text-white">
{formatCurrency(totalAccountValue)}
</div>
</CardContent>
</Card>
);
};

O Painel de controlo O componente transmite valores calculados e funções de formatação aos componentes filhos, que se encarregam da apresentação visual e do estilo dos dados de negociação.

Conclusão

Parabéns! Conseguiu criar com sucesso um sistema de acompanhamento de carteiras em tempo real com o Hyperliquid, utilizando o endpoint de informação do Hyperliquid da Quicknode. Aprendeu a obter dados de negociação contínuos, a estruturar uma base de dados PostgreSQL para garantir precisão financeira e a criar um painel de controlo responsivo que se atualiza em tempo real. Esta base abre novas possibilidades para ferramentas de negociação avançadas, como a monitorização automatizada de riscos e a comparação entre várias carteiras.

Podes aprofundar ainda mais este projeto, integrando bibliotecas de gráficos como a Recharts ou criando alertas de negociação utilizando o teu serviço de notificações preferido. Consulta os nossos outros guias sobre o Hyperliquid para descobrires mais formas de desenvolver aplicações com o Hyperliquid.

Próximos passos

Agora que já tem um gestor de carteira funcional, eis várias formas de ampliar e melhorar a aplicação:

  • Avisos de liquidação quando as posições se aproximam de níveis de margem perigosos
  • Acompanhamento do desempenho da carteira ao longo do tempo através de gráficos
  • Tempos de carregamento mais curtos entre as pesquisas na carteira

Outros recursos


Se estiver com dificuldades ou tiver dúvidas, partilhe-as no nosso Discord. Mantenha-se a par das últimas novidades seguindo-nos no Twitter (@Quicknode) ou no nosso canal de anúncios do Telegram.

Adoramos ❤️ os vossos comentários!

Diz-nos se tiveres algum comentário ou sugestão de novos temas. Adoraríamos saber a tua opinião.

Partilhe este guia