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,
};
}
| Field | Type | Description |
|---|---|---|
dwallet_program | &AccountView | The dWallet program account |
cpi_authority | &AccountView | Your program’s CPI authority PDA |
caller_program | &AccountView | Your program’s account (must be executable) |
cpi_authority_bump | u8 | Bump 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 types – Signer, 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
| Consideration | Pinocchio | Native | Anchor | Quasar |
|---|---|---|---|---|
| CU efficiency | Best | Good | Good | Best |
| Binary size | Smallest | Medium | Largest | Small |
no_std support | Yes | No | No | Yes |
| Account validation | Manual | Manual | Declarative | Declarative |
| Zero-copy | Manual | No | No | Built-in |
| Learning curve | Steepest | Medium | Easiest | Medium |
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
| Pinocchio | Anchor | Quasar | |
|---|---|---|---|
| Account types | &AccountView | AccountInfo | Owned Signer/UncheckedAccount |
| CPI | invoke_signed | invoke_signed (via solana_program) | invoke_signed_unchecked |
| CPI data | Heap Vec | Heap Vec | Stack [u8; N] |
| Instruction dispatch | Manual match | #[program] (hash-based) | #[program] + #[instruction(discriminator = N)] |
| Field access | Raw byte offsets | Borsh deserialized | Zero-copy Pod types |
| Account init | Manual CreateAccount | #[account(init)] | #[account(init)] |
| Error handling | ProgramResult | Result<()> | 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.