Skip to main content
This guide walks you through bridging USDC from Ethereum to NEAR. By the end, you’ll understand the pattern that works for all chains.

Install

npm install @omni-bridge/core @omni-bridge/evm

The Pattern

Every transfer follows these steps:
  1. Get fees — Query the relayer fee so your transfer gets finalized automatically
  2. Validate — Check that addresses, amounts, and tokens are valid
  3. Approve — For ERC20 tokens, approve the bridge to spend them
  4. Build & Send — Get an unsigned transaction and broadcast it
import { createBridge, ChainKind, BridgeAPI } from "@omni-bridge/core"
import { createEvmBuilder } from "@omni-bridge/evm"
import { createWalletClient, http } from "viem"
import { mainnet } from "viem/chains"
import { privateKeyToAccount } from "viem/accounts"

// Setup
const bridge = createBridge({ network: "mainnet" })
const evm = createEvmBuilder({ network: "mainnet", chain: ChainKind.Eth })
const api = new BridgeAPI("mainnet")

const account = privateKeyToAccount("0x...")
const wallet = createWalletClient({
  chain: mainnet,
  transport: http(),
  account,
})

const sender = `eth:${account.address}`
const recipient = "near:alice.near"
const token = "eth:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" // USDC
const amount = 1_000_000n // 1 USDC (6 decimals)

// 1. Get the relayer fee quote
const fee = await api.getFee(sender, recipient, token, amount)

// 2. Validate the transfer
const validated = await bridge.validateTransfer({
  token,
  amount,
  sender,
  recipient,
  fee: BigInt(fee.transferred_token_fee ?? "0"),
  nativeFee: fee.native_token_fee ?? 0n,
})

// 3. Approve the bridge to spend your tokens (ERC20 only)
const approval = evm.buildApproval(
  "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
  amount
)
await wallet.sendTransaction(approval)

// 4. Build and send the transfer
const tx = evm.buildTransfer(validated)
const hash = await wallet.sendTransaction(tx)

console.log("Transfer initiated:", hash)
That’s it. The transfer is now in progress. Because you included fees, relayers will automatically finalize it on NEAR within a few minutes.

What Just Happened

Let’s break down the key parts:

Relayer Fees

The getFee() call returns the fee required for relayers to finalize your transfer on the destination chain. You can pay in the transfer token (fee) or in native ETH (nativeFee). Without fees, you’d need to finalize manually. See Relayer Fees for more details.

OmniAddress Format

Addresses include a chain prefix so the SDK knows which chain they belong to:
"eth:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"  // Token on Ethereum
"near:alice.near"                                   // Account on NEAR
"sol:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" // Token on Solana
See OmniAddress Format for the full list.

Validation

validateTransfer() does the heavy lifting:
  • Checks that addresses are valid for their chains
  • Verifies the token is registered on the bridge
  • Ensures the amount survives decimal normalization
  • Returns a ValidatedTransfer object the builders need

Unsigned Transactions

buildTransfer() returns a plain object — not a signed transaction:
{
  to: "0x...",      // Bridge contract
  data: "0x...",    // Encoded function call
  value: 0n,        // Native token amount (for ETH transfers)
  chainId: 1        // Ethereum mainnet
}
This works directly with viem’s sendTransaction() or ethers’ signer.sendTransaction().

Using Testnet

For development, switch to testnet:
const bridge = createBridge({ network: "testnet" })
const evm = createEvmBuilder({ network: "testnet", chain: ChainKind.Eth })
Testnet uses Sepolia for Ethereum. Make sure your wallet and RPC are configured for the right network.

Track Your Transfer

Check the status using the API client:
import { BridgeAPI } from "@omni-bridge/core"

const api = new BridgeAPI("mainnet")
const status = await api.getTransferStatus({ transactionHash: hash })

console.log("Current status:", status[status.length - 1])
// "Initialized" → "Signed" → "FinalisedOnNear" → "Finalised"
See Tracking Transfers for polling patterns and status meanings.

Next Steps

Now that you understand the pattern, pick the guide for your source chain: Or learn more about the core concepts: