Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Quasar Framework

Pre-Alpha Disclaimer: This is an early pre-alpha release for exploring the SDK and starting development only. There is no real MPC signing – all signatures are generated by a single mock signer, not a distributed network. Do not submit any real transactions for signing or rely on any security guarantees. The dWallet keys, trust model, and signing protocol are not final; do not rely on any key material until mainnet. All interfaces, APIs, and data formats are subject to change without notice. The Solana program and all on-chain data will be wiped periodically and everything will be deleted when we transition to Ika Alpha 1. This software is provided “as is” without warranty of any kind; use is entirely at your own risk and dWallet Labs assumes no liability for any damages arising from its use.

The ika-dwallet-quasar crate provides a Quasar-native CPI SDK for the dWallet program. Quasar is a zero-copy Solana program framework with alignment-1 Pod types, declarative account validation, and low-level CPI control via invoke_signed_unchecked.

Dependencies

[dependencies]
ika-dwallet-quasar = { git = "https://github.com/dwallet-labs/ika-pre-alpha" }
quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" }
solana-address = { version = "2.4", features = ["curve25519"] }

[lib]
crate-type = ["cdylib", "lib"]

DWalletContext

#![allow(unused)]
fn main() {
use ika_dwallet_quasar::DWalletContext;

let ctx = DWalletContext {
    dwallet_program: self.dwallet_program.to_account_view(),
    cpi_authority: self.cpi_authority.to_account_view(),
    caller_program: self.caller_program.to_account_view(),
    cpi_authority_bump: bump,
};
}
FieldTypeDescription
dwallet_program&AccountViewThe dWallet program account
cpi_authority&AccountViewYour program’s CPI authority PDA
caller_program&AccountViewYour program’s account (must be executable)
cpi_authority_bumpu8Bump seed for the CPI authority PDA

Convert Quasar account types to &AccountView using .to_account_view() (available on Signer, UncheckedAccount, Program<T>, Account<T>).

CPI Authority PDA

#![allow(unused)]
fn main() {
use ika_dwallet_quasar::CPI_AUTHORITY_SEED;
use solana_address::Address;

let (cpi_authority, bump) = Address::find_program_address(
    &[CPI_AUTHORITY_SEED],
    &your_program_id,
);
}

Methods

approve_message

Creates a MessageApproval PDA requesting a signature.

#![allow(unused)]
fn main() {
ctx.approve_message(
    self.coordinator.to_account_view(),
    self.message_approval.to_account_view(),
    self.dwallet.to_account_view(),
    self.payer.to_account_view(),
    self.system_program.to_account_view(),
    message_digest,         // [u8; 32]
    message_metadata_digest, // [u8; 32] -- zero if no metadata
    user_pubkey,            // [u8; 32]
    signature_scheme,       // u16
    bump,                   // u8 -- MessageApproval PDA bump
)?;
}

transfer_dwallet

Transfers dWallet authority to a new pubkey.

#![allow(unused)]
fn main() {
ctx.transfer_dwallet(
    self.dwallet.to_account_view(),
    new_authority,  // [u8; 32]
)?;
}

transfer_future_sign

Transfers the completion authority of a PartialUserSignature.

#![allow(unused)]
fn main() {
ctx.transfer_future_sign(
    self.partial_user_sig.to_account_view(),
    new_authority,  // [u8; 32]
)?;
}

Example: Voting-Controlled dWallet

Source: chains/solana/examples/voting/quasar/

Quasar programs use #[program] with explicit instruction discriminators, owned account types (no lifetimes), and impl handlers on account structs:

#![allow(unused)]
#![no_std]

fn main() {
use ika_dwallet_quasar::DWalletContext;
use quasar_lang::prelude::*;
use solana_address::Address;

declare_id!("US517G5965aydkZ46HS38QLi7UQiSojurfbQfKCELFx");

#[program]
mod voting_quasar {
    use super::*;

    #[instruction(discriminator = 0)]
    pub fn create_proposal(
        ctx: Ctx<CreateProposal>,
        message_digest: [u8; 32],
        /* ... */
    ) -> Result<(), ProgramError> {
        ctx.accounts.create(message_digest, /* ... */)
    }

    #[instruction(discriminator = 1)]
    pub fn cast_vote(
        ctx: Ctx<CastVote>,
        vote: bool,
        cpi_authority_bump: u8,
    ) -> Result<(), ProgramError> {
        ctx.accounts.cast(vote, cpi_authority_bump)
    }
}
}

Account Definitions (Quasar style)

Quasar uses owned types (no lifetime parameters), zero-copy #[account] with explicit discriminators, and #[seeds] on state structs:

