Trading Perp Futures with Rupiah: Removing USDT Friction Layer

Crypto Futures (Perps) on Ajaib were already live and doing well, but adoption had a ceiling. Every Indonesian user who wanted to trade Perps had to first convert their Rupiah (IDR) into Tether (USDT) in their Spot wallet, then move it into Futures wallet, then trade in dollars. That's a lot of steps and a lot of foreign-currency math, all wrapped around a leveraged product where seconds matter. This project removed that layer entirely. Users can now deposit Rupiah, see prices in Rupiah, and trade Perps in Rupiah without ever worry about USDT conversion.

Year

2025

Service

Product Design

Category

Mobile App Design

Tool

Figma

Key Results

  • 84% new users adoption.

  • ~40% existing user adoption within a month of full rollout.

Key Results

  • 84% new users adoption

  • ~40% existing users adoption within a month of 100% rollout

Role & Timeline

  • Product Designer

  • Oct 2025 - Nov 2025

Methods

  • User Research

  • Competitive Analysis

  • Design Audit

  • UX Writing

  • Prototyping

  • Testing

  • Dev Handoff

Methods

  • User Research

  • Competitive Analysis

  • UX Writing

  • Prototyping

  • Testing

  • Dev Handoff

Background

For a long time, trading crypto perpetuals on Ajaib looked like this:

  1. Deposit Rupiah into your Ajaib wallet

  2. Convert Rupiah to USDT (a Spot trade)

  3. Move USDT into your Futures wallet

  4. Place a Perps order, where everything (price, P&L, liquidation) is shown in USDT

For a crypto-native user comfortable with USDT, that flow is familiar. But Indonesia's retail crypto base is largely made up of Spot traders who primarily trade in IDR, not USDT. They're used to seeing BTC priced in Rupiah, their balances are in Rupiah, and their mental model of crypto value is anchored in Rupiah. Asking that same user to switch into a USDT context just to access Perps adds three extra steps before they even see the trade screen, plus a constant mental conversion running in the background the entire time they're trading. "Wait, is this position 0.001 BTC at 60k USDT, and how much is that in Rupiah again?"

It's not just inconvenient. On a leveraged product, that kind of cognitive load is a real risk. Users misjudge position size, miscalculate liquidation levels, and hesitate when they should be acting.

Why Now?

There was also a clear precedent. In India, when local exchanges launched INR-denominated perpetuals, INR Perps quickly overtook USDT volumes. The pattern was obvious: remove the FX cognitive layer and adoption follows. Indonesia had no reason to be different.

The direction was clear: Ajaib's Futures had healthy volume but it was concentrated in a small number of users. The ceiling wasn't product-market fit, it was the USDT barrier keeping the broader retail base out.

What made this particularly interesting to work on: Ajaib would be the first platform in Indonesia to offer IDR-margin crypto perpetuals, and remains the only one to this day. There was no local reference to follow, and my job was to figure out what trading in Rupiah should actually feel like.

Research & Analytics

Where users were dropping off

Working with the PM, I broke down the existing Futures funnel. The biggest drop-off was right between the IDR-to-USDT conversion, transferring between Spot wallet ←→ Futures wallet and the first Futures trade. Users would deposit Rupiah, hit the Spot conversion step, and stall. UX Research's interviews and Customer Support tickets were repeating the same questions over and over:

  • "Why is my balance in dollars?"

  • "How much is this in Rupiah?"

  • "Did I lose money or did the dollar go up?"

People were doing math on every screen. The friction wasn't a single broken flow, it was the entire conceptual frame.

Looking at other fiat-margined platforms, and why our problem is different

(left to right) Exness, Phantom, Kraken Futures Fiat-margined Trade Page

The other reference points I kept coming back to were fiat-margined trading platforms that had already solved some version of this problem: Exness, Phantom, and Kraken.

All three denominate their crypto perpetuals in USD, not USDT. Exness comes from an FX broker background and extended into bluechip crypto (BTC, ETH) and US stocks. Phantom is a crypto-native wallet that added USD-denominated perpetuals. Kraken, one of the largest global crypto exchanges, offers USD-denominated perpetuals across hundreds of assets.

What's happening on the backend for any of these, whether the contract actually settle in fiat or whether they're using stablecoins for liquidity and just labeling them as fiat, isn't visible to users. And honestly, it doesn't really matter for USD-based platforms, USD and USDT are functionally 1:1 in value, so the gap between "what the user sees" and "what the system does" is essentially zero.

