🌌
Wormhole Docs Brasil
  • Bem-vindo!
  • Materiais
    • Build
      • Começer a Buildar
        • Redes Suportadas
        • Testnet Faucets
        • Demos
      • Construindo Aplicações Frontend
        • Wormhole SDK
          • Wormhole TypeScript SDK
          • Data Layouts
          • Construção de Protocolos e Payloads
        • Queries
          • Overview
          • Usando Queries
          • F.A.Q.
        • Conexão
          • Overview
          • Routes
          • Features
          • Configuração
          • v1 Migration
          • F.A.Q.
      • Construindo Integrações de contratos
        • Wormhole Relayer
        • Core Contracts
        • CCTP
        • Transferências de Tokens Nativos
          • Processos de Deployment
        • Comandos NTT CLI
        • Configuração de NTT
          • Limitação de Taxas
          • Controle de Acesso
        • Managers e Transceivers
        • F.A.Q. Wormhole NTT
      • MultiGov
        • Deployment
        • Upgrades Contracts
        • F.A.Q. Tecnicas
      • Ambiente de Desenvolvimento
      • F.A.Q sobre Integrações de Contratos
      • Toolkit
        • Wormholescan
        • Wormhole CLI
        • Wormhole SDK
          • TypeScript SDK
          • Data Layouts
          • Construindo Protocolos e Payloads
        • Solidity SDK
        • Tilt
        • Toolkit F.A.Q.
      • Referências
    • Infraestrutura
      • Run a Relayer
      • Run a Spy
    • Tutoriais
      • Tutorial de Conexão
      • Tutorial de Contratos Cross-Chain
        • Criação de Contratos de Mensagens Cross-Chain
        • Criação de contratos de transferência de tokens Cross-Chain
      • Tutoriais de Transferências de Tokens Nativos (NTT - Native Token Transfers)
        • Crie Tokens Multichain
      • Tutorial MultiGov
        • Proposta Cross-Chain treasury management
      • Tutoriais do Wormhole SDK
        • Transferir USDC via CCTP
        • Transferir Tokens via a Token Bridge
    • Learn
      • Fundamentos
        • Introdução
        • Segurança
        • Overview de Arquitetura
        • Glossário
      • Componentes de Infraestrutura
        • Core Contracts
        • VAAs (Verified Action Approvals)
        • Guardians
        • Spy
        • Relayers
      • Messaging
        • Token Bridge
        • Circle's CCTP Bridge
        • Transferencias de Token Nativos
          • Overview
          • Arquitetura
          • Modelos de Deploy
          • Security
      • Multigov
        • MultiGov: Governança Cross-Chain com Wormhole
        • MultiGov Architecture
        • FAQs
    • Links úteis
Powered by GitBook
On this page
  1. Materiais
  2. Build
  3. Construindo Aplicações Frontend
  4. Wormhole SDK

Data Layouts

O SDK do Wormhole utiliza o pacote layout para definir, serializar e desserializar estruturas de dados de forma eficiente. Esse sistema modular garante um formato de dados consistente e compatibilidade entre diferentes ambientes, beneficiando projetos que exigem um manuseio robusto de dados estruturados.

Ao compreender o mecanismo de layout, você será capaz de:

  • Definir estruturas de dados (números, arrays e tipos personalizados)

  • Serializar e desserializar dados de forma eficiente utilizando as utilidades do SDK

  • Lidar com layouts específicos de protocolo com facilidade

Este guia é útil para desenvolvedores que buscam integrar o Wormhole em suas aplicações ou protocolos, especialmente aqueles que lidam com payloads complexos ou comunicação entre blockchains.

Conceitos Chave Itens de Layout Um layout define como as estruturas de dados devem ser serializadas (convertidas para formato binário) e desserializadas (convertidas de volta para sua estrutura original). Isso garante um formato de dados consistente ao transmitir informações entre diferentes ambientes de blockchain.

Os layouts são compostos por itens de layout, que descrevem campos individuais ou conjuntos de campos em seus dados. Cada item de layout especifica:

  • name - nome do campo

  • binary - tipo de dado (ex: uint, bytes)

  • size - comprimento em bytes para campos de tamanho fixo dentro de itens uint e bytes apenas

