Skip to content
markdown
# Swapping Tokens

Token swapping is one of the primary features of the LuminaDex. This guide explains how to implement token swapping with the LuminaDex SDK.

## Swap Workflow

The complete swap workflow involves two main steps:

1. **Calculate the swap**: This calculates the expected output amount based on the input amount and current pool state
2. **Execute the swap**: This sends the actual transaction to the blockchain

This two-step process allows users to preview the expected outcome before committing to the transaction.

## Calculating a Swap

To calculate a swap, you send a `ChangeSwapSettings` event to the DEX machine:

```ts
Dex.send({
	type: "ChangeSwapSettings",
	settings: {
		// The pool address to use for the swap
		pool: "B62qjGnANmDdJoBhWCQpbN2v3V4CBb5u1VJSCqCVZbpS5uDs7aZ7TCH",

		// The input token (address and amount)
		from: {
			address: "MINA", // Special case for the native MINA token
			amount: "1" // Amount as a string
		},

		// The output token address
		to: "B62qjDaZ2wDLkFpt7a7eJme6SAJDuc3R3A2j2DRw7VMmJAFahut7e8w",

		// Slippage in percentage
		slippagePercent: 0.5
	}
})
```

The SDK will fetch the current pool state from the blockchain and calculate:

- Expected output amount
- Output amount (with slippage)
- Input amount (with slippage)

These results will be stored in the `context.dex.swap.calculated` object.

## Executing a Swap

Once the calculation is complete, you can execute the swap by sending a `Swap` event:

```ts
Dex.send({ type: "Swap" })
```

The DEX machine will:

1. Prepare the transaction and generate the proof
2. Prompt the user to sign it with the connected wallet
3. Send it to the blockchain
4. Store the transaction result in `context.dex.swap.transactionResult`

## Checking if Actions are Available

The SDK provides a convenient helper function `canDoDexAction` that checks if specific actions are available based on the current state:

```ts
import { canDoDexAction } from "@lumina-dex/sdk"

const canDo = canDoDexAction(Dex.getSnapshot().context)

if (canDo.changeSwapSettings) {
	// Can change swap settings
}

if (canDo.swap) {
	// Can execute swap
}
```

Use this to enable/disable UI elements based on what actions are currently possible.

## Working with Different Token Types

When swapping tokens, you need to be aware of different token types:

### Native MINA Token

Use the special address `"MINA"` for the native MINA token:

```ts
from: {
  address: "MINA",
  amount: "1"
}
```

### Custom Tokens

For custom tokens, use their contract address:

```ts
from: {
  address: "B62qjDaZ2wDLkFpt7a7eJme6SAJDuc3R3A2j2DRw7VMmJAFahut7e8w",
  amount: "10"
}
```

## Token Amounts and Unit Conversion

All calculated token amounts in the SDK are returned as `bigint` in the token's smallest units (similar to wei in Ethereum). Most tokens use 9 decimal places.

The SDK exports four utility functions for converting between human-readable decimals and on-chain units:

### `toUnits(amount, decimals)`

Converts a decimal number to the smallest unit of a token as `bigint`. Uses string manipulation internally to avoid floating-point precision loss.

```ts
import { toUnits } from "@lumina-dex/sdk"

toUnits(1.5, 9) // → 1_500_000_000n
toUnits(10, 6) // → 10_000_000n
```

### `toNanoUnits(amount)`

Convenience wrapper for tokens with 9 decimal places (MINA and most tokens on Mina Protocol).

```ts
import { toNanoUnits } from "@lumina-dex/sdk"

toNanoUnits(1.5) // → 1_500_000_000n
```

### `fromUnits(amount, decimals)`

Converts a `bigint` amount in smallest units back to a human-readable decimal number.

```ts
import { fromUnits } from "@lumina-dex/sdk"

fromUnits(1_500_000_000n, 9) // → 1.5
fromUnits(10_000_000n, 6) // → 10
```

### `fromNanoUnits(amount)`

Convenience wrapper for tokens with 9 decimal places.

```ts
import { fromNanoUnits } from "@lumina-dex/sdk"

fromNanoUnits(1_500_000_000n) // → 1.5
```

### Usage Example

```ts
const calculated = Dex.getSnapshot().context.dex.swap.calculated

if (calculated) {
	// calculated.amountOut is bigint — convert for display
	console.log("Expected output:", fromNanoUnits(calculated.amountOut))
	console.log("Min output (with slippage):", fromNanoUnits(calculated.balanceOutMin))
}
```

## Error Handling

Errors during the swap process are captured in the context:

```ts
const dexError = Dex.getSnapshot().context.dex.error
const contractError = Dex.getSnapshot().context.contract.error

if (dexError) {
	console.error("DEX Error:", dexError.message)
}

if (contractError) {
	console.error("Contract Error:", contractError.message)
}
```

Use these to display appropriate error messages to the user.

Released under the MIT License.