Skip to main content
The Mina class is the main entry point for the Mina Bridge SDK. It provides a unified interface for bridging assets to HyperEVM and depositing to Hyperliquid L1.

Constructor

import { Mina } from '@mina-bridge/sdk';

const mina = new Mina(config: MinaConfig);

MinaConfig

ParameterTypeRequiredDescription
integratorstringYesUnique identifier for your application
rpcUrlsRecord<number, string>NoCustom RPC URLs by chain ID
autoDepositbooleanNoEnable automatic deposit to Hyperliquid L1 after bridge (default: true)
defaultSlippagenumberNoDefault slippage tolerance in decimal format (0.005 = 0.5%)

Example

const mina = new Mina({
  integrator: 'my-trading-app',
  autoDeposit: true,
  defaultSlippage: 0.005, // 0.5%
});

Chain Methods

getChains()

Get all supported source chains for bridging.
async getChains(): Promise<Chain[]>
Returns: Array of 40+ supported origin chains with metadata. Throws: ChainFetchError if API fails and no cache available. Example:
const chains = await mina.getChains();
console.log(`${chains.length} chains supported`);
// Displays: "50 chains supported"

chains.forEach(chain => {
  console.log(`${chain.name} (ID: ${chain.id})`);
});

getDestinationChains()

Get destination chains (HyperEVM).
getDestinationChains(): Chain[]
Returns: Array containing the HyperEVM chain. Example:
const destinations = mina.getDestinationChains();
console.log(destinations[0].name); // "HyperEVM"
console.log(destinations[0].id);   // 999

getChainsByRoutes(toChainId?)

Get chains with valid bridge routes to a specific destination.
async getChainsByRoutes(toChainId?: number): Promise<Chain[]>
ParameterTypeDefaultDescription
toChainIdnumber999Destination chain ID (HyperEVM)
Example:
// Get only chains that can bridge to HyperEVM
const bridgeableChains = await mina.getChainsByRoutes();
console.log(`${bridgeableChains.length} chains can bridge to HyperEVM`);

getChainById(chainId)

Get a specific chain by its ID.
async getChainById(chainId: number): Promise<Chain | undefined>
Example:
const ethereum = await mina.getChainById(1);
console.log(ethereum?.name); // "Ethereum"

const arbitrum = await mina.getChainById(42161);
console.log(arbitrum?.name); // "Arbitrum One"

Token Methods

getTokens(chainId)

Get all available tokens for a specific chain.
async getTokens(chainId: number): Promise<Token[]>
Throws: TokenFetchError if API fails and no cache available. Example:
// Get Ethereum tokens
const tokens = await mina.getTokens(1);
console.log(`Found ${tokens.length} tokens on Ethereum`);

// Find USDC
const usdc = tokens.find(t => t.symbol === 'USDC');
console.log(`USDC address: ${usdc?.address}`);

getBridgeableTokens(chainId)

Get tokens that can be bridged from a specific chain to HyperEVM.
async getBridgeableTokens(chainId: number): Promise<Token[]>
Example:
// Get only tokens that can bridge from Ethereum to HyperEVM
const bridgeableTokens = await mina.getBridgeableTokens(1);
console.log(`${bridgeableTokens.length} tokens can bridge to HyperEVM`);

getDestinationTokens()

Get tokens available on HyperEVM destination.
getDestinationTokens(): Token[]
Returns: Array of tokens receivable on HyperEVM (USDC, HYPE). Example:
const destTokens = mina.getDestinationTokens();
console.log(destTokens.map(t => t.symbol)); // ['USDC', 'HYPE']

getTokenByAddress(chainId, tokenAddress)

Get a specific token by its address on a chain.
async getTokenByAddress(
  chainId: number,
  tokenAddress: string
): Promise<Token | undefined>
Example:
const usdc = await mina.getTokenByAddress(
  1,
  '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
);
console.log(usdc?.symbol); // 'USDC'

Balance Methods

getBalance(chainId, tokenAddress, walletAddress)

Get token balance for a wallet address.
async getBalance(
  chainId: number,
  tokenAddress: string,
  walletAddress: string
): Promise<BalanceWithMetadata>
Throws: BalanceFetchError if API fails and no cache available. Example:
import { NATIVE_TOKEN_ADDRESS } from '@mina-bridge/sdk';