Os itens de layout podem representar:

  • Tipos primitivos - tipos básicos de dados como inteiros não assinados (uint) ou arrays de bytes (bytes)

  • Tipos compostos - estruturas mais complexas, como arrays ou objetos aninhados

Abaixo está um exemplo de um layout que poderia ser usado para serializar uma mensagem através do protocolo Wormhole:

const exampleLayout = [
  { name: 'sourceChain', binary: 'uint', size: 2 },
  { name: 'orderSender', binary: 'bytes', size: 32 },
  { name: 'redeemer', binary: 'bytes', size: 32 },
  { name: 'redeemerMessage', binary: 'bytes', lengthSize: 4 },
] as const;

Neste exemplo:

  • sourceChain é um inteiro não assinado de 2 bytes (uint) identificando a blockchain de origem

  • orderSender é um array de bytes de 32 bytes representando o endereço do remetente

  • redeemer é outro array de 32 bytes utilizado para o endereço do resgatador

  • redeemerMessage é uma sequência de bytes de comprimento variável, com seu comprimento especificado por um inteiro de 4 bytes

Essa definição de layout garante que todos os campos de dados necessários sejam codificados de forma consistente e possam ser interpretados corretamente quando desserializados.

Serialização e Desserialização A serialização converte dados estruturados em formato binário; a desserialização reverte isso, reconstruindo os objetos originais.

Você pode serializar dados utilizando a função serializeLayout:

const serialized = serializeLayout(fillLayout, exampleFill);

Para desserializar os dados binários de volta em um objeto estruturado, utilize a função deserializeLayout:

const deserialized = deserializeLayout(fillLayout, serialized);

Conversões Personalizadas Os layouts também permitem conversões personalizadas, o que ajuda a mapear tipos complexos ou personalizados (como IDs de cadeia ou endereços universais) para um formato mais utilizável. Isso é útil ao serializar ou desserializar dados que não se encaixam bem em tipos simples, como inteiros ou arrays de bytes.

Por exemplo, considere uma conversão personalizada para um ID de cadeia:

const chainCustomConversion = {
  to: (chainId: number) => toChain(chainId),
  from: (chain: Chain) => chainToChainId(chain),
} satisfies CustomConversion<number, Chain>;

Essa configuração permite que o Wormhole converta entre formatos legíveis por humanos e dados codificados binariamente usados em payloads.

Tratamento de Erros O sistema de layout realiza verificações de erro durante a serialização e desserialização. Um erro é lançado se os dados estiverem com tamanho incorreto ou no formato errado. Veja o exemplo abaixo:

try {
  deserializeLayout(fillLayout, corruptedData);
} catch (error) {
  console.error('Erro durante a desserialização:', error.message);
}

Aplicação de Layouts Esta seção se concentrará na aplicação dos conceitos explicados anteriormente através de exemplos. Eles ajudarão os desenvolvedores a entender melhor como definir layouts, serializar e desserializar dados, e usar conversões personalizadas quando necessário.

Definindo Layouts Para começar com layouts no Wormhole, você precisa definir sua estrutura. Um layout é simplesmente uma lista de campos (itens de layout) que descrevem como cada parte dos dados será serializada.

Considere o seguinte layout para um payload:

const exampleLayout = [
  { name: 'sourceChain', binary: 'uint', size: 2 },
  { name: 'orderSender', binary: 'bytes', size: 32 },
  { name: 'redeemer', binary: 'bytes', size: 32 },
  { name: 'redeemerMessage', binary: 'bytes', lengthSize: 4 },
] as const;

Neste exemplo:

  • sourceChain é um inteiro não assinado (uint) de 2 bytes

  • orderSender é um array de bytes de 32 bytes de comprimento fixo

  • redeemer é outro array de 32 bytes

  • redeemerMessage é um array de bytes com comprimento prefixado, com o comprimento especificado por um inteiro de 4 bytes

Serializar Dados Uma vez que o layout esteja definido, o próximo passo é serializar os dados de acordo com essa estrutura. Você pode fazer isso utilizando a função serializeLayout do SDK do Wormhole:

const examplePayload = {
  sourceChain: 6,
  orderSender: new Uint8Array(32),
  redeemer: new Uint8Array(32),
  redeemerMessage: new Uint8Array([0x01, 0x02, 0x03]),
};

