data-book="docs" DEX (Native API example) | The Root Network
Skip to content

2.40 DEX (Native API example) ​
At a glance
What it isSwap one token for another, and add or remove liquidity. Futureverse’s Native API example for The Root Network, with its README and source.
Where it sitsPart II — Building · Chapter 2.40
CoversExamples · Source files
Sourcegithub.com/futureversecom/trn-examples/tree/main/examples/substrate/use-dex

Swap one token for another, and add or remove liquidity. Reference: dex pallet.

Copied from Futureverse’s futureversecom/trn-examples, deleted with its GitHub organisation, at commit 44c9e16 of 2024-10-31. Apache-2.0: license. Before you run it, read Running the examples.

Offline destinations

Some places this page points to did not answer when last checked:

  • docs-beta.therootnetwork.com — does not resolve (checked 2026-10-18)
  • stackblitz.com/github/futureversecom — StackBlitz loads these projects from the deleted futureversecom organisation on GitHub (checked 2026-10-18)

Run in StackBlitz (repository deleted, checked 2026-10-18) · Pallet Documentation (offline, checked 2026-10-18)

IMPORTANT

Ensure the following ENV vars are available before running the examples

2.40.1 Examples ​

bash
# change your working directory to this example first
cd examples/substrate/use-dex

# export all required environments
export CALLER_PRIVATE_KEY=

# swap one token to another
pnpm call:swap

# add liquidity to liquidity pool
pnpm call:addLiquidity

# remove liquidity from liquidity pool
pnpm call:removeLiquidity

2.40.2 Source files ​

src/addLiquidity.ts2.40.2.1 ​

ts
import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents";
import { formatEventData } from "@trne/utils/formatEventData";
import { ASTO_ASSET_ID, XRP_ASSET_ID } from "@trne/utils/porcini-assets";
import { sendExtrinsic } from "@trne/utils/sendExtrinsic";
import { withChainApi } from "@trne/utils/withChainApi";

interface Liquidity {
	0: number;
	1: number;
}

/**
 * Use `dex.addLiquidity` to add more liquidity for existing pair [XRP, ASTO], following the
 * existing ratio between the 2 tokens
 *
 * Assumes caller has ASTO for liquidity and XRP for both gas and liquidity.
 */
withChainApi("porcini", async (api, caller, logger) => {
	const tokenA = XRP_ASSET_ID;
	const tokenB = ASTO_ASSET_ID;

	// 💡 use `api.rpc.dex.getLiquidity` to get current ratio
	const liquidity = (await api.rpc.dex.getLiquidity(tokenA, tokenB)) as unknown as Liquidity;

	const tokenALiquidity = BigInt(liquidity["0"]);
	const tokenBLiquidity = BigInt(liquidity["1"]);

	const amountADesired = BigInt(1_000_000); // 1 XRP
	const amountBDesired = (amountADesired * tokenBLiquidity) / tokenALiquidity;

	const amountAMin = (amountADesired * BigInt(95)) / BigInt(100); // 5% slippage
	const amountBMin = (amountBDesired * BigInt(95)) / BigInt(100); // 5% slippage

	logger.info(
		{
			parameters: {
				tokenA,
				tokenB,
				amountADesired,
				amountBDesired,
				amountAMin,
				amountBMin,
			},
		},
		`create a "dex.addLiquidity" extrinsic`
	);

	const extrinsic = api.tx.dex.addLiquidity(
		tokenA,
		tokenB,
		amountADesired.toString(),
		amountBDesired.toString(),
		amountAMin.toString(),
		amountBMin.toString(),
		null, // to
		null // deadline
	);

	logger.info(`dispatch extrinsic from caller="${caller.address}"`);
	const { result, extrinsicId } = await sendExtrinsic(extrinsic, caller, { log: logger });
	const [addEvent] = filterExtrinsicEvents(result.events, ["Dex.AddLiquidity"]);

	logger.info(
		{
			result: {
				extrinsicId,
				blockNumber: result.blockNumber,
				addEvent: formatEventData(addEvent.event),
			},
		},
		"receive result"
	);
});

src/removeLiquidity.ts2.40.2.2 ​

ts
import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents";
import { formatEventData } from "@trne/utils/formatEventData";
import { ASTO_ASSET_ID, XRP_ASSET_ID } from "@trne/utils/porcini-assets";
import { sendExtrinsic } from "@trne/utils/sendExtrinsic";
import { withChainApi } from "@trne/utils/withChainApi";
import assert from "node:assert";

interface LiquidityToken {
	Ok: number;
}

/**
 * Use `dex.removeLiquidity` to remove your own liqidity from the pair [XRP, ASTO]
 *
 * Assumes caller liquidity of the pair and XRP to pay gas.
 */
