@zethub/bridge
Getting started

Quick start

Bridge USDC from Base Sepolia to Stellar testnet in one page.

The full flow

Every bridge is three signed transactions: an approve, a burn, and a receive. The SDK builds all three as unsigned RawTransaction objects. You sign and broadcast them with the wallet library you already use.

import {
  ZetHubBridge,
  NetworkId,
  AssetSymbol,
  Environment,
} from "@zethub/bridge";

const sdk = new ZetHubBridge({ environment: Environment.TESTNET });

// 1. Discovery
const chains = await sdk.chainDetailsMap();
const sourceToken = chains[NetworkId.BASE_SEPOLIA].tokens.find(
  (t) => t.symbol === AssetSymbol.USDC,
)!;
const destinationToken = chains[NetworkId.STELLAR_TESTNET].tokens.find(
  (t) => t.symbol === AssetSymbol.USDC,
)!;

// 2. Allowance check (optional)
const enough = await sdk.bridge.checkAllowance({
  token: sourceToken,
  owner: myEvmAddress,
  amount: "1.0",
});

if (!enough) {
  const approveTx = await sdk.bridge.rawTxBuilder.approve({
    token: sourceToken,
    owner: myEvmAddress,
  });
  await sendEvm(approveTx); // your wallet code
}

// 3. Build and broadcast the burn
const burnTx = await sdk.bridge.rawTxBuilder.send({
  sourceToken,
  destinationToken,
  amount: "1.0",
  fromAccountAddress: myEvmAddress,
  toAccountAddress: myStellarAddress,
});
const burnHash = await sendEvm(burnTx);

// 4. Wait for Circle to attest
const att = await sdk.attestation.waitFor(
  NetworkId.BASE_SEPOLIA,
  burnHash,
  { onPoll: ({ attempt }) => console.log("Iris attempt", attempt) },
);

// 5. Build and broadcast the mint
const mintTx = await sdk.bridge.rawTxBuilder.receive({
  destinationToken,
  toAccountAddress: myStellarAddress,
  message: att.message,
  attestation: att.attestation,
});
await sendSoroban(mintTx);

That is the entire flow. See Signing transactions for the sendEvm and sendSoroban glue.

Discovery without a signer

Every read call works without any wallet setup. Chains, tokens, quotes, balances, and allowances are all available on a bare instance.

const sdk = new ZetHubBridge();

await sdk.chainDetailsMap();
await sdk.tokens();
await sdk.tokensByChain(NetworkId.ETHEREUM);
await sdk.getTokenBalance({ token, address });
await sdk.getGasBalance({ chainSymbol: NetworkId.ETHEREUM, address });

await sdk.bridge.quote({ sourceToken, destinationToken });
await sdk.bridge.getAllowance({ token, owner });

Next

On this page