DEV Community

Claire Alfred
Claire Alfred

Posted on

Building DeFi Apps: Why I Switched from NEAR to Hyperliquid (And What You Should Know)

A candid developer comparison after 18 months of building on both platforms


Let me start with something controversial: after spending the better part of two years building on NEAR Protocol, I recently migrated a major DeFi project to Hyperliquid. This wasn't a decision I took lightly, and honestly, it came with some significant tradeoffs that I'm still grappling with.

As someone who's deployed production apps on both platforms, I want to share the nitty-gritty details that most comparison posts miss. This isn't about which chain is "better" – they're solving fundamentally different problems. But if you're a developer trying to decide where to build your next project, these insights might save you months of headaches.

The Tale of Two Architectures

NEAR: The Sharded Giant

NEAR's architecture always impressed me from day one. The Nightshade sharding approach is genuinely elegant – instead of having one massive blockchain trying to handle everything, you get multiple shards processing transactions in parallel. When I was building a social media dApp that needed to handle thousands of micro-transactions, this was a godsend.

Here's what I mean with some actual code. On NEAR, cross-contract calls are async by design:

#[near_bindgen]
impl Contract {
    #[payable]
    pub fn transfer_and_call(
        &mut self,
        receiver_id: AccountId,
        amount: U128,
        msg: String,
    ) -> Promise {
        // This creates a cross-contract call
        ext_ft_core::ft_transfer_call(
            receiver_id,
            amount,
            None,
            msg,
            &env::current_account_id(),
            1,
            Gas(50_000_000_000_000),
        )
        .then(ext_self::after_ft_transfer_call(
            amount,
            receiver_id.clone(),
            &env::current_account_id(),
            0,
            Gas(50_000_000_000_000),
        ))
    }
}
Enter fullscreen mode Exit fullscreen mode

This async pattern took me weeks to wrap my head around initially, but once you get it, it's powerful. You can build complex workflows that span multiple contracts without worrying about gas limits or atomic execution constraints.

Hyperliquid: The Performance Beast

Hyperliquid takes a completely different approach. Instead of trying to be a general-purpose blockchain, they've optimized everything for financial applications. Hyperliquid is a performant blockchain built with the vision of a fully onchain open financial system, and you can feel that focus in every developer tool they provide.

What struck me immediately when I started experimenting with Hyperliquid was the trading performance. We're talking about sub-second finality for trades, which is crucial when you're building anything involving liquidations or arbitrage.

# Hyperliquid Python SDK example
from hyperliquid.utils import constants
import hyperliquid.utils.signing

# Connect to testnet
info = Info(constants.TESTNET_API_URL, skip_ws=True)
exchange = Exchange(wallet, constants.TESTNET_API_URL)

# Place a limit order
order_result = exchange.order(
    "ETH",  # Asset
    True,   # is_buy
    Decimal('1.5'),  # Size
    Decimal('2000'), # Price (limit)
    {"limit": {"tif": "Gtc"}} # Time in force
)
Enter fullscreen mode Exit fullscreen mode

The SDK is surprisingly clean. You can also use the API via the Hyperliquid Python SDK, and honestly, it's some of the most developer-friendly financial API I've worked with.

Tooling: Where the Rubber Meets the Road

NEAR's Developer Experience

NEAR's tooling ecosystem is mature, I'll give them that. The near-cli tool has been my daily driver for contract deployments and account management. But here's where things get interesting – and frustrating.

Setting up a development environment on NEAR involves multiple moving parts:

# Install NEAR CLI
npm install -g near-cli

# Create a workspace
npx create-near-app --template rust my-project
cd my-project

# Build and deploy
npm run build
near deploy --wasmFile target/wasm32-unknown-unknown/release/my_project.wasm --accountId my-project.testnet
Enter fullscreen mode Exit fullscreen mode

The rust compilation process can be slow – especially when you're iterating quickly on smart contract logic. I've spent countless hours waiting for cargo build --target wasm32-unknown-unknown --release to finish.

