# Quickstart

> Get a swap quote from the Intear DEX Aggregator and execute it on NEAR in a few minutes, with JavaScript or Rust.

This page is part of the DEX Aggregator docs. The aggregator is at `https://router.intear.tech`, with live quotes at `wss://router.intear.tech/route/subscribe`, on NEAR mainnet only. https://docs.intear.tech/dex-aggregator/llms-full.txt has all of its pages in one file, and https://docs.intear.tech/llms.txt lists every page of the Intear docs.

This page goes through swapping 1 NEAR to USDt. It takes one HTTP request to get the route and a few signed transactions to execute it.

**JavaScript**

The examples on this page use `fetch` and [NEAR Connect](https://github.com/hot-dao/near-selector) (`@hot-labs/near-connect`). For signing on a server, see [Executing a route](https://docs.intear.tech/dex-aggregator/guides/executing-routes.md#signing).

**Rust**

The examples on this page use [reqwest](https://docs.rs/reqwest) and [near-kit](https://github.com/r-near/near-kit-rs):

```toml title="Cargo.toml"
anyhow = "1"
base64 = "0.23"
near-kit = "0.19"
reqwest = { version = "0.13", features = ["json"] }
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
```

The whole file, tested in CI: https://docs.intear.tech/snippets/rust/Cargo.toml

1. **Request a route.**

   All amounts are raw integers in the token's smallest unit. 1 NEAR is `10^24` yoctoNEAR.

   **JavaScript**

   ```js
   const params = new URLSearchParams({
     token_in: 'near',
     token_out: 'nep141:usdt.tether-token.near',
     amount_in: '1000000000000000000000000', // 1 NEAR
     slippage_type: 'Fixed',
     slippage: '0.01', // 1%
     trader_account_id: 'alice.near',
   });
   const response = await fetch(`https://router.intear.tech/route?${params}`);
   if (!response.ok) throw new Error(await response.text());
   const quotes = await response.json();
   ```

   The whole file, tested in CI: https://docs.intear.tech/snippets/js/src/quickstart.js

   **Rust**

   ```rust
   use near_kit::{AccountId, NearToken};
   use serde::Deserialize;

   #[derive(Debug, Deserialize)]
   struct Quote {
       dex_id: String,
       estimated_amount: Amount,
       worst_case_amount: Amount,
       execution_instructions: Vec<ExecutionInstruction>,
       token_output: String,
       fee_amount: String,
   }

   #[derive(Debug, Deserialize)]
   #[serde(rename_all = "snake_case")]
   enum Amount {
       AmountIn(String),
       AmountOut(String),
   }

   #[derive(Debug, Deserialize)]
   enum ExecutionInstruction {
       NearTransaction {
           receiver_id: AccountId,
           actions: Vec<InstructionAction>,
           is_fee_transaction: bool,
       },
   }

   #[derive(Debug, Deserialize)]
   enum InstructionAction {
       FunctionCall {
           method_name: String,
           args: String, // base64
           gas: u64,
           deposit: NearToken,
       },
   }

   let url = reqwest::Url::parse_with_params(
       "https://router.intear.tech/route",
       [
           ("token_in", "near"),
           ("token_out", "nep141:usdt.tether-token.near"),
           ("amount_in", "1000000000000000000000000"), // 1 NEAR
           ("slippage_type", "Fixed"),
           ("slippage", "0.01"), // 1%
           ("trader_account_id", "alice.near"),
       ],
   )?;
   let response = reqwest::get(url).await?;
   if !response.status().is_success() {
       anyhow::bail!(response.text().await?);
   }
   let quotes: Vec<Quote> = response.json().await?;
   ```

   The whole file, tested in CI: https://docs.intear.tech/snippets/rust/src/lib.rs

   Always pass `trader_account_id` for real quotes. Without it, the route can't include the storage deposits and registrations the trader is missing, and the swap may fail or lose tokens. It's an optional field, since you might want to still show the rates even when user's wallet is not connected yet.

2. **Pick a quote.**

   The response is an array of quotes, one per DEX that found a route, **sorted best first**. It's already ranked by what the trader gets after gas and storage costs, so in most cases you take the first one. An empty array means no DEX found a route.

   ```json
   [
     {
       "dex_id": "RheaDcl",
       "estimated_amount": { "amount_out": "4880007" },
       "worst_case_amount": { "amount_out": "4831206" },
       "token_output": "nep141:usdt.tether-token.near",
       "execution_instructions": [ ... ],
       "estimated_gas_usage": "8231794617168100000000",
       "estimated_max_gas_cost": "12521020071713600000000",
       "storage_deposits": "1250000000000000000000",
       "fee_amount": "0",
       "needs_unwrap": false
     }
   ]
   ```

   Show the user `estimated_amount` as the expected result and `worst_case_amount` as the minimum they will receive. `estimated_gas_usage` is the amount of NEAR that will likely be spent on gas and actually burnt, while `estimated_max_gas_cost` is all the gas the transactions attach, at NEAR's minimum gas price: the most they can burn. The user needs at least `storage_deposits + estimated_max_gas_cost` NEAR, plus the input when swapping from NEAR, to [execute the transactions](https://docs.intear.tech/dex-aggregator/guides/executing-routes.md#costs-and-balance). Keeping `estimated_max_gas_cost * 10` and another 0.05 NEAR for future gas costs to swap back gives a safe margin.

3. **Sign and send the transactions in order.**

   Each item in `execution_instructions` is a NEAR transaction. Send them **one by one, in order**, and wait for each one to succeed before sending the next. With [app fees](https://docs.intear.tech/dex-aggregator/guides/referral-fees.md), stop before the ones with `is_fee_transaction: true`, and send them only if [`/route/outcome`](https://docs.intear.tech/dex-aggregator/reference/outcome.md) says `charge_fee: true` ([Fee transactions](https://docs.intear.tech/dex-aggregator/guides/executing-routes.md#fee-transactions)).

   **JavaScript**

   ```js
   import { NearConnector } from '@hot-labs/near-connect';

   const connector = new NearConnector({ network: 'mainnet' });
   await connector.connect();
   const wallet = await connector.wallet();

   const quote = quotes[0];
   if (!quote) throw new Error('No route found');
   for (const { NearTransaction: tx } of quote.execution_instructions) {
     // App fees: send these only once /route/outcome says charge_fee is true
     if (tx.is_fee_transaction) break;
     const { status } = await wallet.signAndSendTransaction({
       receiverId: tx.receiver_id,
       actions: tx.actions.map(({ FunctionCall: call }) => ({
         type: 'FunctionCall',
         params: {
           methodName: call.method_name,
           args: JSON.parse(atob(call.args)), // args are base64-encoded JSON
           gas: String(call.gas),
           deposit: call.deposit,
         },
       })),
     });
     if (typeof status === 'object' && status.Failure) {
       throw new Error(`Transaction failed: ${JSON.stringify(status.Failure)}`);
     }
     // ft_transfer_call returns the amount the DEX used: "0" if it refunded everything
     const transferCall = tx.actions.at(-1)?.FunctionCall.method_name === 'ft_transfer_call';
     if (transferCall && typeof status === 'object' && status.SuccessValue === btoa('"0"')) {
       throw new Error('Swap refunded');
     }
   }
   ```

   The whole file, tested in CI: https://docs.intear.tech/snippets/js/src/quickstart.js

   **Rust**

   ```rust
   use base64::prelude::{BASE64_STANDARD, Engine as _};
   use near_kit::{Gas, Near, protocol::Action};

   let near = Near::mainnet()
       .credentials(std::env::var("NEAR_PRIVATE_KEY")?, "alice.near")?
       .build();

   let quote = quotes
       .into_iter()
       .next()
       .ok_or_else(|| anyhow::anyhow!("No route found"))?;
   for ExecutionInstruction::NearTransaction {
       receiver_id,
       actions,
       is_fee_transaction,
   } in quote.execution_instructions
   {
       // App fees: send these only once /route/outcome says charge_fee is true
       if is_fee_transaction {
           break;
       }
       let transfer_call = actions.last().is_some_and(
           |InstructionAction::FunctionCall { method_name, .. }| method_name == "ft_transfer_call",
       );
       let actions = actions
           .into_iter()
           .map(
               |InstructionAction::FunctionCall {
                    method_name,
                    args,
                    gas,
                    deposit,
                }| {
                   Ok(Action::function_call(
                       method_name,
                       BASE64_STANDARD.decode(args)?,
                       Gas::from_gas(gas),
                       deposit,
                   ))
               },
           )
           .collect::<anyhow::Result<Vec<_>>>()?;
       let outcome = near.transaction(receiver_id).add_actions(actions).await?;
       if outcome.is_failure() {
           anyhow::bail!("Transaction failed: {:?}", outcome.failure_message());
       }
       // ft_transfer_call returns the amount the DEX used: "0" if it refunded everything
       if transfer_call && outcome.result()? == b"\"0\"" {
           anyhow::bail!("Swap refunded");
       }
   }
   ```

   The whole file, tested in CI: https://docs.intear.tech/snippets/rust/src/lib.rs

   See [Executing a route](https://docs.intear.tech/dex-aggregator/guides/executing-routes.md) for the instruction format and edge cases.

4. **Check `token_output`.**

   If `token_output` is the same as your `token_out`, you're done. If it's different, the tokens landed in another form of the same token (for example NEAR instead of wNEAR, or in your wallet instead of a DEX's inner balance) and need one more conversion step. See [Tokens and locations](https://docs.intear.tech/dex-aggregator/guides/tokens.md#when-token_output-differs). You don't need to handle this if you use [Outcomes](https://docs.intear.tech/dex-aggregator/reference/outcome.md), it already sends you the next steps, including output conversion, and tells you whether to send the [fee transactions](https://docs.intear.tech/dex-aggregator/guides/executing-routes.md#fee-transactions).

## What's next

- Try different parameters in the [Playground](https://docs.intear.tech/dex-aggregator/playground.md).
- Keep quotes fresh while the user looks at them with [live quotes](https://docs.intear.tech/dex-aggregator/guides/live-quotes.md).
- Earn from the volume you bring with [referral fees](https://docs.intear.tech/dex-aggregator/guides/referral-fees.md).