const serializedData = serializeLayout(exampleLayout, examplePayload);

Isso pega a estrutura de dados (examplePayload) e a serializa de acordo com as regras definidas no layout (exampleLayout). O resultado é um Uint8Array representando os dados binários serializados.

Desserializar Dados A desserialização é o processo reverso da serialização. Dado um Uint8Array serializado, podemos convertê-lo de volta para sua estrutura original utilizando a função deserializeLayout:

const deserializedPayload = deserializeLayout(exampleLayout, serializedData);

Isso gerará o objeto estruturado, facilitando o trabalho com dados transmitidos ou recebidos de outra cadeia.

Manipulando Campos de Comprimento Variável Um aspecto relevante do sistema de layout do SDK do Wormhole é a capacidade de lidar com campos de comprimento variável, como arrays e sequências de bytes com comprimento prefixado.

Por exemplo, se você deseja serializar ou desserializar uma mensagem onde o comprimento do conteúdo não é conhecido de antemão, você pode definir um item de layout com o campo lengthSize:

{ name: 'message', binary: 'bytes', lengthSize: 4 }

Isso informa ao SDK para ler ou escrever o comprimento da mensagem (em 4 bytes) e depois manipular o conteúdo.

Layouts Aninhados e Tipagem Forte O SDK do Wormhole simplifica o manuseio de estruturas complexas com layouts aninhados e tipagem forte. Layouts aninhados representam dados hierárquicos, enquanto a tipagem forte garante a consistência dos dados e captura erros durante o desenvolvimento.

Layout Aninhado Em protocolos complexos, os layouts podem conter estruturas aninhadas. Layouts aninhados são úteis para representar dados hierárquicos (como transações ou mensagens multipartes) de maneira estruturada.

Veja o seguinte layout aninhado onde uma mensagem contém campos aninhados:

const nestedLayout = [
  {
    name: 'source',
    binary: 'bytes',
    layout: [
      { name: 'chainId', binary: 'uint', size: 2 },
      { name: 'sender', binary: 'bytes', size: 32 },
    ],
  },
  {
    name: 'redeemer',
    binary: 'bytes',
    layout: [
      { name: 'address', binary: 'bytes', size: 32 },
      { name: 'message', binary: 'bytes', lengthSize: 4 },
    ],
  },
] as const satisfies Layout;

Neste layout:

  • source é um objeto com dois campos: chainId e sender

  • redeemer é outro objeto com dois campos: address e uma mensagem com comprimento prefixado

Tipagem Forte Uma das vantagens de usar o SDK do Wormhole com TypeScript é seu suporte para tipagem forte. Isso garante que os dados serializados e desserializados estejam conformes as estruturas esperadas, reduzindo erros durante o desenvolvimento ao aplicar verificações de tipo em tempo de compilação.

Usando o TypeScript, a utilidade LayoutToType fornecida pelo SDK gera automaticamente uma estrutura tipada de forma forte com base no layout:

type NestedMessage = LayoutToType<typeof nestedLayout>;

Isso garante que, ao serializar ou desserializar dados, eles correspondam à estrutura esperada.

const message: NestedMessage = {
  source: {
    chainId: 6,
    sender: new Uint8Array(32),
  },
  redeemer: {
    address: new Uint8Array(32),
    message: new Uint8Array([0x01, 0x02, 0x03]),
  },
};

Tentar atribuir dados de tipos incorretos resultará em um erro de compilação. O sistema de layouts do SDK Wormhole aplica tipos fortes, reduzindo erros em tempo de execução e melhorando a confiabilidade do código.

Serialização e Desserialização com Estruturas Aninhadas

Você pode serializar e desserializar estruturas aninhadas da mesma forma que layouts mais simples:

const serializedNested = serializeLayout(nestedLayout, message);
const deserializedNested = deserializeLayout(nestedLayout, serializedNested);

A tipagem forte em TypeScript garante que o objeto message esteja em conformidade com a estrutura do layout aninhado, reduzindo o risco de inconsistência de dados durante a comunicação cross-chain.

Layouts Comumente Usados

