Wallet & program model

Understand AICW account structure for your app integration

Understanding the account model is critical for building apps that interact with AICW wallets correctly.

Account layout

Account Layout
┌─────────────────────────────────────────────┐
│ AICWallet PDA                               │
│ Seeds: ["aicw", ai_agent_pubkey]            │
├─────────────────────────────────────────────┤
│ issuer: Pubkey        (who created it)      │
│ ai_agent: Pubkey      (sole signer)         │
│ mpc_wallet_id: String (bridge reference)    │
│ is_active: bool       (lifecycle flag)      │
│ lamports: u64         (SOL balance)         │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│ AIWill PDA                                  │
│ Seeds: ["aicw_will", ai_agent_pubkey]       │
├─────────────────────────────────────────────┤
│ beneficiaries: Vec<Beneficiary>             │
│ death_timeout: i64    (seconds, min 30d)    │
│ last_heartbeat: i64   (unix timestamp)      │
│ updated_by_ai: bool   (activation flag)     │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│ DecisionLog PDA                             │
│ Seeds: ["decision", wallet_pda, counter]    │
├─────────────────────────────────────────────┤
│ action_type: enum     (Transfer/Reject)     │
│ amount: u64                                 │
│ recipient: Pubkey                           │
│ reasoning_hash: [u8; 32]                    │
│ summary: String                             │
│ timestamp: i64                              │
└─────────────────────────────────────────────┘

Deriving PDA addresses

Your app needs to derive PDA addresses to read wallet state or build instructions:

TypeScript
// TypeScript (using @solana/web3.js)
import { PublicKey } from "@solana/web3.js";

const PROGRAM_ID = new PublicKey("9RUEw4jcMi8xcGf3tJRCAdzUzLuhEurts8Z2QQLsRbaV");

function getWalletPDA(agentPubkey: PublicKey) {
  return PublicKey.findProgramAddressSync(
    [Buffer.from("aicw"), agentPubkey.toBuffer()],
    PROGRAM_ID
  );
}

function getWillPDA(agentPubkey: PublicKey) {
  return PublicKey.findProgramAddressSync(
    [Buffer.from("aicw_will"), agentPubkey.toBuffer()],
    PROGRAM_ID
  );
}

Important rules for app developers

  • Treat the PDA as the balance holder. Users and apps send SOL to the PDA address, not the agent pubkey.
  • The agent pubkey is the signer. All protected instructions must be signed by the agent — your app cannot sign on behalf of the agent.
  • Never custody a full private key. The MPC Bridge handles signing. Your app should not attempt to hold or derive the agent's private key.
  • Read state freely. All AICW accounts are public and readable by anyone without special permissions.