use solana_program::pubkey::Pubkey;
use solana_sdk::{
message::{v0, VersionedMessage},
signature::Keypair,
transaction::VersionedTransaction,
};
use swig_interface::{
AuthorityConfig, ClientAction, CreateInstruction, CreateSubAccountInstruction,
};
use swig_state::{
action::{all::All, sub_account::SubAccount},
authority::AuthorityType,
swig::{sub_account_seeds, swig_account_seeds, swig_wallet_address_seeds},
};
fn create_swig_and_subaccount_in_one_tx(
rpc_client: &RpcClient,
authority: &Keypair,
fee_payer: &Keypair,
) -> Result<(Pubkey, Pubkey), Box<dyn std::error::Error>> {
let swig_id = rand::random::<[u8; 32]>();
let program_id = swig_interface::program_id();
// Derive the Swig account address
let (swig_key, swig_bump) =
Pubkey::find_program_address(&swig_account_seeds(&swig_id), &program_id);
let (swig_wallet_address, wallet_address_bump) = Pubkey::find_program_address(
&swig_wallet_address_seeds(swig_key.as_ref()),
&program_id,
);
// Derive the sub-account address (role_id 0 since this is the initial authority)
let role_id: u32 = 0;
let role_id_bytes = role_id.to_le_bytes();
let (sub_account, sub_account_bump) =
Pubkey::find_program_address(&sub_account_seeds(&swig_id, &role_id_bytes), &program_id);
// Step 1: Create instruction to create Swig account with All + SubAccount permissions
let create_swig_ix = CreateInstruction::new(
swig_key,
swig_bump,
fee_payer.pubkey(),
swig_wallet_address,
wallet_address_bump,
AuthorityConfig {
authority_type: AuthorityType::Ed25519,
authority: authority.pubkey().as_ref(),
},
vec![
ClientAction::All(All {}),
ClientAction::SubAccount(SubAccount::new_for_creation()),
],
swig_id,
)?;
// Step 2: Create instruction to create the subaccount
// This uses role_id 0 since the authority is the initial/root authority
let create_sub_account_ix = CreateSubAccountInstruction::new_with_ed25519_authority(
swig_key,
authority.pubkey(),
fee_payer.pubkey(),
sub_account,
role_id,
sub_account_bump,
)?;
// Step 3: Submit both instructions in a single transaction
let recent_blockhash = rpc_client.get_latest_blockhash()?;
let message = v0::Message::try_compile(
&fee_payer.pubkey(),
&[create_swig_ix, create_sub_account_ix],
&[],
recent_blockhash,
)?;
let tx = VersionedTransaction::try_new(
VersionedMessage::V0(message),
&[fee_payer, authority],
)?;
rpc_client.send_and_confirm_transaction(&tx)?;
// Verify both accounts were created
let swig_account = rpc_client.get_account(&swig_key)?;
let sub_account_data = rpc_client.get_account(&sub_account)?;
assert_eq!(sub_account_data.owner, solana_sdk::system_program::id());
Ok((swig_key, sub_account))
}