O SDK Wormhole inclui layouts pré-definidos comumente usados em mensagens cross-chain. Estes layouts são otimizados para campos padrão, como IDs de cadeia, endereços e assinaturas. Você pode explorar o conjunto completo de layouts pré-definidos no diretório layout-items do SDK Wormhole.

Layouts de Chain ID

Os layouts de Chain ID no SDK Wormhole derivam de uma fundação comum: chainItemBase. Esta estrutura define a representação binária de um Chain ID como um inteiro sem sinal de 2 bytes, garantindo consistência nos processos de serialização e desserialização.

Estrutura Base

Esta estrutura simples é o modelo para layouts mais específicos, padronizando o formato e o tamanho binário.

const chainItemBase = { binary: 'uint', size: 2 } as const;

Layout Dinâmico de Chain ID

O layout dinâmico de Chain ID, chainItem, estende chainItemBase, adicionando lógica de conversão personalizada. Ele permite validação em tempo de execução de Chain IDs, suporta valores nulos opcionais e restringe os Chain IDs a um conjunto predefinido quando necessário.

export const chainItem = <
  const C extends readonly Chain[] = typeof chains,
  const N extends boolean = false,
>(opts?: {
  allowedChains?: C;
  allowNull?: N;
}) =>
  ({
    ...chainItemBase, // Base para a estrutura
    custom: {
      to: (val: number): AllowNull<C[number], N> => { ... },
      from: (val: AllowNull<C[number], N>): number => { ... },
    },
  });

Este layout é versátil. Ele permite a serialização de nomes de cadeias legíveis (ex: Ethereum) para IDs numéricos (ex: 1) e vice-versa, sendo especialmente útil ao trabalhar com configurações dinâmicas ou protocolos que suportam múltiplas cadeias.

Layout Fixo de Chain ID

O layout fixo de Chain ID, fixedChainItem, é mais rígido. Ele também estende chainItemBase, mas o campo custom é codificado para uma única cadeia. Isso elimina a validação em tempo de execução e força a adesão rigorosa a uma cadeia específica.

export const fixedChainItem = <const C extends Chain>(chain: C) => ({
  ...chainItemBase, // Base para a estrutura
  custom: {
    to: chain,
    from: chainToChainId(chain),
  },
});

Este layout permite que os desenvolvedores serializem e desserializem eficientemente mensagens que envolvem um único Chain ID fixo.

Layout de Endereço

O SDK Wormhole usa um Layout de Endereço Universal para serializar e desserializar endereços de blockchain em um formato padronizado. Este layout garante que os endereços sejam sempre representados como valores binários fixos de 32 bytes, possibilitando uma comunicação cross-chain sem problemas.

Estrutura Base

O universalAddressItem define o layout para endereços. Ele usa o tipo binário bytes e impõe um tamanho fixo de 32 bytes para consistência.

export const universalAddressItem = {
  binary: 'bytes',
  size: 32,
  custom: {
    to: (val: Uint8Array): UniversalAddress => new UniversalAddress(val),
    from: (val: UniversalAddress): Uint8Array => val.toUint8Array(),
  } satisfies CustomConversion<Uint8Array, UniversalAddress>,
} as const satisfies LayoutItem;

Este layout garante o manuseio consistente de endereços, definindo o seguinte:

  • Serialização: converte um objeto de UniversalAddress de alto nível em binário bruto (32 bytes) para armazenamento ou transmissão eficientes.

  • Desserialização: converte o binário bruto de volta para um objeto UniversalAddress, permitindo interação adicional em um formato legível ou programático.

Layout de Assinatura

No SDK Wormhole, o Layout de Assinatura define como serializar e desserializar assinaturas criptográficas. Essas assinaturas verificam a autenticidade da mensagem e garantem a integridade dos dados, particularmente nas VAAs assinadas por Guardiões.

Estrutura Base

O signatureLayout especifica a estrutura binária de uma assinatura secp256k1. Ele divide a assinatura em três componentes:

const signatureLayout = [
  { name: 'r', binary: 'uint', size: 32 },
  { name: 's', binary: 'uint', size: 32 },
  { name: 'v', binary: 'uint', size: 1 },
] as const satisfies Layout;

Este layout fornece um formato binário claro para a assinatura secp256k1, tornando o processamento eficiente dentro do protocolo Wormhole.

Layout com Conversão Personalizada

