# プールを作成する

単一のトランザクションで CPMM の定数積プールを作成し、初期流動性を投入します。

CPMM プールを作成する方法は 2 つあります:

| Method             | SDK method                   | Who can call            | Creator fees          |
| ------------------ | ---------------------------- | ----------------------- | --------------------- |
| **Permissionless** | `createPool()`               | Anyone                  | Disabled              |
| **Permissioned**   | `createPoolWithPermission()` | Approved addresses only | Enabled, configurable |

多くのインテグレーターは permissionless の方法を使用します。permissioned の方法は、スワップからの creator fee 収益を必要とする launchpad や承認済みパートナー向けに設計されています。

***

### 手数料設定を取得しています

すべての CPMM プールはオンチェーンの `AmmConfig` を参照しており、これが fee tier を定義します。プールを作成する前に利用可能な config を取得してください。

```typescript
const feeConfigs = await raydium.api.getCpmmConfigs()
```

公開 config ID は以下でも確認できます:

* Mainnet: [api-v3.raydium.io/main/cpmm-config](https://api-v3.raydium.io/main/cpmm-config)
* Devnet: [api-v3-devnet.raydium.io/main/cpmm-config](https://api-v3-devnet.raydium.io/main/cpmm-config)

{% hint style="info" %}
カスタム fee config もサポートされています。fee のカスタマイズが必要な場合はチームにご連絡ください。
{% endhint %}

***

### pool の作成

以下を使用します `raydium.cpmm.createPool()` 2 つの token mint と初期デポジット額を使って新しいプールを初期化します。

```typescript
import {
  CREATE_CPMM_POOL_PROGRAM,
  CREATE_CPMM_POOL_FEE_ACC,
  DEVNET_PROGRAM_ID,
  getCpmmPdaAmmConfigId,
  TxVersion,
} from '@raydium-io/raydium-sdk-v2'
import BN from 'bn.js'
import { initSdk } from '../config'

const createPool = async () => {
  const raydium = await initSdk({ loadToken: true })

  const mintA = await raydium.token.getTokenInfo('So11111111111111111111111111111111111111112')
  const mintB = await raydium.token.getTokenInfo('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v')

  /**
   * 取得する代わりに、mint 情報を直接指定することもできます:
   * {
   *   address: '4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R',
   *   programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
   *   decimals: 6,
   * }
   */

  const feeConfigs = await raydium.api.getCpmmConfigs()

  // devnet では、devnet の program から config ID を再導出する
  if (raydium.cluster === 'devnet') {
    feeConfigs.forEach((config) => {
      config.id = getCpmmPdaAmmConfigId(
        DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_PROGRAM,
        config.index
      ).publicKey.toBase58()
    })
  }

  const { execute, extInfo } = await raydium.cpmm.createPool({
    programId: CREATE_CPMM_POOL_PROGRAM,
    // devnet: DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_PROGRAM
    poolFeeAccount: CREATE_CPMM_POOL_FEE_ACC,
    // devnet: DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_FEE_ACC
    mintA,
    mintB,
    mintAAmount: new BN(1_000_000),
    mintBAmount: new BN(1_000_000),
    startTime: new BN(0),
    feeConfig: feeConfigs[0],
    associatedOnly: false,
    ownerInfo: {
      useSOLBalance: true,
    },
    txVersion: TxVersion.V0,
    // optional: set up priority fee here
    // computeBudgetConfig: {
    //   units: 600000,
    //   microLamports: 46591500,
    // },
  })

  const { txId } = await execute({ sendAndConfirm: true })
  console.log('pool created', {
    txId: `https://explorer.solana.com/tx/${txId}`,
    poolId: extInfo.address.poolId.toBase58(),
  })
}

