> ## Documentation Index
> Fetch the complete documentation index at: https://docs.raydium.io/llms.txt
> Use this file to discover all available pages before exploring further.

# CPMM 풀 배포하기

> 새로운 CPMM 풀을 생성하는 Node 스크립트입니다. 환경 변수로 민트와 초기 유동성을 설정합니다.

<Info>
  **이 페이지는 AI 자동 번역입니다. 모든 내용은 영문판을 기준으로 합니다.**

  [영문판 보기 →](/quick-start/deploy-cpmm-pool)
</Info>

<Info>
  **이 스크립트가 하는 일.** 지정한 두 개의 민트에 대해 새로운 CPMM 풀을 생성하고, 0.25% 수수료 계층을 선택한 후, 초기 유동성을 시드 금액으로 암시된 가격으로 초기화하고, 새로운 풀 ID와 트랜잭션 서명을 출력합니다.
</Info>

## 설정

먼저 [빠른 시작 필수 요구 사항](/ko/quick-start)을 읽고 `RPC_URL`, `KEYPAIR`을 설정하고 종속성을 설치했는지 확인하세요.

또한 **지갑에 두 민트의 초기 금액을 충분히 보유**해야 하며, 일회성 풀 생성 수수료를 커버할 수 있는 SOL도 필요합니다 (메인넷에서 약 0.15 SOL, 현재 값은 [`reference/program-addresses`](/ko/reference/program-addresses) 참조).

## 스크립트

`create-cpmm.mjs`로 저장하세요:

```ts theme={null}
// create-cpmm.mjs
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import {
  Raydium,
  TxVersion,
  CREATE_CPMM_POOL_PROGRAM,
  CREATE_CPMM_POOL_FEE_ACC,
} from "@raydium-io/raydium-sdk-v2";
import BN from "bn.js";
import fs from "node:fs";

// ── Config from env ──────────────────────────────────────────────
const RPC_URL  = process.env.RPC_URL  ?? "https://api.mainnet-beta.solana.com";
const KEYPAIR  = process.env.KEYPAIR  ?? `${process.env.HOME}/.config/solana/id.json`;
const MINT_A   = process.env.MINT_A;   // required, base58
const MINT_B   = process.env.MINT_B;   // required, base58
const AMOUNT_A = process.env.AMOUNT_A; // required, integer raw units
const AMOUNT_B = process.env.AMOUNT_B; // required, integer raw units

if (!MINT_A || !MINT_B || !AMOUNT_A || !AMOUNT_B) {
  console.error("Set MINT_A, MINT_B, AMOUNT_A, AMOUNT_B env vars.");
  process.exit(1);
}

// ── Setup ────────────────────────────────────────────────────────
const connection = new Connection(RPC_URL, "confirmed");
const owner = Keypair.fromSecretKey(
  new Uint8Array(JSON.parse(fs.readFileSync(KEYPAIR, "utf8"))),
);
const raydium = await Raydium.load({
  owner,
  connection,
  cluster: "mainnet",
  disableFeatureCheck: true,
  blockhashCommitment: "finalized",
});

// ── Pick the 0.25% fee tier ─────────────────────────────────────
const feeConfigs = await raydium.api.getCpmmConfigs();
const feeConfig  = feeConfigs.find((c) => c.index === 0);
if (!feeConfig) throw new Error("0.25% fee tier not found in CPMM configs.");

// ── Resolve mint metadata (Token-2022-aware) ────────────────────
const mintA = await raydium.token.getTokenInfo(new PublicKey(MINT_A));
const mintB = await raydium.token.getTokenInfo(new PublicKey(MINT_B));

// ── Build and execute ───────────────────────────────────────────
const { execute, extInfo } = await raydium.cpmm.createPool({
  programId:       CREATE_CPMM_POOL_PROGRAM,
  poolFeeAccount:  CREATE_CPMM_POOL_FEE_ACC,
  mintA,
  mintB,
  mintAAmount:     new BN(AMOUNT_A),
  mintBAmount:     new BN(AMOUNT_B),
  startTime:       new BN(0), // open immediately
  feeConfig,
  associatedOnly:  false,
  ownerInfo:       { useSOLBalance: true },
  txVersion:       TxVersion.V0,
  computeBudgetConfig: {
    units: 600_000,
    microLamports: 100_000,
  },
});

const { txId } = await execute({ sendAndConfirm: true });

console.log(`Pool ID:  ${extInfo.address.poolId.toBase58()}`);
console.log(`LP mint:  ${extInfo.address.lpMint.toBase58()}`);
console.log(`Vault A:  ${extInfo.address.vaultA.toBase58()}`);
console.log(`Vault B:  ${extInfo.address.vaultB.toBase58()}`);
console.log(`Tx:       https://solscan.io/tx/${txId}`);
```

## 실행하기

예시: 1 SOL과 160 USDC를 초기화하여 SOL/USDC 풀 생성:

```bash theme={null}
export MINT_A="So11111111111111111111111111111111111111112"   # wSOL
export MINT_B="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"   # USDC
export AMOUNT_A="1000000000"   # 1 SOL (9 decimals)
export AMOUNT_B="160000000"    # 160 USDC (6 decimals)

