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

dWallet Accounts

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 dWallet is an on-chain account that represents a distributed signing key. It is created through Distributed Key Generation (DKG) and stored as a PDA owned by the dWallet program.

DWallet Account Layout

DWallet PDA:
  Seeds: ["dwallet", curve_byte, public_key_bytes]
  Program: DWALLET_PROGRAM_ID
OffsetFieldSizeDescription
0discriminator1Account type identifier
1version11
2authority32Who can approve messages (user or CPI PDA)
34public_key65dWallet public key (padded to 65 bytes)
99public_key_len1Actual public key length (32 or 33)
100curve1Curve type identifier
101is_imported1Whether the key was imported vs created

The authority field determines who can call approve_message for this dWallet:

  • A user pubkey – the user signs the approve_message instruction directly
  • A CPI authority PDA – a program controls the dWallet via CPI

Creating a dWallet

dWallets are created through the gRPC API, not directly on-chain. The flow:

  1. User sends a DKG request via gRPC with their key share
  2. The Ika network runs the 2PC-MPC DKG protocol
  3. The NOA calls CommitDWallet on-chain to create the dWallet account
  4. The dWallet’s authority is set to the user
#![allow(unused)]
fn main() {
// Client-side: request DKG via gRPC
let request = DWalletRequest::DKG {
    dwallet_network_encryption_public_key: nek_bytes,
    curve: DWalletCurve::Secp256k1,
    centralized_public_key_share_and_proof: user_share,
    encrypted_centralized_secret_share_and_proof: encrypted_share,
    encryption_key: enc_key,
    user_public_output: user_output,
    signer_public_key: signer_pk,
};
}

Transferring Authority

To give a program control over a dWallet, transfer its authority to the program’s CPI authority PDA:

#![allow(unused)]
fn main() {
// Derive the CPI authority PDA for your program
let (cpi_authority, _) = Pubkey::find_program_address(
    &[b"__ika_cpi_authority"],
    &your_program_id,
);

// TransferOwnership instruction (called by current authority)
let ix = Instruction::new_with_bytes(
    dwallet_program_id,
    &transfer_data, // [IX_TRANSFER_OWNERSHIP, new_authority(32)]
    vec![
        AccountMeta::new_readonly(current_authority, true), // signer
        AccountMeta::new(dwallet_pda, false),               // writable
    ],
);
}

After transfer, the dWallet’s authority field equals the CPI authority PDA, and only the owning program can approve messages.

Via CPI (Program-to-Program Transfer)

If a program already controls a dWallet, it can transfer authority to another program’s CPI PDA:

#![allow(unused)]
fn main() {
let ctx = DWalletContext {
    dwallet_program,
    cpi_authority,
    caller_program,
    cpi_authority_bump,
};

ctx.transfer_dwallet(dwallet, new_authority)?;
}

Supported Curves

CurveIDKey SizeChains
Secp256k1033 bytes (compressed)Bitcoin, Ethereum, BSC
Secp256r1133 bytes (compressed)WebAuthn, Apple Secure Enclave
Curve25519232 bytesSolana, Sui, general Ed25519
Ristretto332 bytesSubstrate, Polkadot

Reading dWallet Data Off-Chain

The ika-solana-sdk-types crate provides PDA derivation helpers:

#![allow(unused)]
fn main() {
use ika_sdk_types::pda::*;

let (system_state, _) = find_system_state_address(&program_id);
let (validator, _) = find_validator_address(&program_id, &identity);
let (validator_list, _) = find_validator_list_address(&program_id);
}