createPool()
```

***

### Parameters

| パラメータ            | 型         | 説明                                                                                                                       |
| ---------------- | --------- | ------------------------------------------------------------------------------------------------------------------------ |
| `programId`      | PublicKey | CPMM program ID. Use `CREATE_CPMM_POOL_PROGRAM` を使用し、 `DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_PROGRAM` を devnet で使用します。      |
| `poolFeeAccount` | PublicKey | Protocol fee account. Use `CREATE_CPMM_POOL_FEE_ACC` を使用し、 `DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_FEE_ACC` を devnet で使用します。 |
| `mintA`          | TokenInfo | 最初の token mint 情報（address、programId、decimals）。                                                                           |
| `mintB`          | TokenInfo | 2つ目の token mint 情報。以下と異なる必要があります `mintA`.                                                                                |
| `mintAAmount`    | BN        | token A の初期デポジット額。最小単位で指定します。                                                                                            |
| `mintBAmount`    | BN        | token B の初期デポジット額。最小単位で指定します。                                                                                            |
| `startTime`      | BN        | スワップが有効になる Unix timestamp。 `0` 即時用。                                                                                      |
| `feeConfig`      | object    | 以下から取得した fee tier config `getCpmmConfigs()`。取引手数料とプール作成手数料を決定します。                                                        |
| `associatedOnly` | boolean   | もし `true`の場合、associated token account のみを使用します。                                                                          |
| `ownerInfo`      | object    | `{ useSOLBalance: true }` wrap のために native SOL balance を使用します。                                                           |
| `txVersion`      | TxVersion | トランザクションのバージョン。 `TxVersion.V0` は versioned transactions 用、 `TxVersion.LEGACY` は legacy 用です。                              |

### Return value

The `extInfo.address` オブジェクトには、導出されたプールアドレスが含まれます:

| Field    | 説明                       |
| -------- | ------------------------ |
| `poolId` | 作成されたプールの public key。    |
| `mintA`  | Token A の mint address。  |
| `mintB`  | Token B の mint address。  |
| `lpMint` | LP token の mint address。 |
| `vaultA` | Token A のプール vault。      |
| `vaultB` | Token B のプール vault。      |

***

### Permission 付きでプールを作成する（creator fees）

permissioned の方法では、オンチェーンの `initialize_with_permission` instruction を使用します。これには **Permission PDA** が必要で、Raydium の admin があなたのアドレス向けに作成している必要があります。その見返りとして、以下が得られます:

* **Creator fees enabled** — 通常の取引手数料に加えて、各スワップごとの fee がプール作成者に送られます。
* **Configurable fee token** — creator fee を両方の token から徴収するか、token A のみか、token B のみかを選べます。
* **Separate creator address** — 支払者とプール作成者を別々の wallet にできます。

{% hint style="info" %}
あなたのアドレス用の Permission PDA を要求するには、Raydium チームに連絡してください。これがない場合、 `createPoolWithPermission()` 呼び出しは失敗します。
{% endhint %}

以下を使用します `raydium.cpmm.createPoolWithPermission()` creator fees を有効にしたプールを作成します。

```typescript
import {
  CREATE_CPMM_POOL_PROGRAM,
  CREATE_CPMM_POOL_FEE_ACC,
  DEVNET_PROGRAM_ID,
  getCpmmPdaAmmConfigId,
  FeeOn,
  TxVersion,
} from '@raydium-io/raydium-sdk-v2'
import BN from 'bn.js'
import { initSdk } from '../config'

const createPoolWithPermission = async () => {
  const raydium = await initSdk({ loadToken: true })

  const mintA = await raydium.token.getTokenInfo('So11111111111111111111111111111111111111112')
  const mintB = await raydium.token.getTokenInfo('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v')

  const feeConfigs = await raydium.api.getCpmmConfigs()

  if (raydium.cluster === 'devnet') {
    feeConfigs.forEach((config) => {
      config.id = getCpmmPdaAmmConfigId(
        DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_PROGRAM,
        config.index
      ).publicKey.toBase58()
    })
  }

  const { execute, extInfo } = await raydium.cpmm.createPoolWithPermission({
    programId: CREATE_CPMM_POOL_PROGRAM,
    // devnet: DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_PROGRAM
    poolFeeAccount: CREATE_CPMM_POOL_FEE_ACC,
    // devnet: DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_FEE_ACC
    mintA,
    mintB,
    mintAAmount: new BN(1_000_000),
    mintBAmount: new BN(1_000_000),
    startTime: new BN(0),
    feeConfig: feeConfigs[0],
    associatedOnly: false,
    ownerInfo: {
      useSOLBalance: true,
    },
    feeOn: FeeOn.BothToken, // BothToken | OnlyTokenA | OnlyTokenB
    txVersion: TxVersion.V0,
  })

  const { txId } = await execute({ sendAndConfirm: true })
  console.log('pool created with permission', {
    txId: `https://explorer.solana.com/tx/${txId}`,
    poolId: extInfo.address.poolId.toBase58(),
  })
}

createPoolWithPermission()
```

#### 追加パラメータ（permissionless と比較して）

| パラメータ   | 型     | 説明                                                                              |
| ------- | ----- | ------------------------------------------------------------------------------- |
| `feeOn` | FeeOn | creator fee をどの token に課金するかを制御します。 `BothToken`, `OnlyTokenA`、または `OnlyTokenB`. |

その他のパラメータは permissionless と同じです `createPool()`.

#### `FeeOn` enum

| Value        | Behavior                                         |
| ------------ | ------------------------------------------------ |
| `BothToken`  | creator fee は、swap input となる token のいずれかに課金されます。 |
| `OnlyTokenA` | creator fee は、token A が swap input の場合にのみ課金されます。 |
| `OnlyTokenB` | creator fee は、token B が swap input の場合にのみ課金されます。 |

#### permissionless との主な違い

|                     | `createPool()`                         | `createPoolWithPermission()`                             |
| ------------------- | -------------------------------------- | -------------------------------------------------------- |
| Permission required | None                                   | Raydium admin があなたのアドレス用の Permission PDA を作成する必要があります    |
| Creator fees        | Disabled (`enable_creator_fee: false`) | Enabled (`enable_creator_fee: true`)                     |
| Creator fee model   | Fixed (`BothToken`, unused)            | Caller chooses (`BothToken`, `OnlyTokenA`, `OnlyTokenB`) |
| Payer vs. creator   | Same wallet                            | 別々の wallet にできます                                         |

{% hint style="warning" %}
Creator fee collection (via `collectCreatorFees()`) は、permissioned の方法で作成されたプールでのみ機能します。標準の `createPool()` で作成されたプールでは、program レベルで creator fees が無効になっています。
{% endhint %}
