base on Constant product AMM integrated with the OpenBook CLOB <div align="center"> <h1>raydium-amm</h1> </div> ## Program Deployments | Environment | [PROGRAM](/program) | | ------------------- | ---------------------------------------------- | | Mainnet | `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8` | | Devnet | `DRaya7Kj3aMWQSy19kSjvmuwq9docCHofyP9kanQGaav` | ## Overview - **The Raydium AMM is an on-chain smart contract based on the “constant product” in a permissionless and decentralized manner built on the Solana blockchain.And it also shares its liquidity according to the Fibonacci sequence in the form of limit orders on [OpenBook](https://github.com/openbook-dex/program), the primary central limit order book (CLOB) of Solana** - **The audit process is [here](https://github.com/raydium-io/raydium-docs/tree/master/audit)** - **The dev document is [here](https://github.com/raydium-io/raydium-docs/tree/master/dev-resources)** ## Environment Setup 1. Install [Rust](https://www.rust-lang.org/tools/install). 2. Install [Solana](https://docs.solana.com/cli/install-solana-cli-tools) and then run `solana-keygen new` to create a keypair at the default location. ## Build Clone the repository and enter the source code directory. ```bash git clone https://github.com/raydium-io/raydium-amm cd raydium-amm/program ``` ### Mainnet Build ```bash cargo build-sbf ``` ### Devnet Build ```bash cargo build-sbf --features devnet ``` ### Localnet Build You must update these pubkeys in the "config_feature" as yours over the localnet feature before build; ```bash cargo build-sbf --features localnet ``` After building, the smart contract files are all located in the target directory. ## Deploy ```bash solana deploy ``` Attention, check your configuration and confirm the environment you want to deploy. ## QuickStart 1. You must have an openbook market not associated to any amm pool if you want to initialize a new amm pool. And you can refer to [ListMarket](https://github.com/openbook-dex/program/blob/master/dex/crank/src/lib.rs#L349) to create a new market. 2. Add dependencies in your Cargo.toml ```rust [dependencies] [features] # default is mainnet devnet = [ "amm-cli/devnet", "common/devnet", ] [dependencies] amm-cli = { git = "https://github.com/raydium-io/raydium-library" } common = { git = "https://github.com/raydium-io/raydium-library" } spl-token = { version = "4.0.0", features = ["no-entrypoint"] } spl-associated-token-account = { version = "2.2.0", features = [ "no-entrypoint", ] } spl-token-2022 = { version = "0.9.0", features = ["no-entrypoint"] } solana-client = "<1.17.0" solana-sdk = "<1.17.0" anyhow = "1.0.53" clap = { version = "4.1.8", features = ["derive"] } ``` 3. Import dependent libraries ```rust #![allow(dead_code)] use anyhow::{Ok, Result}; use clap::Parser; use solana_client::rpc_client::RpcClient; use solana_sdk::{commitment_config::CommitmentConfig, signer::Signer}; use std::sync::Arc; use { amm_cli::{self, AmmCommands}, common::{common_types, common_utils, rpc}, }; ``` 4. Custom configuration parameters in your code. ```rust // default config let mut config = common_types::CommonConfig::default(); // Replace the default configuration parameters you need config.set_cluster("http", "ws"); config.set_wallet("your wallet path"); config.set_amm_program("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); config.set_openbook_program("srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX"); config.set_slippage(50); ``` 5. Constructing a signed storage object. ```rust let payer = common_utils::read_keypair_file(&config.wallet())?; let fee_payer = payer.pubkey(); let mut signing_keypairs: Vec<Arc<dyn Signer>> = Vec::new(); let payer: Arc<dyn Signer> = Arc::new(payer); if !signing_keypairs.contains(&payer) { signing_keypairs.push(payer); } ``` 6. initialize a new amm pool with an associate openbook market ```rust // build initialize pool instruction let subcmd = AmmCommands::CreatePool { market: Pubkey::from_str("The amm associated with openbook market").unwrap(), coin_mint: Pubkey::from_str("The openbook market's coin_mint").unwrap(), pc_mint: Pubkey::from_str("The openbook market's pc_mint").unwrap(), user_token_coin: Pubkey::from_str("User's token coin").unwrap(), user_token_pc: Pubkey::from_str("User's token pc").unwrap(), init_coin_amount: 100000u64, init_pc_amount: 100000u64, open_time: 0, }; let instruction = amm_cli::process_amm_commands(subcmd, &config).unwrap(); ``` 3. deposit assets to an amm pool ```rust // build deposit instruction let subcmd = AmmCommands::Deposit { pool_id: Pubkey::from_str("The specified pool of the assets deposite to").unwrap(), deposit_token_coin: Some(Pubkey::from_str("The specified token coin of the user deposit").unwrap()), deposit_token_pc: Some(Pubkey::from_str("The specified token pc of the user deposit").unwrap()), recipient_token_lp: Some(Pubkey::from_str("The specified lp token of the user will receive").unwrap()), amount_specified: 100000u64, another_min_limit: false, base_coin: false, }; let instruction = amm_cli::process_amm_commands(subcmd, &config).unwrap(); ``` ### Note If the parameter of the deposit_token_coin, deposit_token_pc or recipient_token_lp is None, it will be ATA token by default. 4. withdraw assets from amm pool ```rust // build withdraw instruction let subcmd = AmmCommands::Withdraw { pool_id: Pubkey::from_str("The specified pool of the assets withdraw from").unwrap(), withdraw_token_lp: Some(Pubkey::from_str("The specified lp token of the user withdraw").unwrap()), recipient_token_coin: Some(Pubkey::from_str("The specified token coin of the user will receive").unwrap()), recipient_token_pc: Some(Pubkey::from_str("The specified token pc of the user will receive").unwrap()), input_lp_amount: 100000u64, slippage_limit: false, }; let instruction = amm_cli::process_amm_commands(subcmd, &config).unwrap(); ``` ### Note If the parameter of the withdraw_token_lp, recipient_token_coin or recipient_token_pc is None, it will be ATA token by default. 5. swap ```rust // build swap instruction let subcmd = AmmCommands::Swap { pool_id: Pubkey::from_str(" The specified pool of trading").unwrap(), user_input_token: Pubkey::from_str("The token of user want to swap from").unwrap(), user_output_token: Some(Pubkey::from_str("The token of user want to swap to").unwrap()), amount_specified: 100000u64, base_out: false, }; let instruction = amm_cli::process_amm_commands(subcmd, &config).unwrap(); ``` ### Note If the parameter of the user_output_token is None, it will be ATA token by default. For more information, you can see the repo [raydium-library](https://github.com/raydium-io/raydium-library) ", Assign "at most 3 tags" to the expected json: {"id":"12820","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"