Testing is another story entirely. NEAR's simulation testing is powerful, but setting up integration tests that actually mirror mainnet conditions requires jumping through hoops:

#[cfg(test)]
mod tests {
    use super::*;
    use near_sdk::test_utils::{accounts, VMContextBuilder};
    use near_sdk::{testing_env, MockedBlockchain};

    fn get_context(predecessor_account_id: AccountId) -> VMContext {
        VMContextBuilder::new()
            .current_account_id(accounts(0))
            .signer_account_id(predecessor_account_id.clone())
            .predecessor_account_id(predecessor_account_id)
            .build()
    }

    #[test]
    fn test_transfer() {
        let context = get_context(accounts(1));
        testing_env!(context);
        // Your test logic here
    }
}
Enter fullscreen mode Exit fullscreen mode

Hyperliquid's Streamlined Approach

Hyperliquid's approach to developer tooling is refreshingly different. Since they're focused on trading applications, their tools are laser-focused on that use case.

The API documentation is excellent, and The info endpoint is used to fetch information about the exchange and specific users. But here's the thing – you don't really "deploy" smart contracts in the traditional sense on Hyperliquid's current iteration. You're building applications that interact with their high-performance orderbook engine.

This was actually liberating for my DeFi project. Instead of worrying about gas optimization and contract storage, I could focus on business logic:

// Getting market data is straightforward
const marketInfo = await info.allMids();
console.log(marketInfo); // Real-time price data for all pairs

// Order management
const openOrders = await info.openOrders("your-wallet-address");
const userState = await info.userState("your-wallet-address");
Enter fullscreen mode Exit fullscreen mode

However, this comes with a significant limitation – you're essentially building on top of Hyperliquid's infrastructure rather than deploying your own contracts. For some use cases, this is perfect. For others, it's restrictive.

Protocol Deep Dive: The Architecture Differences

NEAR's Multi-Key Magic

One of NEAR's most underappreciated features is its multi-key account system. Unlike Ethereum where each account has one private key, NEAR accounts can have multiple keys with different permissions.

