> For the complete documentation index, see [llms.txt](https://helvex.gitbook.io/helvex-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://helvex.gitbook.io/helvex-docs/02-helvex-how-the-app-works.md).

# How the app works

Permissioned, trader-first RFQ on Canton Network. You set the minimum you'll receive. Solvers bid to meet or beat it. Fees, acceptance, expiry, escrow, and atomic settlement.

Helvex is a permissioned, trader-first RFQ desk on Canton Network — a Dream Capital product. This page is the reference for that claim. It matches the live product on TestNet and MainNet.

KYC-verified traders swap CC, CBTC, or USDCx using a Helvex trading ID. You set the minimum amount you'll receive. Solvers bid to meet or beat it. A qualifying bid is not a guaranteed fill. There is no public order book. When a fill is accepted, settlement is atomic: both assets move, or neither does.

For request bodies and HMAC headers, use the [API integrator guide](/helvex-docs/01-helvex-api-integrator-guide.md).

## How trader-first RFQ works

Trader-first means the trade starts from your floor, not from a price the desk assigns and asks you to take.

You choose the pair, the size, and the **minimum you'll receive**. The app field uses that same label. The API field is `minBuyAmount`. A fresh indicative quote can pre-fill that number from `minReceive`. You can keep it or set your own floor before you submit. That quote lasts **30 seconds** and is not itself a locked trade. Refresh it if it expires before you post.

A solver bid qualifies only when the amount they deliver is **equal to or greater than** that minimum. A higher amount is price improvement. It is still not a guaranteed fill. The first accepted fill wins. A second solver who races it gets HTTP `409`. You cannot fill your own RFQ.

If no qualifying bid is accepted before you cancel, or before the RFQ deadline, there is no trade. The locked sell amount returns to **available**. The trade does not slip to a worse price.

**Illustrative only, not a live quote.** Sell 1,000 USDCx and set the minimum at 9,040 CC, near 0.11 USDCx per CC. 9,091 CC meets it. 9,140 CC beats it. 8,800 CC does not qualify. A live RFQ must still pass `withinLimits` on `GET /v1/quote` (notional **$10–$1,000**).

| Rule               | What actually happens                                                                                                                                                     |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Your minimum**   | `minBuyAmount` on the RFQ. Solvers must meet or beat it.                                                                                                                  |
| **Bid acceptance** | Only a `LOCKED` RFQ can be filled, and only by a different verified account. First accepted fill wins.                                                                    |
| **Fees**           | Helvex app fee is **0 bps** ($0). Canton still burns a small amount of **CC** as network traffic on lock, settle, deposit, and withdraw. That cost is set by the network. |
| **Escrow**         | Posting locks the sell amount in its own Canton transaction. It cannot be spent, withdrawn, or reused until a fill, a cancel, or the deadline.                            |
| **Expiry**         | The RFQ `deadline` must be in the future and at most **24 hours** out. An unfilled RFQ goes `REFUNDING` → `REFUNDED`.                                                     |
| **Settlement**     | After the accepted fill, both legs move in **one** Canton transaction, or neither does. Lock and settlement are two transactions.                                         |

The sections below are the same rules in operating order.

***

## 1. Open these sites (do not invent hosts)

| What            | TestNet (practice, faucet tokens)   | MainNet (real CC and real assets) |
| --------------- | ----------------------------------- | --------------------------------- |
| **Helvex app**  | <https://testnet-app.helvex.cc>     | <https://app.helvex.cc>           |
| **KYC**         | <https://testnet-app.helvex.cc/kyc> | <https://app.helvex.cc/kyc>       |
| **Helvex API**  | <https://testnet-api.helvex.cc>     | <https://api.helvex.cc>           |
| **Loop wallet** | <https://testnet.cantonloop.com>    | <https://cantonloop.com>          |

Keep Helvex and Loop on the **same** network. TestNet Loop with MainNet Helvex (or the reverse) will not work. If Loop asks you to pick a network, pick the same one as the Helvex URL you opened.

Health check: <https://testnet-api.helvex.cc/health> and <https://api.helvex.cc/health> each return `{"status":"ok"}`.

***

## 2. Words used in this guide

| Word             | Meaning                                                                                                                                                    |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Canton**       | The network Helvex settles on.                                                                                                                             |
| **CC**           | Canton Coin. Used as gas for ledger actions, and it can also be traded.                                                                                    |
| **CBTC**         | Bitcoin issued on Canton (BitSafe).                                                                                                                        |
| **USDCx**        | USDC issued on Canton (Circle).                                                                                                                            |
| **Loop**         | The self-custody Canton wallet in the browser. You hold keys there. Helvex uses it only to **deposit** and **withdraw**.                                   |
| **Trading ID**   | Your Helvex account on Canton (also called the app party). You **trade** from this ID, not from Loop. It looks like `40965c4d…::12207f81…`.                |
| **Maker**        | The person who posts a trade request.                                                                                                                      |
| **Solver**       | The other person, who fills that request. One login cannot fill its own request.                                                                           |
| **RFQ**          | Trader-first request for quote. The maker posts a sell amount and the minimum they'll receive. A solver qualifies only by meeting or beating that minimum. |
| **Lock**         | Helvex moves the maker’s sell amount into escrow on Canton so it cannot be spent twice.                                                                    |
| **Settle / DvP** | Delivery versus payment: both assets move in **one** Canton transaction, or neither does.                                                                  |
| **KYC**          | Identity check (government ID + live selfie via Didit) before you can use the app. This guide assumes that is already done.                                |
| **Available**    | Balance you can spend on a new RFQ, fill, or transfer. Not the same as `total` (which includes locked funds).                                              |

***

## 3. Two places money can sit

```
Loop wallet  ──deposit──▶  Helvex trading ID  ──trade──▶  other user’s trading ID
 (your keys)                 (on Helvex’s validator)
      ◀──────────────── withdraw (only to that same Loop wallet)
```

1. **Loop** is your wallet. You send assets from here into Helvex, and you take assets back here.
2. **Trading ID** is the Helvex account created when you click **Activate trading account**. Trades, locks, and fills happen here. Helvex’s validator submits those ledger actions.

Helvex reads trading balances from Canton. It does not invent a separate off-ledger balance.

Connecting Loop binds that wallet as the **only** deposit source and the **only** withdraw destination. An API client cannot pick a different address.

You can **Activate** and **trade** without Loop if the trading ID already has funds (for example someone sent you an internal transfer). You still need Loop to deposit or withdraw.

***

## 4. What you do, in order

Typical first-time path:

{% stepper %}
{% step %}

## Verify and log in

Open the KYC URL for your network. Enter email, name, an allowed country, profile Individual, role Both. Complete Didit (government ID + live selfie). Ignore the browser redirect after Didit — Helvex waits for the provider webhook.

When status is VERIFIED you get a Helvex email. Enter the 6-character code and set a password (the code expires in **7 days**). Log in at `/login`.
{% endstep %}

{% step %}

## Activate your trading ID

**Account** → **Activate trading account**, or home → **Activate now**. Until this succeeds you cannot deposit, post, or fill. The page then shows your trading ID (`…::1220…`).
{% endstep %}

{% step %}

## Connect Loop (only if you will deposit or withdraw)

**Connect Wallet** — Loop on the same network as Helvex. Required for deposit and withdraw. Not required to post or fill if the trading ID is already funded.
{% endstep %}

{% step %}

## Fund the trading ID

Put **CC** on Loop first (gas). Then send CC / CBTC / USDCx from Loop to your trading ID. Wait about **30 seconds** for Helvex to accept. The trading ID **available** balance should rise.

On TestNet, send faucets to the **Loop** party, not the trading ID:

* CC: <https://testnet-faucet.canton.foundation/> (often next business day)
* CBTC: <https://cbtc-faucet.bitsafe.finance>

USDCx on TestNet is a multi-step bridge. Skip it if you already have USDCx on the trading ID.

On MainNet, use real CC and real assets. Do not send TestNet tokens to MainNet addresses.
{% endstep %}

{% step %}

## Trade, then withdraw if you want

Trade from the trading ID. **Loop does not pop up** when you post or fill. Withdraw back to the same linked Loop wallet when you want funds out. Leave some CC on the trading ID for withdraw gas.
{% endstep %}
{% endstepper %}

***

## 5. Assets, pairs, and size limits

Three instruments: **CC**, **CBTC**, **USDCx**.

Minimum size per instrument (both networks):

* CC: **0.10**
* CBTC: **0.00001**
* USDCx: **1.0**

Each trade must also sit between **$10 and $1,000** USD notional. Confirm with `GET /v1/limits` (`minNotionalUsd` / `maxNotionalUsd`) and with the quote field `withinLimits` — do not guess a CBTC size from a mental BTC price.

Pairs on **both** TestNet and MainNet:

* `CBTC_USDCX` — sell CBTC, buy USDCx
* `USDCX_CBTC` — sell USDCx, buy CBTC
* `CC_USDCX` — sell CC, buy USDCx
* `USDCX_CC` — sell USDCx, buy CC
* `CC_CBTC` — sell CC, buy CBTC
* `CBTC_CC` — sell CBTC, buy CC

`GET /v1/pairs` is the source of truth. There is no CC-to-CC pair.

An RFQ `deadline` must be in the future and at most **24 hours** out (`maxIntentTtlSeconds` = 86400 on `GET /v1/limits`).

Amounts are always **decimal strings** (`"0.00015"`, not a JSON number). CC and CBTC use 10 decimal places. USDCx uses **6** decimals on TestNet and **10** on MainNet.

Access is KYC-gated and follows OFAC sanctions screening. Public market data (`/v1/pairs`, `/v1/limits`, `/v1/quote`) needs no login but is still geo-gated.

***

## 6. How a trade works

### 6.1 Quote (indicative, 30 seconds)

The app (or `GET /v1/quote`) shows a price. That price is **not** locked on Canton.

* CBTC ≈ Bitcoin from CoinGecko
* CC ≈ the Canton network CC price
* USDCx = **$1.00**

The quote’s **`minReceive`** is the suggested minimum. The RFQ stores the `minBuyAmount` you submit — keep the suggestion, or set your own floor. A solver must meet or beat that stored minimum. If the quote expires (**30 seconds**), refresh it before you post.

### 6.2 Maker posts an RFQ

The maker is your **trading ID**. Helvex authorizes the post from your login or your API client. There is **no Loop signature** on TestNet or MainNet.

The request includes a `signature` field. That field is a hash of the trade terms (`session:` plus SHA-256 of the JSON). It stops the body being changed in flight. It is not a wallet pop-up.

Helvex then locks the sell amount on Canton.

Status: `SUBMITTED` → `LOCK_PENDING` → `LOCKED`.

At `LOCKED`:

* The sell amount is in escrow. It cannot be spent, withdrawn, or used on another RFQ.
* Solvers can see the RFQ.
* Your **available** balance drops; **locked** rises.

### 6.3 Solver fills

A **second** Helvex account, with its own trading ID and enough **available** buy asset, fills the RFQ.

* The solver must deliver at least the maker’s `minBuyAmount`.
* Filling your own RFQ is refused.
* If two solvers race, the first accepted wins; the other gets HTTP `409`.

Status: `MATCHED`.

### 6.4 Helvex settles (atomic DvP)

A background worker completes the swap. In **one** Canton transaction both legs move: maker’s sell asset to the solver, solver’s buy asset to the maker. If that transaction fails, neither leg completes.

Status: `SETTLING` → `SETTLED`.

Lock and settle are **two** Canton transactions by design. The honest wording is **atomic settlement**, not “the whole product journey is one blockchain transaction.”

**Helvex app fee is $0 today** (0 basis points, $0 flat). Canton still burns a small amount of **CC** as network traffic on lock, settle, deposit, and withdraw. That traffic cost is set by the network, not by a fixed Helvex API number.

Default pace: **2 RFQs per minute** per account (`POST /v1/intents`). Fills are not in that cap.

### 6.5 Cancel or timeout

If nobody fills before you cancel, or the deadline passes:

`LOCKED` → `REFUNDING` → `REFUNDED`

The sell amount returns to **available**.

### 6.6 Withdraw

Only from a logged-in app session (not from an API client). Always to the linked Loop party. There is no destination field you can change.

Withdrawals at or above **$10,000** USD notional wait for Helvex approval. Amounts below **$10,000** auto-approve.

Leave some **CC** on the trading ID so the withdraw has gas.

***

## 7. What is atomic and what is not

| Step                                          | One Canton transaction?                                                                          |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| Deposit (prepare → Loop send → Helvex accept) | No. Two-phase. Credit usually appears in about 30 seconds.                                       |
| Lock the maker’s sell amount                  | Its own transaction.                                                                             |
| Settlement (both assets move)                 | **Yes — atomic.**                                                                                |
| App fee                                       | Not charged today. It would be a separate transfer after settlement, not inside the atomic swap. |
| Internal transfer (Helvex user → Helvex user) | Yes — one internal ledger move. No Loop.                                                         |
| Withdraw to Loop                              | Its own transaction.                                                                             |

***

## 8. RFQ statuses

| Status         | What it means                                       |
| -------------- | --------------------------------------------------- |
| `SUBMITTED`    | Helvex accepted the request. Lock has not finished. |
| `LOCK_PENDING` | Lock is in flight on Canton.                        |
| `LOCKED`       | Sell amount is in escrow. Solvers can see it.       |
| `MATCHED`      | A solver filled. Settlement is next.                |
| `SETTLING`     | The atomic swap is in flight.                       |
| `SETTLED`      | Both assets moved. Done.                            |
| `REFUNDING`    | Unlock in progress (cancel or deadline).            |
| `REFUNDED`     | Sell amount is available again.                     |
| `FAILED`       | Stopped with an error.                              |

***

## 9. App session vs API client

| Action                               | Website login                                | API client key                            |
| ------------------------------------ | -------------------------------------------- | ----------------------------------------- |
| Activate trading ID                  | Yes                                          | No                                        |
| Deposit / withdraw                   | Yes                                          | No                                        |
| See pairs, limits, quotes            | Yes (also public, no login; still geo-gated) | Yes (public, or signed if you send a key) |
| Post or cancel an RFQ                | Yes                                          | Yes, if the key has `maker`               |
| List and fill RFQs                   | Yes                                          | Yes, if the key has `solver`              |
| Read balances                        | Yes                                          | Yes, if the key has `read`                |
| Send to another Helvex user by email | Yes                                          | Yes, if the key has `transfer`            |

Mint an API key on **Account** after Activate. The secret is shown once.

API clients automate trading after the account is funded in the app. They cannot deposit, withdraw, or Activate — even if a `withdraw` scope name exists on the key. Self-serve keys: **2 API requests per minute**.

***

## 10. Gas, security, and privacy

* New Loop wallets need **CC** before they can send CBTC or USDCx.
* The Loop wallet pays gas for the deposit send. Helvex’s validator pays traffic for lock, settle, and withdraw.
* Withdraw destination is the linked Loop party only. A leaked API key cannot redirect cash-out.
* Party IDs are visible to the other side of a trade. Helvex uses an opaque id (not your email) as the left-hand part of the trading ID.

***

## 11. Try a full swap (no prior Helvex knowledge)

Use TestNet unless you intend to spend real CC.

1. Create **two** verified Helvex users (or use two provided reviewer accounts). One account cannot fill its own RFQ.
2. On each account: Activate the trading ID. Connect Loop only if you need to deposit or withdraw.
3. Fund each **trading ID** (not only Loop) so one side can sell and the other can buy. You can also fund the second trading ID with an internal transfer (no Loop).
4. Maker: home → pick pair → enter sell amount → wait for a fresh quote → set **Minimum you'll receive** → confirm the size is inside **$10–$1,000** → Submit. Confirm status **`LOCKED`**. No Loop pop-up.
5. Solver: other browser or incognito → `/solver` → fill the `LOCKED` RFQ. Confirm it under **Your fills** and on Create intent activity (**Filled**). Status goes **`MATCHED`** then **`SETTLED`**.
6. Both Account pages should show the swapped balances (`available` changed; `locked` back to zero on that RFQ).
7. Optional: cancel an unfilled `LOCKED` RFQ and confirm **`REFUNDED`**. Optional: withdraw a small amount and confirm it arrives only on the linked Loop wallet.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://helvex.gitbook.io/helvex-docs/02-helvex-how-the-app-works.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
