Skip to main content

Onboarding

This document describes the on-chain account lifecycle, funding flows, and API wallet management for Market Makers.

Overview

HyperCall uses a manager/agent model:

  • Manager: The EOA that owns the account (typically your main wallet)
  • Account: A minimal proxy contract (clone) that holds funds and executes on-chain actions
  • API Wallet: An EOA authorized by the manager to sign trading requests (agent)

All on-chain interactions occur via the Exchange contract.

Account Lifecycle

1. Check Existing Accounts

Before creating a new account, check if you already have accounts:

function getAccounts(address manager) external view returns (ManagedAccount[] memory);

Example (ethers.js):

const exchange = new ethers.Contract(EXCHANGE_ADDRESS, EXCHANGE_ABI, provider);
const accounts = await exchange.getAccounts(managerAddress);
// Returns: [{ account: "0x...", manager: "0x...", apiWallets: ["0x..."] }]

2. Create Account

Creates a new account with msg.sender as the manager:

function createAccount() external payable returns (address account);

Requirements:

  • accountImpl must be set by governance
  • msg.value >= getCreationDeposit() (minimum deposit in HYPE)
    • If creationDepositUsd == 0, no minimum deposit is required
    • Otherwise, getCreationDeposit() converts USD amount to HYPE using current spot price

Behavior:

  • Deploys a deterministic minimal proxy (clone) of accountImpl
  • Sets msg.sender as the account manager
  • If msg.value > 0, performs a HYPE deposit on behalf of the account
    • Transfers HYPE to HYPE_SYSTEM_ADDRESS (HyperCore bridge)
    • If deposit >= $1 worth of HYPE, account is activated on HyperCore (activation fee deducted)

Example (ethers.js):

// Get minimum deposit (in HYPE wei)
const minDeposit = await exchange.getCreationDeposit();
// Or set to ~$1-2 worth of HYPE for activation
const depositAmount = ethers.parseEther("0.001"); // Adjust based on HYPE price

const tx = await exchange.createAccount({ value: depositAmount });
const receipt = await tx.wait();
// Account address is deterministic - can predict before creation

Predict Account Address:

function predictNextAccount(address manager) external view returns (address);

Use this to know the account address before creation (useful for UI/UX).

3. Account Transfer

Managers can transfer account ownership (not directly callable; occurs during creation or via governance):

event AccountTransferred(address indexed account, address indexed oldManager, address indexed newManager);

Account transfer functionality is provided on request.

API Wallet Management

API wallets are EOAs authorized by the manager to sign trading requests. They sign EIP-712 messages that are verified on-chain.

Add API Wallet

function addApiWallet(address account, address apiWallet) external;

Requirements:

  • msg.sender == managers[account] (must be the account manager)
  • apiWallet must not be active for any other account/manager
  • account != address(0) and apiWallet != address(0)

Behavior:

  • Maps apiWallet -> account and apiWallet -> manager
  • Adds apiWallet to the account's API wallet set
  • Emits ApiWalletAdded(account, manager, apiWallet)

Example:

const tx = await exchange.addApiWallet(accountAddress, apiWalletAddress);
await tx.wait();

Remove API Wallet

function removeApiWallet(address account, address apiWallet) external;

Requirements:

  • msg.sender == managers[account]
  • apiWallet must be active for this account/manager

Behavior:

  • Removes mappings for apiWallet
  • Removes apiWallet from the account's API wallet set
  • Emits ApiWalletRemoved(account, manager, apiWallet)

Query API Wallets

function getAccountByApiWallet(address apiWallet) external view returns (ManagedAccount memory);

Returns the account, manager, and all API wallets for the account if apiWallet is active. Returns zero struct if inactive.

Example:

const managedAccount = await exchange.getAccountByApiWallet(apiWalletAddress);
if (managedAccount.account !== ethers.ZeroAddress) {
console.log("Account:", managedAccount.account);
console.log("Manager:", managedAccount.manager);
console.log("API Wallets:", managedAccount.apiWallets);
}

Funding & Deposits

Deposit Function

function deposit(address account, address token, uint256 amount) external payable;