// Get USDC balance on Ethereum
const balance = await mina.getBalance(
  1,
  '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  '0xYourWallet...'
);
console.log(`Balance: ${balance.formatted} ${balance.token.symbol}`);
console.log(`USD Value: $${balance.balanceUsd?.toFixed(2) ?? 'N/A'}`);

// Get native ETH balance
const ethBalance = await mina.getBalance(
  1,
  NATIVE_TOKEN_ADDRESS,
  '0xYourWallet...'
);
console.log(`ETH Balance: ${ethBalance.formatted}`);

getBalances(walletAddress, chainIds, tokenAddresses?)

Get token balances across multiple chains in parallel.
async getBalances(
  walletAddress: string,
  chainIds: number[],
  tokenAddresses?: Record<number, string[]>
): Promise<BalancesResponse>
Example:
// Get native token balances on Ethereum and Arbitrum
const response = await mina.getBalances('0x...', [1, 42161]);
console.log(`Total USD: $${response.totalUsd.toFixed(2)}`);

// Get specific token balances
const response = await mina.getBalances('0x...', [1], {
  1: ['0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'] // USDC on Ethereum
});

getChainBalances(walletAddress, chainId)

Get all supported token balances for a specific chain.
async getChainBalances(
  walletAddress: string,
  chainId: number
): Promise<BalanceWithMetadata[]>
Example:
const balances = await mina.getChainBalances('0x...', 1);
for (const balance of balances) {
  if (balance.hasBalance) {
    console.log(`${balance.token.symbol}: ${balance.formatted}`);
  }
}

Quote Methods

getQuote(params, timeoutMs?)

Get a single optimal bridge quote.
async getQuote(
  params: QuoteParams,
  timeoutMs?: number
): Promise<Quote>
QuoteParams:
ParameterTypeRequiredDescription
fromChainIdnumberYesSource chain ID
toChainIdnumberNoDestination chain ID (default: 999 HyperEVM)
fromTokenstringYesSource token address
toTokenstringYesDestination token address
fromAmountstringYesAmount in smallest unit (wei)
fromAddressstringYesUser’s wallet address
toAddressstringNoDestination address (defaults to fromAddress)
slippageTolerancenumberNoSlippage tolerance as percentage (0.5 = 0.5%)
routePreferenceRoutePreferenceNo’recommended’, ‘fastest’, or ‘cheapest’
Throws:
  • InvalidQuoteParamsError if parameters are invalid
  • NoRouteFoundError if no route is available
  • NetworkError if API request fails
Example:
const quote = await mina.getQuote({
  fromChainId: 1,
  toChainId: 999,
  fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
  toToken: '0xb88339cb7199b77e23db6e890353e22632ba630f',   // HyperEVM USDC
  fromAmount: '1000000000', // 1000 USDC (6 decimals)
  fromAddress: '0x...',
});

console.log(`Will receive: ${quote.toAmount}`);
console.log(`Estimated time: ${quote.estimatedTime}s`);
console.log(`Total fees: $${quote.fees.totalUsd}`);
console.log(`Price impact: ${quote.priceImpact * 100}%`);

getQuotes(params, timeoutMs?)

Get multiple bridge quotes for comparison.
async getQuotes(
  params: QuoteParams,
  timeoutMs?: number
): Promise<QuotesResponse>
Returns: { quotes: Quote[], recommendedIndex: number } Example:
const { quotes, recommendedIndex } = await mina.getQuotes({
  fromChainId: 1,
  toChainId: 999,
  fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  toToken: '0xb88339cb7199b77e23db6e890353e22632ba630f',
  fromAmount: '1000000000',
  fromAddress: '0x...',
});

console.log(`Found ${quotes.length} routes`);
console.log(`Recommended: ${quotes[recommendedIndex].steps[0].tool}`);

// Compare routes
quotes.forEach((quote, i) => {
  console.log(`Route ${i + 1}: ${quote.estimatedTime}s, $${quote.fees.totalUsd}`);
});

Execution Methods

execute(options)

