Quick Start
This guide walks you through bridging assets from any supported chain to Hyperliquid using the Mina SDK. By the end, you will have executed a complete cross-chain bridge with automatic deposit to your trading account.
Prerequisites
Before you begin, ensure you have:
Install the Mina SDK and its peer dependency: npm install @siphoyawe/mina-sdk viem
An EVM wallet with tokens you want to bridge
Sufficient native token (ETH, MATIC, etc.) for gas fees
TypeScript Setup (Recommended)
The SDK is written in TypeScript and provides full type definitions. While not required, TypeScript is recommended for the best development experience.
Step 1: Initialize the SDK
Create a new Mina instance with your configuration. The integrator field is required and identifies your application.
import { Mina } from '@siphoyawe/mina-sdk' ;
// Initialize the SDK
const mina = new Mina ({
integrator: 'my-app' , // Your app identifier
autoDeposit: true , // Auto-deposit to Hyperliquid L1
defaultSlippage: 0.005 // 0.5% slippage tolerance
});
The autoDeposit option ensures bridged USDC is automatically deposited to your Hyperliquid L1 trading account. Set to false if you want USDC to remain on HyperEVM.
Step 2: Discover Chains
Fetch the list of supported source chains. The SDK supports 40+ chains that can bridge to HyperEVM.
// Get all supported chains
const { chains } = await mina . getChains ();
console . log ( `Found ${ chains . length } supported chains` );
// Find a specific chain (e.g., Arbitrum)
const arbitrum = chains . find ( chain => chain . id === 42161 );
console . log ( `Arbitrum: ${ arbitrum ?. name } ` );
Example Response:
{
chains : [
{ id: 1 , name: 'Ethereum' , nativeToken: { symbol: 'ETH' , ... } },
{ id: 42161 , name: 'Arbitrum' , nativeToken: { symbol: 'ETH' , ... } },
{ id: 10 , name: 'Optimism' , nativeToken: { symbol: 'ETH' , ... } },
// ... 40+ more chains
]
}
Step 3: Get Tokens
Fetch the tokens available for bridging on your source chain.
// Get tokens available on Arbitrum (chain ID: 42161)
const { tokens } = await mina . getTokens ( 42161 );
console . log ( `Found ${ tokens . length } bridgeable tokens on Arbitrum` );
// Find USDC on Arbitrum
const usdc = tokens . find ( token => token . symbol === 'USDC' );
console . log ( `USDC address: ${ usdc ?. address } ` );
Common token addresses on Arbitrum:
USDC: 0xaf88d065e77c8cC2239327C5EDb3A432268e5831
USDC.e (Bridged): 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8
Step 4: Get a Quote
Request a bridge quote specifying the source chain, tokens, and amount.
// Get a quote to bridge 100 USDC from Arbitrum to HyperEVM
const quote = await mina . getQuote ({
fromChain: 42161 , // Arbitrum
toChain: 999 , // HyperEVM
fromToken: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831' , // USDC on Arbitrum
toToken: '0x0000000000000000000000000000000000000000' , // Native representation
amount: '100000000' , // 100 USDC (6 decimals)
fromAddress: '0xYourWalletAddress' // Your wallet address
});
console . log ( 'Quote received:' );
console . log ( ` From: ${ quote . fromAmount } ${ quote . fromToken . symbol } ` );
console . log ( ` To: ${ quote . toAmount } ${ quote . toToken . symbol } ` );
console . log ( ` Estimated time: ${ quote . estimatedTime } s` );
console . log ( ` Gas cost: $ ${ quote . gasCostUSD } ` );
Quote Response Structure:
{
id : 'quote_abc123' ,
fromChain : 42161 ,
toChain : 999 ,
fromToken : { symbol : 'USDC' , address : '0x...' , decimals : 6 },
toToken : { symbol : 'USDC' , address : '0x...' , decimals : 6 },
fromAmount : '100000000' ,
toAmount : '99850000' , // Amount after fees
estimatedTime : 120 , // Seconds
gasCostUSD : '0.45' ,
route : { ... } // Bridge route details
}
Step 5: Execute the Bridge
Execute the bridge transaction using a viem wallet client. The SDK handles token approval, bridge execution, and auto-deposit.
import { createWalletClient , custom } from 'viem' ;
import { arbitrum } from 'viem/chains' ;
// Create a wallet client (browser environment with MetaMask)
const walletClient = createWalletClient ({
chain: arbitrum ,
transport: custom ( window . ethereum )
});
// Get the connected account
const [ account ] = await walletClient . getAddresses ();
// Execute the bridge
const result = await mina . execute ({
quote ,
walletClient ,
account ,
onStepChange : ( step ) => {
console . log ( `Step: ${ step . type } - ${ step . status } ` );
}
});
console . log ( 'Bridge completed!' );
console . log ( ` Transaction hash: ${ result . transactionHash } ` );
console . log ( ` Deposited to L1: ${ result . depositedToL1 } ` );
Always ensure the user has sufficient native token balance for gas fees before executing. The SDK will throw an error if gas estimation fails.
Complete Example
Here is a complete, working example that bridges 100 USDC from Arbitrum to Hyperliquid:
import { Mina } from '@siphoyawe/mina-sdk' ;
import { createWalletClient , custom , parseUnits } from 'viem' ;
import { arbitrum } from 'viem/chains' ;
async function bridgeToHyperliquid () {
// 1. Initialize the SDK
const mina = new Mina ({
integrator: 'my-app' ,
autoDeposit: true ,
defaultSlippage: 0.005
});
// 2. Create wallet client (browser with MetaMask)
const walletClient = createWalletClient ({
chain: arbitrum ,
transport: custom ( window . ethereum )
});
// 3. Get connected account
const [ account ] = await walletClient . getAddresses ();
console . log ( `Connected wallet: ${ account } ` );
// 4. Get available tokens on Arbitrum
const { tokens } = await mina . getTokens ( 42161 );
const usdc = tokens . find ( t => t . symbol === 'USDC' );
if ( ! usdc ) {
throw new Error ( 'USDC not found on Arbitrum' );
}
// 5. Get a quote for 100 USDC
const amount = parseUnits ( '100' , 6 ). toString (); // 100 USDC
const quote = await mina . getQuote ({
fromChain: 42161 ,
toChain: 999 ,
fromToken: usdc . address ,
toToken: '0x0000000000000000000000000000000000000000' ,
amount ,
fromAddress: account
});
console . log ( `Quote: Bridge ${ quote . fromAmount } USDC` );
console . log ( ` Receive: ~ ${ quote . toAmount } USDC` );
console . log ( ` Est. time: ${ quote . estimatedTime } s` );
// 6. Execute the bridge
const result = await mina . execute ({
quote ,
walletClient ,
account ,
onStepChange : ( step ) => {
console . log ( `[ ${ step . type } ] ${ step . status } : ${ step . message || '' } ` );
}
});
console . log ( 'Bridge complete!' );
console . log ( ` TX Hash: ${ result . transactionHash } ` );
console . log ( ` Deposited to L1: ${ result . depositedToL1 } ` );
return result ;
}
// Run the bridge
bridgeToHyperliquid ()
. then ( result => console . log ( 'Success!' , result ))
. catch ( error => console . error ( 'Failed:' , error ));
What Happens During Execution
When you call mina.execute(), the SDK performs the following steps automatically:
Validate Quote
Verifies the quote is still valid and has not expired.
Check Allowance
Checks if the bridge contract has permission to spend your tokens.
Approve Tokens (if needed)
Prompts for token approval if the current allowance is insufficient.
Submit Bridge Transaction
Signs and submits the cross-chain bridge transaction.
Wait for Confirmation
Waits for the source chain transaction to be confirmed.
Monitor Bridge Progress
Tracks the cross-chain message until USDC arrives on HyperEVM.
Auto-Deposit (if enabled)
Detects USDC arrival, approves the deposit contract, and deposits to Hyperliquid L1.
Confirm L1 Balance
Verifies the deposit is reflected in your Hyperliquid trading account.
The onStepChange callback keeps you informed of progress throughout this process.
Next Steps
Now that you have completed your first bridge, explore these topics to learn more:
Configuration Learn about all configuration options including custom RPCs and slippage settings.
React Hooks Use the SDK with React hooks for a seamless UI integration.
Quote Options Understand route preferences, slippage, and quote parameters.
Error Handling Handle errors gracefully with typed error classes and recovery actions.