Skip to main content

defituna_client/txbuilder/
open_tuna_spot_position.rs

1use crate::instructions::{OpenTunaSpotPosition, OpenTunaSpotPositionInstructionArgs};
2use crate::types::PoolToken;
3use crate::{get_market_address, get_tuna_spot_position_address};
4use anyhow::{anyhow, Result};
5use fusionamm_client::{FusionPool, FUSIONAMM_ID};
6use orca_whirlpools_client::{Whirlpool, WHIRLPOOL_ID};
7use solana_client::rpc_client::RpcClient;
8use solana_instruction::Instruction;
9use solana_pubkey::Pubkey;
10use solana_sdk_ids::system_program;
11use spl_associated_token_account::get_associated_token_address_with_program_id;
12
13impl Default for OpenTunaSpotPositionInstructionArgs {
14    fn default() -> Self {
15        OpenTunaSpotPositionInstructionArgs {
16            position_token: PoolToken::A,
17            collateral_token: PoolToken::A,
18        }
19    }
20}
21
22pub fn open_tuna_spot_position_instructions(
23    rpc: &RpcClient,
24    authority: &Pubkey,
25    pool: &Pubkey,
26    args: OpenTunaSpotPositionInstructionArgs,
27) -> Result<Vec<Instruction>> {
28    let pool_account = rpc.get_account(pool)?;
29
30    let (mint_a_address, mint_b_address) = if pool_account.owner == FUSIONAMM_ID {
31        let pool = FusionPool::from_bytes(&pool_account.data)?;
32        (pool.token_mint_a, pool.token_mint_b)
33    } else if pool_account.owner == WHIRLPOOL_ID {
34        let pool = Whirlpool::from_bytes(&pool_account.data)?;
35        (pool.token_mint_a, pool.token_mint_b)
36    } else {
37        return Err(anyhow!("Incorrect fusion or orca pool"));
38    };
39
40    let mint_accounts = rpc.get_multiple_accounts(&[mint_a_address.into(), mint_b_address.into()])?;
41    let mint_a_account = mint_accounts[0].as_ref().ok_or(anyhow!("Token A mint account not found"))?;
42    let mint_b_account = mint_accounts[1].as_ref().ok_or(anyhow!("Token B mint account not found"))?;
43
44    let mut instructions = vec![];
45
46    instructions.push(open_tuna_spot_position_instruction(
47        authority,
48        pool,
49        &mint_a_address,
50        &mint_b_address,
51        &mint_a_account.owner,
52        &mint_b_account.owner,
53        args,
54    ));
55
56    Ok(instructions)
57}
58
59pub fn open_tuna_spot_position_instruction(
60    authority: &Pubkey,
61    pool: &Pubkey,
62    mint_a: &Pubkey,
63    mint_b: &Pubkey,
64    token_program_a: &Pubkey,
65    token_program_b: &Pubkey,
66    args: OpenTunaSpotPositionInstructionArgs,
67) -> Instruction {
68    let tuna_position_address = get_tuna_spot_position_address(authority, pool).0;
69    let market = get_market_address(pool).0;
70
71    let ix_builder = OpenTunaSpotPosition {
72        authority: *authority,
73        mint_a: *mint_a,
74        mint_b: *mint_b,
75        token_program_a: *token_program_a,
76        token_program_b: *token_program_b,
77        market,
78        tuna_position: tuna_position_address,
79        tuna_position_ata_a: get_associated_token_address_with_program_id(&tuna_position_address, mint_a, token_program_a),
80        tuna_position_ata_b: get_associated_token_address_with_program_id(&tuna_position_address, mint_b, token_program_b),
81        pool: *pool,
82        system_program: system_program::ID,
83        associated_token_program: spl_associated_token_account::ID,
84    };
85
86    ix_builder.instruction(args)
87}