Skip to content

💡 [REQUEST] - Better set account experience #439

@SteMak

Description

@SteMak

Summary

The set_account_custom function requires AccountSharedData to be constructed by developer which requires manual data packing

    pub fn set_account_custom(&mut self, address: &Pubkey, account: &AccountSharedData) {
        self.client.set_account(address, account, false);
    }

Generated types.rs does not include discriminators for state accounts
This limits developer ability to manually pack state accounts

It would be nice to have additional helper functions processing accounts mocking in such ease way as get_account_with_type do
Discriminators for state accounts should be included to generated types.rs

Basic Example

E.g. such helper functions would simplify accounts mocking

    // Easy mocking of custom state accounts
    fn set_account_with_type<T: BorshSerialize + Discriminator>(&mut self, key: &Pubkey, account: T, owner: Pubkey) {
        let mut buffer = T::discriminator();
        account.serialize(&mut buffer).unwrap();

        let shared_data = AccountSharedData::create(
            self.trident.get_sysvar::<Rent>().minimum_balance(buffer.len()),
            buffer,
            owner,
            false,
            Epoch::default(),
        );
        self.trident.set_account_custom(key, &shared_data);
    }

    // Easy mocking of system state accounts such as Mint and Account
    fn set_account_packed<T: Pack>(&mut self, key: &Pubkey, account: T, owner: Pubkey) {
        let mut buffer = vec![0; T::get_packed_len()];
        T::pack(account, &mut buffer).unwrap();

        let shared_data = AccountSharedData::create(
            self.trident.get_sysvar::<Rent>().minimum_balance(buffer.len()),
            buffer,
            owner,
            false,
            Epoch::default(),
        );
        self.trident.set_account_custom(key, &shared_data);
    }

Improvement for types.rs for set_account_with_type to work

pub trait Discriminator {
    fn discriminator() -> Vec<u8>;
}

/// Custom struct: Account
#[derive(Debug, BorshDeserialize, BorshSerialize, Clone)]
pub struct Account {
    ...
}

impl Discriminator for Account {
    fn discriminator() -> Vec<u8> {
        vec![...]
    }
}

Usage sample

        // Now devs have to do smth like this
        let account = Account::new(...);
        let mut account_buffer = vec![/* hardcoded discriminator */];
        account_a.serialize(&mut account_buffer).unwrap();

        let account_shared_data = AccountSharedData::create(
            self.trident.get_sysvar::<Rent>().minimum_balance(account_buffer.len()),
            account_buffer,
            PROGRAM_NAME::program_id(),
            false,
            Epoch::default(),
        );
        self.trident.set_account_custom(address, &account_shared_data);

        // Proposal application result
        self.trident.set_account_with_type(
            &address,
            Account::new(...),
            PROGRAM_NAME::program_id(),
        );

Drawbacks

No response

Unresolved questions

No response

Implementation PR

No response

Reference Issues

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions