Liquidity Provisioning
Overview
To provide liquidity to a specific DeDust pool, you must supply both assets. After doing so, the pool issues LP tokens to the depositor's address.
Due to TON's limitations, executing two transfers simultaneously isn't feasible. Thus, the balances of user deposits must be retained until the LP tokens are distributed.
To manage this process, the DeDust Protocol uses a Liquidity Deposit contract. This contract is activated when one of the assets is deposited and automatically terminates after the pool has either accepted the liquidity or the deposit has been withdrawn.
Deposit liquidity
To add liquidity to a Pool (A, B), deposit asset A into Vault (A) and asset B into Vault (B). That's all.
In order to deposit liquidity, you should deposit two assets. After the first deposit DeDust deploys a temporary “liquidity deposit contract” which stores information about deposited assets. In DEX but not in pool yet. As soon as balances reach target balances It deposits liquidity to a pool, a pool mints LP to a user. At this moment this “liquidity deposit” contract gets destroyed.
Now, let's attempt to add some liquidity to the Pool (TON, DUST).
Step 1. Prepare input
Next, we'll need both assets and targetBalances to be identical for each deposit.
import { Asset } from '@dedust/sdk';
/* ... */
const tonAmount = toNano("5"); // 5 TON
const dustAmount = toNano("10"); // 10 DUST
const TON = Asset.native();
const DUST = Asset.jetton(DUST_ADDRESS);
const assets: [Asset, Asset] = [TON, DUST];
const targetBalances: [bigint, bigint] = [tonAmount, dustAmount];
Step 2. Deposit TON to Vault (TON)
import { PoolType } from '@dedust/sdk';
/* ... */
const tonVault = tonClient.open(await factory.getNativeVault());
await tonVault.sendDepositLiquidity(sender, {
poolType: PoolType.VOLATILE,
assets,
targetBalances,
amount: tonAmount,
});
Step 3. Deposit DUST to Vault (DUST)
import { JettonRoot, PoolType, VaultJetton } from '@dedust/sdk';
/* ... */
const dustRoot = tonClient.open(JettonRoot.createFromAddress(DUST_ADDRESS));
const dustWallet = tonClient.open(await dustRoot.getWallet(sender.address));
await dustWallet.sendTransfer(sender, toNano('0.5'), {
amount: dustAmount,
destination: dustVault.address,
responseAddress: sender.address,
forwardAmount: toNano('0.4'),
forwardPayload: VaultJetton.createDepositLiquidityPayload({
poolType: PoolType.VOLATILE,
assets,
targetBalances,
}),
});
You can get it by using this getter on the pool where you want to add liquidity:
https://github.com/dedust-io/sdk/blob/ecd9ee9a8ddbee74c7432f8755e4b3192932d5d5/src/contracts/dex/pool/Pool.ts#L75
if target balances reached - user gets LP and excess of DUST.
For example - 1 TON + 0.1 DUST: https://tonviewer.com/transaction/ce3aa7520f512efdd45986901191f78f61332793f5e1d1f4c7d7cf09977efaf7
Withdraw liquidity
To withdraw liquidity, we need to burn LP tokens. Here's how:
const pool = tonClient.open(await factory.getPool(PoolType.VOLATILE, [TON, DUST]));
const lpWallet = tonClient.open(await pool.getWallet(sender.address));
await lpWallet.sendBurn(sender, toNano('0.5'), {
amount: await lpWallet.getBalance(),
});
Cancel pending deposits
The deposit contract expects both tokens for mint lp. If one of the tokens has not yet been sent, the deposit will be in pending status. To return funds from the pending, you need to send a cancellation of the deposit.
const liquidityDeposit = tonClient.open(
await factory.getLiquidityDeposit({
ownerAddress: sender.address,
poolType: PoolType.VOLATILE,
assets,
}),
);
await liquidityDeposit.sendCancelDeposit(sender, {});