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

Voting Example

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.

Overview

A governance program where anyone can create proposals referencing a dWallet. Voters cast yes/no votes, and when the quorum of yes votes is reached, the program automatically CPI-calls approve_message on the dWallet program to authorize signing.

Use case: DAO governance, treasury management, group signing authorization.

Program Design

Accounts

AccountSeedsSizeDescription
Proposal["proposal", proposal_id]195 bytesStores vote counts, quorum, message hash, dWallet reference
VoteRecord["vote", proposal_id, voter]69 bytesPrevents double voting — one per voter per proposal

Instructions

DiscInstructionDescription
0CreateProposalCreate a proposal with message hash, quorum, and dWallet reference
1CastVoteRecord a vote; when quorum reached, CPI-calls approve_message

Proposal Layout (195 bytes)

disc(1) + version(1) + proposal_id(32) + dwallet(32) + message_hash(32) +
user_pubkey(32) + signature_scheme(1) + creator(32) + yes_votes(4) +
no_votes(4) + quorum(4) + status(1) + message_approval_bump(1) +
bump(1) + _reserved(16)

Key Offsets

FieldOffsetSizeType
yes_votes1634u32 LE
no_votes1674u32 LE
quorum1714u32 LE
status17510=Open, 1=Approved

CPI Flow

When yes_votes >= quorum, the program:

  1. Reads message hash, user pubkey, and signature scheme from the Proposal account
  2. Constructs a DWalletContext with the CPI authority PDA
  3. Calls ctx.approve_message(...) which creates a MessageApproval PDA on the dWallet program
  4. Sets proposal status to Approved

The caller then sends a gRPC Sign request with ApprovalProof::Solana { transaction_signature, slot } to obtain the actual signature.

E2E Flow

1. gRPC DKG          → dWallet created on-chain, authority = caller
2. Transfer authority → CPI PDA owns the dWallet
3. Create proposal    → quorum=3, message="Transfer 100 USDC"
4. Cast 3 YES votes   → last vote triggers approve_message CPI
5. Verify approval    → MessageApproval PDA exists, status=Pending
6. gRPC presign       → allocate presign
7. gRPC sign          → 64-byte signature returned

Testing

# Mollusk (instruction-level, no infrastructure needed)
cargo test -p ika-example-voting-pinocchio --test mollusk
cargo test -p ika-example-voting-native --test mollusk

# TypeScript E2E (requires validator + mock)
cd chains/solana/examples/voting/e2e && bun main.ts <DWALLET_ID> <VOTING_ID>

Source Files

  • Pinocchio: chains/solana/examples/voting/pinocchio/src/lib.rs
  • Native: chains/solana/examples/voting/native/src/lib.rs
  • Anchor: chains/solana/examples/voting/anchor/src/lib.rs
  • TypeScript E2E: chains/solana/examples/voting/e2e/main.ts