node create-cpmm.mjs
```

예상 출력:

```
Pool ID:  HgC5...3kXb
LP mint:  4ZAS...9rkV
Vault A:  J9Mu...mP2k
Vault B:  AaJq...8wxx
Tx:       https://solscan.io/tx/5dQ...
```

## 방금 어떤 일이 일어났나요

1. \*\*`getCpmmConfigs`\*\*는 `api-v3.raydium.io`에서 현재 수수료 계층 목록을 가져오고 인덱스 0 (0.25% 계층)을 선택했습니다. 전체 수수료 목록은 [`reference/fee-comparison`](/ko/reference/fee-comparison)을 참조하세요.
2. \*\*`getTokenInfo`\*\*는 각 민트의 메타데이터를 확인했으며, 어떤 토큰 프로그램이 소유하고 있는지도 포함됩니다. CPMM은 SPL Token과 Token-2022 민트를 모두 지원하며, SDK가 자동으로 라우팅합니다.
3. \*\*`createPool`\*\*은 다음을 수행하는 하나의 트랜잭션을 생성했습니다:
   * 민트를 정규 순서로 정렬
   * 풀 PDA, 볼트, LP 민트 및 권한 도출
   * 일회성 `create_pool_fee`를 `CREATE_CPMM_POOL_FEE_ACC`에 지불
   * 호출자의 ATA 생성 (없는 경우)
   * 볼트를 `AMOUNT_A`와 `AMOUNT_B`로 초기화
4. **초기 가격**은 시드 비율로 설정됩니다: 소수 조정 후 `price = AMOUNT_B / AMOUNT_A`. 이를 신중하게 선택하세요. 봇들은 풀이 열린 직후 가격 오류를 거의 즉시 차익거래할 것입니다.
5. \*\*`startTime: new BN(0)`\*\*은 거래를 즉시 개시합니다. 공개 전에 유동성을 준비하려면 미래의 Unix 타임스탐프를 설정하세요.

## 일반적인 오류

* **`pool already exists`** — 이 민트 쌍과 수수료 계층에 대한 풀이 이미 존재합니다. 생성하기 전에 검색하세요.
* **`insufficient funds`** — 지갑에 `MINT_A`, `MINT_B` 또는 SOL (풀 생성 수수료 + 렌트)이 부족합니다.
* **`Token-2022 extension not supported`** — 민트 중 하나가 CPMM이 지원하지 않는 확장 기능을 사용합니다. [`reference/token-2022-support`](/ko/reference/token-2022-support)를 참조하세요.

## 배포 후

새 풀에 대해 즉시 스왑할 수 있습니다. [CLI에서 스왑](/ko/quick-start/swap-from-cli) 스크립트가 새 `POOL_ID`를 직접 허용합니다. 수집기 (Jupiter 등)는 몇 분 내에 새 풀을 인덱싱할 것입니다.

## 다음

* [`products/cpmm/overview`](/ko/products/cpmm/overview) — CPMM이 무엇이고 언제 선택할지.
* [`user-flows/create-cpmm-pool`](/ko/user-flows/create-cpmm-pool) — Raydium UI를 통한 스크린샷이 있는 동일한 흐름.
* [`user-flows/choosing-a-pool-type`](/ko/user-flows/choosing-a-pool-type) — 대신 CLMM을 사용했어야 했나요?
