🌌
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. Toolkit
  4. Wormhole SDK

TypeScript SDK

O Wormhole TypeScript SDK é uma ferramenta valiosa para interagir com as blockchains suportadas pelo Wormhole e com os protocolos construídos sobre ele. Este pacote reúne funções, definições e constantes que simplificam o processo de conectar blockchains e realizar transferências utilizando o Wormhole. O SDK também oferece subpacotes específicos para plataformas integradas ao Wormhole, permitindo adicionar suporte multichain sem criar dependências excessivas.

Esta seção abrange tudo o que você precisa saber sobre as funcionalidades e a facilidade de desenvolvimento proporcionadas pelo Wormhole TypeScript SDK. Explore o pacote para descobrir como ele facilita as integrações. Entenda como o SDK abstrai as complexidades associadas a conceitos como plataformas, contextos e signatários. Por fim, você encontrará orientações sobre uso, juntamente com exemplos de código, para demonstrar como utilizar as ferramentas oferecidas pelo SDK.

Instalação

Básica

Para instalar o pacote meta usando npm, execute o seguinte comando no diretório raiz do seu projeto:

npm install @wormhole-foundation/sdk  

Este pacote combina todos os pacotes individuais, facilitando a configuração e permitindo tree shaking.

Avançada

Alternativamente, você pode instalar um conjunto específico de pacotes publicados individualmente:

Tradução Técnica

Pacotes do SDK

  • sdk-base: expõe constantes.

    npm install @wormhole-foundation/sdk-base  
  • sdk-definitions: expõe interfaces de contrato, tipos básicos e definições de payload para VAA.

    npm install @wormhole-foundation/sdk-definitions  
  • sdk-evm: expõe utilitários específicos para EVM.

    npm install @wormhole-foundation/sdk-evm  
  • sdk-evm-tokenbridge: expõe o cliente para o protocolo EVM Token Bridge.

    npm install @wormhole-foundation/sdk-evm-tokenbridge  

Uso

Iniciar sua integração é simples. Primeiro, importe o Wormhole:

import { wormhole } from '@wormhole-foundation/sdk';  

Em seguida, importe cada uma das plataformas do ecossistema que você deseja suportar:

import algorand from '@wormhole-foundation/sdk/algorand';  
import aptos from '@wormhole-foundation/sdk/aptos';  
import cosmwasm from '@wormhole-foundation/sdk/cosmwasm';  
import evm from '@wormhole-foundation/sdk/evm';  
import solana from '@wormhole-foundation/sdk/solana';  
import sui from '@wormhole-foundation/sdk/sui';  

Para tornar os módulos das plataformas utilizáveis, passe-os para o construtor do Wormhole:

const wh = await wormhole('Testnet', [  
  evm,  
  solana,  
  aptos,  
  algorand,  
  cosmwasm,  
  sui,  
]);  

Com um objeto Wormhole configurado, você pode realizar operações como:

  • Analisar endereços para as plataformas fornecidas.

  • Obter um objeto ChainContext.

  • Buscar VAAs (Verified Action Approvals).

Por exemplo, para obter um contexto de cadeia específico:

const ctx = wh.getChain('Solana');  

Para recuperar um VAA, utilize o seguinte exemplo, configurando um tempo limite de 60.000 milissegundos (60 segundos). O tempo necessário para o VAA ficar disponível pode variar de acordo com a rede:

const vaa = await wh.getVaa(  
  // ID da Mensagem Wormhole  
  whm!,  
  // Nome do Protocolo:Payload usado para decodificar o payload do VAA  
  'TokenBridge:Transfer',  
  // Tempo limite em milissegundos. Dependendo da cadeia e rede, o VAA pode levar tempo para estar disponível  
  60_000  
);  

Configuração Opcional do WormholeConfig

Você pode substituir a configuração padrão utilizando um objeto parcial do tipo WormholeConfig, para ajustar campos específicos, como um endpoint RPC diferente:

const wh = await wormhole('Testnet', [solana], {
  chains: {
    Solana: {
      contracts: {
        coreBridge: '11111111111111111111111111111',
      },
      rpc: 'https://api.devnet.solana.com',
    },
  },
});

Conceitos

Visão Geral

Compreender conceitos de alto nível do Wormhole e como o SDK abstrai essas funcionalidades pode ajudar a utilizar as ferramentas de forma mais eficaz. A seguir, abordaremos as noções de plataformas, contextos de cadeia, endereços, assinantes e protocolos. Explicaremos como cada conceito é usado no Wormhole e como o SDK simplifica o desenvolvimento em cada área.


Plataformas

Embora cada blockchain tenha características únicas, cadeias dentro da mesma plataforma compartilham funcionalidades padrão. O SDK inclui módulos de Plataforma, que fornecem uma interface padronizada para interagir com cadeias de uma mesma plataforma suportada.

