@zethub/bridge
Reference

Types

Every public type the SDK exports.

The SDK is fully typed. Every value you touch, from the tokens to the raw transactions to the transfer records, has a first class type. This page lists the public shapes.

Raw transactions

type RawTransaction = RawEvmTransaction | RawSorobanTransaction;

interface RawEvmTransaction {
  family: "evm";
  chainId: number;
  from: `0x${string}`;
  to: `0x${string}`;
  data: `0x${string}`;
  value?: bigint;
}

interface RawSorobanTransaction {
  family: "stellar";
  networkPassphrase: string;
  from: string;
  xdr: string; // already prepared, ready to sign
}

function isRawEvm(tx: RawTransaction): tx is RawEvmTransaction;
function isRawSoroban(tx: RawTransaction): tx is RawSorobanTransaction;

Tokens and networks

interface TokenWithChainDetails {
  symbol: AssetSymbol;
  name: string;
  decimals: number;
  address: string;
  issuer?: string;      // Stellar only
  assetCode?: string;   // Stellar only
  logoUrl?: string;
  chainSymbol: NetworkIdInput;
  network: Network;
}

interface ChainDetails {
  network: Network;
  tokens: readonly TokenWithChainDetails[];
}

type ChainDetailsMap = Record<string, ChainDetails>;

class Network {
  readonly id: string;
  readonly name: string;
  readonly shortName: string;
  readonly family: ChainFamily;
  readonly environment: Environment;
  readonly cctpDomain: number;
  readonly evmChainId?: number;
  readonly stellarPassphrase?: string;
  readonly tokens: readonly TokenAsset[];
  readonly defaultAsset: AssetSymbol;
  readonly tokenMessenger: string;
  readonly messageTransmitter: string;
  readonly cctpForwarder?: string;
  readonly rpcUrls: readonly string[];
  readonly explorerUrl: string;
  readonly accentColor: string;

  hasToken(symbol: AssetSymbol): boolean;
  token(symbol?: AssetSymbol): TokenAsset;
  isEvm(): boolean;
  isStellar(): boolean;
}

class TokenAsset {
  readonly symbol: AssetSymbol;
  readonly name: string;
  readonly decimals: number;
  readonly address: string;
  readonly issuer?: string;
  readonly assetCode?: string;
  readonly logoUrl?: string;
}

Amount

Amount wraps a fixed-point token value as a bigint plus its decimals so arithmetic stays exact and display is easy. The primary factories take a ChainFamily and resolve USDC decimals internally: 6 on EVM, 7 on Stellar. Non-USDC amounts (native gas, custom tokens) use the WithDecimals variants.

class Amount {
  readonly raw: bigint;
  readonly decimals: number;

  // USDC: pick the family, decimals are set for you
  static fromRaw(raw: bigint, family: ChainFamily): Amount;
  static fromHuman(value: string | number, family: ChainFamily): Amount;

  // Non-USDC escape hatches
  static fromRawWithDecimals(raw: bigint, decimals: number): Amount;
  static fromHumanWithDecimals(value: string | number, decimals: number): Amount;

  scaleTo(newDecimals: number): Amount;
  toHuman(displayDecimals?: number): string;
  gte(other: Amount): boolean;
  isZero(): boolean;
}

Examples:

Amount.fromHuman("5.25", ChainFamily.EVM).raw;      // 5_250_000n  (6 decimals)
Amount.fromHuman("5.25", ChainFamily.STELLAR).raw;  // 52_500_000n (7 decimals)

Amount.fromRawWithDecimals(1_500_000_000_000_000_000n, 18).toHuman(); // "1.5"

Address validation

class Address {
  static isEvm(value: string): boolean;
  static isStellar(value: string): boolean;
  static parseEvm(value: string): `0x${string}`;
  static parseStellar(value: string): string;
  static validate(value: string, family: ChainFamily): AddressValidation;
  static checksumEvm(value: string): `0x${string}`;
}

interface AddressValidation {
  valid: boolean;
  reason?: ValidationMessage;
}

Attestation

interface AttestationEnvelope {
  message: `0x${string}`;
  attestation: `0x${string}`;
  eventNonce?: string;
  status: AttestationStatus; // "pending_confirmations" | "complete"
}

interface AttestationPollUpdate {
  attempt: number;
  status?: AttestationStatus;
  delayReason?: string;
}

interface AttestationWaitOptions {
  intervalMs?: number;
  timeoutMs?: number;
  onPoll?: (update: AttestationPollUpdate) => void;
}

Bridge results

interface BridgeQuote {
  feeBps: number;
  minFinalityThreshold: number;
  estimatedSeconds: number;
}

interface BridgeTransactionState {
  status: BridgeStatus;
  burnTxHash?: string;
  mintTxHash?: string;
  messageHex?: string;
  attestationHex?: string;
  error?: string;
  startedAt?: number;
  completedAt?: number;
  events?: BridgeEventRecord[];
}

interface BridgeEventRecord {
  name: string;
  side: BridgeSide;
  txHash?: string;
  block?: number;
  observedAt: number;
}

interface BridgeMemo {
  type: MemoType;
  value: string;
}

Enums

const ChainFamily = { EVM: "evm", STELLAR: "stellar" };
const Environment = { MAINNET: "mainnet", TESTNET: "testnet" };
const BridgeStatus = {
  IDLE: "idle",
  APPROVING: "approving",
  BURNING: "burning",
  WAITING_ATTESTATION: "waiting_attestation",
  MINTING: "minting",
  COMPLETED: "completed",
  FAILED: "failed",
};
const BridgeSide = { SOURCE: "source", DESTINATION: "destination" };
const FinalityThreshold = { FAST: 1000, STANDARD: 2000 };
const MemoType = { TEXT: "text", ID: "id", HASH: "hash", RETURN: "return" };
const AttestationStatus = {
  PENDING: "pending_confirmations",
  COMPLETE: "complete",
};
const AssetSymbol = { USDC: "USDC" };

Types for the values are exported alongside each constant object (type Environment = ..., etc).

Ports (interfaces)

Implement any of these to swap out a piece of the SDK.

interface IChainConnector {
  readonly family: ChainFamily;
  buildApproveTx(params: BuildApproveTxParams): Promise<RawTransaction>;
  buildBurnTx(params: BuildBurnTxParams): Promise<RawTransaction>;
  buildReceiveTx(params: BuildReceiveTxParams): Promise<RawTransaction>;
  getAllowance(params: GetAllowanceOnChainParams): Promise<Amount>;
  getTokenBalance(params: GetTokenBalanceOnChainParams): Promise<Amount>;
  getNativeBalance(params: GetNativeBalanceOnChainParams): Promise<Amount>;
}

interface IAttestationService {
  host(environment: Environment): string;
  waitForAttestation(params: WaitForAttestationParams): Promise<AttestationResult>;
}

interface IFeeService {
  getQuote(params: FeeQuoteParams): Promise<BridgeQuote>;
}

interface INetworkService {
  list(environment: Environment): readonly Network[];
  byId(environment: Environment, id: string): Network | undefined;
  byDomain(environment: Environment, domain: number): Network | undefined;
  byEvmChainId(environment: Environment, chainId: number): Network | undefined;
}

On this page