diff --git a/rust-sdk/client/README.md b/rust-sdk/client/README.md index cf2c5954..6a2adff2 100644 --- a/rust-sdk/client/README.md +++ b/rust-sdk/client/README.md @@ -1 +1,91 @@ -# Orca Whirlpools Rust Client +# 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 Rust projects, particularly those related to Orca's Whirlpool Program. This package offers granular control for advanced use cases. + +> NOTE: To ensure compatibility, use version 1.18 of the `solana-sdk` crate, which matches the version used to build the Whirlpool program. + +## 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. It handles all decoding and encoding of instructions and account data, making it much easier to interact with the program. +- **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 derivation for developers. + +## Installation +```bash +cargo add orca_whirlpools_client +``` + +## Usage +Here are some basic examples of how to use the package: + +### Deriving a PDA +To derive a PDA for a Whirlpool account, you can use the `get_whirlpool_address` PDA utility. + +```rust +use orca_whirlpools_client::get_whirlpool_address; +use solana_sdk::pubkey::Pubkey; +use std::str::FromStr; + +fn main() { + let whirlpool_config_address = Pubkey::from_str("FcrweFY1G9HJAHG5inkGB6pKg1HZ6x9UC2WioAfWrGkR").unwrap(); + let token_mint_a = Pubkey::from_str("So11111111111111111111111111111111111111112").unwrap(); // wSOL + let token_mint_b = Pubkey::from_str("BRjpCHtyQLNCo8gqRUr8jtdAj5AjPYQaoqbvcZiHok1k").unwrap(); // DevUSDC + let tick_spacing = 64; + + let (whirlpool_pda, _bump) = get_whirlpool_address(&whirlpool_config_address, &token_mint_a, &token_mint_b, tick_spacing).unwrap(); + println!("{:?}", whirlpool_pda); +} +``` + +### Example: Initialize Pool Instruction + +The following example demonstrates how to create an `InitializePool` instruction: + +```rust +use orca_whirlpools_client::{ + instructions::InitializePoolV2Builder, + get_fee_tier_address, + get_token_badge_address, + get_whirlpool_address, +}; +use solana_sdk::{ + pubkey::Pubkey, + signer::{keypair::Keypair, Signer}, +}; +use std::str::FromStr; + +fn main() { + let whirlpool_config_address = Pubkey::from_str("FcrweFY1G9HJAHG5inkGB6pKg1HZ6x9UC2WioAfWrGkR").unwrap(); + let token_mint_a = Pubkey::from_str("So11111111111111111111111111111111111111112").unwrap(); // wSOL + let token_mint_b = Pubkey::from_str("BRjpCHtyQLNCo8gqRUr8jtdAj5AjPYQaoqbvcZiHok1k").unwrap(); // DevUSDC + let (token_badge_a, _bump) = get_token_badge_address(&whirlpool_config_address, &token_mint_a).unwrap(); + let (token_badge_b, _bump) = get_token_badge_address(&whirlpool_config_address, &token_mint_b).unwrap(); + let wallet = Keypair::new(); // CAUTION: this wallet is not persistent + let tick_spacing = 8; + let (whirlpool_pda, _bump) = get_whirlpool_address(&whirlpool_config_address, &token_mint_a, &token_mint_b, tick_spacing).unwrap(); + let token_vault_a = Keypair::new(); + let token_vault_b = Keypair::new(); + let (fee_tier, _bump) = get_fee_tier_address(&whirlpool_config_address, tick_spacing).unwrap(); + let token_program_a = Pubkey::from_str("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA").unwrap(); + let token_program_b = Pubkey::from_str("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA").unwrap(); + let initial_sqrt_price = 7459106261056563200u128; + + let initialize_pool_v2_instruction = InitializePoolV2Builder::new() + .whirlpools_config(whirlpool_config_address) + .token_mint_a(token_mint_a) + .token_mint_b(token_mint_b) + .token_badge_a(token_badge_a) + .token_badge_b(token_badge_b) + .funder(wallet.pubkey()) + .whirlpool(whirlpool_pda) + .token_vault_a(token_vault_a.pubkey()) + .token_vault_b(token_vault_b.pubkey()) + .fee_tier(fee_tier) + .token_program_a(token_program_a) + .token_program_b(token_program_b) + .tick_spacing(tick_spacing) + .initial_sqrt_price(initial_sqrt_price) + .instruction(); + + println!("{:?}", initialize_pool_v2_instruction); +} +``` \ No newline at end of file diff --git a/rust-sdk/core/README.md b/rust-sdk/core/README.md index a679c349..423e60b3 100644 --- a/rust-sdk/core/README.md +++ b/rust-sdk/core/README.md @@ -1 +1,79 @@ -# Orca Whirlpools Rust Core +# Orca Whirlpools Core SDK + +This package provides developers with advanced functionalities for interacting with the Whirlpool Program on Solana. The Core SDK offers convenient methods for math calculations, quotes, and other utilities, making it easier to manage complex liquidity and swap operations within Rust projects. It serves as the foundation for the High-Level SDK, providing key building blocks that enable developers to perform sophisticated actions while maintaining control over core details. + +## Key Features + +- **Math Library**: Contains a variety of functions for math operations related to bundles, positions, prices, ticks, and tokens, including calculations such as determining position status or price conversions. +- **Quote Library**: Provides utility functions for generating quotes, such as increasing liquidity, collecting fees or rewards, and swapping, enabling precise and optimized decision-making in liquidity management. + +## Installation +```bash +cargo add orca_whirlpools_core +``` + +## Usage +Here are some basic examples of how to use the package: + +### Math Example +The following example demonstrates how to use the `is_position_in_range` function to determine whether a position is currently in range. + +```rust +use orca_whirlpools_core::is_position_in_range; + +fn main() { + let current_sqrt_price = 7448043534253661173u128; + let tick_index_1 = -18304; + let tick_index_2 = -17956; + + let in_range = is_position_in_range(current_sqrt_price.into(), tick_index_1, tick_index_2); + println!("Position in range? {:?}", in_range); +} +``` + +Expected output: +``` +Position in range? true +``` + +### Quote Example + +The following example demonstrates how to use the increase_liquidity_quote_a function to calculate a quote for increasing liquidity given a token A amount. + +```rust +use orca_whirlpools_core::increase_liquidity_quote_a; +use orca_whirlpools_core::TransferFee; + +fn main() { + let token_amount_a = 1000000000u64; + let slippage_tolerance_bps = 100u16; + let current_sqrt_price = 7437568627975669726u128; + let tick_index_1 = -18568; + let tick_index_2 = -17668; + let transfer_fee_a = Some(TransferFee::new(200)); + let transfer_fee_b = None; + + let quote = increase_liquidity_quote_a( + token_amount_a, + slippage_tolerance_bps, + current_sqrt_price.into(), + tick_index_1, + tick_index_2, + transfer_fee_a, + transfer_fee_b, + ).unwrap(); + + println!("{:?}", quote); +} +``` + +Expected output: +``` +IncreaseLiquidityQuote { + liquidity_delta: 16011047470, + token_est_a: 1000000000, + token_est_b: 127889169, + token_max_a: 1010000000, + token_max_b: 129168061, +} +``` \ No newline at end of file diff --git a/ts-sdk/client/README.md b/ts-sdk/client/README.md index 5a4453d6..a58d8b4a 100644 --- a/ts-sdk/client/README.md +++ b/ts-sdk/client/README.md @@ -1 +1,101 @@ -# Orca Whirlpools Typescript Client +# 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, [@orca-so/whirlpools](https://www.npmjs.com/package/@orca-so/whirlpools), this package offers more granular control for advanced use cases. + +> **Note:** This SDK uses Solana Web3.js SDK v2, which is currently in Release Candidate (RC) status. 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 @orca-so/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 "@orca-so/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 "@orca-so/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 "@orca-so/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); +``` \ No newline at end of file diff --git a/ts-sdk/core/README.md b/ts-sdk/core/README.md index ecdd4a3f..374b6178 100644 --- a/ts-sdk/core/README.md +++ b/ts-sdk/core/README.md @@ -1 +1,70 @@ -# Orca Whirlpools Typescript Core +# Orca Whirlpools Core SDK (WebAssembly) +This package provides developers with advanced functionalities for interacting with the Whirlpool Program on Solana. Originally written in Rust, it has been compiled to WebAssembly (Wasm). This compilation makes the SDK accessible in JavaScript/TypeScript environments, offering developers the same core features and calculations for their Typescript projects. The SDK exposes convenient methods for math calculations, quotes, and other utilities, enabling seamless integration within web-based projects. + +## Key Features +- **Math Library**: Contains a variety of functions for math operations related to bundles, positions, prices, ticks, and tokens, including calculations such as determining position status or price conversions. +- **Quote Library**: Provides utility functions for generating quotes, such as increasing liquidity, collecting fees or rewards, and swapping, to help developers make informed decisions regarding liquidity management. + +## Installation +You can install the package via npm: +```bash +npm install @orca-so/whirlpools-core +``` + +## Usage +Here are some basic examples of how to use the package: + +### Math Example +The following example demonstrates how to use the `isPositionInRange` function to determine whether a position is currently in range. + +```tsx +import { isPositionInRange } from "@orca-so/whirlpools-core"; + +const currentSqrtPrice = 7448043534253661173n; +const tickIndex1 = -18304; +const tickIndex2 = -17956; + +const inRange = isPositionInRange(currentSqrtPrice, tickIndex1, tickIndex2); +console.log("Position in range:", inRange); +``` + +Expected output: +``` +Position in range? true +``` + +### Quote Example +The following example demonstrates how to use the `increaseLiquidityQuoteA` function to calculate a quote for increasing liquidity given a token A amount. + +```tsx +import { increaseLiquidityQuoteA } from "@orca-so/whirlpools-core"; + +const tokenAmountA = 1000000000n; +const slippageToleranceBps = 100; +const currentSqrtPrice = 7437568627975669726n; +const tickIndex1 = -18568; +const tickIndex2 = -17668; +const transferFeeA = { feeBps: 200, maxFee: 1000000000n }; + +const quote = increaseLiquidityQuoteA( + tokenAmountA, + slippageToleranceBps, + currentSqrtPrice, + tickIndex1, + tickIndex2, + transferFeeA, +); + +console.log(quote); +``` + +Expected output: +``` +{ + liquidityDelta: 16011047470n, + tokenEstA: 1000000000n, + tokenEstB: 127889169n, + tokenMaxA: 1010000000n, + tokenMaxB: 129168061n +} +``` \ No newline at end of file