Skip to main content

universalsettle_api/
sdk.rs

1use steel::*;
2
3use crate::{
4    instruction::*,
5    state::{config_pda, split_vault_pda, vault_sol_storage_pda},
6};
7
8/// Builds an instruction to create a SplitVault for a seller.
9///
10/// # Arguments
11///
12/// * `payer` - Fee payer for the account creation (signer)
13/// * `seller` - Resource owner wallet address
14pub fn create_vault(payer: Pubkey, seller: Pubkey) -> Instruction {
15    let (vault_pda, _) = split_vault_pda(&seller);
16    let (vault_sol_storage, _) = vault_sol_storage_pda(vault_pda);
17    Instruction {
18        program_id: crate::ID,
19        accounts: vec![
20            AccountMeta::new(payer, true),
21            AccountMeta::new(vault_pda, false),
22            AccountMeta::new(vault_sol_storage, false),
23            AccountMeta::new_readonly(solana_program::system_program::ID, false),
24        ],
25        data: CreateVault { seller }.to_bytes(),
26    }
27}
28
29/// Builds an instruction to sweep funds from a vault to the seller and facilitator.
30///
31/// # Arguments
32///
33/// * `payer` - The fee payer and authorized signer (Facilitator)
34/// * `vault` - The SplitVault PDA
35/// * `seller` - The seller's wallet
36/// * `fee_destination` - The facilitator's fee wallet
37/// * `token_mint` - For SOL: Pubkey::default(), For SPL: the mint address
38/// * `amount` - Amount to sweep (0 = all)
39/// * `is_sol` - Whether to sweep native SOL or SPL tokens
40/// * `vault_tokens` - The vault's token account (for SPL)
41/// * `seller_tokens` - The seller's token account (for SPL)
42/// * `fee_dest_tokens` - The facilitator's token account (for SPL)
43#[allow(clippy::too_many_arguments)]
44pub fn sweep(
45    payer: Pubkey,
46    vault: Pubkey,
47    seller: Pubkey,
48    fee_destination: Pubkey,
49    token_mint: Pubkey,
50    amount: u64,
51    is_sol: bool,
52    vault_tokens: Option<Pubkey>,
53    seller_tokens: Option<Pubkey>,
54    fee_dest_tokens: Option<Pubkey>,
55    token_program: Option<Pubkey>,
56) -> Instruction {
57    let (config_pda, _) = config_pda();
58    let mut accounts = vec![
59        AccountMeta::new(payer, true),
60        // vault (SplitVault PDA) is read-only in sweep — funds leave via vault_sol_storage / ATA
61        AccountMeta::new_readonly(vault, false),
62        AccountMeta::new_readonly(config_pda, false),
63    ];
64
65    if is_sol {
66        let (vault_sol_storage, _) = vault_sol_storage_pda(vault);
67        accounts.push(AccountMeta::new(vault_sol_storage, false));
68        accounts.push(AccountMeta::new(seller, false));
69        accounts.push(AccountMeta::new(fee_destination, false));
70        accounts.push(AccountMeta::new_readonly(
71            solana_program::system_program::ID,
72            false,
73        ));
74    } else {
75        accounts.push(AccountMeta::new(
76            vault_tokens.expect("vault_tokens is required for SPL sweep"),
77            false,
78        ));
79        accounts.push(AccountMeta::new(
80            seller_tokens.expect("seller_tokens is required for SPL sweep"),
81            false,
82        ));
83        accounts.push(AccountMeta::new(
84            fee_dest_tokens.expect("fee_dest_tokens is required for SPL sweep"),
85            false,
86        ));
87        accounts.push(AccountMeta::new_readonly(
88            token_program.unwrap_or(spl_token::ID),
89            false,
90        ));
91    }
92
93    Instruction {
94        program_id: crate::ID,
95        accounts,
96        data: Sweep {
97            token_mint,
98            amount: amount.to_le_bytes(),
99            is_sol: if is_sol { [1] } else { [0] },
100            _padding: [0; 7],
101        }
102        .to_bytes(),
103    }
104}
105
106/// Create an initialize instruction
107pub fn initialize(
108    authority: Pubkey,
109    fee_destination: Pubkey,
110    fee_bps: Option<u16>,
111    min_fee_amount: Option<u64>,
112) -> Instruction {
113    let (config_pda, _) = config_pda();
114    Instruction {
115        program_id: crate::ID,
116        accounts: vec![
117            AccountMeta::new(authority, true),
118            AccountMeta::new(config_pda, false),
119            AccountMeta::new_readonly(solana_program::system_program::ID, false),
120            AccountMeta::new_readonly(solana_program::sysvar::rent::ID, false),
121        ],
122        data: Initialize {
123            fee_destination,
124            min_fee_amount: (min_fee_amount.unwrap_or(10000)).to_le_bytes(),
125            fee_bps: (fee_bps.unwrap_or(100)).to_le_bytes(),
126            _padding: [0; 6],
127        }
128        .to_bytes(),
129    }
130}
131
132/// Create an update authority instruction
133pub fn update_authority(current_authority: Pubkey, new_authority: Pubkey) -> Instruction {
134    let (config_pda, _) = config_pda();
135    Instruction {
136        program_id: crate::ID,
137        accounts: vec![
138            AccountMeta::new(current_authority, true),
139            AccountMeta::new(config_pda, false),
140        ],
141        data: UpdateAuthority { new_authority }.to_bytes(),
142    }
143}
144
145/// Create an update fee rate instruction
146pub fn update_fee_rate(authority: Pubkey, new_fee_bps: u16) -> Instruction {
147    let (config_pda, _) = config_pda();
148    Instruction {
149        program_id: crate::ID,
150        accounts: vec![
151            AccountMeta::new(authority, true),
152            AccountMeta::new(config_pda, false),
153        ],
154        data: UpdateFeeRate {
155            new_fee_bps: new_fee_bps.to_le_bytes(),
156            _padding: [0; 6],
157        }
158        .to_bytes(),
159    }
160}
161
162/// Create an update fee destination instruction
163pub fn update_fee_destination(authority: Pubkey, new_fee_destination: Pubkey) -> Instruction {
164    let (config_pda, _) = config_pda();
165    Instruction {
166        program_id: crate::ID,
167        accounts: vec![
168            AccountMeta::new(authority, true),
169            AccountMeta::new(config_pda, false),
170        ],
171        data: UpdateFeeDestination {
172            new_fee_destination,
173        }
174        .to_bytes(),
175    }
176}
177
178/// Create an update min fee amount instruction
179pub fn update_min_fee_amount(authority: Pubkey, new_min_fee_amount: u64) -> Instruction {
180    let (config_pda, _) = config_pda();
181    Instruction {
182        program_id: crate::ID,
183        accounts: vec![
184            AccountMeta::new(authority, true),
185            AccountMeta::new(config_pda, false),
186        ],
187        data: UpdateMinFeeAmount {
188            new_min_fee_amount: new_min_fee_amount.to_le_bytes(),
189        }
190        .to_bytes(),
191    }
192}