# Buying and selling a token

トークンがローンチされると、資金調達目標が達成されるまでボンディングカーブ上でユーザーは購入および販売ができます。ここでは取引機能の統合方法について説明します。

## ボンディングカーブ取引の仕組み

LaunchLabは供給と需要に基づいてトークン価格を決定するためにボンディングカーブを使用します：

* **購入** 価格が上昇します — 各購入によりカーブ上で価格が上がります
* **販売** 価格が下落します — 各販売によりカーブ上で価格が下がります
* **価格発見** — 早期購入者はより低価格を得られ、早期参加へのインセンティブが生まれます

取引は次の時点まで継続します `totalFundRaisingB` 相当のクオートトークンが収集され、その時点でプールはRaydium AMMへ移行します。

## トークンを購入する

を使用してください `buyToken()` でクオートトークン（例：SOL）を使ってトークンを購入します。

```typescript
import { TxVersion } from '@raydium-io/raydium-sdk-v2'
import { initSdk } from './config'
import { PublicKey } from '@solana/web3.js'
import BN from 'bn.js'

const buyTokens = async () => {
  const raydium = await initSdk()

  const { execute, extInfo } = await raydium.launchpad.buyToken({
    mintA: new PublicKey('token-mint-address'),
    buyAmount: new BN(1_000_000_000),  // 1 SOL を lamports で表した量
    slippage: new BN(100),             // 1% のスリッページ
    txVersion: TxVersion.V0,
  })

  console.log('Expected tokens:', extInfo.decimalOutAmount.toString())

  const { txId } = await execute({ sendAndConfirm: true })
  console.log('Transaction:', txId)
}
```

### 購入パラメータ

| パラメータ             | 型         | 必須  | 説明                                               |
| ----------------- | --------- | --- | ------------------------------------------------ |
| `mintA`           | PublicKey | はい  | 購入するトークンのミント。                                    |
| `mintAProgram`    | PublicKey | いいえ | トークンプログラム（SPL や Token-2022）。省略された場合は SDK が検出します。 |
| `buyAmount`       | BN        | はい  | 支払うクオートトークンの量（例えば SOL の場合は lamports）。            |
| `poolInfo`        | object    | いいえ | プールの状態データ。省略された場合は SDK が取得します。                   |
| `configInfo`      | object    | いいえ | グローバル設定データ。省略された場合は SDK が取得します。                  |
| `platformFeeRate` | BN        | いいえ | プラットフォームの手数料率。省略された場合は SDK が取得します。               |
| `slippage`        | BN        | いいえ | 最大スリッページ（bps 単位、`100 = 1%`）。デフォルト： `100`.        |
| `minMintAAmount`  | BN        | いいえ | 受け取る最小トークン量。省略された場合は SDK が計算します。                 |

### 正確なトークン量を購入する

を使用してください `buyTokenExactOut()` 受け取りたいトークン量を正確に指定するために使用します。

```typescript
const { execute, extInfo } = await raydium.launchpad.buyTokenExactOut({
  programId: LAUNCHPAD_PROGRAM,
  mintA,
  poolInfo,

  // 正確な出力を指定
  outAmount: new BN('1000000000000'),  // 受け取る正確なトークン量
  maxBuyAmount: new BN('2000000000'),  // 支払う最大クオートトークン量

  slippage: new BN(100),
  txVersion: TxVersion.V0,
})
```

## トークンを販売する

を使用してください `sellToken()` トークンをクオートトークンに戻して売却するために使用します。

```typescript
const sellTokens = async () => {
  const raydium = await initSdk()

  const mintA = new PublicKey('token-mint-address')
  const sellAmount = new BN('500000000000')  // 売却するトークン量

  const { execute, extInfo } = await raydium.launchpad.sellToken({
    programId: LAUNCHPAD_PROGRAM,

    // 売却するトークン
    mintA,

    // 売却パラメータ
    sellAmount,             // 売却するトークン量
    slippage: new BN(100),  // 1% のスリッページ許容

    txVersion: TxVersion.V0,
  })

  console.log('Expected quote tokens:', extInfo.outAmount.toString())

  await execute({ sendAndConfirm: true })
}
```

### 売却パラメータ

| パラメータ        | 型         | 必須  | 説明                                        |
| ------------ | --------- | --- | ----------------------------------------- |
| `mintA`      | PublicKey | はい  | 売却するトークンのミント。                             |
| `sellAmount` | BN        | はい  | 売却するトークン量。                                |
| `poolInfo`   | object    | いいえ | プールの状態データ。省略された場合は SDK が取得します。            |
| `slippage`   | BN        | いいえ | 最大スリッページ（bps 単位、`100 = 1%`）。デフォルト： `100`. |
| `minAmountB` | BN        | いいえ | 受け取る最小クオートトークン量。省略された場合は SDK が計算します。      |

