npm package: @saturnbtcio/whirlpools-client
Description: Typescript client to interact with Orca's on-chain Whirlpool program.
Author: team@orca.so
Latest version: 1.0.3

# Orca Whirlpools Client SDK

## Overview

This package provides developers with low-level functionalities for interacting with the Whirlpool Program on Solana. It serves as a foundational tool that allows developers to manage and integrate detailed operations into their Typescript projects, particularly those related to Orca's Whirlpool Program. While a high-level SDK is available for easier integration, [@saturnbtcio/whirlpools](https://www.npmjs.com/package/@saturnbtcio/whirlpools), this package offers more granular control for advanced use cases.

> **Note:** This SDK uses Solana Web3.js SDK v2. It is not compatible with the widely used v1.x.x version.

## Key Features

- **Codama Client**: The package includes a set of generated client code based on the Whirlpool Program IDL. This ensures all the necessary program information is easily accessible in a structured format and handles all decoding and encoding of instructions and account data, making it much easier to interact with the program.
- **GPA (Get Program Accounts) Filters**: This feature contains utilities to add filters to program accounts, allowing developers to fetch program account data more selectively and efficiently.
- **PDA (Program Derived Addresses) Utilities**: This feature contains utility functions that help derive Program Derived Addresses (PDAs) for accounts within the Whirlpool Program, simplifying address generation for developers.

## Installation

You can install the package via npm:

```bash
npm install @saturnbtcio/whirlpools-client
```

## Usage

Here are some basic examples of how to use the package.

### Fetching Whirlpool Accounts with Filters

The following example demonstrates how to fetch Whirlpools accounts based on specific filters, using the GPA utilities:

```tsx
import { createSolanaRpc, address, devnet } from "@solana/web3.js";
import { fetchAllWhirlpoolWithFilter, whirlpoolTokenMintAFilter } from "@saturnbtcio/whirlpools-client";

const rpc = createSolanaRpc(devnet("https://api.devnet.solana.com"));

const tokenMintA = address("BRjpCHtyQLNCo8gqRUr8jtdAj5AjPYQaoqbvcZiHok1k"); //DevUSDC
const filter = whirlpoolTokenMintAFilter(tokenMintA);

const accounts = await fetchAllWhirlpoolWithFilter(rpc, filter);
console.log(accounts);
```

### Deriving a PDA

To derive a PDA for a Whirlpool account, you can use the `getWhirlpoolAddress` PDA utility.

```tsx
import { getWhirlpoolAddress } from "@saturnbtcio/whirlpools-client";
import { address } from "@solana/web3.js";

const whirlpoolConfigAddress = address("FcrweFY1G9HJAHG5inkGB6pKg1HZ6x9UC2WioAfWrGkR");
const tokenMintA = address("So11111111111111111111111111111111111111112"); //wSOL
const tokenMintB = address("BRjpCHtyQLNCo8gqRUr8jtdAj5AjPYQaoqbvcZiHok1k"); //DevUSDC
const tickSpacing = 64;

const whirlpoolPda = await getWhirlpoolAddress(whirlpoolConfigAddress, tokenMintA, tokenMintB, tickSpacing);
console.log(whirlpoolPda);
```

### Example: Initialize Pool Instruction

The following example demonstrates how to create an InitializePool instruction using the Codama-IDL autogenerated code:

```tsx
import {
  getInitializePoolV2Instruction,
  getTokenBadgeAddress,
  getWhirlpoolAddress,
  getFeeTierAddress,
} from "@saturnbtcio/whirlpools-client";
import { address, generateKeyPairSigner } from "@solana/web3.js";

const whirlpoolConfigAddress = address("FcrweFY1G9HJAHG5inkGB6pKg1HZ6x9UC2WioAfWrGkR");
const tokenMintA = address("So11111111111111111111111111111111111111112"); // wSOL
const tokenMintB = address("BRjpCHtyQLNCo8gqRUr8jtdAj5AjPYQaoqbvcZiHok1k"); // DevUSDC
const tokenBadgeA = await getTokenBadgeAddress(whirlpoolConfigAddress, tokenMintA);
const tokenBadgeB = await getTokenBadgeAddress(whirlpoolConfigAddress, tokenMintB);
const wallet = await generateKeyPairSigner(); // CAUTION: this wallet is not persistent
const tickSpacing = 8;
const whirlpool = await getWhirlpoolAddress(whirlpoolConfigAddress, tokenMintA, tokenMintB, tickSpacing);
const tokenVaultA = await generateKeyPairSigner();
const tokenVaultB = await generateKeyPairSigner();
const feeTier = await getFeeTierAddress(whirlpoolConfigAddress, tickSpacing);
const tokenProgramA = address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
const tokenProgramB = address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
const initialSqrtPrice = BigInt(7459106261056563200n);

const initializePoolInstruction = getInitializePoolV2Instruction({
  whirlpoolsConfig: whirlpoolConfigAddress,
  tokenMintA,
  tokenMintB,
  tokenBadgeA,
  tokenBadgeB,
  funder: wallet,
  whirlpool,
  tokenVaultA,
  tokenVaultB,
  feeTier,
  whirlpoolBump: 1,
  tickSpacing,
  tokenProgramA,
  tokenProgramB,
  initialSqrtPrice,
});

console.log(initializePoolInstruction);
```