# Pools

> Plach pools: public, private and launch pools, creating a pool, editing fees and locking a private pool, older pool types, and reading pools.

This page is part of the Plach docs. Plach is the DEX `slimedragon.near/xyk` on the Intear DEX contract, `dex.intear.near`, and every call goes to that contract. https://docs.intear.tech/plach/llms-full.txt has all of its pages in one file, and https://docs.intear.tech/llms.txt lists every page of the Intear docs.

A pool holds two different assets, NEAR, NEP-141 or NEP-245, and swaps between them. Pool IDs are counted from 0 in the order pools were created.

## Kinds of pools

### Public

Anyone can [add liquidity](https://docs.intear.tech/plach/guides/liquidity.md#public-pools) and gets shares. A public pool is created with its first liquidity, and the creator gets 10<sup>18</sup> shares for it, so nobody else can set its starting price. If all its liquidity is removed, though, the next one to add liquidity [sets the price again](https://docs.intear.tech/plach/guides/liquidity.md#add). Its fees can never change. Its `Pool` fees go to its liquidity providers, each in the [way it chooses](https://docs.intear.tech/plach/guides/liquidity.md#fees).

### Private

The owner, who created it, is the only one who adds and removes liquidity, and can change the fees. The owner can **lock** the pool, which is final: after that, its liquidity can't be removed and its fees can't change. Locking a pool shows traders and holders of a token that its liquidity stays.

### Launch

For launching a token. The creator gives the pool all of the new token, and sets an amount of **phantom liquidity** of the quote asset (often NEAR): liquidity that isn't there, but sets the starting price as if it were. As people buy, real quote asset comes in. A swap that would take the pool's quote balance below the phantom liquidity fails, so sellers can only take out quote asset that buyers put in.

Launch pools don't take or give back liquidity after creation, and their fees can't change. An `Account` receiver with `ConvertToFirstAsset` is paid in the quote asset, sells included, and a `Pool` fee stays in the pool. See [The asset a fee is paid in](https://docs.intear.tech/plach/guides/fees.md#the-asset-a-fee-is-paid-in).

## Create a pool

`create_pool` takes:

```rust
struct CreatePoolArgs {
    assets: (AssetId, AssetId),
    fees: FeeConfiguration,
    pool_type: PoolType,
    /// Required for public pools, optional for private pools,
    /// not accepted for launch pools
    initial_liquidity: Option<(u128, u128)>,
    /// How the creator takes its part of the pool fees, as the provider of
    /// the first liquidity. Required for public pools, not accepted for others
    creator_fee_payout_type: Option<FeePayoutType>,
}
```

See [Types](https://docs.intear.tech/plach/reference/types.md) for [`FeeConfiguration`](https://docs.intear.tech/plach/reference/types.md#feeconfiguration), [`PoolType`](https://docs.intear.tech/plach/reference/types.md#pooltype) and [`FeePayoutType`](https://docs.intear.tech/plach/reference/types.md#feepayouttype), [Fees](https://docs.intear.tech/plach/guides/fees.md) for what a fee configuration can do, and [Liquidity](https://docs.intear.tech/plach/guides/liquidity.md#fees) for the payout of the creator's part of a public pool's fees.

Attach:

- **NEAR for storage**, always. What's left after the storage is sent to your wallet.
- **The initial liquidity**, exactly. If one of the assets is NEAR, its amount comes out of the same attached NEAR as the storage.
- For a launch pool, **the launched token** (the second asset), all of it. The first asset is the quote asset, and `pool_type` has the phantom liquidity.

Both assets must be [registered](https://docs.intear.tech/intear-dex/guides/inner-balances.md#register-assets) for Plach in the engine, or the call fails with `Asset <asset> is not registered for Dex(slimedragon.near/xyk)`. NEAR and USDt already are, but a new token, like any launched one, isn't: check with `are_assets_registered` and register it with `register_assets`, both with `"for": {"Dex": "slimedragon.near/xyk"}`.

The response is the new pool's ID, a Borsh `u32`. This creates a private pool of NEAR and USDt with a 0.3% fee for the pool, of which 0.24% stays in it and 0.06% is the protocol's, and 1 NEAR and 5 USDt of liquidity:

```
00                                       asset 0: near
01 16 00 00 00 "usdt.tether-token.near"  asset 1: nep141:usdt.tether-token.near
01 00 00 00                              fees: 1 receiver
01                                         Pool
00 b8 0b 00 00                             Fixed(3000), 0.3%
00                                       pool type: PrivateLatest
01                                       initial liquidity: Some
00 00 00 a1 ed cc ce 1b c2 d3 00 00 00 00 00 00    1000000000000000000000000 (1 NEAR)
40 4b 4c 00 00 00 00 00 00 00 00 00 00 00 00 00    5000000 (5 USDt)
00                                       creator's fee payout: None, since the pool is private
```

It runs after a [storage deposit](https://docs.intear.tech/intear-dex/guides/storage.md#accounts), registering NEAR and USDt, and depositing 1.01 NEAR and 5 USDt, as in [this script](#the-whole-script). `near --quiet` prints only the result, so the pool ID can be kept for the next calls:

```sh
# A private pool of NEAR and USDt with a 0.3% fee that stays in the pool, and
# 1 NEAR and 5 USDt of liquidity. The other 0.01 NEAR pays for its storage.
# --quiet prints only the result: the ID of the new pool, in Borsh and base64.
POOL_ID=$(near --quiet contract call-function as-transaction dex.intear.near dex_call \
  json-args '{
    "dex_id": "slimedragon.near/xyk",
    "method": "create_pool",
    "args": "AAEWAAAAdXNkdC50ZXRoZXItdG9rZW4ubmVhcgEAAAABALgLAAAAAQAAAKHtzM4bwtMAAAAAAABAS0wAAAAAAAAAAAAAAAAAAA==",
    "attached_assets": {
      "near": "1010000000000000000000000",
      "nep141:usdt.tether-token.near": "5000000"
    }
  }' \
  prepaid-gas '100.0 Tgas' attached-deposit '1 yoctoNEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send | jq -r .)
echo "Created pool $(echo "$POOL_ID" | base64 -d | od -An -tu4)"
```

The whole file, tested in CI: https://docs.intear.tech/snippets/cli/plach-pools.sh

## Read pools

`get_pool` takes a pool ID and returns a Borsh `Option<PoolView>`, `None` if there's no such pool. The pool ID that `create_pool` returned is already the whole argument:

```sh
# The pool ID in Borsh is also the whole argument of get_pool
near contract call-function as-read-only dex.intear.near dex_view \
  json-args "$(jq -n --arg pool_id "$POOL_ID" '{
    "dex_id": "slimedragon.near/xyk",
    "method": "get_pool",
    "args": $pool_id
  }')" \
  network-config mainnet now
```

The whole file, tested in CI: https://docs.intear.tech/snippets/cli/plach-pools.sh

A [`PoolView`](https://docs.intear.tech/plach/reference/types.md#poolview) has the pool's kind, assets and balances, its fees with the protocol fee, and its fee configuration. `get_pools` returns several, from `start_index`, and `get_pool_count` the number of pools. The ID of each pool in a page is `start_index` plus its position. See [Methods](https://docs.intear.tech/plach/reference/methods.md#views).

## Edit fees

The owner of a private pool can replace its fee configuration with `edit_fees`, which takes the pool ID followed by the new configuration. Attach NEAR if the new configuration takes more storage than the old one, like a new receiver, which the pool registers for the assets its payout takes, or a scheduled fee in place of a fixed one. Plach uses what it needs and sends the rest to your wallet. This sets the fee to 0.1%, which takes the same storage, so nothing is attached:

```sh
# The pool ID, followed by the new fee: 0.1% that stays in the pool
ARGS=$({ echo "$POOL_ID" | base64 -d; echo "AQAAAAEA6AMAAA==" | base64 -d; } | base64)

near contract call-function as-transaction dex.intear.near dex_call \
  json-args "$(jq -n --arg args "$ARGS" '{
    "dex_id": "slimedragon.near/xyk",
    "method": "edit_fees",
    "args": $args,
    "attached_assets": {}
  }')" \
  prepaid-gas '100.0 Tgas' attached-deposit '1 yoctoNEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send
```

The whole file, tested in CI: https://docs.intear.tech/snippets/cli/plach-pools.sh

## Lock a private pool

`lock_pool` takes the pool ID. Only the owner can lock a pool, and it can't be unlocked.

```sh
near contract call-function as-transaction dex.intear.near dex_call \
  json-args "$(jq -n --arg pool_id "$POOL_ID" '{
    "dex_id": "slimedragon.near/xyk",
    "method": "lock_pool",
    "args": $pool_id,
    "attached_assets": {}
  }')" \
  prepaid-gas '100.0 Tgas' attached-deposit '1 yoctoNEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send
```

The whole file, tested in CI: https://docs.intear.tech/snippets/cli/plach-pools.sh

## Older pool types

`create_pool` also takes the pool types of older versions, like `PublicV2` or `LaunchV1`, and creates a pool of the current version of its kind. Use the `Latest` types. `LaunchV1` still requires NEAR as the first asset.

Every existing pool was upgraded to the current version, so there's no `upgrade_pool` or `pool_needs_upgrade` any more.

## The whole script

```sh
#!/usr/bin/env bash
# Creates a private NEAR/USDt pool on Plach, changes its fee, and locks it.
# alice.near holds USDt in the wallet and has never used Intear DEX.
set -euo pipefail

near contract call-function as-transaction dex.intear.near storage_deposit \
  json-args '{}' \
  prepaid-gas '30.0 Tgas' attached-deposit '0.01 NEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send

near contract call-function as-transaction dex.intear.near register_assets \
  json-args '{"asset_ids": ["near", "nep141:usdt.tether-token.near"]}' \
  prepaid-gas '30.0 Tgas' attached-deposit '1 yoctoNEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send

near contract call-function as-transaction dex.intear.near deposit_near \
  json-args '{}' \
  prepaid-gas '30.0 Tgas' attached-deposit '1.01 NEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send

near contract call-function as-transaction usdt.tether-token.near ft_transfer_call \
  json-args '{"receiver_id": "dex.intear.near", "amount": "5000000", "msg": ""}' \
  prepaid-gas '50.0 Tgas' attached-deposit '1 yoctoNEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send

# A private pool of NEAR and USDt with a 0.3% fee that stays in the pool, and
# 1 NEAR and 5 USDt of liquidity. The other 0.01 NEAR pays for its storage.
# --quiet prints only the result: the ID of the new pool, in Borsh and base64.
POOL_ID=$(near --quiet contract call-function as-transaction dex.intear.near dex_call \
  json-args '{
    "dex_id": "slimedragon.near/xyk",
    "method": "create_pool",
    "args": "AAEWAAAAdXNkdC50ZXRoZXItdG9rZW4ubmVhcgEAAAABALgLAAAAAQAAAKHtzM4bwtMAAAAAAABAS0wAAAAAAAAAAAAAAAAAAA==",
    "attached_assets": {
      "near": "1010000000000000000000000",
      "nep141:usdt.tether-token.near": "5000000"
    }
  }' \
  prepaid-gas '100.0 Tgas' attached-deposit '1 yoctoNEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send | jq -r .)
echo "Created pool $(echo "$POOL_ID" | base64 -d | od -An -tu4)"

# The pool ID in Borsh is also the whole argument of get_pool
near contract call-function as-read-only dex.intear.near dex_view \
  json-args "$(jq -n --arg pool_id "$POOL_ID" '{
    "dex_id": "slimedragon.near/xyk",
    "method": "get_pool",
    "args": $pool_id
  }')" \
  network-config mainnet now

# The pool ID, followed by the new fee: 0.1% that stays in the pool
ARGS=$({ echo "$POOL_ID" | base64 -d; echo "AQAAAAEA6AMAAA==" | base64 -d; } | base64)

near contract call-function as-transaction dex.intear.near dex_call \
  json-args "$(jq -n --arg args "$ARGS" '{
    "dex_id": "slimedragon.near/xyk",
    "method": "edit_fees",
    "args": $args,
    "attached_assets": {}
  }')" \
  prepaid-gas '100.0 Tgas' attached-deposit '1 yoctoNEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send

near contract call-function as-transaction dex.intear.near dex_call \
  json-args "$(jq -n --arg pool_id "$POOL_ID" '{
    "dex_id": "slimedragon.near/xyk",
    "method": "lock_pool",
    "args": $pool_id,
    "attached_assets": {}
  }')" \
  prepaid-gas '100.0 Tgas' attached-deposit '1 yoctoNEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send
```
