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

E2E Tests

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

E2E tests run the full dWallet lifecycle against Solana devnet and the pre-alpha dWallet gRPC service. This tests the complete flow including on-chain program execution, CPI, and signing.

Prerequisites

ResourceEndpoint
dWallet gRPChttps://pre-alpha-dev-1.ika.ika-network.net:443
Solana RPChttps://api.devnet.solana.com

Deploy your program to devnet, then run:

cargo run -p e2e-voting -- <DWALLET_PROGRAM_ID> <VOTING_PROGRAM_ID>

Override endpoints via environment variables:

RPC_URL=https://api.devnet.solana.com \
GRPC_URL=pre-alpha-dev-1.ika.ika-network.net:443 \
cargo run -p e2e-voting -- <DWALLET_PROGRAM_ID> <VOTING_PROGRAM_ID>

E2E Flow

The voting E2E demo performs 7 steps:

Step 1: Wait for Program Initialization

The mock signer creates:

  • DWalletCoordinator PDA (["dwallet_coordinator"]) – 116 bytes
  • NetworkEncryptionKey PDA (["network_encryption_key", noa_pubkey]) – 164 bytes
#![allow(unused)]
fn main() {
let (coordinator_pda, _) =
    Pubkey::find_program_address(&[b"dwallet_coordinator"], &dwallet_program_id);

poll_until(&client, &coordinator_pda, |data| {
    data.len() >= 116 && data[0] == 1 // DISC_COORDINATOR
}, Duration::from_secs(30));
}

Step 2: Create dWallet

The NOA commits a dWallet via CommitDWallet (discriminator 31):

#![allow(unused)]
fn main() {
let (dwallet_pda, dwallet_bump) = Pubkey::find_program_address(
    &[b"dwallet", &[curve], &public_key],
    &dwallet_program_id,
);
}

Step 3: Transfer Authority

Transfer dWallet authority to the voting program’s CPI PDA:

#![allow(unused)]
fn main() {
let (cpi_authority, _) = Pubkey::find_program_address(
    &[b"__ika_cpi_authority"],
    &voting_program_id,
);
}

Step 4: Create Proposal

Create a proposal with quorum = 3:

#![allow(unused)]
fn main() {
let message = b"Transfer 100 USDC to treasury";
let message_hash = keccak256(message);
}

Step 5: Cast 3 Votes

Three voters (Alice, Bob, Charlie) each cast YES. Charlie’s vote reaches quorum and triggers the approve_message CPI.

The last vote transaction includes 10 accounts (5 base + 5 CPI accounts).

Step 6: Verify MessageApproval

#![allow(unused)]
fn main() {
let ma_data = client.get_account(&message_approval_pda)?.data;
assert_eq!(ma_data[0], 14);  // discriminator
assert_eq!(ma_data[139], 0); // status = Pending
}

Step 7: Sign and Verify

The mock signer signs the message and calls CommitSignature (discriminator 43):

#![allow(unused)]
fn main() {
let signed_data = client.get_account(&message_approval_pda)?.data;
let sig_len = u16::from_le_bytes(signed_data[140..142].try_into().unwrap()) as usize;
let signature = &signed_data[142..142 + sig_len];
}

Key PDA Seeds

PDASeedsProgram
DWalletCoordinator["dwallet_coordinator"]dWallet
NetworkEncryptionKey["network_encryption_key", noa_pubkey]dWallet
DWallet["dwallet", curve, public_key]dWallet
MessageApproval["message_approval", dwallet, message_hash]dWallet
CPI Authority["__ika_cpi_authority"]Your program
Proposal["proposal", proposal_id]Voting
VoteRecord["vote", proposal_id, voter]Voting

Key Discriminators

InstructionDiscriminator
CreateProposal (voting)0
CastVote (voting)1
ApproveMessage (dWallet)8
TransferOwnership (dWallet)24
CommitDWallet (dWallet)31
CommitSignature (dWallet)43

Running the E2E Test

cargo run -p e2e-voting -- <DWALLET_PROGRAM_ID> <VOTING_PROGRAM_ID>

Expected output:

=== dWallet Voting E2E Demo ===

[Setup] Funding payer...
  > Payer: <pubkey>
[1/7] Creating dWallet via CommitDWallet...
  > dWallet created: <pubkey>
[2/7] Transferring dWallet authority to voting program...
  > Authority transferred to CPI PDA: <pubkey>
[3/7] Creating voting proposal (quorum=3)...
  > Proposal: <pubkey>
[4/7] Vote 1/3: Alice casts YES...
[4/7] Vote 2/3: Bob casts YES...
[4/7] Vote 3/3: Charlie casts YES...
  > Proposal approved (yes_votes=3)
[5/7] Verifying MessageApproval on-chain...
  > MessageApproval: <pubkey>
[6/7] Signing message with NOA key and committing on-chain...
  > Signature committed on-chain!
[7/7] Reading signature from MessageApproval...
  > Signature: <hex>

=== E2E Test Passed! ===