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
| Resource | Endpoint |
|---|---|
| dWallet gRPC | https://pre-alpha-dev-1.ika.ika-network.net:443 |
| Solana RPC | https://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
| PDA | Seeds | Program |
|---|---|---|
| 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
| Instruction | Discriminator |
|---|---|
| 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! ===