Documentation Index
Fetch the complete documentation index at: https://mintlify.com/blueshift-gg/quasar/llms.txt
Use this file to discover all available pages before exploring further.
Account<T> is the standard way to declare a typed, program-owned data account in a Quasar instruction. During account parsing, Quasar validates that the account is owned by T::OWNER, that its data begins with T::DISCRIMINATOR, and that its data length is at least T::SPACE. Once all checks pass, the wrapper is available as Account<T>, which is #[repr(transparent)] over T — no heap allocation, no deserialization.
What Account<T> Validates
When Quasar’s#[derive(Accounts)] macro parses an Account<T> field, it performs three checks in order:
- Owner check —
view.owner() == T::OWNER. ReturnsProgramError::IllegalOwnerif wrong. - Discriminator check — the first bytes of account data must equal
T::DISCRIMINATOR. ReturnsProgramError::InvalidAccountDataif missing. - Data length check — account data must be at least
T::SPACEbytes. ReturnsProgramError::AccountDataTooSmallif too short.
Account<T> via a #[repr(transparent)] cast over T.
Zero-Copy Deref
Account<T> implements Deref<Target = T> and DerefMut<Target = T>. Because T itself is a zero-copy wrapper generated by the #[account] macro, all field accesses dereference directly into the live account data — no copies, no allocations.
T here is the struct generated by #[account], and its fields are Pod types (PodU64, Address, etc.) accessed through raw pointer arithmetic to the account’s data region.
Declaring Account<T> in Accounts Structs
UseAccount<T> inside any #[derive(Accounts)] struct. The #[account(mut)] attribute marks the account as writable; omitting it makes it read-only.
Read vs Write Access
Read-only: Account<T>
Omit
#[account(mut)]. The account is only accessible via Deref. Quasar does not check is_writable at parse time, but the SVM will reject any attempt to modify the account.Writable: #[account(mut)]
Add
#[account(mut)]. Required if you call set_inner(), close(), or realloc(). The DerefMut impl is available, giving &mut T access.Accessing Address and Lamports
Account<T> implements AsAccountView, which provides uniform access to the underlying AccountView. The address() method is inherited from this trait:
Writing Account Data with set_inner
When the#[account(..., set_inner)] attribute is present on an account struct, Quasar generates a set_inner method. This is the idiomatic way to write all fields of an account after initialization:
set_inner uses ptr::copy_nonoverlapping to write directly into the account’s data region, past the discriminator prefix.
Constraint Attributes
The#[account(...)] attribute on a field in #[derive(Accounts)] accepts several built-in constraints:
#[account(mut)]
#[account(mut)]
Marks the account as writable. Required for any handler that modifies account data or lamports.
#[account(has_one(field))]
#[account(has_one(field))]
Validates that
account.field == field_account.address(). Quasar compares the stored Address inside the account data against the address of the named account in the same struct. Returns QuasarError::HasOneMismatch if the addresses do not match.#[account(close(dest = target))]
#[account(close(dest = target))]
After the handler returns, Quasar zeros the discriminator, drains all lamports to
target, reassigns the account owner to System, and resizes to zero. The account is effectively closed in the epilogue.#[account(address = expr)]
#[account(address = expr)]
Validates that the account’s address matches the result of
expr. Typically used with PDA derivation helpers like Escrow::seeds(maker.address()).#[account(init, payer = field)]
#[account(init, payer = field)]
Creates a new account via system program CPI, writes the discriminator, and returns an initialized
Account<T>. Requires the account to be uninitialized (owned by System program).#[account(init(idempotent), payer = field)]
#[account(init(idempotent), payer = field)]
Like
init, but skips account creation if the account already exists and is initialized. Useful for token accounts or other accounts that may be created by an earlier instruction in the same transaction or a prior transaction.AccountLayout Trait
TheAccountLayout trait associates three compile-time constants with an account type:
Account<T> forwards AccountLayout to T. The DATA_OFFSET is the length of T::DISCRIMINATOR, ensuring that Deref skips past the discriminator bytes when returning a reference to the account’s payload.
Complete Escrow Example
The following shows howAccount<T> is used end-to-end in the escrow example:
- State definition
- Make instruction
- Take instruction
Account<T> vs UncheckedAccount
Use Account<T>
- You own the account type (it’s defined in your program)
- You need validated owner + discriminator + data length checks
- You want zero-copy field access via Deref
- You need
set_inner(),close(), orrealloc()
Use UncheckedAccount
- The account is from an external program with no Quasar type
- You’re forwarding the account to a CPI without inspecting data
- You need to perform fully custom validation logic
- You want raw
AccountViewaccess
