Transferir Tokens via a Token Bridge
Este tutorial orienta você na construção de uma aplicação de transferência de tokens cross-chain usando o SDK TypeScript do Wormhole e seu método Token Bridge. O método Token Bridge permite transferências seguras e eficientes de ativos entre diferentes redes blockchain, permitindo que os usuários movam tokens de maneira contínua.
Aproveitando o Token Bridge do Wormhole, este guia mostra como construir uma aplicação que suporta vários tipos de transferências:
EVM para EVM (por exemplo, Ethereum para Avalanche)
EVM para blockchains não EVM (por exemplo, Ethereum para Solana)
Não EVM para EVM (por exemplo, Sui para Avalanche)
Não EVM para não EVM (por exemplo, Solana para Sui)
Soluções existentes para transferências cross-chain podem ser complexas e ineficientes, exigindo múltiplos passos e taxas de transação. No entanto, o método Token Bridge do Wormhole simplifica o processo ao lidar com a atestação subjacente, validação de transações e passagem de mensagens entre blockchains.
Ao final deste guia, você terá uma configuração totalmente funcional para transferir ativos entre blockchains usando o método Token Bridge do Wormhole.
Pré-requisitos Antes de começar, certifique-se de ter o seguinte:
Node.js e npm instalados em sua máquina
TypeScript instalado globalmente
Tokens nativos (testnet ou mainnet) nas carteiras de Solana e Sui
Uma carteira com uma chave privada, alimentada com tokens nativos (testnet ou mainnet) para taxas de gas
Blockchains Suportadas
O SDK Wormhole suporta uma ampla gama de blockchains EVM e não-EVM, permitindo que você facilite transferências cross-chain de forma eficiente. Você pode encontrar uma lista completa de blockchains suportados no repositório GitHub do SDK Wormhole, que cobre ambientes testnet e mainnet.
Configuração do Projeto Nesta seção, vamos guiá-lo através da inicialização do projeto, instalação de dependências e preparação do ambiente para transferências cross-chain.
Inicialize o projeto - comece criando um novo diretório para seu projeto e inicializando-o com npm, o que criará o arquivo package.json para seu projeto:
mkdir native-transfers
cd native-transfers
npm init -y
Instale as dependências - instale as dependências necessárias, incluindo o SDK Wormhole e bibliotecas auxiliares:
npm install @wormhole-foundation/sdk dotenv tsx
Configure variáveis de ambiente - para armazenar sua chave privada de forma segura, crie um arquivo .env na raiz do seu projeto:
otouch .env
Dentro do arquivo .env, adicione suas chaves privadas:
ETH_PRIVATE_KEY="INSIRA_SUA_CHAVE_PRIVADA"
SOL_PRIVATE_KEY="INSIRA_SUA_CHAVE_PRIVADA"
SUI_PRIVATE_KEY="INSIRA_SUA_MNEMONICA_SUI"
Nota: Certifique-se de que sua chave privada contenha tokens nativos para gas em ambas as blockchains de origem e destino. Para Sui, você deve fornecer uma mnemônica em vez de uma chave privada.
Crie um arquivo helpers.ts - para simplificar a interação entre as blockchains, crie um arquivo para armazenar funções utilitárias que buscam sua chave privada, configuram signers para diferentes blockchains e gerenciam os relays de transações.
Crie o arquivo helpers:
mkdir -p src/helpers
touch src/helpers/helpers.ts
Abra o arquivo helpers.ts e adicione o seguinte código:
import {
ChainAddress,
ChainContext,
Network,
Signer,
Wormhole,
Chain,
TokenId,
isTokenId,
} from '@wormhole-foundation/sdk';
import evm from '@wormhole-foundation/sdk/evm';
import solana from '@wormhole-foundation/sdk/solana';
import sui from '@wormhole-foundation/sdk/sui';
import { config } from 'dotenv';
config();
export interface SignerStuff<N extends Network, C extends Chain> {
chain: ChainContext<N, C>;
signer: Signer<N, C>;
address: ChainAddress<C>;
}
// Função para buscar variáveis de ambiente (como sua chave privada)
function getEnv(key: string): string {
const val = process.env[key];
if (!val) throw new Error(`Variável de ambiente ausente: ${key}`);
return val;
}
// Função para configurar o signer em diferentes plataformas blockchain
export async function getSigner<N extends Network, C extends Chain>(
chain: ChainContext<N, C>
): Promise<{
chain: ChainContext<N, C>;
signer: Signer<N, C>;
address: ChainAddress<C>;
}> {
let signer: Signer;
const platform = chain.platform.utils()._platform;
switch (platform) {
case 'Solana':
signer = await (
await solana()
).getSigner(await chain.getRpc(), getEnv('SOL_PRIVATE_KEY'));
break;
case 'Evm':
signer = await (
await evm()
).getSigner(await chain.getRpc(), getEnv('ETH_PRIVATE_KEY'));
break;
case 'Sui':
signer = await (
await sui()
).getSigner(await chain.getRpc(), getEnv('SUI_PRIVATE_KEY'));
break;
default:
throw new Error('Plataforma não suportada: ' + platform);
}
return {
chain,
signer: signer as Signer<N, C>,
address: Wormhole.chainAddress(chain.chain, signer.address()),
};
}
export async function getTokenDecimals<
N extends 'Mainnet' | 'Testnet' | 'Devnet'
>(
wh: Wormhole<N>,
token: TokenId,
sendChain: ChainContext<N, any>
): Promise<number> {
return isTokenId(token)
? Number(await wh.getDecimals(token.chain, token.address))
: sendChain.config.nativeTokenDecimals;
}
Explicação das funções:
getEnv
: Essa função busca variáveis de ambiente, como sua chave privada, do arquivo .env.getSigner
: Dependendo da blockchain com a qual você está trabalhando (EVM, Solana, Sui, etc.), essa função recupera o signer para essa plataforma específica. O signer é responsável por assinar transações e interagir com a blockchain, utilizando a chave privada armazenada no arquivo .env.getTokenDecimals
: Essa função busca o número de casas decimais de um token em uma blockchain específica, ajudando a tratar os valores de tokens com precisão durante as transferências.
Transferências de Tokens Nativos Nesta seção, você criará um script para transferir tokens nativos entre blockchains usando o método Token Bridge do Wormhole. O script lidará com a transferência de tokens nativos de Sui para Solana, demonstrando as capacidades de transferência cross-chain do SDK Wormhole. Como ambas as blockchains não são compatíveis com EVM, você precisará lidar manualmente com as etapas de atestação e finalização.
Configuração dos Detalhes da Transferência Antes de iniciar uma transferência cross-chain, você deve configurar o contexto das blockchains e os signers para as blockchains de origem e destino.
Crie o arquivo native-transfer.ts na pasta src para armazenar o script de transferência de tokens nativos entre as blockchains:
mkdir -p src/scripts
touch src/scripts/native-transfer.ts
Abra o arquivo native-transfer.ts e comece importando os módulos necessários do SDK e dos arquivos auxiliares:
import {
Chain,
Network,
Wormhole,
amount,
wormhole,
TokenId,
TokenTransfer,
} from '@wormhole-foundation/sdk';
import evm from '@wormhole-foundation/sdk/evm';
import solana from '@wormhole-foundation/sdk/solana';
import sui from '@wormhole-foundation/sdk/sui';
import { SignerStuff, getSigner, getTokenDecimals } from '../helpers/helpers';
Nota: Você pode substituir 'Testnet' por 'Mainnet' se quiser realizar transferências na Mainnet.
Prossiga com a configuração das blockchains de origem e destino, recuperando as respectivas redes com o método getChain
e configurando os signers para realizar as transferências entre elas.
native-transfer.ts
import {
Chain,
Network,
Wormhole,
amount,
wormhole,
TokenId,
TokenTransfer,
} from '@wormhole-foundation/sdk';
import evm from '@wormhole-foundation/sdk/evm';
import solana from '@wormhole-foundation/sdk/solana';
import sui from '@wormhole-foundation/sdk/sui';
import { SignerStuff, getSigner, getTokenDecimals } from '../helpers/helpers';
(async function () {
const wh = await wormhole('Testnet', [evm, solana, sui]);
// Configuração das blockchains de origem e destino
const sendChain = wh.getChain('Sui');
const rcvChain = wh.getChain('Solana');
// Obter o signatário a partir da chave local, mas qualquer implementação pode ser usada
const source = await getSigner(sendChain);
const destination = await getSigner(rcvChain);
// Atalho para permitir a transferência do token nativo (gas)
const token = Wormhole.tokenId(sendChain.chain, 'native');
// Definir a quantidade de tokens a serem transferidos
const amt = '1';
// Configurar transferência automática como falsa para transferência manual
const automatic = false;
// Usado para normalizar a quantidade de tokens considerando as casas decimais
const decimals = await getTokenDecimals(wh, token, sendChain);
// Realizar a transferência de token caso nenhum ID de transação de recuperação seja fornecido
const xfer = await tokenTransfer(wh, {
token,
amount: amount.units(amount.parse(amt, decimals)),
source,
destination,
automatic,
});
process.exit(0);
})();
async function tokenTransfer<N extends Network>(wh: Wormhole<N>, route: { token: TokenId; amount: bigint; source: SignerStuff<N, Chain>; destination: SignerStuff<N, Chain>; automatic: boolean; payload?: Uint8Array; }) {
// Lógica de Transferência de Token
// Criar um objeto TokenTransfer para acompanhar o estado da transferência ao longo do tempo
const xfer = await wh.tokenTransfer(route.token, route.amount, route.source.address, route.destination.address, route.automatic ?? false, route.payload);
const quote = await TokenTransfer.quoteTransfer(wh, route.source.chain, route.destination.chain, xfer.transfer);
if (xfer.transfer.automatic && quote.destinationToken.amount < 0)
throw 'A quantidade solicitada é muito baixa para cobrir a taxa e o gás nativo solicitado.';
// Submeter as transações para a cadeia de origem, passando um signatário para assinar qualquer transação
console.log('Iniciando a transferência');
const srcTxids = await xfer.initiateTransfer(route.source.signer);
console.log(`ID da Transação na Fonte: ${srcTxids[0]}`);
console.log(`ID da Transação Wormhole: ${srcTxids[1] ?? srcTxids[0]}`);
// Aguardar a assinatura da VAA (não necessário para transferências automáticas)
console.log('Obtendo a Atentação');
await xfer.fetchAttestation(60_000);
// Resgatar a VAA na cadeia de destino
console.log('Finalizando Transferência');
const destTxids = await xfer.completeTransfer(route.destination.signer);
console.log(`Transferência Concluída: `, destTxids);
}
Executando a Transferência de Token Nativo
Agora que você configurou o projeto e definiu a lógica de transferência, pode executar o script para transferir tokens nativos da cadeia Sui para Solana. Você pode usar o comando tsx
para rodar diretamente o arquivo TypeScript:
npx tsx src/scripts/native-transfer.ts
Isso iniciará a transferência do token nativo da cadeia de origem (Sui) e a concluirá na cadeia de destino (Solana).
Você pode monitorar o status da transação no explorador Wormhole.
Recursos Se você deseja explorar o projeto completo ou precisa de uma referência enquanto segue este tutorial, pode encontrar o código completo no repositório demo do Wormhole no GitHub. O repositório inclui todos os scripts e configurações de exemplo necessários para realizar transferências de tokens nativos entre cadeias, incluindo transferências manuais, automáticas e parciais usando o SDK Wormhole.
Conclusão Você construiu com sucesso uma aplicação de transferência de tokens entre cadeias utilizando o SDK TypeScript do Wormhole e o método Token Bridge. Este guia percorreu a configuração, a configuração e a lógica de transferência necessárias para mover tokens nativos entre cadeias não compatíveis com EVM, como Sui e Solana.
A mesma lógica de transferência se aplica caso você deseje estender essa aplicação para diferentes combinações de cadeias, incluindo cadeias compatíveis com EVM.
Last updated