Supported Token Types:

  1. Native HYPE (token == address(0) or token == NATIVE_TOKEN):

    • msg.value == amount (required)
    • Transfers HYPE to HYPE_SYSTEM_ADDRESS (HyperCore bridge)
    • Increases account's Spot HYPE balance
    • Used for account activation if >= $1 worth
  2. Quote Token (token == QUOTE_TOKEN, typically USDC):

    • msg.value == 0 (required)
    • Transfers ERC20 from msg.sender to account
    • Calls account.depositToCore(CORE_DEPOSIT, QUOTE_TOKEN, amount)
    • Increases account's Perp available margin
  3. ERC20 Spot Tokens (registered in TOKEN_REGISTRY):

    • msg.value == 0 (required)
    • Transfers ERC20 from msg.sender to account
    • Transfers to system address ERC20_SYSTEM_ADDRESS + tokenIndex
    • Increases account's Spot token balance
  4. Option ERC20 Tokens (registered in OptionRegistry):

    • msg.value == 0 (required)
    • Burns the option token via IOptionToken(token).burnFrom(msg.sender, amount)
    • Emits Deposit(account, msg.sender, token, amount)
    • RSM indexer picks up the event and credits the account's option position

Requirements:

  • managers[account] != address(0) (account must exist)
  • optionRegistry != address(0) (must be set)
  • For ERC20 tokens: msg.sender must have approved Exchange for amount

Example (USDC deposit):

const usdc = new ethers.Contract(USDC_ADDRESS, ERC20_ABI, signer);
const exchange = new ethers.Contract(EXCHANGE_ADDRESS, EXCHANGE_ABI, signer);

// Approve first
await usdc.approve(EXCHANGE_ADDRESS, amount);
// Then deposit
await exchange.deposit(accountAddress, USDC_ADDRESS, amount);

Example (HYPE deposit):

await exchange.deposit(accountAddress, ethers.ZeroAddress, amount, { value: amount });

Transfer From Account

Managers can transfer tokens from their account to any recipient on HyperEVM:

function transferFromAccount(address account, address token, address recipient, uint256 amount) external;

Requirements:

  • msg.sender == managers[account]
  • recipient != address(0)

Use Cases:

  • Complete HyperCore -> HyperEVM transfers initiated by the account
  • Rescue funds from an account
  • Withdraw to a different address

Example:

await exchange.transferFromAccount(
accountAddress,
tokenAddress,
recipientAddress,
amount
);

Integration with Off-Chain API

Once an account is created and an API wallet is added:

  1. Off-chain API authentication: Use the API wallet's private key to sign EIP-712 messages (see Authentication)
  2. On-chain verification: The RSM Sequencer calls Exchange.hlRequestOrder (or similar) with your signed request
  3. Execution: The Exchange verifies the signature, recovers the API wallet, maps it to your account, and executes on-chain actions

See Also:

Events

event AccountTransferred(address indexed account, address indexed oldManager, address indexed newManager);
event ApiWalletAdded(address indexed account, address indexed manager, address indexed apiWallet);
event ApiWalletRemoved(address indexed account, address indexed manager, address indexed apiWallet);
event Deposit(address indexed account, address indexed from, address indexed token, uint256 amount);
event Withdraw(address indexed account, address indexed to, address indexed token, uint256 amount);

Errors

All errors are defined in IExchangeBase.sol:

  • Exchange__AccountManagerNotSet(address account): Account doesn't exist
  • Exchange__ApiWalletAlreadyActive(address apiWallet): API wallet already in use
  • Exchange__ApiWalletNotActive(address apiWallet): API wallet not found
  • Exchange__CreationDepositNotMet(uint256 expected): Insufficient msg.value
  • Exchange__TokenNotSupported(address token): Token not supported for deposit
  • Exchange__MsgValueIncorrect(uint256 expected): msg.value mismatch
  • Exchange__NotManager(address account, address notManager): Caller is not the manager

Security Considerations

  1. Manager Key Security: The manager key controls account ownership and API wallet management. Store securely (hardware wallet recommended).

  2. API Wallet Key Security: API wallet keys sign trading requests. Use separate keys per account/environment. Rotate regularly.

  3. Nonce Management: Each signer (API wallet, manager, RSM) has a separate nonce space. Track nonces off-chain to avoid replay attacks.

  4. Account Activation: Accounts must be activated on HyperCore (deposit >= $1 HYPE) before they can trade perps. Check activation status via HyperCore API.

  5. Deterministic Addresses: Account addresses are deterministic based on manager address and creation count. Use predictNextAccount to know addresses before creation.