Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Commit

Permalink
feat: add lp example
Browse files Browse the repository at this point in the history
  • Loading branch information
a-bahdanau committed Sep 30, 2024
1 parent 990123c commit a643467
Showing 1 changed file with 195 additions and 2 deletions.
197 changes: 195 additions & 2 deletions pages/cookbook/dexes/dedust.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import { Callout } from 'nextra-theme-docs';

{/* See: https://nextra.site/docs/guide/built-ins */}

[DeDust](https://dedust.io) is a decentralized exchange (DEX) and automated market maker (AMM) built natively on [TON Blockchain](https://ton.org) and [DeDust Protocol 2.0](https://docs.dedust.io/reference/tlb-schemes). DeDust is designed with a meticulous attention to user experience (UX), gas efficiency, and extensibility.

## Swaps
Expand Down Expand Up @@ -152,3 +150,198 @@ fun makeJettonSwap() {
});
}
```


## Liquidity Provisioning

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.

You can read more about liquidity provisioning on [DeDust documentation](https://docs.dedust.io/docs/liquidity-provisioning).

```tact
const PoolTypeVolatile: Int = 0;
const PoolTypeStable: Int = 1;
const AssetTypeNative: Int = 0b0000;
const AssetTypeJetton: Int = 0b0001;
const JettonProvideLpGas: Int = ton("0.5");
const JettonProvideLpGasFwd: Int = ton("0.4");
const TonProvideLpGas: Int = ton("0.15");
const JettonMaster: Address = address("kQDkRHlWaibL7Tww48T6xAUFevPflca7i8TIiQTacBmnDOrb");
//const JettonMasterRaw: RawAddress = JettonMaster.toRaw(); TODO: maybe there is contants evaluation in tact? Did not find anything
const JettonVault: Address = address("kQDcUuH4xhKejjilZAIeGuBh5JRWpzbVDcO9Qfh_Q_K4q9vk");
const TonVault: Address = address("EQDa4VOnTYlLvDJ0gZjNYm5PXfSmmtL6Vs6A_CZEtXCNICq_");
struct RawAddress {
workchain: Int as uint8;
hash: Int as uint256;
}
extends fun toRaw(self: Address): RawAddress {
let addressSlice: Slice = self.asSlice();
addressSlice.skipBits(3);
return RawAddress {
workchain: addressSlice.loadUint(8),
hash: addressSlice.loadUint(256),
}
}
message(0xf8a7ea5) JettonTransfer {
queryId: Int as uint64;
amount: Int as coins;
destination: Address;
responseDestination: Address?;
customPayload: Cell? = null;
forwardTonAmount: Int as coins;
forwardPayload: Cell?;
}
struct Asset {
type: Int as uint4;
workchain: Int? as uint8 = null;
hash: Int? as uint256 = null;
}
extends fun build(self: Asset): Cell {
let assetBuilder = beginCell()
.storeUint(self.type, 4);
if (self.type == AssetTypeNative) {
return assetBuilder.endCell();
}
if (self.type == AssetTypeJetton) {
return assetBuilder
.storeUint(self.workchain!!, 8)
.storeUint(self.hash!!, 256)
.endCell();
}
require(false, "Unknown asset type");
return beginCell().endCell();
}
message(0x40e108d6) JettonDepositLiquidity {
poolType: Int as uint1; // PoolType
asset0: Asset;
asset1: Asset;
minimalLpAmount: Int as coins = 0;
targetBalances0: Int as coins;
targetBalances1: Int as coins;
fulfillPayload: Cell? = null;
rejectPayload: Cell? = null;
}
extends fun build(self: JettonDepositLiquidity): Cell {
return beginCell()
.storeUint(0x40e108d6, 32)
.storeUint(self.poolType, 1)
.storeSlice(self.asset0.build().asSlice())
.storeSlice(self.asset1.build().asSlice())
.storeCoins(self.minimalLpAmount)
.storeCoins(self.targetBalances0)
.storeCoins(self.targetBalances1)
.storeMaybeRef(self.fulfillPayload)
.storeMaybeRef(self.rejectPayload)
.endCell();
}
message(0xd55e4686) NativeDepositLiquidity {
queryId: Int as uint64;
amount: Int as coins;
poolType: Int as uint1;
asset0: Asset;
asset1: Asset;
minimalLpAmount: Int as coins = 0;
targetBalances0: Int as coins;
targetBalances1: Int as coins;
fulfillPayload: Cell? = null;
rejectPayload: Cell? = null;
}
extends fun build(self: NativeDepositLiquidity): Cell {
return beginCell()
.storeUint(0xd55e4686, 32)
.storeUint(self.queryId, 64)
.storeCoins(self.amount)
.storeUint(self.poolType, 1)
.storeSlice(self.asset0.build().asSlice())
.storeSlice(self.asset1.build().asSlice())
.storeRef(
beginCell()
.storeCoins(self.minimalLpAmount)
.storeCoins(self.targetBalances0)
.storeCoins(self.targetBalances1)
.endCell()
)
.storeMaybeRef(self.fulfillPayload)
.storeMaybeRef(self.rejectPayload)
.endCell();
}
message ProvideLp {
myJettonWalletAddress: Address; // calculated offchain for ease of example, in real world scenarios should be calculated onchain
}
contract Example {
receive() {}
receive(msg: ProvideLp) {
let jettonMasterRaw: RawAddress = JettonMaster.toRaw();
// Step 1. Prepare input
let jettonAmount = ton("1");
let tonAmount = ton("1");
let asset0 = Asset{
type: AssetTypeNative,
};
let asset1 = Asset{
type: AssetTypeJetton,
workchain: jettonMasterRaw.workchain,
hash: jettonMasterRaw.hash,
};
// Step 2. Deposit Jetton to Vault
let jettonDepositBody = JettonDepositLiquidity{
poolType: PoolTypeVolatile,
asset0,
asset1,
targetBalances0: tonAmount,
targetBalances1: jettonAmount,
}.build();
send(SendParameters{
to: msg.myJettonWalletAddress,
value: JettonProvideLpGas,
body: JettonTransfer{
queryId: 42,
amount: jettonAmount,
destination: JettonVault,
responseDestination: myAddress(),
forwardTonAmount: JettonProvideLpGasFwd,
forwardPayload: jettonDepositBody,
}.toCell()
});
// Step 3. Deposit TON to Vault
let nativeDepositBody = NativeDepositLiquidity{
queryId: 42,
amount: tonAmount,
poolType: PoolTypeVolatile,
asset0,
asset1,
targetBalances0: tonAmount,
targetBalances1: jettonAmount,
}.build();
send(SendParameters{
to: TonVault,
value: tonAmount + TonProvideLpGas,
body: nativeDepositBody,
});
}
}
```

0 comments on commit a643467

Please sign in to comment.