# Sell Token

Sells tokens back to the bonding curve in exchange for SOL.

## Instruction

```rust
SCBondingCurveInstruction::SellToken {
    pda_token_nonce: u8,
    token_to_spend: u64,
    min_sol_to_receive: u64,
    logging_account_bump: u8,
}
```

## Parameters

| Parameter              | Type  | Description                                                    |
| ---------------------- | ----- | -------------------------------------------------------------- |
| `pda_token_nonce`      | `u8`  | Nonce for the token owner PDA                                  |
| `token_to_spend`       | `u64` | Amount of tokens to sell                                       |
| `min_sol_to_receive`   | `u64` | Minimum acceptable SOL amount to receive (slippage protection) |
| `logging_account_bump` | `u8`  | Bump for the logging authority PDA                             |

## Account Setup

| #  | Account               | Description                      | Derivation                                               |
| -- | --------------------- | -------------------------------- | -------------------------------------------------------- |
| 1  | Payer account         | Transaction signer (User wallet) | -                                                        |
| 2  | Token program         | SPL Token program                | `TOKEN_PROGRAM_ID`                                       |
| 3  | Token owner PDA       | Bonding curve account            | `[Buffer.from("token_owner"), mint.toBuffer(), [nonce]]` |
| 4  | Token mint            | Token mint address               | Provided by user                                         |
| 5  | Owner token account   | Token account for PDA            | `getAssociatedTokenAddress(mint, ownerPDA, true)`        |
| 6  | User token account    | User's token account             | `getAssociatedTokenAddress(mint, userWallet, false)`     |
| 7  | Fee account           | Platform fee account             | Fixed address (see Reference section)                    |
| 8  | Program account       | SC bonding curve program         | SC bonding curve program ID                              |
| 9  | Properties account    | Platform configuration           | `[Buffer.from("settings")]`                              |
| 10 | Log authority account | For structured logs              | `[Buffer.from("logging_authority")]`                     |

## Function Logic

1. Verifies the PDA token owner matches the expected PDA for the token mint
2. Retrieves platform fee from properties account (currently 1%)
3. Verifies the token is not finalized or mark as finalized if migration threshold is crossed
4. Checks if trading is closed for the token
5. Calculates expected SOL return amount using the bonding curve formula
6. Verifies expected SOL amount meets minimum specified (slippage check)
7. Updates pool balances in the bonding curve account
8. Transfers tokens from user to the bonding curve
9. Calculates fee amount and deducts from the SOL return
10. Transfers remaining SOL to the user
11. Transfers fee amount to the fee account
12. Records sell data in logs

## Price Calculation

```
sol_amount = pool_sol_balance * token_amount / (pool_token_balance + token_amount)
```

Where:

* `pool_token_balance` = virtual\_token + real\_token
* `pool_sol_balance` = virtual\_sol + real\_sol
* `token_amount` = amount of tokens being sold

## Notes

* The platform fee is deducted from the SOL return amount
* If the sale would leave less than POOL\_MIGRATION\_RESERVES tokens in the pool, the token is marked as finalized
* Once finalized, a token can no longer be traded on the bonding curve

## Example Usage

```javascript
// Derive PDAs and other accounts
const [tokenOwnerPDA, pdaTokenNonce] = PublicKey.findProgramAddressSync(
  [Buffer.from("token_owner"), tokenMint.toBuffer()],
  SC_BONDING_CURVE_PROGRAM_ID
)

const [propertiesAccount] = PublicKey.findProgramAddressSync(
  [Buffer.from("settings")],
  SC_BONDING_CURVE_PROGRAM_ID
)

const [logAuthority, logAuthorityBump] = PublicKey.findProgramAddressSync(
  [Buffer.from("logging_authority")],
  SC_BONDING_CURVE_PROGRAM_ID
)

// Get token accounts
const ownerTokenAccount = getAssociatedTokenAddressSync(tokenMint, tokenOwnerPDA, true)

const userTokenAccount = getAssociatedTokenAddressSync(tokenMint, wallet.publicKey, false)

// Create instruction data buffer
const data = Buffer.alloc(18)
data.writeUint8(3, 0) // Instruction index for SellToken
data.writeUint8(pdaTokenNonce, 1) // PDA nonce
data.writeBigUInt64LE(tokenToSpend, 2) // Token amount
data.writeBigUInt64LE(minSolToReceive, 10) // Minimum SOL
data.writeUint8(logAuthorityBump, 18) // Log authority bump

const sellTokenIx = new TransactionInstruction({
  programId: SC_BONDING_CURVE_PROGRAM_ID,
  keys: [
    { pubkey: wallet.publicKey, isSigner: true, isWritable: true },
    { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
    { pubkey: tokenOwnerPDA, isSigner: false, isWritable: true },
    { pubkey: tokenMint, isSigner: false, isWritable: false },
    { pubkey: ownerTokenAccount, isSigner: false, isWritable: true },
    { pubkey: userTokenAccount, isSigner: false, isWritable: true },
    { pubkey: FEE_ACCOUNT, isSigner: false, isWritable: true },
    { pubkey: SC_BONDING_CURVE_PROGRAM_ID, isSigner: false, isWritable: false },
    { pubkey: propertiesAccount, isSigner: false, isWritable: false },
    { pubkey: logAuthority, isSigner: false, isWritable: false },
  ],
  data: data,
})
```