Os módulos podem incluir:

  • Protocolos como o Wormhole Core, configurados para a plataforma selecionada.

  • Definições e configurações para tipos, assinantes, endereços e cadeias.

  • Utilitários para lidar com transações não assinadas na plataforma selecionada.

Esses módulos também importam e expõem funções essenciais, reduzindo a necessidade de dependências completas de pacotes nativos. Isso mantém as dependências do projeto enxutas ao instalar apenas pacotes essenciais.

Plataformas atualmente suportadas pelo Wormhole:

  • EVM

  • Solana

  • Cosmos

  • Sui

  • Aptos

  • Algorand

Para uma lista atualizada, consulte a pasta Platforms no SDK TypeScript do Wormhole.


Contexto de Cadeia (Chain Context)

O pacote sdk-definitions inclui a classe ChainContext, que cria uma interface padronizada para trabalhar com cadeias conectadas. Ela fornece:

  • Configurações de rede, cadeia e plataforma.

  • Clientes de RPC e protocolo em cache.

  • Métodos e utilitários específicos de cadeias.

Por exemplo:

const srcChain = wh.getChain(senderAddress.chain);
const dstChain = wh.getChain(receiverAddress.chain);

const tb = await srcChain.getTokenBridge(); // => TokenBridge<'Evm'>
srcChain.getRpcClient(); // => RpcClient<'Evm'>

Endereços

O SDK utiliza a classe UniversalAddress, que implementa a interface Address. Endereços de diferentes redes são convertidos em uma representação binária de 32 bytes. Cada plataforma possui um tipo de endereço nativo, chamado NativeAddress.

Exemplo:

// Converter um endereço em string para NativeAddress
const ethAddr: NativeAddress<'Evm'> = toNative('Ethereum', '0xbeef...');

// Criar um ChainAddress, adicionando o contexto da cadeia relevante
const senderAddress: ChainAddress = Wormhole.chainAddress(
  'Ethereum',
  '0xbeef...'
);
const receiverAddress: ChainAddress = Wormhole.chainAddress(
  'Solana',
  'Sol1111...'
);

// Converter o ChainAddress para o formato canônico de string
const strAddress = Wormhole.canonicalAddress(senderAddress); // => '0xbeef...'

// Converter NativeAddress para UniversalAddress
const emitterAddr = ethAddr.toUniversalAddress().toString();

Tokens

O tipo TokenId é usado para identificar exclusivamente qualquer token, seja um token padrão ou a moeda nativa de uma blockchain (como ETH no Ethereum).

Para tokens padrão, o Wormhole utiliza o endereço do contrato. Para moedas nativas, é usado o termo native no lugar de um endereço.

Exemplo:

const sourceToken: TokenId = Wormhole.tokenId('Ethereum', '0xbeef...');
const gasToken: TokenId = Wormhole.tokenId('Ethereum', 'native');

// Converter TokenId ou ChainAddress para string
const strAddress = Wormhole.canonicalAddress(senderAddress); // => '0xbeef...'

Signatários e Protocolos na Wormhole SDK

Signatários (Signers)

Certos métodos para assinar transações no SDK da Wormhole requerem a interface Signer, que pode ser implementada por dois tipos principais:

  • SignOnlySigner: Ideal para casos onde o signatário está offline ou prefere não transmitir transações diretamente. Este recebe um array de transações não assinadas e retorna um array de transações assinadas e serializadas. Antes da assinatura, é possível inspecionar ou alterar as transações. A serialização depende da blockchain em uso (por exemplo, EVM ou Solana).

  • SignAndSendSigner: Utilizado quando o signatário está conectado à rede e pretende enviar as transações. Ele também aceita um array de transações não assinadas, mas retorna IDs das transações na mesma ordem do array original.

Definições de Tipos:

export type Signer = SignOnlySigner | SignAndSendSigner;

export interface SignOnlySigner {
  chain(): ChainName;
  address(): string;
  sign(tx: UnsignedTransaction[]): Promise<SignedTx[]>;
}

export interface SignAndSendSigner {
  chain(): ChainName;
  address(): string;
  signAndSend(tx: UnsignedTransaction[]): Promise<TxHash[]>;
}

Configurando um Signatário com Ethers.js

Para gerenciar assinaturas programaticamente, é possível integrar o Ethers.js. Aqui está um exemplo prático:

import { ethers } from 'ethers';

const rpcUrl = 'INSIRA_URL_RPC';
const privateKey = 'INSIRA_CHAVE_PRIVADA';
const toAddress = 'INSIRA_ENDEREÇO_DESTINO';

const provider = new ethers.JsonRpcProvider(rpcUrl);
const signer = new ethers.Wallet(privateKey, provider);