#![allow(unused)]
fn main() {
#[account(discriminator = 1, set_inner)]
#[seeds(b"proposal", proposal_id: Address)]
pub struct Proposal {
    pub proposal_id: Address,
    pub dwallet: Address,
    pub message_digest: [u8; 32],
    pub user_pubkey: [u8; 32],
    pub signature_scheme: u16,
    pub creator: Address,
    pub yes_votes: u32,
    pub no_votes: u32,
    pub quorum: u32,
    pub status: u8,
    pub message_approval_bump: u8,
}
}

Account Validation (Quasar constraints)

#![allow(unused)]
fn main() {
#[derive(Accounts)]
pub struct CastVote {
    pub proposal_id: UncheckedAccount,

    #[account(mut, seeds = Proposal::seeds(proposal_id), bump)]
    pub proposal: Account<Proposal>,

    #[account(init, payer = payer, seeds = VoteRecord::seeds(proposal_id, voter), bump)]
    pub vote_record: Account<VoteRecord>,

    pub voter: Signer,

    #[account(mut)]
    pub payer: Signer,

    pub system_program: Program<System>,

    // CPI accounts for dWallet interaction
    pub coordinator: UncheckedAccount,
    #[account(mut)]
    pub message_approval: UncheckedAccount,
    pub dwallet: UncheckedAccount,
    pub caller_program: UncheckedAccount,
    pub cpi_authority: UncheckedAccount,
    pub dwallet_program: UncheckedAccount,
}
}

Handler Pattern (impl on Accounts struct)

#![allow(unused)]
fn main() {
impl CastVote {
    pub fn cast(&mut self, vote: bool, cpi_authority_bump: u8) -> Result<(), ProgramError> {
        // Mutate fields via zero-copy Pod types
        self.proposal.yes_votes = self.proposal.yes_votes
            .checked_add(1u32)
            .ok_or(VotingError::ArithmeticOverflow)?;

        // CPI when quorum reached
        if self.proposal.yes_votes >= self.proposal.quorum {
            let dwallet_ctx = DWalletContext {
                dwallet_program: self.dwallet_program.to_account_view(),
                cpi_authority: self.cpi_authority.to_account_view(),
                caller_program: self.caller_program.to_account_view(),
                cpi_authority_bump,
            };
            dwallet_ctx.approve_message(/* ... */)?;
            self.proposal.status = 1; // Approved
        }
        Ok(())
    }
}
}

Error Codes

#![allow(unused)]
fn main() {
#[error_code]
pub enum VotingError {
    ProposalClosed = 6000,
    InvalidQuorum,
    ArithmeticOverflow,
}
}

Key Patterns

Seed components as accounts – Quasar resolves PDA seeds from account addresses. Pass seed values (like proposal_id) as UncheckedAccount fields whose addresses are the seed bytes.

Owned account typesSigner, UncheckedAccount, Program<System>, Account<T> are owned (no lifetime parameters or references).

Pod arithmetic – Multi-byte fields are zero-copy Pod types (PodU16, PodU32). Use .checked_add(), .into(), and direct comparison operators.

set_inner() for initialization – The #[account(set_inner)] macro generates a companion Inner struct with original Rust types for initialization.

Stack-allocated CPI – The Quasar SDK uses invoke_signed_unchecked with stack-allocated buffers (no heap allocation), making it the most CU-efficient CPI variant.

When to Use Quasar

ConsiderationPinocchioNativeAnchorQuasar
CU efficiencyBestGoodGoodBest
Binary sizeSmallestMediumLargestSmall
no_std supportYesNoNoYes
Account validationManualManualDeclarativeDeclarative
Zero-copyManualNoNoBuilt-in
Learning curveSteepestMediumEasiestMedium

Choose Quasar when you want declarative account validation (like Anchor) combined with zero-copy performance (like Pinocchio), built-in Pod types for safe zero-copy field access, and no_std compatibility.

Differences from Other SDKs

PinocchioAnchorQuasar
Account types&AccountViewAccountInfoOwned Signer/UncheckedAccount
CPIinvoke_signedinvoke_signed (via solana_program)invoke_signed_unchecked
CPI dataHeap VecHeap VecStack [u8; N]
Instruction dispatchManual match#[program] (hash-based)#[program] + #[instruction(discriminator = N)]
Field accessRaw byte offsetsBorsh deserializedZero-copy Pod types
Account initManual CreateAccount#[account(init)]#[account(init)]
Error handlingProgramResultResult<()>Result<(), ProgramError>

All four SDKs use the same CPI authority seed (b"__ika_cpi_authority"), the same instruction discriminators, and the same wire format. Programs built with any SDK are fully interoperable at the dWallet program level.