withChainApi("porcini", async (api, caller, logger) => {
	const tokenA = XRP_ASSET_ID;
	const tokenB = ASTO_ASSET_ID;

	const lpAssetId = (await api.rpc.dex.getLPTokenID(tokenA, tokenB)) as unknown as LiquidityToken;
	const liquidity = await api.query.assets.account(lpAssetId.Ok, caller.address);
	assert(liquidity.isSome);

	logger.info(
		{
			liquidityBalance: {
				lpAssetId: lpAssetId.Ok,
				liquidity,
			},
		},
		`${caller.address} liquidity balance`
	);

	const amountAMin = 0;
	const amountBMin = 0;

	logger.info(
		{
			parameters: {
				tokenA,
				tokenB,
				liquidity: liquidity.unwrap().balance.toString(),
				amountAMin,
				amountBMin,
			},
		},
		`create a "futurepass.proxyExtrinsic" extrinsic`
	);
	const extrinsic = api.tx.dex.removeLiquidity(
		tokenA,
		tokenB,
		liquidity.unwrap().balance,
		amountAMin,
		amountBMin,
		null, // to
		null // deadline
	);

	const { result, extrinsicId } = await sendExtrinsic(extrinsic, caller, { log: logger });
	const [removeEvent] = filterExtrinsicEvents(result.events, ["Dex.RemoveLiquidity"]);

	logger.info(
		{
			result: {
				extrinsicId,
				blockNumber: result.blockNumber,
				removeEvent: formatEventData(removeEvent.event),
			},
		},
		"receive result"
	);
});

src/swap.ts2.40.2.3 ​

ts
import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents";
import { formatEventData } from "@trne/utils/formatEventData";
import { ASTO_ASSET_ID, XRP_ASSET_ID } from "@trne/utils/porcini-assets";
import { sendExtrinsic } from "@trne/utils/sendExtrinsic";
import { withChainApi } from "@trne/utils/withChainApi";

interface AmountsOut {
	Ok: [number, number];
}

/**
 * Use `dex.swapWithExactSupply` to swap XRP for ASTO, with exact amount in.
 *
 * Similar swap called can be used is `dex.swapWithExactTarget` to swap token with exact amount out.
 *
 * Assumes caller has XRP to pay for gas and to swap for ASTO.
 */
withChainApi("porcini", async (api, caller, logger) => {
	const tokenA = XRP_ASSET_ID;
	const tokenB = ASTO_ASSET_ID;
	const oneXrp = 1_000_000;
	// use `dex.getAmountsOut` to determin the minimum amount of ASTO from 1 XRP
	const {
		Ok: [amountIn, amountOut],
	} = (await api.rpc.dex.getAmountsOut(oneXrp, [tokenA, tokenB])) as unknown as AmountsOut;

	const amountOutMin = amountOut * 0.95; // 5% slippage

	logger.info(
		{
			parameters: {
				amountIn,
				amountOutMin,
				path: [tokenA, tokenB],
			},
		},
		`create a "dex.swapWithExactSupply" extrinsic`
	);
	const extrinsic = api.tx.dex.swapWithExactSupply(
		amountIn.toString(),
		amountOutMin.toString(),
		[tokenA, tokenB],
		null, // to
		null // deadline
	);

	logger.info(`dispatch extrinsic from caller="${caller.address}"`);
	const { result, extrinsicId } = await sendExtrinsic(extrinsic, caller, { log: logger });
	const [swapEvent] = filterExtrinsicEvents(result.events, ["Dex.Swap"]);

	logger.info(
		{
			result: {
				extrinsicId,
				blockNumber: result.blockNumber,
				swapEvent: formatEventData(swapEvent.event),
			},
		},
		"receive result"
	);
});

package.json2.40.2.4 ​

json
{
  "scripts": {
    "call": "tsx --tsconfig ../../../tsconfig.json",
    "call:swap": "pnpm call src/swap.ts",
    "call:addLiquidity": "pnpm call src/addLiquidity.ts",
    "call:removeLiquidity": "pnpm call src/removeLiquidity.ts"
  }
}
Source: futureversecom/trn-examples, examples/substrate/use-dex (deleted) · commit 44c9e16, 2024-10-31 · Apache-2.0, license · part of Code examples

Associated docs

Where else you might go from here. Following one is optional — this chapter stands without them.

Back matter — read in order
See also — The whole of Back matter as one continuous page, reprinted from its chapters without change.
Code examples
See also — Futureverse’s code examples for The Root Network: scripts for the native API and the EVM, and two contract projects, each with its README and source.
Contents
See also — Every chapter in this book, each with the one line that tells you what you get by reading it.
Decentralized Exchange
See also — The Root Network supports automated decentralized spot exchanges. It will allow users to:
Dex
See also — Add liquidity to Enabled trading pair, or add provision to Provisioning trading pair.
Front matter — read in order
See also — The whole of Front matter as one continuous page, reprinted from its chapters without change.
Guides for the code examples
See also — How Futureverse’s TRN code examples get a test account: create one in MetaMask and fund it from the Porcini faucet.
Index · A
See also — 609 index terms that start with A, each linked to the pages that define or use it.

Curated independently and source-attributed. Not affiliated with Futureverse or TRN Labs. Sources

Curated independently and source-attributed. Not affiliated with Futureverse or TRN Labs.