### 正確なクオート金額で売却する

を使用してください `sellTokenExactOut()` 受け取りたいクオートトークン量を正確に指定するために使用します。

```typescript
const { execute } = await raydium.launchpad.sellTokenExactOut({
  programId: LAUNCHPAD_PROGRAM,
  mintA,
  poolInfo,

  // 正確な出力を指定
  inAmount: new BN('1000000000'),        // 受け取る正確なクオートトークン量
  maxSellAmount: new BN('600000000000'), // 売却する最大トークン量

  slippage: new BN(100),
  txVersion: TxVersion.V0,
})
```

## 高度：見積りの計算

を使用して `Curve` 取引を実行する前に期待される出力を計算するユーティリティ（例：UIに期待額を表示する場合）。

```typescript
import { Curve, PlatformConfig } from '@raydium-io/raydium-sdk-v2'

// 必要なデータを取得
const poolInfo = await raydium.launchpad.getRpcPoolInfo({ poolId })
const platformData = await raydium.connection.getAccountInfo(poolInfo.platformId)
const platformInfo = PlatformConfig.decode(platformData!.data)
const mintInfo = await raydium.token.getTokenInfo(mintA)
const slot = await raydium.connection.getSlot()

// 購入見積りを計算
const buyQuote = Curve.buyExactIn({
  poolInfo,
  amountB: new BN('1000000000'),  // 1 SOL
  protocolFeeRate: poolInfo.configInfo.tradeFeeRate,
  platformFeeRate: platformInfo.feeRate,
  curveType: poolInfo.configInfo.curveType,
  shareFeeRate: new BN(0),
  creatorFeeRate: platformInfo.creatorFeeRate,
  transferFeeConfigA: mintInfo.extensions.feeConfig,  // Token-2022 用
  slot,
})

console.log('Tokens out:', buyQuote.amountA.amount.toString())
console.log('Fees:', {
  protocol: buyQuote.splitFee.protocolFee.toString(),
  platform: buyQuote.splitFee.platformFee.toString(),
  creator: buyQuote.splitFee.creatorFee.toString(),
  share: buyQuote.splitFee.shareFee.toString(),
})

// 売却見積りを計算
const sellQuote = Curve.sellExactIn({
  poolInfo,
  amountA: new BN('500000000000'),  // 売却するトークン量
  protocolFeeRate: poolInfo.configInfo.tradeFeeRate,
  platformFeeRate: platformInfo.feeRate,
  curveType: poolInfo.configInfo.curveType,
  shareFeeRate: new BN(0),
  creatorFeeRate: platformInfo.creatorFeeRate,
  transferFeeConfigA: mintInfo.extensions.feeConfig,
  slot,
})

console.log('Quote tokens out:', sellQuote.amountB.toString())
```

### 利用可能な見積りメソッド

| メソッド                   | 説明                                 |
| ---------------------- | ---------------------------------- |
| `Curve.buyExactIn()`   | 指定したクオートトークン入力に対して受け取るトークン量を計算する   |
| `Curve.buyExactOut()`  | 特定のトークン出力のために必要なクオートトークン量を計算する     |
| `Curve.sellExactIn()`  | 指定したトークン入力に対して受け取るクオートトークン量を計算する   |
| `Curve.sellExactOut()` | 特定のクオートトークン出力を受け取るために必要なトークン量を計算する |

## リファラル手数料

統合者は次のパラメータを渡すことでリファラル手数料を得ることができます： `shareFeeRate` および `shareFeeReceiver` パラメータ。

```typescript
const { execute } = await raydium.launchpad.buyToken({
  // ... 他のパラメータ ...

  // リファラル設定
  shareFeeRate: new BN(5000),  // 0.5% のリファラル手数料
  shareFeeReceiver: new PublicKey('referrer-wallet'),
})
```

> **注：** `shareFeeRate` は超えてはなりません `maxShareFeeRate` グローバル設定の。リファラル手数料はクオートトークン（例：SOL）で支払われ、直接に `shareFeeReceiver` wallet.

## プールのステータス確認

取引前に、プールがまだ取引ステータスにあることを確認してください：

```typescript
const poolInfo = await raydium.launchpad.getRpcPoolInfo({ poolId })

if (poolInfo.status === 0) {
  console.log('Pool is active - trading enabled')
} else if (poolInfo.status === 1) {
  console.log('Pool is migrating - trading disabled')
} else if (poolInfo.status === 2) {
  console.log('Pool has migrated - trade on Raydium AMM instead')
}

// マイグレーションの進捗を確認
const progress = poolInfo.realB.mul(new BN(100)).div(poolInfo.totalFundRaisingB)
console.log(`Fundraising progress: ${progress.toString()}%`)
```
