Ler para transferir a aplicação Gate
qrCode
Mais opções de transferência
Não me lembre disso novamente hoje.

Desenvolvimento do sistema de carteiras da bolsa de valores — integração com a cadeia Solana

Na nossa última publicação, complementámos o sistema de controlo de riscos da bolsa. Nesta, vamos abordar a integração da carteira da bolsa com a cadeia Solana. O modelo de contas, armazenamento de logs e mecanismo de confirmação do Solana diferem bastante das cadeias baseadas em Ethereum. Se utilizarmos a abordagem do Ethereum, é fácil cometer erros. A seguir, faremos uma análise geral do raciocínio para lidar com o Solana.

Compreender o Solana de forma única

Modelo de contas do Solana

O Solana utiliza um modelo de separação entre programas e dados, onde os programas podem ser reutilizados, enquanto os dados do programa são armazenados em contas PDA (Program Derived Address) específicas. Como os programas são comuns, é necessário um Token Mint para distinguir diferentes tokens. A conta Token Mint armazena metadados globais do token, como autoridade de emissão (mint_authority), suprimento total (supply), número de casas decimais (decimals), etc.
Cada token possui um endereço de conta Mint único, por exemplo, o USD Coin (USDC) na rede principal do Solana tem o endereço de Mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v.

No Solana, existem duas versões de programas SPL Token: uma é SPL Token e outra é SPL Token-2022. Cada SPL Token tem uma ATA (Associated Token Account) independente que armazena o saldo do utilizador. Quando ocorre uma transferência de token, na verdade, chama-se o programa correspondente para transferir entre contas ATA.

Limitações do Log do Solana

No Ethereum, obtém-se as transferências de tokens analisando os logs históricos. No entanto, os logs do Solana não são preservados permanentemente por padrão, e não pertencem ao estado do livro-razão (não há um filtro Bloom para logs). Além disso, podem ser truncados durante a execução.
Por isso, não podemos simplesmente escanear logs para reconciliar depósitos, mas sim usar funções como getBlock ou getSignaturesForAddress para interpretar as instruções.

Confirmação e reorganização do Solana

O tempo de bloco do Solana é de aproximadamente 400ms. Após 32 confirmações (cerca de 12 segundos), o bloco atinge o estado finalizado (finalized). Se a exigência de tempo real não for alta, uma abordagem simples é confiar apenas nos blocos finalizados.
Para maior reatividade, é necessário considerar possíveis reorganizações de blocos, embora sejam raras. O consenso do Solana não depende do parentBlockHash para formar a cadeia, ao contrário do Ethereum, que usa parentBlockHash e blockHash para detectar forks. Como determinar se um bloco foi reorganizado?
Ao escanear localmente, devemos registrar o hash do bloco de cada slot. Se o hash de um slot específico mudar, indica uma reversão.

Compreendendo as diferenças do Solana, podemos avançar para a implementação, começando pelas modificações na base de dados:

Design da base de dados

Como o Solana possui dois tipos de tokens, devemos acrescentar uma coluna token_type na tabela tokens para distinguir entre spl-token e spl-token-2022.

Embora os endereços do Solana sejam diferentes dos do Ethereum, podem ser derivados usando BIP32 e BIP44, apenas com caminhos de derivação diferentes. Assim, podemos manter a tabela wallets existente, mas para suportar o mapeamento ATA e rastreamento de blocos do Solana, é necessário criar as seguintes tabelas:

Nome da Tabela Campos-Chave Descrição
solana_slots slot, block_hash, status, parent_slot Armazena informações redundantes de slots, útil para detectar forks e acionar rollback
solana_transactions tx_hash, slot, to_addr, token_mint, amount, type Detalhes de depósitos/saques, tx_hash único para rastreamento de assinaturas duplas
solana_token_accounts wallet_id, wallet_address, token_mint, ata_address Regista o mapeamento ATA do utilizador, o módulo de scan pode consultar por ata_address

Detalhes adicionais:

  • solana_slots regista estados como confirmed, finalized ou skipped, e o scanner decide se armazena ou faz rollback com base nisso.
  • solana_transactions armazena valores em lamports ou unidades mínimas do token, com o campo type para distinguir entre depósitos, retiradas, etc.
  • solana_token_accounts garante a unicidade do ATA (combinando wallet_address e token_mint), sendo o índice principal na lógica de scan.

Para detalhes de definição, consulte db_gateway/database.md.

Processamento de depósitos de utilizador

Para processar depósitos, é necessário escanear continuamente os dados na cadeia do Solana, usando principalmente duas abordagens:

  1. Escanear assinaturas com getSignaturesForAddress
  2. Escanear blocos com getBlock

Método 1:
Escanear assinaturas de um endereço, chamando getSignaturesForAddress com o endereço do ATA gerado para o utilizador ou o programID (atenção: transferências do spl-token não incluem o endereço de mint na instrução). Passando os parâmetros before, until e limit, podemos obter assinaturas incrementais. Depois, usamos getTransaction para obter detalhes das transações.

Este método é adequado para poucos utilizadores ou contas. Para um volume elevado, o método de escanear blocos é preferível, que é o que utilizamos aqui.

Método 2:
Escanear blocos, obtendo o slot mais recente, chamando getBlock para obter detalhes completos, assinaturas e contas, filtrando por instruções e contas relevantes.