async function sendTransaction() {
  const tx = {
    to: toAddress,
    value: ethers.parseUnits('0.1'),
    gasPrice: await provider.getGasPrice(),
    gasLimit: ethers.toBeHex(21000),
  };

  const transaction = await signer.sendTransaction(tx);
  console.log('Hash da transação:', transaction.hash);
}
sendTransaction();

Componentes principais:

  • Provider: Conecta o aplicativo à rede blockchain, permitindo consultas e envio de transações.

  • Signer: Representa a conta que autoriza transações por meio de assinaturas digitais.

  • Wallet: Combina o provider e o signer, facilitando a assinatura e envio de transações.

Boas práticas para gerenciamento de chaves privadas:

  • Use variáveis de ambiente para evitar armazenar chaves diretamente no código.

  • Considere carteiras físicas (hardware wallets) em ambientes de produção.


Protocolos

Wormhole Core

O Wormhole Core é o protocolo central responsável pela emissão de mensagens para interoperabilidade entre blockchains. Estas mensagens contêm:

  • Endereço do emissor.

  • Número de sequência.

  • Payload (dados da mensagem).

Exemplo de Uso no Solana:

import { wormhole, encoding, signSendWait } from '@wormhole-foundation/sdk';
import solana from '@wormhole-foundation/sdk/solana';

(async function () {
  const wh = await wormhole('Testnet', [solana]);
  const chain = wh.getChain('Solana');
  const { signer, address } = await chain.getSigner();

  const coreBridge = await chain.getWormholeCore();
  const publishTxs = coreBridge.publishMessage(
    address.address,
    encoding.bytes.encode('Hello, Wormhole!'),
    0, // Nonce
    0  // Consistency level
  );

  const txids = await signSendWait(chain, publishTxs, signer);
  const [whm] = await chain.parseTransaction(txids[txids.length - 1].txid);
  const vaa = await wh.getVaa(whm, 'Uint8Array', 60_000);
  console.log(vaa);
})();

Token Bridge

Este protocolo, construído sobre o Wormhole Core, fornece uma interface consistente para transferências de tokens entre blockchains.

Exemplo de Transferência de Tokens:

import { signSendWait } from '@wormhole-foundation/sdk';

const tb = await srcChain.getTokenBridge();
const token = '0xdeadbeef...';
const txGenerator = tb.createAttestation(token);
const txids = await signSendWait(srcChain, txGenerator, src.signer);

Transfers

A interface WormholeTransfer facilita transferências cross-chain de tokens, oferecendo uma abstração que engloba todas as etapas do processo, desde a origem até o destino.

Exemplo Completo de Transferência de Tokens:

const xfer = await wh.tokenTransfer(
  route.token,
  route.amount,
  route.source.address,
  route.destination.address,
  route.delivery?.automatic ?? false,
  route.payload,
  route.delivery?.nativeGas
);

const srcTxids = await xfer.initiateTransfer(route.source.signer);
console.log('Transferência iniciada:', srcTxids);

if (!route.delivery?.automatic) {
  const attestIds = await xfer.fetchAttestation(60_000);
  console.log('Attestation recebida:', attestIds);

  const destTxids = await xfer.completeTransfer(route.destination.signer);
  console.log('Transferência completada:', destTxids);
}

Etapas principais:

  1. Iniciar a transferência na cadeia de origem.

  2. Aguardar a attestation (se necessário).

  3. Completar a transferência na cadeia de destino.

Internamente, o sistema utiliza o cliente do protocolo TokenBridge para realizar transferências de tokens. Como outros protocolos, o TokenBridge fornece um conjunto consistente de métodos para todas as blockchains suportadas, gerando um conjunto de transações específicas para cada cadeia.

Transferências de USDC Nativo

Também é possível transferir USDC nativo utilizando o CCTP da Circle. Note que, no modo Automático, uma taxa pelo serviço de relay será incluída no valor da cotação. Esta taxa será deduzida do montante total solicitado para envio. Por exemplo, se o usuário deseja receber 1,0 no destino, o valor enviado deve ser ajustado para 1,0 acrescido da taxa de relay. O mesmo se aplica para entregas de gas nativo.

No exemplo a seguir, a função wh.circleTransfer é chamada com vários parâmetros para configurar a transferência. Esta função recebe:

  • O valor a ser transferido (em unidades base do token),

  • A cadeia e o endereço do remetente,

  • A cadeia e o endereço do destinatário,

  • Um booleano para definir se a transferência será automática,

  • Um payload opcional (definido como undefined neste exemplo),

  • E, se a transferência for automática, a opção de enviar gas nativo (a moeda nativa da blockchain) ao destinatário.

Além disso, é configurado um tempo limite de 60.000 milissegundos para aguardar a VAA (Verified Action Approval), que varia de acordo com a rede.