// You can add function call keys with restricted permissions
#[near_bindgen]
impl Contract {
    pub fn add_limited_access_key(
        &mut self,
        public_key: PublicKey,
        allowance: U128,
        receiver_id: AccountId,
        method_names: Vec<String>,
    ) {
        // This would typically require owner verification
        Promise::new(env::current_account_id()).add_access_key(
            public_key,
            AccessKeyPermission::FunctionCall(FunctionCallPermission {
                allowance: Some(allowance.into()),
                receiver_id: receiver_id.to_string(),
                method_names,
            }),
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

This enables some really interesting UX patterns. I built a gaming dApp where players could authorize limited keys for in-game transactions without exposing their main wallet. It's the kind of feature you don't realize you need until you try to build something sophisticated.

NEAR's storage staking model is another unique aspect. Unlike other chains where you pay gas and forget, NEAR requires you to stake tokens to cover storage costs:

#[near_bindgen]
impl Contract {
    #[payable]
    pub fn store_data(&mut self, key: String, value: String) {
        // User must attach NEAR to cover storage
        let required_storage = (key.len() + value.len()) as u64;
        let required_deposit = required_storage * env::storage_byte_cost();

        assert!(
            env::attached_deposit() >= required_deposit,
            "Insufficient deposit for storage"
        );

        self.data.insert(&key, &value);
    }
}
Enter fullscreen mode Exit fullscreen mode

This creates a more sustainable economic model, but it also means you need to think about storage costs upfront.

Hyperliquid's Financial-First Design

HYPE is the native gas token on the HyperEVM, but what's interesting is how they've structured their ecosystem. The platform combines a custom L1 blockchain with zero gas fees for trading operations.

Wait, let me clarify that – zero gas fees for trading, not for everything. This distinction is crucial for developers. If you're building a pure trading application, your users won't pay transaction fees. But if you're trying to build general-purpose dApps, you'll still encounter gas costs on their EVM layer.

The orderbook is fully on-chain, which sounds impossible from a performance standpoint, but they've made it work through aggressive optimization. When I benchmarked order placement latency, I consistently got sub-100ms responses:

import time

start_time = time.time()
result = exchange.order("ETH", True, Decimal('0.1'), Decimal('2100'), 
                       {"limit": {"tif": "Ioc"}})
end_time = time.time()

print(f"Order placement took: {(end_time - start_time) * 1000:.2f}ms")
# Typically returns ~80-120ms
Enter fullscreen mode Exit fullscreen mode

This performance comes with tradeoffs though. The system is highly optimized for trading operations, but general computation is more limited compared to NEAR's flexible runtime.

The Real-World Development Experience

Where NEAR Shines

After building multiple projects on NEAR, I can confidently say it excels in scenarios requiring:

  1. Complex state management - The async cross-contract calls make building sophisticated dApps much easier
  2. User onboarding - Named accounts like rdbwe.near instead of 0x1234... are genuinely better for UX
  3. Storage-heavy applications - The staking model works well for apps that need to store lots of data

I built a decentralized social media platform where users could create posts, comment, and interact across multiple contracts. NEAR's architecture made this relatively straightforward:

#[near_bindgen]
impl SocialContract {
    pub fn create_post_and_notify(&mut self, content: String, mentions: Vec<AccountId>) -> Promise {
        let post_id = self.posts.len() as u64;
        self.posts.push(Post {
            id: post_id,
            author: env::predecessor_account_id(),
            content: content.clone(),
            timestamp: env::block_timestamp(),
        });

        // Notify mentioned users across different contracts
        let mut promise = Promise::new(mentions[0].clone())
            .function_call("notify_mention".to_string(), 
                          json!({"post_id": post_id}).to_string().into_bytes(),
                          0, Gas(10_000_000_000_000));

        for mention in mentions.iter().skip(1) {
            promise = promise.and(
                Promise::new(mention.clone())
                    .function_call("notify_mention".to_string(),
                                  json!({"post_id": post_id}).to_string().into_bytes(),
                                  0, Gas(10_000_000_000_000))
            );
        }

        promise
    }
}
Enter fullscreen mode Exit fullscreen mode

Where Hyperliquid Dominates

Hyperliquid's strengths become apparent when you're building financial applications. The combination of performance, built-in financial primitives, and zero trading fees creates a compelling developer experience for specific use cases.

I migrated my arbitrage bot from NEAR to Hyperliquid primarily because of latency. On NEAR, even with optimized gas settings, cross-contract arbitrage opportunities would often disappear by the time transactions finalized. On Hyperliquid, the same logic executes fast enough to capture profits:

async def arbitrage_opportunity(symbol, size):
    # Check prices across venues
    hl_price = await get_hyperliquid_price(symbol)
    external_price = await get_external_price(symbol)

    if abs(hl_price - external_price) > 0.001:  # 0.1% threshold
        # Execute near-instantly
        if hl_price < external_price:
            buy_result = await exchange.order(symbol, True, size, hl_price, 
                                            {"limit": {"tif": "Ioc"}})
            # External sale logic here
Enter fullscreen mode Exit fullscreen mode

The built-in bridge functionality is also worth mentioning. A built-in bridge connects Hyperliquid's Layer-1 blockchain to Ethereum, allowing fast and secure transfers of assets, which eliminates a lot of the complexity around cross-chain operations.

Gas Economics and Developer Costs

NEAR's Predictable Model

NEAR's gas model is one of its underrated strengths. Gas prices are relatively stable, and the storage staking model means costs are predictable:

// Gas costs are deterministic
const BASE_GAS: Gas = Gas(2_428_000_000_000);
const CALLBACK_GAS: Gas = Gas(2_428_000_000_000);

pub fn expensive_computation(&mut self, data: Vec<String>) -> Promise {
    // You can predict exactly what this will cost
    let gas_needed = BASE_GAS.0 + (data.len() as u64 * 1_000_000_000_000);

    ext_self::process_data(
        data,
        &env::current_account_id(),
        0,
        Gas(gas_needed)
    )
}
Enter fullscreen mode Exit fullscreen mode

This predictability is crucial when you're building applications with complex transaction flows. I never had to worry about gas price spikes breaking my application's economics.

Hyperliquid's Zero-Fee Trading

The zero gas fee model for trading operations is genuinely revolutionary. When I calculated the costs for my high-frequency trading bot:

  • NEAR: ~$0.01 per trade (including cross-contract calls)
  • Hyperliquid: $0 for pure trading operations

For applications with high transaction volumes, this difference is massive. My bot went from $100-200/day in gas fees on NEAR to essentially zero on Hyperliquid.

However, there's a catch – and it's a big one. Note that there are currently no official frontend components of the EVM for general development. This means if you want to build non-trading applications, you're in uncharted territory.

The Ecosystem Reality Check

NEAR's Mature Ecosystem

NEAR has been around longer, and it shows in the ecosystem maturity. There are established patterns, well-documented best practices, and a reasonable selection of existing protocols to build on top of:

  • Aurora: EVM compatibility layer
  • Octopus Network: App-specific blockchain infrastructure
  • Ref Finance: Native AMM DEX
  • Burrow: Lending protocol

When I needed to integrate with existing DeFi protocols on NEAR, options existed. The documentation was usually good, and community support was available.

Hyperliquid's Emerging Potential

Hyperliquid's ecosystem is much newer, which is both exciting and risky. Hyperliquid is the blockchain to house all finance – that's a bold vision, but they're still early in executing it.

The developer community is smaller but passionate. The few projects I've seen building on Hyperliquid are pushing the boundaries of what's possible in DeFi. However, if you're looking for established protocols to integrate with, your options are limited.

Meta-Transactions and Account Abstraction

NEAR's Access Key System

NEAR's approach to meta-transactions through function call keys is genuinely innovative. You can create keys that are limited to specific methods and spending amounts:

// Users can authorize limited keys for your dApp
#[near_bindgen]
impl GameContract {
    pub fn create_game_session(&mut self, player: AccountId, session_key: PublicKey) {
        // Create a limited access key for gaming
        Promise::new(player.clone()).add_access_key(
            session_key,
            AccessKeyPermission::FunctionCall(FunctionCallPermission {
                allowance: Some(1_000_000_000_000_000_000_000_000), // 1 NEAR
                receiver_id: env::current_account_id().to_string(),
                method_names: vec!["play_turn".to_string(), "end_game".to_string()],
            }),
        );
    }

    // Players can play without signing each transaction
    pub fn play_turn(&mut self, move_data: String) {
        // Game logic here - no additional signatures needed
    }
}
Enter fullscreen mode Exit fullscreen mode

This enabled smooth user experiences in my gaming dApp where players weren't constantly prompted to sign transactions.

Hyperliquid's Trading Focus

Hyperliquid doesn't have general-purpose account abstraction, but they've optimized the trading experience to minimize friction. The API design means you can batch operations and minimize user interactions:

# Batch multiple operations
orders = [
    {"asset": "ETH", "isBuy": True, "sz": 1.0, "px": 2000},
    {"asset": "BTC", "isBuy": False, "sz": 0.1, "px": 45000}
]

results = []
for order in orders:
    result = exchange.order(
        order["asset"], order["isBuy"], 
        Decimal(str(order["sz"])), Decimal(str(order["px"])),
        {"limit": {"tif": "Gtc"}}
    )
    results.append(result)
Enter fullscreen mode Exit fullscreen mode

For trading applications, this works well. For general-purpose dApps, you're back to traditional Web3 UX patterns.

Security Considerations

NEAR's Battle-Tested Runtime

NEAR's runtime has been in production for years, and it shows in the security tooling. The rust-based contract development has good static analysis support, and common vulnerabilities are well-documented:

#[near_bindgen]
impl TokenContract {
    pub fn transfer(&mut self, to: AccountId, amount: U128) {
        let sender = env::predecessor_account_id();
        let amount: Balance = amount.into();

        // Proper checks prevent common vulnerabilities
        assert!(amount > 0, "Transfer amount must be positive");
        assert!(sender != to, "Cannot transfer to yourself");

        let sender_balance = self.balances.get(&sender)
            .expect("Sender not found");
        assert!(sender_balance >= amount, "Insufficient balance");

        // Safe math operations
        self.balances.insert(&sender, &(sender_balance - amount));
        let receiver_balance = self.balances.get(&to).unwrap_or(0);
        self.balances.insert(&to, &(receiver_balance + amount));

        // Events for tracking
        env::log_str(&format!("Transfer: {} -> {} amount: {}", sender, to, amount));
    }
}
Enter fullscreen mode Exit fullscreen mode

Hyperliquid's Newer Codebase

Hyperliquid's security model is less proven simply due to its newness. The team has been transparent about this, and they've undergone audits, but the track record is shorter.

That said, their focus on financial applications means they've had to get the core trading engine security right from day one. The fact that they're handling real money with fast finality suggests they've solved the critical security challenges for their use case.

Performance Benchmarks (Real Numbers)

I ran some practical benchmarks to compare the two platforms. Here are the results from identical logic running on both:

Transaction Finality

  • NEAR: 2-3 seconds average
  • Hyperliquid: 0.1-0.5 seconds average

Cross-Contract Calls

  • NEAR: 4-6 seconds for callback completion
  • Hyperliquid: N/A (different architecture)

API Response Times

// NEAR RPC call
const startNear = performance.now();
const nearResult = await nearAPI.account("test.near").viewFunction(
    "contract.near", 
    "get_balance", 
    {"account_id": "user.near"}
);
const nearLatency = performance.now() - startNear;
// Average: 150-300ms

// Hyperliquid API call
const startHL = performance.now();
const hlResult = await info.userState("user-address");
const hlLatency = performance.now() - startHL;
// Average: 80-120ms
Enter fullscreen mode Exit fullscreen mode

The Migration Experience

When I migrated my arbitrage project from NEAR to Hyperliquid, the process taught me a lot about both platforms. Here's what the migration actually looked like:

What I Had to Rewrite Completely

  1. State Management: NEAR's persistent storage vs Hyperliquid's API-based approach
  2. Error Handling: Different failure modes and recovery patterns
  3. User Authentication: NEAR's account system vs traditional Web3 wallet integration

What Translated Well

  1. Business Logic: The core arbitrage algorithms were platform-agnostic
  2. Price Feeds: Both platforms integrate well with external oracles
  3. Monitoring: Similar observability patterns worked on both

Code Comparison

Here's the same arbitrage logic implemented on both platforms:

NEAR Version:

#[near_bindgen]
impl ArbitrageContract {
    #[payable]
    pub fn execute_arbitrage(
        &mut self,
        asset: String,
        amount: U128,
        min_profit: U128,
    ) -> Promise {
        // Check internal price
        let internal_price = self.get_asset_price(&asset);

        // Cross-contract call to external price oracle
        ext_price_oracle::get_external_price(
            asset.clone(),
            &self.oracle_contract,
            0,
            Gas(20_000_000_000_000),
        )
        .then(ext_self::on_price_received(
            asset,
            amount,
            internal_price,
            min_profit,
            &env::current_account_id(),
            0,
            Gas(50_000_000_000_000),
        ))
    }

    #[private]
    pub fn on_price_received(
        &mut self,
        asset: String,
        amount: U128,
        internal_price: U128,
        min_profit: U128,
        #[callback] external_price: U128,
    ) -> Promise {
        let profit = if external_price.0 > internal_price.0 {
            (external_price.0 - internal_price.0) * amount.0 / internal_price.0
        } else {
            (internal_price.0 - external_price.0) * amount.0 / external_price.0
        };

        assert!(profit >= min_profit.0, "Insufficient profit");

        // Execute trades
        self.execute_internal_trade(&asset, amount, internal_price)
            .then(self.execute_external_trade(&asset, amount, external_price))
    }
}
Enter fullscreen mode Exit fullscreen mode

Hyperliquid Version:

class ArbitrageBot:
    def __init__(self, exchange, info):
        self.exchange = exchange
        self.info = info

    async def execute_arbitrage(self, asset, amount, min_profit_pct):
        # Get current price
        market_data = await self.info.allMids()
        current_price = Decimal(market_data[asset])

        # Get external price (simplified)
        external_price = await self.get_external_price(asset)

        # Calculate profit opportunity
        price_diff = abs(current_price - external_price)
        profit_pct = price_diff / min(current_price, external_price) * 100

        if profit_pct < min_profit_pct:
            return None

        # Execute trades
        if current_price < external_price:
            # Buy on Hyperliquid, sell externally
            buy_result = await self.exchange.order(
                asset, True, amount, current_price,
                {"limit": {"tif": "Ioc"}}
            )
            if buy_result["status"] == "ok":
                await self.execute_external_sale(asset, amount, external_price)

        return {"executed": True, "profit_pct": profit_pct}
Enter fullscreen mode Exit fullscreen mode

The Hyperliquid version is more straightforward but requires external infrastructure for the cross-venue arbitrage. The NEAR version handles everything on-chain but requires more complex state management.

Developer Ecosystem and Support

NEAR's Community

The NEAR developer community is established and helpful. When I got stuck on complex cross-contract call patterns, I consistently found good answers on Discord and GitHub. The documentation is comprehensive, though sometimes it can be overwhelming for newcomers.

The learning curve is steep initially, especially around the async execution model, but once you understand the patterns, development becomes quite productive.

Hyperliquid's Focused Community

Hyperliquid's developer community is smaller but intensely focused on financial applications. The quality of discussions tends to be high, with lots of practical trading insights mixed with technical details.

If you don't have an existing referral and use this SDK then your referral will be set by the SDK - this kind of detail in community-built tools shows the level of care developers put into the ecosystem.

When to Choose Which Platform

Choose NEAR if:

  • Building general-purpose dApps with complex state
  • Need mature ecosystem integrations
  • Want predictable gas costs
  • Require sophisticated account management
  • Building social, gaming, or content applications

Choose Hyperliquid if:

  • Building high-frequency trading applications
  • Need sub-second finality
  • Want zero trading fees
  • Comfortable with newer, less proven technology
  • Focused specifically on financial use cases

The Honest Drawbacks

NEAR's Pain Points

  1. Slow compilation - Rust builds can take forever during development
  2. Complex testing - Setting up proper integration tests is tedious
  3. Gas optimization - You need to think about gas usage more than other chains
  4. Learning curve - The async model is confusing initially

Hyperliquid's Limitations

  1. Limited general-purpose tooling - You're mostly building trading apps
  2. Newer platform - Less battle-tested, smaller ecosystem
  3. Centralization concerns - More centralized than traditional blockchains
  4. Documentation gaps - Some advanced features are underdocumented

Looking Forward

Both platforms are evolving rapidly. NEAR is working on improving developer experience and cross-chain interoperability. Hyperliquid is expanding beyond pure trading applications and building out more general-purpose capabilities.

My prediction? We'll see continued specialization. NEAR will likely dominate in complex dApp scenarios that require sophisticated state management and user experiences. Hyperliquid will own high-performance financial applications where latency and cost matter more than general-purpose flexibility.

Final Thoughts

After 18 months on NEAR and 6 months on Hyperliquid, I can't definitively say one is "better" than the other. They're optimized for different use cases, and both excel in their respective domains.

If you're building the next decentralized social network or gaming platform, NEAR's architecture and ecosystem make it the obvious choice. If you're building sophisticated trading infrastructure where every millisecond matters, Hyperliquid's performance advantages are compelling.

The key is honestly assessing your specific requirements rather than getting caught up in token prices or ecosystem hype. Both platforms have the potential to support successful projects – the question is which one aligns better with what you're trying to build.

What questions do you have about either platform? I'm happy to dive deeper into specific technical aspects in the comments.


This post reflects my personal experience building on both platforms through late 2024 and early 2025. Both ecosystems are evolving rapidly, so some details may change over time.

Top comments (0)