For us, the gap is real and significant:

  • The user sees BTC at Rp960,000,000. The system places an order against BTC at 60,000 USDT (for argument's sake, let's say US$1 = Rp16.000)

  • The user types an IDR price. The system rounds it to fit USDT's 4-decimal precision.

If we surfaced any of this in the UI, a rate tooltip, a "you're actually trading USDT" disclosure, a rounding indicator, the whole point of the project would collapse. We'd just be replacing one cognitive load (mental USDT conversion) with another (mental rate tracking, rounding awareness, "is the rate stale?"). Users would still be doing math.

So the design principle that emerged was:

We don't want users to feel like they're trading USDT pairs with an IDR cover. We want them to trade like they're trading IDR pairs, full stop. Mark Price, Last Price, Bid/Ask in the orderbook, Required Margin, Free Margin, TP/SL, all in IDR, all the time. No conversion layer surfaced anywhere.

This became the throughline for every design decision downstream.

Two reasons users would actually want IDR over USDT

The USDT-friction story was obvious, but as I sketched through real trading scenarios, a second reason kept showing up that nobody had really articulated yet: the readability of the price itself depends on the asset.

Memecoins and micro-caps look better in IDR

Take a coin priced at $0.00002341 in USDT. That's six leading zeros, hard to scan, easy to misread by a decimal place when you're placing orders quickly. Convert that to Rupiah at ~Rp16,000 per dollar and you get Rp 0.37, or for slightly higher tokens, clean whole numbers like Rp24, Rp358, Rp1.200. Mental math becomes trivial. Users trading meme tokens are usually placing many small orders fast, and readability matters.

Blue-chips like BTC, ETH, SOL look better in USDT

Now flip it. BTCUSDT at 106,513.12 USDT is clean, five digits, easy to anchor on. Convert that same price to Rupiah and you get Rp1.704.209.920. Ten digits and small percentage price change moves produce noisy nine-digit changes that are hard to track at a glance. USDT just reads better here.

So the choice between IDR and USDT isn't really about user comfort, it tracks the asset class. This reframed the project for me. 

IDR Perps wasn't a replacement for USDT Perps. It was a complementary mode, and a sophisticated trader might rationally want both at a time depending on what they're trading.

That had two direct design implications:

  1. Discovery surfaces (Home, Search, Market, Futures' Product Detail Page) needed to expose both currencies, side by side, without forcing a choice up front.

  2. The currency-switching flow couldn't be an afterthought, it would be a tool users genuinely use, not just an edge case.

What the system actually allows

Early conversations with backend team pinned down some non-negotiable technical constraints that ended up shaping every design decision downstream:

One CFX account per user

A quick aside for context, CFX (Bursa Komoditi dan Derivatif Indonesia) is the sole legal crypto futures clearing house and liquidity provider in Indonesia. Under Indonesian regulation (Bappebti, the commodity futures regulatory body), every crypto futures exchange operating in the country is required to route through CFX as the de facto liquidity layer. All Indonesian crypto exchanges share the same underlying trading pool because of this. From a user's perspective in the Ajaib app, none of this is visible, they just see Ajaib. But on the backend, every Perps position is really a position on CFX, held under a CFX account that Ajaib opens on behalf of the user.

That structure matters here because CFX runs cross-margin and can't separate USDT-denominated and IDR-denominated positions on the same account. Translation: users can hold IDR margin OR USDT margin, never both at the same time. To switch, they have to close everything, withdraw, and re-deposit.

Fixed FX rate, hidden from users

To protect the business from rate volatility as well as constant floating rate conversion (which can take hit on performance), the USDT/IDR rate is fixed and adjusted periodically by ops. But here's the design choice we made deliberately, we never show this rate anywhere in the user journey. No tooltip, no rate badge, no "1 USDT = RpX" disclosure. The user sees Rupiah everywhere, and the conversion is purely a backend concern. (The rate is documented in the T&Cs for users who want the full mechanics, but it's not something users need to think about while trading.)

Rounding mismatches

USDT prices can have up to 9 decimal places depending on the coin (PEPEUSDT being an extreme example), while IDR prices max out at 4 decimal places, since the weaker currency means even micro-cap coins still produce whole or near-whole Rupiah values. So when the system converts an IDR order into a USDT order on the exchange, there's always a rounding gap. All silent, all backend.

