Skip to main content
Socket supports swapping assets from any EVM chain to HyperCore and from HyperCore to any EVM chain. This guide walks you through swapping assets between EVM chains and HyperCore using Socket, including transaction options and current limitations.

Quick Start

Key differences

Follow the “Auto routing” guides when going from any EVM to HyperCore. The main differences when integrating HyperCore compared to standard EVM chains: Transaction Flow from HyperCore to EVM
  • User sends funds to a Deposit contract with the quote ID
  • Socket indexes the transaction and delivers the funds on the destination chain
API Behavior
  • Both userAddress and receiverAddress required for quotes
  • The only assets supported from/to HyperCore are USDC (Spot) and USDC (Perps)
  • There is no Fee collection currently from HyperCore to EVM
  • Quote responses already account for HyperCore’s 1 USDC activation fee for new account activations and withdrawals
  • Only USDC (Perps) is supported when bridging out of Hypercore

inputAmount format for HyperCore

The inputAmount parameter must be provided as an integer string in 6-decimal base units (micro-units):
Human-readableinputAmount value
9.99 USDC"9990000"
2.00 USDC"2000000"
10.23 USDC"10230000"
Conversion formula: inputAmount = humanAmount × 10^6 (rounded to integer)

Integration Steps

HyperCore to EVM

  1. Select Chains: Choose source and destination chains.
  2. Fetch Routes: Retrieve the deposit route using the /quote endpoint. The response contains depositRoute.signTypedData and depositRoute.quoteId.
  3. Sign and Submit: Sign the signTypedData with primaryType: "HyperCoreTransaction:SendAsset", then submit the signed data to HyperLiquid’s API endpoint (https://api.hyperliquid.xyz/exchange).
  4. Track Transaction Status: Poll the /status endpoint using the quoteId until the bridging process is complete.
For HyperCore quotes, ensure both userAddress and receiverAddress are defined.HyperCore to EVM is under depositRoute (not autoRoute).

Examples

Queries

https://public-backend.bungee.exchange/api/v1/bungee/quote?userAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&receiverAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&originChainId=10&destinationChainId=1337&inputToken=0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85&outputToken=0x2000000000000000000000000000000000000000&inputAmount=2000000
https://public-backend.bungee.exchange/api/v1/bungee/quote?userAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&receiverAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&originChainId=1337&destinationChainId=10&inputToken=0x6d1e7cde53ba9467b783cb7c530ce054&outputToken=0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85&inputAmount=10230000

Scripts

import { privateKeyToAccount } from "viem/accounts";
import { createPublicClient, http, createWalletClient } from "viem";
import { optimism } from "viem/chains";

if (!process.env.PRIVATE_KEY) {
  console.error("Error: PRIVATE_KEY environment variable is not set");
  process.exit(1);
}

const account = privateKeyToAccount(
  process.env.PRIVATE_KEY.startsWith('0x')
    ? process.env.PRIVATE_KEY
    : `0x${process.env.PRIVATE_KEY}`
);

const publicClient = createPublicClient({ chain: optimism, transport: http() });
const walletClient = createWalletClient({ account, chain: optimism, transport: http() });

const BUNGEE_API_BASE_URL = "https://public-backend.bungee.exchange";

const quoteParams = {
  userAddress: account.address,
  receiverAddress: account.address,
  originChainId: 10,        // Optimism
  destinationChainId: 1337, // HyperCore
  inputToken: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", // USDC on Optimism
  outputToken: "0x2000000000000000000000000000000000000000", // USDC (SPOT) on HyperCore
  inputAmount: "2000000", // 2 USDC
};

async function getQuote(params) {
  const url = `${BUNGEE_API_BASE_URL}/api/v1/bungee/quote?${new URLSearchParams(params)}`;
  const response = await fetch(url);
  const data = await response.json();
  if (!data.success || !data.result.autoRoute) {
    throw new Error(`Quote failed: ${data.message}`);
  }
  return {
    quoteId: data.result.autoRoute.quoteId,
    requestType: data.result.autoRoute.requestType,
    signTypedData: data.result.autoRoute.signTypedData,
    approvalData: data.result.autoRoute.approvalData,
  };
}

async function main() {
  console.log("Getting quote...");
  const quote = await getQuote(quoteParams);
  console.log("Quote ID:", quote.quoteId);
  console.log("Request Type:", quote.requestType);

  // Sign the typed data with primaryType: "PermitWitnessTransferFrom"
  // Submit to /api/v1/bungee/submit and poll /status with requestHash
}

main();
import { privateKeyToAccount } from "viem/accounts";
import { http, createWalletClient, parseSignature } from "viem";
import { arbitrum } from "viem/chains";

if (!process.env.PRIVATE_KEY) {
  process.exit(1);
}

const normalizedKey = process.env.PRIVATE_KEY.trim().startsWith('0x')
  ? process.env.PRIVATE_KEY.trim()
  : `0x${process.env.PRIVATE_KEY.trim()}`;
const account = privateKeyToAccount(normalizedKey);
const walletClient = createWalletClient({ account, chain: arbitrum, transport: http() });

const BUNGEE_API_BASE_URL = "https://public-backend.bungee.exchange";
const HYPERLIQUID_API_URL = "https://api.hyperliquid.xyz/exchange";

const quoteParams = {
  userAddress: account.address,
  receiverAddress: account.address,
  originChainId: 1337,  // HyperCore
  destinationChainId: 10, // Optimism
  inputToken: "0x6d1e7cde53ba9467b783cb7c530ce054", // USDC (Perps)
  outputToken: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", // USDC on Optimism
  inputAmount: "10230000",
};

async function main() {
  const url = `${BUNGEE_API_BASE_URL}/api/v1/bungee/quote?${new URLSearchParams(quoteParams)}`;
  const response = await fetch(url);
  const data = await response.json();

  if (!data.success || !data.result.depositRoute) {
    throw new Error(`Quote failed: ${data.message}`);
  }

  const { quoteId, signTypedData } = data.result.depositRoute;

  // Sign with primaryType: "HyperCoreTransaction:SendAsset"
  const signature = await walletClient.signTypedData({
    types: signTypedData.types,
    primaryType: "HyperCoreTransaction:SendAsset",
    message: signTypedData.values,
    domain: signTypedData.domain,
  });

  const { r, s, v } = parseSignature(signature);

  // Submit to HyperLiquid API
  await fetch(HYPERLIQUID_API_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      action: signTypedData.values,
      nonce: signTypedData.values.nonce,
      signature: { r, s, v: Number(v) },
    }),
  });

  // Poll /status with quoteId
  console.log("Quote ID:", quoteId);
}

main();