O signatureItem baseia-se no signatureLayout adicionando lógica de conversão personalizada. Essa conversão transforma os dados binários brutos em um objeto Signature de alto nível e vice-versa.

export const signatureItem = {
  binary: 'bytes',
  layout: signatureLayout,
  custom: {
    to: (val: LayoutToType<typeof signatureLayout>) =>
      new Signature(val.r, val.s, val.v),
    from: (val: Signature) => ({ r: val.r, s: val.s, v: val.v }),
  } satisfies CustomConversion<LayoutToType<typeof signatureLayout>, Signature>,
} as const satisfies BytesLayoutItem;

O campo custom garante a integração perfeita de dados binários brutos com a classe Signature, encapsulando a lógica específica da assinatura.

Casos de Uso Avançados

O sistema de layout do SDK Wormhole foi projetado para lidar com várias estruturas de dados e necessidades de serialização. Esta seção explorará casos de uso mais avançados, como o tratamento de estruturas de dados condicionais, conversões fixas e otimização de desempenho de serialização.

Instruções Switch para Layouts Condicionais

Em alguns casos, a estrutura dos dados serializados pode mudar com base em um campo específico, como um ID de payload. O tipo de layout switch define layouts condicionalmente com base em um valor.

Por exemplo, diferentes tipos de mensagens podem ser identificados usando um ID de payload, e o layout para cada mensagem pode ser determinado em tempo de execução:

const switchLayout = {
  binary: 'switch',
  idSize: 1, // tamanho do ID do payload
  idTag: 'messageType', // tag para identificar o tipo de mensagem
  layouts: [
    [[1, 'messageType1'], fillLayout], // layout para tipo 1
    [[2, 'messageType2'], fastFillLayout], // layout para tipo 2
  ],
} as const satisfies Layout;

A instrução switch ajuda os desenvolvedores a analisar múltiplos tipos de payload usando a mesma estrutura, dependendo de um campo de controle como um ID.

Conversões Fixas e Campos Omitidos

Conversões fixas e campos omitidos permitem que os desenvolvedores manipulem dados estáticos conhecidos sem incluí-los em cada operação de serialização ou desserialização. Por exemplo, quando campos específicos em um layout sempre contêm um valor constante, eles podem ser omitidos do objeto desserializado.

Exemplo: Conversão Fixa

Em alguns casos, um campo pode sempre conter um valor predefinido. O sistema de layout oferece suporte a conversões fixas, permitindo que os desenvolvedores "codifiquem" esses valores:

const fixedConversionLayout = {
  binary: 'uint',
  size: 2,
  custom: {
    to: 'Ethereum',
    from: chainToChainId('Ethereum'),
  },
} as const satisfies Layout;

Exemplo: Campos Omitidos

Campos omitidos são úteis para lidar com preenchimento ou campos reservados que não carregam informações significativas e podem ser excluídos com segurança da saída desserializada:

const omittedFieldLayout = [
  { name: 'reserved', binary: 'uint', size: 2, omit: true },
] as const satisfies Layout;

Neste exemplo, reserved é um campo de preenchimento com um valor fixo, não dinâmico, que não tem propósito funcional. Ele é omitido do resultado desserializado, mas ainda é considerado durante a serialização para manter o formato binário correto.

Somente campos com valor fixo e conhecido, como preenchimento ou campos reservados, devem ser marcados como omit: true. Campos com informações significativas ou dinâmicas, como sourceChain ou version, devem permanecer na estrutura desserializada para garantir a integridade dos dados e permitir conversões consistentes entre as representações serializadas e desserializadas.

Integração com o Protocolo Wormhole

O sistema de layout facilita a interação com o protocolo Wormhole, especialmente quando se trata de VAAs. Essas mensagens cross-chain precisam ser serializadas e desserializadas para garantir que possam ser transmitidas e processadas com precisão entre diferentes cadeias.

VAAs e Layouts

VAAs são a espinha dorsal da comunicação cross-chain do Wormhole. Cada VAA é uma mensagem assinada que encapsula informações importantes, como a cadeia de origem, o endereço do emissor, um número de sequência e assinaturas de Guardiões. O SDK Wormhole usa seu sistema de layout para definir, serializar e desserializar VAAs, garantindo integridade dos dados e compatibilidade entre as cadeias.

