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 });