Execute a bridge transaction.
async execute(options: ExecuteOptions): Promise<ExecutionResult>
ExecuteOptions:
ParameterTypeRequiredDescription
quoteQuoteYesQuote to execute
signerTransactionSignerYesWallet signer (viem WalletClient compatible)
onStepChangeOnStepChangeNoCallback for step status updates
onStatusChangeOnStatusChangeNoCallback for overall status updates
onApprovalRequest() => voidNoCallback before approval transaction
onTransactionRequest() => voidNoCallback before main transaction
infiniteApprovalbooleanNoAllow infinite token approval
Throws:
  • QuoteExpiredError if the quote has expired
  • InvalidQuoteError if the quote is malformed
  • TransactionFailedError if the transaction fails
  • UserRejectedError if the user rejects the transaction
Example:
const quote = await mina.getQuote({ ... });
const result = await mina.execute({
  quote,
  signer: walletClient,
  onStepChange: (step) => {
    console.log(`Step ${step.stepId}: ${step.status}`);
    if (step.txHash) {
      console.log(`Transaction: ${step.txHash}`);
    }
  },
  onStatusChange: (status) => {
    console.log(`Progress: ${status.progress}%`);
    console.log(`Status: ${status.substatus}`);
  },
  infiniteApproval: true,
});

if (result.status === 'completed') {
  console.log('Bridge complete! TxHash:', result.txHash);
  console.log('Received:', result.receivedAmount);
}

getExecutionStatus(executionId)

Get the status of an execution by ID.
getExecutionStatus(executionId: string): ExecutionStatusResult
Example:
const result = await mina.execute({ quote, signer });
const executionId = result.executionId;

// Poll for status
const status = mina.getExecutionStatus(executionId);
console.log(`Progress: ${status.progress}%`);
console.log(`Current step: ${status.currentStep?.type}`);

if (status.error) {
  console.error(`Failed: ${status.error.message}`);
  console.log(`Recoverable: ${status.error.recoverable}`);
}

getStatus(txHash)

Get the status of a bridge transaction by transaction hash.
async getStatus(txHash: string): Promise<TransactionStatus | null>
Example:
const status = await mina.getStatus('0x123...');
if (status) {
  console.log(`Status: ${status.status}`);
  console.log(`Steps: ${status.steps.length}`);
}

Deposit Detection Methods

detectUsdcArrival(walletAddress, options?)

Detect USDC arrival on HyperEVM after a bridge transaction.
async detectUsdcArrival(
  walletAddress: string,
  options?: DetectionOptions
): Promise<UsdcArrivalResult>
DetectionOptions:
ParameterTypeDefaultDescription
timeoutnumber300000Timeout in milliseconds (5 minutes)
pollIntervalnumber5000Polling interval in milliseconds
onPoll(attempt, balance) => void-Callback for each poll attempt
expectedAmountstring-Expected amount for validation
Example:
// After bridge execution completes
const arrival = await mina.detectUsdcArrival('0x...', {
  timeout: 300000, // 5 minutes
  onPoll: (attempt, balance) => console.log(`Poll ${attempt}: ${balance}`),
});

if (arrival.detected) {
  console.log(`USDC arrived: ${arrival.amountFormatted} USDC`);
  if (mina.isAutoDepositEnabled()) {
    // Proceed with deposit to Hyperliquid L1
  }
}

snapshotUsdcBalance(walletAddress)

Take a snapshot of USDC balance on HyperEVM before bridging.
async snapshotUsdcBalance(walletAddress: string): Promise<string>
Example:
const preBalance = await mina.snapshotUsdcBalance('0x...');
// Store preBalance for later comparison

detectUsdcArrivalFromSnapshot(walletAddress, previousBalance, options?)

Detect USDC arrival starting from a known balance snapshot.
async detectUsdcArrivalFromSnapshot(
  walletAddress: string,
  previousBalance: string,
  options?: DetectionOptions
): Promise<UsdcArrivalResult>
Example:
// Before bridge
const preBalance = await mina.snapshotUsdcBalance('0x...');

// Execute bridge...
await mina.execute({ quote, signer });

// Detect arrival from snapshot
const arrival = await mina.detectUsdcArrivalFromSnapshot(
  '0x...',
  preBalance,
  { expectedAmount: quote.toAmount }
);