Exemplo de código:

const xfer = await wh.circleTransfer(
  req.amount,       // Quantia em bigint (unidades base)
  src.address,      // Cadeia/endereço do remetente
  dst.address,      // Cadeia/endereço do destinatário
  req.automatic,    // Entrega automática
  undefined,        // Payload opcional
  req.nativeGas     // Solicitação de gas nativo
);

// Cotação para transferência automática
const quote = await CircleTransfer.quoteTransfer(
  src.chain,
  dst.chain,
  xfer.transfer
);
console.log('Cotação', quote);

// Início da transferência
const srcTxids = await xfer.initiateTransfer(src.signer);
console.log('Transferência iniciada:', srcTxids);

if (req.automatic) {
  const relayStatus = await waitForRelay(srcTxids[srcTxids.length - 1]!);
  console.log('Relay concluído:', relayStatus);
  return;
}

// Processo manual
console.log('Aguardando Attestation');
const attestIds = await xfer.fetchAttestation(60_000);
console.log('Attestation obtido:', attestIds);

console.log('Concluindo a transferência');
const dstTxids = await xfer.completeTransfer(dst.signer);
console.log('Transferência concluída:', dstTxids);

Recuperação de Transferências

Caso uma transferência seja abandonada antes da conclusão, é possível recuperá-la. Para isso, utilize a classe Transfer com o método estático from, passando um TransactionId ou WormholeMessageId para identificar a transferência.

Exemplo de código:

const xfer = await CircleTransfer.from(wh, txid);

const attestIds = await xfer.fetchAttestation(60 * 60 * 1000);
console.log('Attestation obtido:', attestIds);

const dstTxIds = await xfer.completeTransfer(signer);
console.log('Transferência concluída:', dstTxIds);

Rotas

O uso de transferências específicas, como TokenTransfer ou CCTPTransfer, exige que o desenvolvedor saiba qual tipo de transferência utilizar. Para simplificar, a classe Wormhole oferece um método que gera um RouteResolver, configurado com um conjunto de rotas possíveis.

Exemplo de Configuração de Rotas:

const resolver = wh.resolver([
  routes.TokenBridgeRoute,      // Token bridge manual
  routes.AutomaticTokenBridgeRoute, // Token bridge automático
  routes.CCTPRoute,             // CCTP manual
  routes.AutomaticCCTPRoute,    // CCTP automático
  routes.AutomaticPorticoRoute, // Transferências nativas de ETH
]);

// Tokens disponíveis na cadeia de origem
const srcTokens = await resolver.supportedSourceTokens(sendChain);
console.log('Tokens de origem permitidos:', srcTokens.map(canonicalAddress));

// Seleção do token de envio
const sendToken = Wormhole.tokenId(sendChain.chain, 'native');

// Tokens disponíveis no destino
const destTokens = await resolver.supportedDestinationTokens(
  sendToken,
  sendChain,
  destChain
);
console.log('Tokens disponíveis no destino:', destTokens.map(canonicalAddress));

// Configuração de transferência
const tr = await routes.RouteTransferRequest.create(wh, {
  source: sendToken,
  destination: destinationToken,
});

// Validação e cotação
const validated = await bestRoute.validate(tr, { amount: '0.001', options: { nativeGas: 0 } });
const quote = await bestRoute.quote(tr, validated.params);

// Inicia a transferência
const receipt = await bestRoute.initiate(tr, sender.signer, quote, receiver.address);
console.log('Transferência iniciada com recibo:', receipt);

Considerações

Essa abordagem oferece flexibilidade na escolha de rotas e configurações, mas a responsabilidade de selecionar a melhor rota (com base no tempo estimado, taxas e outros critérios) permanece com o desenvolvedor.

Veja o exemplo de router.ts no diretório de exemplos para um exemplo completo funcional.

Rotas como Plugins

As rotas podem ser importadas de qualquer pacote npm que as exporte e configuradas com o resolver. Rotas personalizadas devem estender a classe Route e implementar os métodos estáticos definidos em StaticRouteMethods.

Aqui está um exemplo de como criar uma rota personalizada:

import { Network, routes } from '@wormhole-foundation/sdk-connect';

export class CustomRoute<N extends Network>
  extends routes.Route<N>
  implements routes.StaticRouteMethods<typeof CustomRoute>
{
  static meta = {
    name: 'CustomRoute',
  };
  // implementação...
}

Exemplo Notável

Um exemplo notável de uma rota exportada de um pacote npm separado é o Wormhole Native Token Transfers (NTT). Confira a implementação da rota NttAutomaticRoute para detalhes.

Consulte Também

PreviousWormhole SDKNextData Layouts

Last updated 4 months ago

A documentação completa em TSdoc está disponível no.

GitHub