Estrutura Base do VAA

O SDK Wormhole organiza a estrutura do VAA em três componentes principais:

  • Cabeçalho: contém metadados, como o índice do conjunto de Guardiões e um array de assinaturas de Guardiões.

  • Envelope: inclui detalhes específicos da cadeia, como a cadeia do emissor, o endereço, a sequência e o nível de consistência.

  • Payload: fornece dados específicos da aplicação, como a mensagem ou operação sendo realizada.

Layout do Cabeçalho:

const guardianSignatureLayout = [
  { name: 'guardianIndex', binary: 'uint', size: 1 },
  { name: 'signature', ...signatureItem },
] as const satisfies Layout;

export const headerLayout = [
  { name: 'version', binary: 'uint', size: 1, custom: 1, omit: true },
  { name: 'guardianSet', ...guardianSetItem },
  {
    name: 'signatures',
    binary: 'array',
    lengthSize: 1,
    layout: guardianSignatureLayout,
  },
] as const satisfies Layout;

O cabeçalho define os metadados para validar e processar o VAA, como o índice do conjunto de Guardiões e as assinaturas. Cada assinatura é representada usando o layout signatureItem, garantindo consistência e compatibilidade entre plataformas.

Layout do Envelope:

export const envelopeLayout = [
  { name: 'timestamp', binary: 'uint', size: 4 },
  { name: 'nonce', binary: 'uint', size: 4 },
  { name: 'emitterChain', ...chainItem() },
  { name: 'emitterAddress', ...universalAddressItem },
  { name: 'sequence', ...sequenceItem },
  { name: 'consistencyLevel', binary: 'uint', size: 1 },
] as const satisfies Layout;

O envelope encapsula os dados principais da mensagem VAA, incluindo informações específicas da cadeia, como o endereço do emissor e o número da sequência. Este layout estruturado garante que o VAA possa ser transmitido de forma segura entre cadeias.

Layout da Payload:

A Payload contém os dados definidos pelo usuário específicos para o aplicativo ou protocolo, como uma mensagem de transferência de token, ação de governança ou outra operação entre cadeias. O layout da payload é dinâmico e depende do tipo de payload, identificado pelo campo payloadLiteral.

const examplePayloadLayout = [
  { name: 'type', binary: 'uint', size: 1 },
  { name: 'data', binary: 'bytes', lengthSize: 2 },
] as const satisfies Layout;

Este exemplo demonstra uma payload contendo:

  • Um campo type que especifica o tipo da operação (por exemplo, transferência ou ação de governança)

  • Um campo data que possui prefixo de comprimento e pode armazenar informações específicas da operação

Layouts de payload dinâmicos são selecionados em tempo de execução utilizando o campo payloadLiteral, que mapeia para um layout predefinido no SDK Wormhole.

Layout Base Combinado:

O layout base VAA combina o cabeçalho, envelope e o layout de payload selecionado dinamicamente:

export const baseLayout = [...headerLayout, ...envelopeLayout] as const;

Em tempo de execução, o layout da payload é adicionado ao baseLayout para formar a estrutura completa.

Serializando Dados VAA:

O SDK Wormhole fornece a função serialize para serializar uma mensagem VAA. Essa função combina o layout base (cabeçalho e envelope) com o layout da payload apropriado, garantindo que o formato da mensagem esteja correto para transmissão entre cadeias.

import { serialize } from '@wormhole-foundation/sdk-core/vaa/functions';

const vaaData = {
  guardianSet: 1,
  signatures: [{ guardianIndex: 0, signature: new Uint8Array(65).fill(0) }],
  timestamp: 1633000000,
  nonce: 42,
  emitterChain: 2, // Ethereum
  emitterAddress: new Uint8Array(32).fill(0),
  sequence: BigInt(1),
  consistencyLevel: 1,
  payloadLiteral: 'SomePayloadType',
  payload: { key: 'value' },
};

const serializedVAA = serialize(vaaData);

Como funciona?

Internamente, a função serialize combina dinamicamente o baseLayout (cabeçalho e envelope) com o layout da payload definido pelo payloadLiteral. O layout completo é passado para a função serializeLayout, que converte os dados em formato binário.