Event System

on(event, callback)

Subscribe to an SDK event.
on<K extends SDKEventName>(
  event: K,
  callback: (data: SDKEventPayloads[K]) => void
): void
Available Events:
EventPayloadDescription
stepChangedStepStatusPayloadStep status updated
statusChangedTransactionStatusPayloadOverall status updated
executionStarted{ executionId, quoteId, timestamp }Execution started
executionCompleted{ executionId, txHash, receivedAmount }Execution completed
executionFailed{ executionId, error, step }Execution failed
approvalRequired{ tokenAddress, amount, spender }Approval needed
transactionSent{ txHash, chainId, stepType }Transaction sent
transactionConfirmed{ txHash, chainId, stepType }Transaction confirmed
Example:
mina.on('stepChanged', (step) => {
  console.log(`Step ${step.stepId}: ${step.status}`);
});

mina.on('executionCompleted', (result) => {
  console.log('Bridge complete!', result.txHash);
});

off(event, callback)

Unsubscribe from an SDK event.
off<K extends SDKEventName>(
  event: K,
  callback: (data: SDKEventPayloads[K]) => void
): void
Example:
const handler = (step) => console.log(step);
mina.on('stepChanged', handler);
// Later...
mina.off('stepChanged', handler);

once(event, callback)

Subscribe to an SDK event once (auto-unsubscribes after first call).
once<K extends SDKEventName>(
  event: K,
  callback: (data: SDKEventPayloads[K]) => void
): void
Example:
mina.once('executionCompleted', (result) => {
  console.log('First execution completed!', result.txHash);
});

getEmitter()

Get the internal event emitter (for advanced use).
getEmitter(): SDKEventEmitter

Cache Management

invalidateChainCache()

Force a fresh fetch on next getChains() call.
invalidateChainCache(): void

invalidateTokenCache(chainId?)

Force a fresh fetch on next getTokens() call.
invalidateTokenCache(chainId?: number): void
ParameterTypeDescription
chainIdnumberOptional chain ID to invalidate (invalidates all if not provided)

invalidateBalanceCache(walletAddress?)

Force a fresh fetch on next getBalance() call.
invalidateBalanceCache(walletAddress?: string): void

invalidateQuoteCache()

Force fresh quotes on next getQuote() call.
invalidateQuoteCache(): void

Utility Methods

getConfig()

Get the current client configuration.
getConfig(): MinaConfig

isAutoDepositEnabled()

Check if auto-deposit is enabled.
isAutoDepositEnabled(): boolean

setAutoDeposit(enabled)

Set auto-deposit preference.
setAutoDeposit(enabled: boolean): void

validateQuote(quote)

Validate a quote before execution.
validateQuote(quote: Quote): void
Throws:
  • QuoteExpiredError if the quote has expired
  • InvalidQuoteError if the quote is malformed

validateBalance(quote, walletAddress)

Validate user balance against a quote.
async validateBalance(
  quote: Quote,
  walletAddress: string
): Promise<BalanceValidation>
Example:
const quote = await mina.getQuote({ ... });
const validation = await mina.validateBalance(quote, '0x...');

if (!validation.valid) {
  for (const warning of validation.warnings) {
    if (warning.type === 'INSUFFICIENT_BALANCE') {
      console.error(`Need ${warning.shortfall} more ${warning.token.symbol}`);
    } else if (warning.type === 'INSUFFICIENT_GAS') {
      console.error(`Need more gas: ${warning.message}`);
    }
  }
}

checkBalance(chainId, tokenAddress, walletAddress, amount)

Lightweight balance check without requiring a full quote.
async checkBalance(
  chainId: number,
  tokenAddress: string,
  walletAddress: string,
  amount: string
): Promise<BalanceCheckResult>
Example:
// Check if user has 1000 USDC before showing quote
const check = await mina.checkBalance(
  1,                                          // Ethereum
  '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
  '0x...',                                     // Wallet
  '1000000000'                                 // 1000 USDC (6 decimals)
);

if (!check.sufficient) {
  console.log(`Balance: ${check.formatted}, need ${check.shortfall} more`);
}