# Guide

This guide outlines how to use the Swap API to execute a swap.\
\
The full source code of this guide can be found in this [Github](https://github.com/0xoogabooga/ooga-booga-api-example) repository.

Follow these steps to complete a swap:

{% stepper %}
{% step %}

### Obtain API Key

Get an API key by reaching out to a member of our team.
{% endstep %}

{% step %}

### Check Allowances

Check the current allowances for the tokens involved in the swap.
{% endstep %}

{% step %}

### Set Allowances

Use an approval transaction to set the required allowances for the swap.
{% endstep %}

{% step %}

### Execute Swap

Initiate the swap transaction.
{% endstep %}
{% endstepper %}

## 1. Obtain an API Key

The API is currently available by request only. To obtain API keys, contact the team directly on Telegram: [@whoiskevinn](https://t.me/whoiskevinn) or [@beranoulli](https://t.me/beranoulli).

## 2. Check Allowances

Before initiating trades with the Swap API, it is crucial to approve the ERC20 token intended for the swap (the input token) against the router. Ensure there is sufficient allowance granted to `OBRouter`. You can verify this programmatically or manually by calling the `allowance` function directly on the ERC20's contract on-chain.

The example code is written using `bun` and `viem`. But it should be equally simple to integrate using other runtimes such as `node.js` and other EVM libraries such as `ether.js`

Setting up the environment:

```typescript
import {
	http,
	type Address,
	createWalletClient,
	maxUint256,
	parseEther,
	publicActions,
	zeroAddress,
} from "viem"; // Main library used to interface with the blockchain
import { privateKeyToAccount } from "viem/accounts";
import { berachainTestnetbArtio } from "viem/chains";

if (!process.env.PRIVATE_KEY) throw new Error("PRIVATE_KEY is required");
if (!process.env.PUBLIC_API_URL) throw new Error("PUBLIC_API_URL is required");
if (!process.env.API_KEY) throw new Error("API_KEY is required");

const PRIVATE_KEY = process.env.PRIVATE_KEY as Address; // Private key of the account to make the trade
const PUBLIC_API_URL = process.env.PUBLIC_API_URL;
const API_KEY = process.env.API_KEY;
```

Setting the account and initializing the EVM libraries:

```typescript
const account = privateKeyToAccount(PRIVATE_KEY);
const client = createWalletClient({
	chain: berachainTestnetbArtio,
	transport: http(),
	account,
}).extend(publicActions);
```

Defining the swap parameters (this example uses a 0.01 HONEY to BERA swap):

```typescript
// Bartio token addresses
const NATIVE_TOKEN: Address = zeroAddress; // Default address for Bera native token
const HONEY: Address = "0x0E4aaF1351de4c0264C5c7056Ef3777b41BD8e03"; // 


const swapParams = {
	tokenIn: HONEY, // Address of the token swapping from (HONEY)
	tokenOut: NATIVE_TOKEN, // Address of the token swapping to (BERA)
	amount: parseEther("0.02"), // Amount of tokenIn to swap
	to: account.address, // Address to send tokenOut to (optional and defaults to `from`)
	slippage: 0.01, // Range from 0 to 1 to allow for price slippage
};
type SwapParams = typeof swapParams;
```

The Swap API also allows developers to query the allowances directly instead of doing on-chain.

{% hint style="info" %}
If you are trading the native token no allowance is required. In this example, for simplicity, the allowance is set to `maxUint256` in the native token case.
{% endhint %}

```typescript
const headers = {
	Authorization: `Bearer ${API_KEY}`,
};

const getAllowance = async (token: Address, from: Address) => {
  // Native token does not require approvals for allowance
	if (token === NATIVE_TOKEN) return maxUint256;

	const publicApiUrl = new URL(`${PUBLIC_API_URL}/v1/approve/allowance`);
	publicApiUrl.searchParams.set("token", token);
	publicApiUrl.searchParams.set("from", from);

	const res = await fetch(publicApiUrl, {
		headers,
	});
	const json = await res.json();
	return json.allowance;
};
```

{% hint style="warning" %}
Everytime the Swap API is queried, the `API_KEY` has to be provided on the `fetch` call.&#x20;
{% endhint %}

`getAllowance` fits into the main execution body likeso:

```typescript
async function main() {

	// Check allowance
	const allowance = await getAllowance(swapParams.tokenIn, swapParams.from);
	console.log("Allowance", allowance);

	// Approve if necessary
	if (allowance < swapParams.amount) {
		await approveAllowance(
			swapParams.tokenIn,
			swapParams.from,
			swapParams.amount - allowance, // Only approve amount remaining
		);
	}
	// Swap
	await swap(swapParams);
}
```

## 3. Approving Allowances

{% hint style="info" %}
The `amount` parameter can be left out, generating a transaction to approve unlimited amounts for the given token to the router. This is useful to save gas on subsequent swap requests.
{% endhint %}

```typescript
const approveAllowance = async (
	token: Address,
	amount: bigint,
) => {
	const publicApiUrl = new URL(`${PUBLIC_API_URL}/v1/approve`);
	publicApiUrl.searchParams.set("token", token);
	publicApiUrl.searchParams.set("amount", amount.toString());

	const res = await fetch(publicApiUrl, { headers });
	const { tx } = await res.json();

	console.log("Submitting approve...");
	const hash = await client.sendTransaction({
		from: tx.from as Address,
		to: tx.to as Address,
		data: tx.data as `0x${string}`,
	});

	const rcpt = await client.waitForTransactionReceipt({
		hash,
	});
	console.log("Approval complete", rcpt.transactionHash, rcpt.status);
};
```

Approving if neccesary:

```typescript
async function main() {
	// Check allowance
	const allowance = await getAllowance(swapParams.tokenIn, swapParams.from);
	console.log("Allowance", allowance);


	// Approve if necessary
	if (allowance < swapParams.amount) {
		await approveAllowance(
			swapParams.tokenIn,
			swapParams.from,
			swapParams.amount - allowance, // Only approve amount remaining
		);
	}
	// Swap
	await swap(swapParams);
}
```

## 4. Execute Swap

Once the necessary allowances are in place, you can call the final API endpoint to generate a quote. If the quote meets your expectations, proceed to execute the trade.

The swap query doubles as a quote, providing essential details about the trade. Comprehensive information about the quote can be found in the API reference.

Additionally, the quote endpoint generates the complete transaction body, ready to be signed and submitted directly on-chain.

```typescript
const swap = async (swapParams: SwapParams) => {
	const publicApiUrl = new URL(`${PUBLIC_API_URL}/v1/swap`);
	publicApiUrl.searchParams.set("tokenIn", swapParams.tokenIn);
	publicApiUrl.searchParams.set("amount", swapParams.amount.toString());
	publicApiUrl.searchParams.set("tokenOut", swapParams.tokenOut);
	publicApiUrl.searchParams.set("to", swapParams.to);
	publicApiUrl.searchParams.set("slippage", swapParams.slippage.toString());

	const res = await fetch(publicApiUrl, { headers });
	const { tx } = await res.json();

	console.log("Submitting swap...");
	const hash = await client.sendTransaction({
		from: tx.from as Address,
		to: tx.to as Address,
		data: tx.data as `0x${string}`,
		value: tx.value ? BigInt(tx.value) : 0n,
	});
	console.log("hash", hash);

	const rcpt = await client.waitForTransactionReceipt({
		hash,
	});
	console.log("Swap complete", rcpt.status);
};
```

{% hint style="info" %}
If the `tokenIn` is the native token, ensure that a `value` is passed. This will automatically wrap the native token into WBERA, enabling it to be traded.

If `BERA` is the `tokenOut` then it will be returned unwrapped.
{% endhint %}

{% hint style="success" %}
The`res` object can be printed to view the complete routing path and detailed information about the swap. For a comprehensive breakdown of the response, refer to the API Reference.
{% endhint %}

Executing:

```typescript
async function main() {
	// Check allowance
	const allowance = await getAllowance(swapParams.tokenIn, account.address);
	console.log("Allowance", allowance);

	// Approve if necessary
	if (allowance < swapParams.amount) {
		await approveAllowance(
			swapParams.tokenIn,
			swapParams.amount - allowance, // Only approve amount remaining
		);
	}
	// Swap
	await swap(swapParams);
}
```