Nota: devido ao alto volume de transações e TPS do Solana, em produção, a velocidade de análise pode ficar aquém do ritmo de blocos. Recomenda-se usar filas de mensagens (Kafka, RabbitMQ) para filtrar transferências de tokens e enviar eventos potenciais de depósito. Utilizar Redis para armazenar dados de hotspots pode acelerar a filtragem. Para muitas addresses, dividir por ATA e usar múltiplos consumidores aumenta a eficiência.

Se não desejar escanear blocos manualmente, pode usar serviços de indexadores de terceiros, que oferecem Webhook, monitorização de contas e filtragem avançada, suportando grandes volumes de dados.

Fluxo de escaneamento de blocos

Utilizamos o método 2, com código principal em scan/solana-scan, nos ficheiros blockScanner.ts e txParser.ts. O fluxo geral:

1. Sincronização inicial (performInitialSync):

  • Começa do último slot escaneado, até ao mais recente.
  • A cada 100 slots, verifica se há novos slots.
  • Usa confirmação confirmada para equilibrar entre velocidade e fiabilidade.

2. Escaneamento contínuo (scanNewSlots):

  • Verifica constantemente novos slots.
  • Revalida slots confirmados, detectando rollback.

3. Análise do bloco (txParser.parseBlock):

  • Usa getBlock com commitment “confirmed” e encoding “jsonParsed”.
  • Percorre cada transação, analisando instructions e innerInstructions.
  • Processa apenas transações bem-sucedidas (tx.meta.err === null).

4. Análise de instruções (txParser.parseInstruction):

  • Transferências SOL: verifica se a instruction do System Program é do tipo transfer e se o destino está na lista de monitorados.
  • Transferências SPL Token: verifica se a instruction do Token Program ou Token-2022, do tipo transfer ou transferChecked, e se o destino é uma ATA mapeada.
  • Para cada instrução, mapeia ATA para endereço de carteira e token mint usando o banco de dados.

Ao detectar uma transação de depósito, após validação de segurança com DB Gateway e assinatura de risco, os dados são gravados na tabela de fluxos de fundos (credits).

Retiradas

O processo de retirada no Solana é semelhante ao do EVM, mas com diferenças na construção da transação:

  1. Existem dois tipos de tokens: SPL-Token e SPL-Token 2022, com programIDs diferentes. Na construção, é preciso distinguir. (Atualmente, SPL-Token 2022 é menos comum e pode não ser suportado).
  2. Uma transação do Solana consiste em duas partes: signatures (assinaturas ed25519) e message (com header, accountKeys, recentBlockhash, instructions). O recentBlockhash é usado para limitar a validade da transação, com uma validade de cerca de 150 blocos (~1 minuto). Assim, ao fazer uma retirada, deve-se obter o recentBlockhash mais recente na cadeia. Se a retirada precisar de revisão manual, é necessário reobter o recentBlockhash e assinar novamente.

Fluxo de retirada

[Imagem ilustrativa]

A obtenção do recentBlockhash deve ocorrer após a verificação de risco, para garantir que a transação seja válida.

Código principal de assinatura:

  • Para transferir SOL, cria-se uma instrução getTransferSolInstruction com origem, destino e valor.
  • Para transferir tokens, usa-se getTransferInstruction com ATA de origem, ATA de destino, autoridade e valor.
  • Constrói-se a mensagem de transação com createTransactionMessage, definindo o fee payer, o recentBlockhash, e adicionando a instrução.
  • A assinatura é feita com signTransactionMessageWithSigners.
  • A transação final é codificada em Base64 para envio.

Envio da transação à rede

Usa-se @solana/web3.js:

const solanaRpc = chainConfigManager.getSolanaRpc();
const txSignature = await solanaRpc.sendTransaction(signedTransaction, ...);

Os detalhes completos do código de retirada encontram-se em:

  • Wallet: walletBusinessService.ts:405-754
  • Signer: solanaSigner.ts:29-122
  • Script de teste: requestWithdrawOnSolana.ts

Duas melhorias pendentes:

  1. Verificação prévia de ATA: antes de retirar, garantir que a ATA de destino já exista, ou criar com custo adicional.
  2. Prioridade de taxa: em congestão, ajustar computeUnitPrice para acelerar a transação.

Resumo

A integração do Solana na bolsa mantém a arquitetura geral, mas requer adaptação ao seu modelo de contas, estrutura de transações e mecanismo de consenso.
No processamento de depósitos, criar e manter o mapeamento ATA → carteira, monitorar mudanças de blockhash para detectar reorganizações, e atualizar o estado da transação de confirmed para finalized.
Na retirada, obter o recentBlockhash mais recente, distinguir entre SPL Token e Token-2022, e construir transações específicas para cada caso.

SOL2.47%
ETH3.23%
USDC-0.02%
Ver original
Esta página pode conter conteúdos de terceiros, que são fornecidos apenas para fins informativos (sem representações/garantias) e não devem ser considerados como uma aprovação dos seus pontos de vista pela Gate, nem como aconselhamento financeiro ou profissional. Consulte a Declaração de exoneração de responsabilidade para obter mais informações.
  • Recompensa
  • Comentar
  • Republicar
  • Partilhar
Comentar
0/400
Nenhum comentário
  • Fixar
Negocie cripto em qualquer lugar e a qualquer hora
qrCode
Digitalizar para transferir a aplicação Gate
Novidades
Português (Portugal)
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)