Observação: pode haver imprecisões ou áreas a serem melhoradas. Qualquer correção será bem-vinda.
Custos Operacionais
Não operei um produto com um grande número de acessos, então isso pode não ser muito relevante, mas consigo operá-lo pelo custo de uma única moeda por mês. O custo base envolve uma taxa de armazenamento de chave de $1 por KMS, e quaisquer custos adicionais vêm ao exceder os limites da camada gratuita.
Prioridades (O que é Importante)
Aqui está o foco:
UX! UX!
Transações sem gás!
Meta transações!
Alta taxa de transferência (o máximo possível)!
Custos baixos!
Arquitetura
Estou revelando a arquitetura que utilizo, a qual depende fortemente da AWS. Em termos simples, é construída sobre uma arquitetura sem servidor. Para pequenos empreendimentos Web3 como o nosso, serviços custosos como EC2 ou ECS estão fora de questão. Eles não são uma opção.
Principais Funcionalidades
O sistema tem amplas funcionalidades:
- Receber pedidos de usuários.
- Assinar esses pedidos e enviá-los como transações para o nó RPC.
- (Opcional) Lidar com exceções quando um pedido de usuário falha.
- Indexar dados on-chain.
É bastante simples.
Aqui está um diagrama de sequência para os pontos 1 e 2:
Detalhes das Funcionalidades
Vamos nos aprofundar no que cada função faz.
1. Receber Pedidos de Usuários
Isso envolve receber pedidos de usuários e gravá-los no DynamoDB. No lado dos Dapps, uma assinatura conforme a ERC712 é gerada e enviada para o API Gateway. No lado do servidor, fazemos uma verificação 'dry-run' desses pedidos e, se estiver tudo bem, os gravamos no registro de recepção do DynamoDB.
https://eips.ethereum.org/EIPS/eip-712
Um Pouco de Engenhosidade para o UX
Normalmente, os clientes não conseguem ver as transações que enviaram até que sejam confirmadas. A experiência do usuário pode ser instável dependendo da carga da blockchain e do nó RPC. No produto que estou desenvolvendo, o resultado do processamento do pedido é visível imediatamente após o servidor gravar o registro de recepção, sem esperar pela gravação na blockchain. Isso garante uma experiência do usuário sem depender da velocidade da blockchain ou do nó RPC. No entanto, isso se aplica apenas quando as informações fora da cadeia (como tokenId) podem ser definitivamente derivadas do pedido do usuário.
2. Enviar Pedidos como Transações
Processamos registros recebidos na etapa 1 lendo-os do DynamoDB. Para garantir a consistência do valor do nonce, o processo de assinatura da transação requer alguma engenhosidade. Essa função lambda usa gravações condicionais no DynamoDB para impor um bloqueio atômico, impedindo o processamento paralelo e garantindo que os nonces sejam obtidos e processados em ordem.
https://blog.manabusakai.com/2016/07/lambda-atomic-lock/
As transações são enviadas usando Multicall ou nosso próprio executor em lote para garantir o desempenho.
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Multicall.sol
3. Tratamento de Exceções para Pedidos de Usuários Falhos
Também incluímos um sistema de segurança para exceções, que basicamente é repetir a etapa 2. Vou omitir os detalhes.
4. Processo de Indexação
Como as informações mostradas aos usuários são determinísticas e gravadas no DynamoDB, elas podem servir como indexação. No entanto, também verificamos as informações na cadeia. É crucial (e tedioso) verificar se as transações enviadas foram realmente confirmadas. Se os fundos fossem abundantes, seria legal usar o The Graph ou configurar nosso próprio indexador, mas não temos esse orçamento.
Notificação do Cliente de Transações Confirmadas
O lado dos Dapps verifica o status da transação. Em termos de implementação, após a confirmação da transação, ele notifica o servidor com as informações necessárias e o número do bloco. O servidor recupera logs deste número de bloco, analisa o evento desejado e os grava no DynamoDB. Isso funciona bem e reduz a carga do servidor, mas não pode indexar transações não enviadas através dos nossos Dapps (por exemplo, NFTs).
Uso de Serviços de Ganchos de Eventos
Usamos serviços como streams Moralis para ouvir eventos na cadeia e conectá-los como eventos. Embora sua camada gratuita tenha sido reduzida há meio ano, ainda é suficiente para eventos menores. Se ficar difícil, podemos mudar para outros serviços.
No processamento lambda, recebemos o número do bloco alvo para indexação, analisamos logs e os despejamos no DynamoDB. É simples se pudermos conectar o evento.
Conclusão
A batalha de um pequeno engenheiro Web3 continua... (Continuará)
Recentemente, criei um Dapps pessoal usando o Cloudflare, então planejo escrever sobre o Cloudflare no meu próximo artigo. (Algum dia...)
Notas de Rodapé
Assinaturas geradas com base em padrões como a ERC712.
Artigo escrito por Polonity. Traduzido por Marcelo Panegali.
Oldest comments (0)