-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[example project] LP Repositioning Bot #558
Merged
Merged
Changes from 18 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
b1b39d3
Add base repositioning logic
calintje cdf95a7
Add clap for cli input. Add loop.
calintje 5515f3e
Refactor
calintje 0953218
Refactor
calintje e8f27ec
Add README. Add RPC URL as const to main.rs. Add directory for rust-s…
calintje f54bf86
Resolve comments. Add display functions for wallet and position balan…
calintje f1b104e
Update README
calintje abbdc6b
Fix typo
calintje 7092895
Resolve comments, except for
calintje 9d6b14c
Revert change nx.json
calintje 96f24d5
Revert change nx.json
calintje 584d06c
Improve calculations with prices. Update send transaction (wip)
calintje c21acfb
Improve calculations with prices. Update send transaction (wip)
calintje 6760b09
Fix send_transaction. Add .env.template for RPC_URL. Fix calculation …
calintje 07285c4
Merge branch 'main' into calintje/example-lp-bot
calintje 5cd3e90
Fix yarn. Fix next example.
calintje ea55dbb
Format
calintje 294a041
Remove test script from package.json
calintje bf1504b
Update lint script
calintje File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,4 +27,5 @@ generated | |
**/Cargo.lock | ||
.next | ||
.env | ||
wallet.json | ||
solana-release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,5 +6,6 @@ members = [ | |
exclude = [ | ||
"rust-sdk", | ||
"ts-sdk", | ||
"docs" | ||
"docs", | ||
"examples" | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Whirlpools SDK Examples | ||
|
||
This directory contains example projects showcasing how to use the Whirlpools SDK suite in different environments. Each project demonstrates specific functionalities, providing a starting point for developers. | ||
|
||
## Building the Examples | ||
To build the examples, run the following commands from the root of the monorepo: | ||
|
||
```bash | ||
yarn install | ||
yarn build | ||
``` | ||
|
||
### General Note on Dependencies | ||
All examples in this directory use local versions of the Orca SDK dependencies from this monorepo. If you plan to move an example project outside of the monorepo, you must update the dependencies to ensure compatibility. | ||
|
||
## Available Examples | ||
### Rust | ||
#### 1. Whirlpool Repositioning Bot | ||
- Path: examples/rust-sdk/whirlpools-repositioning-bot | ||
- Description: A CLI tool to automatically reposition positions based on configurable thresholds. | ||
- Highlights: | ||
- Utilizes the Whirlpools Rust SDKs. | ||
- Dynamically fetches on-chain data to manage LP positions. | ||
|
||
### Typescript | ||
#### 2. Next.js Integration | ||
- Path: examples/ts-sdk/whirlpools-next | ||
- Description: Demonstrates how to integrate the Whirlpools TS SDK `@orca-so/whirlpools` with a Next.js application. | ||
- Highlights: | ||
- Configures WebAssembly (`asyncWebAssembly`) support in Next.js. | ||
- Provides a working setup to query and interact with Orca's whirlpools. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
RPC_URL="https://api.mainnet-beta.solana.com" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
[package] | ||
name = "whirlpool_repositioning_bot" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
clap = { version = "^4.5.21", features = ["derive"] } | ||
colored = { version = "^2.0" } | ||
orca_whirlpools = { path = '../../../rust-sdk/whirlpool' } | ||
orca_whirlpools_client = { path = '../../../rust-sdk/client' } | ||
orca_whirlpools_core = { path = '../../../rust-sdk/core' } | ||
serde_json = { version = "^1.0" } | ||
solana-client = { version = "^1.18" } | ||
solana-sdk = { version = "^1.18" } | ||
spl-token-2022 = { version = "^3.0" } | ||
spl-associated-token-account = { version = "^3.0" } | ||
tokio = { version = "^1.41.1" } | ||
tokio-retry = { version = "^0.3.0" } | ||
dotenv = { version = "^0.15.0"} |
112 changes: 112 additions & 0 deletions
112
examples/rust-sdk/whirlpool_repositioning_bot/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
# LP Bot - position rebalance | ||
A Rust-based CLI bot for interacting with the Orca Whirlpools program on Solana. This bot monitors and rebalances a liquidity position by closing and reopening positions when price deviations exceed a user-defined threshold. | ||
|
||
--- | ||
|
||
## Features | ||
- **Automated Position Monitoring**: Monitors price deviation of a liquidity position on Orca Whirlpool by calculating the center of the position's price range and comparing it to the current pool price. If the deviation exceeds the specified threshold (in percentage), the bot initiates rebalancing. | ||
- **Automated Rebalancing**: Closes and reopens liquidity positions by centering the new position around the current pool price, maintaining the same width (distance between the lower and upper price bounds) as the initial position. | ||
- **Customizable Priority Fees**: Integrates compute budget priority fees to enhance transaction speed and landing, with options ranging from `none` to `turbo` for different levels of prioritization. | ||
|
||
--- | ||
|
||
## Prerequisites | ||
1. **Solana Wallet**: | ||
- Place a `wallet.json` file in the working directory with the keypair that owns the positions. | ||
- Ensure the wallet has sufficient funds for transactions. | ||
2. **Existing Position**: | ||
- You must have an active position on Orca Whirlpools. You can open a position using our SDKs or through our UI at https://www.orca.so/pools. | ||
3. **Rust**: | ||
- Install Rust using [rustup](https://rustup.rs/). | ||
|
||
--- | ||
|
||
## Installation | ||
1. Clone this repository: | ||
```bash | ||
git clone https://github.com/orca-so/whirlpools.git | ||
cd examples/rust-sdk/lp-bot | ||
``` | ||
2. Build the bot: | ||
```bash | ||
cargo build --release | ||
``` | ||
3. The executable will be located in target/release/lp-bot | ||
|
||
> NOTE: This project uses the local version of the dependency. If you want to move this example project outside of this monorepo, make sure you install the necessary dependecies: | ||
```bash | ||
cargo add orca_whirlpools orca_whirlpools_client orca_whirlpools_core | ||
``` | ||
|
||
|
||
--- | ||
|
||
## RPC Configuration | ||
The bot connects to an SVM network by using an RPC URL. Make a local copy of `.env.template` to `.env` and set your RPC URL there. It is strongly recommended to you use a URL from an RPC provider, or your own RPC node. | ||
|
||
```bash | ||
RPC_URL="https://your-rpc-url.com" | ||
``` | ||
|
||
--- | ||
|
||
## Usage | ||
Run the bot with the following arguments | ||
```bash | ||
./target/release/lp-bot \ | ||
--position-mint-address <POSITION_MINT_ADDRESS> \ | ||
--threshold <THRESHOLD_PERCENTAGE> \ | ||
--interval <INTERVAL_IN_SECONDS> \ | ||
--priority-fee-tier <PRIORITY_FEE_TIER> | ||
``` | ||
|
||
### Arguments | ||
- `--position-mint-address` (required): The mint address of the position to monitor and rebalance. | ||
- `--threshold` (optional): The percentage deviation from the center price at which rebalancing is triggered. Default: 1.0. | ||
- `--interval` (optional): The time interval (in seconds) between checks. Default: 60. | ||
- `--priority-fee-tier` (optional): The priority fee tier for transaction processing. Options: | ||
- `none`: No priority fee. | ||
- `low`: Lower 25th quartile prioritization fee. | ||
- `medium`: Median prioritization fee (default). | ||
- `high`: Upper 80th quartile prioritization fee. | ||
- `turbo`: Upper 99th quartile prioritization fee. | ||
- `max_priority_fee_lamports` (optional): Maximum total priority fee in lamports. Default: 10_000_000 (0.01 SOL). | ||
- `slippage_tolerance_bps` (optional): Slippage tolerance in basis points (bps). Default: 100. | ||
|
||
### Example Usage | ||
Monitor and rebalance with default settings: | ||
```bash | ||
./target/release/lp-bot \ | ||
--position-mint-address 5m1izNWC3ioBaKm63e3gSNFeZ44o13ncre5QknTXBJUS | ||
``` | ||
|
||
Monitor with custom threshold and interval: | ||
```bash | ||
./target/release/lp-bot \ | ||
--position-mint-address 5m1izNWC3ioBaKm63e3gSNFeZ44o13ncre5QknTXBJUS \ | ||
--threshold 0.5 \ | ||
--interval 30 | ||
``` | ||
|
||
Monitor with turbo priority fees: | ||
```bash | ||
./target/release/lp-bot \ | ||
--position-mint-address 5m1izNWC3ioBaKm63e3gSNFeZ44o13ncre5QknTXBJUS \ | ||
--priority-fee-tier turbo | ||
``` | ||
|
||
--- | ||
|
||
## Directory Structure | ||
|
||
```bash | ||
examples/ | ||
├── rust-sdk/ | ||
└── lp-bot/ | ||
└── src/ | ||
├── main.rs # Entry point | ||
├── cli.rs # CLI argument parsing | ||
├── wallet.rs # Wallet management | ||
├── position_manager.rs # Position monitoring and rebalancing | ||
├── solana_utils.rs # RPC utilities | ||
``` |
15 changes: 15 additions & 0 deletions
15
examples/rust-sdk/whirlpool_repositioning_bot/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"name": "@orca-so/whirlpools-example-rust-repositioning-bot", | ||
"version": "0.0.1", | ||
"scripts": { | ||
"build": "cargo build", | ||
"format": "cargo clippy --fix --allow-dirty --allow-staged && cargo fmt", | ||
"lint": "cargo clippy", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed this command in #522 so you might want to do that here too |
||
"clean": "cargo clean" | ||
}, | ||
"devDependencies": { | ||
"@orca-so/whirlpools-rust": "*", | ||
"@orca-so/whirlpools-rust-client": "*", | ||
"@orca-so/whirlpools-rust-core": "*" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
use clap::Parser; | ||
|
||
use crate::utils::PriorityFeeTier; | ||
|
||
#[derive(Parser, Debug)] | ||
#[command(author, version, about, long_about = None)] | ||
pub struct Args { | ||
#[arg( | ||
short = 'p', | ||
long, | ||
help = "The position mint address to monitor and rebalance." | ||
)] | ||
pub position_mint_address: String, | ||
|
||
#[arg( | ||
short = 't', | ||
long, | ||
default_value_t = 100, | ||
help = "Threshold for repositioning in bps.\n" | ||
)] | ||
pub threshold: u16, | ||
|
||
#[arg( | ||
short = 'i', | ||
long, | ||
default_value_t = 60, | ||
help = "Time interval for checking in seconds.\n" | ||
)] | ||
pub interval: u64, | ||
|
||
#[arg( | ||
short = 'f', | ||
long, | ||
value_enum, | ||
default_value_t = PriorityFeeTier::Medium, | ||
help = "Priority fee tier for transaction processing based on recently paid priority fees. Options:\n \ | ||
- `none`: No priority fee\n \ | ||
- `low`: Lower 25th quartile prioritization fee\n \ | ||
- `medium`: Median prioritization fee\n \ | ||
- `high`: Upper 80th quartile prioritization fee\n \ | ||
- `turbo`: Upper 99th quartile prioritization fee\n" | ||
)] | ||
pub priority_fee_tier: PriorityFeeTier, | ||
|
||
#[arg( | ||
short = 'm', | ||
long, | ||
default_value_t = 10_000_000, | ||
help = "Maximum total priority fee in lamports.\n" | ||
)] | ||
pub max_priority_fee_lamports: u64, | ||
|
||
#[arg( | ||
short = 's', | ||
long, | ||
default_value_t = 100, | ||
help = "Slippage tolerance in basis points (bps).\n" | ||
)] | ||
pub slippage_tolerance_bps: u16, | ||
} |
101 changes: 101 additions & 0 deletions
101
examples/rust-sdk/whirlpool_repositioning_bot/src/main.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
mod cli; | ||
mod position_manager; | ||
mod utils; | ||
mod wallet; | ||
|
||
use clap::Parser; | ||
use cli::Args; | ||
use colored::Colorize; | ||
use dotenv::dotenv; | ||
use orca_whirlpools::{set_funder, set_whirlpools_config_address, WhirlpoolsConfigInput}; | ||
use orca_whirlpools_client::get_position_address; | ||
use position_manager::run_position_manager; | ||
use solana_client::nonblocking::rpc_client::RpcClient; | ||
use solana_sdk::pubkey::Pubkey; | ||
use std::env; | ||
use std::str::FromStr; | ||
use tokio::time::{sleep, Duration}; | ||
use utils::{ | ||
display_position_balances, display_wallet_balances, fetch_mint, fetch_position, fetch_whirlpool, | ||
}; | ||
|
||
#[tokio::main] | ||
async fn main() { | ||
let args = Args::parse(); | ||
dotenv().ok(); | ||
let rpc_url = env::var("RPC_URL").unwrap(); | ||
let rpc = RpcClient::new(rpc_url.to_string()); | ||
set_whirlpools_config_address(WhirlpoolsConfigInput::SolanaMainnet) | ||
.expect("Failed to set Whirlpools config address for specified network."); | ||
let wallet = wallet::load_wallet(); | ||
set_funder(wallet.pubkey()).expect("Failed to set funder address."); | ||
|
||
let position_mint_address = Pubkey::from_str(&args.position_mint_address) | ||
.expect("Invalid position mint address provided."); | ||
|
||
println!( | ||
"\n\ | ||
====================\n\ | ||
🌀 Whirlpool LP BOT \n\ | ||
====================\n" | ||
); | ||
println!("Configuration:"); | ||
println!( | ||
" Position Mint Address: {}\n Threshold: {:.2}%\n Interval: {} seconds\n Priority Fee Tier: {:?}\n Slippage tolerance bps: {:?}\n", | ||
args.position_mint_address, args.threshold, args.interval, args.priority_fee_tier, args.slippage_tolerance_bps | ||
); | ||
|
||
println!("-------------------------------------\n"); | ||
|
||
let (position_address, _) = | ||
get_position_address(&position_mint_address).expect("Failed to derive position address."); | ||
let mut position = fetch_position(&rpc, &position_address) | ||
.await | ||
.expect("Failed to fetch position data."); | ||
let whirlpool = fetch_whirlpool(&rpc, &position.whirlpool) | ||
.await | ||
.expect("Failed to fetch Whirlpool data."); | ||
let token_mint_a = fetch_mint(&rpc, &whirlpool.token_mint_a) | ||
.await | ||
.expect("Failed to fetch Token Mint A data."); | ||
let token_mint_b = fetch_mint(&rpc, &whirlpool.token_mint_b) | ||
.await | ||
.expect("Failed to fetch Token Mint B data."); | ||
|
||
display_wallet_balances( | ||
&rpc, | ||
&wallet.pubkey(), | ||
&whirlpool.token_mint_a, | ||
&whirlpool.token_mint_b, | ||
) | ||
.await | ||
.expect("Failed to display wallet balances."); | ||
|
||
display_position_balances( | ||
&rpc, | ||
&position, | ||
&whirlpool.token_mint_a, | ||
&whirlpool.token_mint_b, | ||
token_mint_a.decimals, | ||
token_mint_b.decimals, | ||
args.slippage_tolerance_bps, | ||
) | ||
.await | ||
.expect("Failed to display position balances."); | ||
|
||
loop { | ||
if let Err(err) = run_position_manager( | ||
&rpc, | ||
&args, | ||
&wallet, | ||
&mut position, | ||
&token_mint_a, | ||
&token_mint_b, | ||
) | ||
.await | ||
{ | ||
eprintln!("{}", format!("Error: {}", err).to_string().red()); | ||
} | ||
sleep(Duration::from_secs(args.interval)).await; | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Useful to add a readme to the examples folder with a little more description on each example?