const layout = [
  ...baseLayout, // Layout de cabeçalho e envelope
  payloadLiteralToPayloadItemLayout(vaa.payloadLiteral), // Layout da payload
] as const;

return serializeLayout(layout, vaa as LayoutToType<typeof layout>);

Deserializando Dados VAA:

O SDK Wormhole fornece a função deserialize para analisar um VAA de seu formato binário de volta para um objeto estruturado. Essa função usa o baseLayout e a lógica de discriminador de payload para garantir que o VAA seja interpretado corretamente.

import { deserialize } from '@wormhole-foundation/sdk-core/vaa/functions';

const serializedVAA = new Uint8Array([
  /* Dados binários VAA serializados */
]);

const vaaPayloadType = 'SomePayloadType'; // O tipo de payload esperado para este VAA
const deserializedVAA = deserialize(vaaPayloadType, serializedVAA);

Como funciona?

Internamente, a função deserialize usa o baseLayout (cabeçalho e envelope) para analisar a estrutura principal do VAA. Em seguida, ela identifica o layout adequado da payload usando o tipo de payload ou discriminador fornecido.

const [header, envelopeOffset] = deserializeLayout(headerLayout, data, {
  consumeAll: false,
});

const [envelope, payloadOffset] = deserializeLayout(envelopeLayout, data, {
  offset: envelopeOffset,
  consumeAll: false,
});

const [payloadLiteral, payload] =
  typeof payloadDet === 'string'
    ? [
        payloadDet as PayloadLiteral,
        deserializePayload(payloadDet as PayloadLiteral, data, payloadOffset),
      ]
    : deserializePayload(
        payloadDet as PayloadDiscriminator,
        data,
        payloadOffset
      );

return {
  ...header,
  ...envelope,
  payloadLiteral,
  payload,
} satisfies VAA;

Registrando Payloads Personalizadas:

No SDK Wormhole, as payloads dependem de layouts para definir sua estrutura binária, garantindo consistência e segurança de tipo entre protocolos. Payloads personalizadas ampliam essa funcionalidade, permitindo que os desenvolvedores tratem recursos específicos de protocolos ou casos de uso exclusivos.

Para aprender como definir e registrar payloads usando layouts, consulte a página "Construindo Protocolos e Payloads" para um guia detalhado.

Armadilhas Comuns e Melhores Práticas:

Ao trabalhar com o sistema de layouts do SDK Wormhole, é importante estar atento a alguns problemas comuns que podem surgir. Abaixo estão algumas armadilhas a evitar e melhores práticas para garantir uma integração suave.

Armadilhas a Evitar:

  • Definindo Tamanhos para Tipos de Dados: Ao definir os tamanhos para cada tipo de dado, certifique-se de que o comprimento dos dados corresponda ao tamanho especificado para evitar erros de serialização e deserialização.

  • Arrays Definidos de Forma Incorreta: Arrays podem ser de comprimento fixo ou prefixados por comprimento, por isso é importante definí-los corretamente.

Melhores Práticas:

  • Reutilizar Itens de Layout Predefinidos: Em vez de definir tamanhos ou tipos manualmente, reutilize os itens de layout predefinidos fornecidos pelo SDK Wormhole. Esses itens garantem formatação consistente e reforçam tipos fortes.

  • Usar Instâncias de Classes: Sempre que possível, converta dados desserializados em instâncias de classes de nível superior. Isso facilita a validação, manipulação e interação com dados estruturados.

Considerações de Desempenho:

A serialização e desserialização eficientes são cruciais ao lidar com grandes volumes de dados entre cadeias. Algumas estratégias incluem a Instanciação Preguiçosa para construir discriminadores apenas quando necessário, o que melhora a eficiência.

Recursos:

  • SDK TypeScript Wormhole: O repositório do SDK Wormhole contém a implementação central dos layouts, incluindo itens de layout predefinidos e utilitários como serializeLayout e deserializeLayout.

  • Repositório de Testes de Layout: Para experimentação prática, consulte este repositório de pacotes de layout, que fornece exemplos e testes unitários para ajudar a entender melhor a serialização, desserialização e o mecanismo de tipos fortes.

PreviousWormhole TypeScript SDKNextConstrução de Protocolos e Payloads

Last updated 5 months ago