These constraints became the spine of the design problem. The most interesting one wasn't the math, it was behavioral: how do you ask a user to pick a single trading currency without making it feel like a punishment?

Ideation

Three ways to handle currency switching

This was the hardest design problem in the project. Switching is destructive (you have to close positions, withdraw funds, sometimes sell USDT on Spot first), and easy to break. I explored three directions:

Option 1: Hard separation

Treat IDR Perps and USDT Perps as two completely separate products with their own tabs, their own discovery, their own flows. Cleanest mental model, but breaks discovery (users wouldn't find an IDR pair from the global search) and would mean maintaining two parallel UIs forever.

Option 2 - Always-visible toggle

A top-level currency switcher, always present at the top of the trading screens. Like a language picker. Easy to find, but invites accidental switching, hides the constraint that switching requires closing positions, and creates a high risk of frustration when users tap it not realizing what they just triggered.

Option 3 - Contextual, surfaced only when needed

Both currencies show up in discovery (Home, Search, Market). On the Trade Page, the system follows whichever currency the user currently has margin in. If a user lands on a mismatched pair, the page is browsable but order entry is gated, and the constraint surfaces only when they try to deposit funds into the margin.

We went with Option 3. It respected the technical constraint, kept discovery fully open (which mattered for the asset-class readability point above), and turned the painful "one currency at a time" rule into a deliberate moment instead of a surprise error.

Design

Discovery

The goal here was making BTCIDR pairs discoverable everywhere, alongside their USDT counterparts, without making the app feel cluttered.

Home & Market

Caption

Inside the Futures section, I added a currency tab (IDR / USDT). The table data switches based on the selected tab. The default tab follows whatever currency the user currently has margin in, with a sensible fallback to USDT for first-time users.

Search

Caption

Both BTCUSDT-PERP and BTCIDR-PERP show up as separate tradeable instruments. Users can search either one and land on the respective detail page. The pair label itself (BTCIDR-PERP vs BTCUSDT-PERP) does most of the disambiguation work, no extra badging needed.

Futures Detail Page (FDP)

Futures Detail Page in IDR-margin and USDT-margin.

This was the most important surface to get right. For BTCIDR-PERP, every single data point on the FDP is rendered in Rupiah, last price, 24h change, volume, orderbook, chart axes, tooltips.

From the user's perspective, BTCIDR-PERP looks and feels like a native IDR instrument. They never see a USDT figure or a conversion rate.

The chart shape is identical to BTCUSDT-PERP (because it has to be, it's the same underlying market), but every label is in Rupiah.

The Trade Page

Futures Trade Page in IDR-margin and USDT-margin.

If you're an IDR-margin user on a BTCIDR trade page, or a USDT-margin user on a BTCUSDT trade page, everything works normally and Free Margin reflects your actual balance. But if you cross-visit, a USDT-margin user browsing BTCIDR for example, the page is fully accessible, the chart works, the orderbook works, Free Margin just shows 0. The moment they try to deposit is when the system steps in with the switching prompt.

Two things this design gets right:

  • Discovery stays unrestricted. Users with USDT-margin can still explore BTCIDR, see the chart, read the orderbook, get a feel for whether the Rupiah numbers read better for that asset, before committing.

  • The constraint surfaces at the right moment. Not at navigation, not at search, but at the deposit attempt, the moment the user is actually putting money to work. Friction lands on a deliberate action, not on browsing.

Currency context is set at the page level

Once a user is on the Trade Page, every number on the screen follows the active currency. Not just the headline price, every field:

  • Last Price & Mark Price

  • Bid and Ask prices in the orderbook

  • Entry price input

  • Notional order value

  • Required Margin and Free Margin

  • TP/SL price inputs

  • Liquidation Price

  • Unrealized P&L

  • Fees

No mixed units. No "$60,000 (≈ Rp960,000,000)" parenthetical conversions. No fine-print USDT equivalents. From the user's perspective on the BTCIDR Trade Page, they're trading an IDR pair, not a USDT pair wearing an IDR cover.

Order entry stays in the user's currency end-to-end

Flow of screens from creating an order, order confirmation, turned into open order and into a position.

The user types an IDR price, places the order, sees the order in IDR, and the position appears in IDR. The conversion to USDT happens in the backend, the rounding logic operates silently. From their perspective, the price they typed is the price that got placed.

Cross-currency state

If a USDT-margin user lands on the BTCIDR-PERP Trade Page (or vice versa), they can browse freely, the page is fully populated, the chart works, the orderbook works. But the Free Margin shows 0 and the order entry is gated. Tapping into deposit triggers a bottom sheet that explains the currency mismatch and offers the switching flow.

This was the key behavioral choice, the system never blocks browsing the other currency. It only surfaces friction when the user tries to act.

Futures Onboarding

Futures Onboarding Margin Currency selector screen.

New users who complete the KYC flow are presented with a currency selection screen ("Pilih Mata Uang Margin Futures") before they can start trading. The screen shows both options as a radio list with a short description under each:

  • Rupiah (IDR): framed around simplicity, trade directly using your Rupiah balance without converting to USDT first

  • Tether (USDT): framed around familiarity, the go-to for users already comfortable with USDT or who hold an existing USDT balance

Each description speaks to a different user type without talking down to either. There's no "recommended" label, no "most popular" badge, no persuasive hierarchy in the copy.

That said, IDR is pre-selected by default and carries a "Baru" (New) label. The default selection is a conscious design decision: a non-crypto-native user who isn't sure which to pick gets a sensible starting point without having to understand the difference between IDR and USDT margin first. A crypto-native user, on the other hand, will immediately know which option fits their trading preference and will switch without hesitation. The default serves the uncertain user without patronizing the informed one.

Currency Switching

This was the most design-heavy flow in the project, and the hardest to get right. Switching currency isn't a preference change, it's a financial operation. The user's open positions, open orders, and margin balance all live in their current currency and none of it can carry over. Everything has to be resolved before the switch can happen.

Requirements to switch

Switching currency is a one-step action, but only if the user has a clean slate. To switch without going through the full multi-step flow, the user cannot have:

  • Any active open orders (including TP/SL orders tied to a position)

  • Any active open positions

If either condition exists, the switch can't happen in one tap. The user has to resolve them first, closing positions and cancelling orders, before the system can move their margin across. This is what the multi-step flow is designed to handle.

The first instinct was to make this as seamless as possible, auto-close the user's positions, auto-cancel their orders, move the funds, done. But we quickly ruled that out. Open positions are active financial decisions the user made deliberately. Auto-closing them means auto-realizing their PnL, potentially at the worst moment, without their input. That's not a UX convenience, it's a liability. The same goes for open orders: silently cancelling them removes something the user intentionally set up. Keeping the user in control of closing their own positions and cancelling their own orders wasn't just the safer legal call, it was the right design call.

That said, the fully seamless flow is on the roadmap for the next phase. Getting there requires explicit user consent acknowledging that auto-realized P&L may not be fully accurate or real-time at the moment of switching. That's a legal and compliance requirement that needs its own agreement framework, something we decided was worth getting right rather than rushing into the first release.

The second benefit of not auto-closing was operational: it kept the switching flow itself clean and non-blocking. If we handled position closure inside the flow, the flow would have to wait for async confirmations from the exchange before proceeding. Instead, we route the user out to the existing close-position UI they already know, let them handle it there, then bring them back into the switching flow. The flow stays predictable and fast, and the user stays in control.

How users get into it

Two paths:

  1. The user manually taps "Switch Currency" from the Trade Page or wallet.

  2. The user attempts to deposit margin from a mismatched Trade Page, which triggers a bottom sheet explaining the mismatch and offering the switch.

Switching Flow

Switching Flow between USDT-margin and IDR-margin (vice-versa).

The flow opens with a plain-language explanation of what's about to happen and why, then shows the user a snapshot of everything they currently hold so they know exactly what needs to be resolved before anything moves. If they have a remaining margin balance, the system prompts them to transfer it out before switching: USDT → IDR users move their balance back to their Spot USDT wallet, IDR → USDT users move theirs back to Rekening Aset Global.

For users switching from USDT to IDR, we also offer an entry point to sell their transferred USDT balance via the USDT/IDR Spot trade page, in case they want to convert it to Rupiah right away, but this is optional and outside the switching flow itself. Once the slate is clean, the system switches the margin currency. The flow closes with a transfer status screen covering pending, success, and fail states at equal fidelity, so the user always knows where they stand and what to do next.

✦ THANK YOU ✦ FOR VISITING

JD

© Copyright 2026

✦ THANK YOU ✦ FOR VISITING

JD

© Copyright 2026

✦ THANK YOU ✦ FOR VISITING

JD

© Copyright 2026