Smart Wallets

Four-component wallet architecture using Motr Enclaves, DID Controllers, DWN Vaults as ServiceWorkers, and InterchainAccounts for unified blockchain interactions

Smart Wallets

Scope

This document covers Sonr's wallet architecture, including the four core components (Motr Enclaves, DID Controllers, DWN Vaults, InterchainAccounts), their integration patterns, and security models. It explains technical implementation, ServiceWorker architecture, and cross-chain capabilities. This document does not cover specific API implementations or deployment procedures—see the SDK reference for implementation details.

Audience

Developers building wallet integrations. System architects designing blockchain applications. Security engineers evaluating wallet architectures. Prerequisites: Understanding of WebAssembly, ServiceWorkers, DIDs, and basic blockchain concepts (especially IBC).

Summary

Sonr implements a four-component wallet architecture: Motr Enclaves provide secure WebAssembly computation, DID Controllers manage W3C-compliant identities, DWN Vaults run as ServiceWorkers for persistent data management, and InterchainAccounts enable cross-chain operations via IBC. These components integrate through a unified SDK, creating wallets that operate without seed phrases while maintaining user sovereignty.

Architecture Overview

Component Integration

The wallet architecture integrates four components:

Core Components

  1. Motr Enclave: WebAssembly-based secure computation environment
  2. DID Controller: W3C-compliant identity management system
  3. DWN Vault: ServiceWorker-based decentralized storage
  4. InterchainAccount: IBC-enabled cross-chain transaction executor

Technical Implementation

Motr Enclave

The Motr Enclave provides isolated computation:

interface MotrEnclave {
  // Computation
  executeContract(wasmCode: Uint8Array, input: any): Promise<any>;

  // MPC operations
  generateMPCShare(keyId: string): Promise<MPCShare>;
  reconstructKey(shares: MPCShare[]): Promise<CryptoKey>;

  // Cryptography
  sign(message: Uint8Array, keyId: string): Promise<Signature>;
  encrypt(data: Uint8Array, recipient: PublicKey): Promise<EncryptedData>;
  decrypt(encrypted: EncryptedData, keyId: string): Promise<Uint8Array>;

  // State management
  getVaultState(): Promise<VaultState>;
  updateVaultState(state: VaultState): Promise<void>;
}

Key features:

  • Sandboxed execution: WASM isolation for security
  • MPC integration: Distributed key management
  • Deterministic operations: Reproducible computations
  • Hardware security: Device feature integration

DID Controller

Manages W3C-compliant decentralized identities:

interface DIDController {
  // Identity operations
  createDID(options: DIDCreationOptions): Promise<DID>;
  updateDIDDocument(updates: DIDDocumentUpdate): Promise<void>;
  revokeDID(): Promise<void>;

  // Key management
  rotateKeys(newKeys: KeySet): Promise<void>;
  addVerificationMethod(method: VerificationMethod): Promise<void>;

  // Authentication
  authenticate(challenge: string): Promise<AuthenticationProof>;
  createVerifiableCredential(data: any): Promise<VerifiableCredential>;
  verifyCredential(credential: VerifiableCredential): Promise<boolean>;
}

DID Document structure follows W3C standards:

{
  "@context": ["https://www.w3.org/ns/did/v1"],
  "id": "did:sonr:alice123",
  "controller": "did:sonr:alice123",
  "verificationMethod": [
    {
      "id": "did:sonr:alice123#webauthn-1",
      "type": "WebAuthn2023",
      "controller": "did:sonr:alice123",
      "publicKeyWebAuthn": {
        "credentialId": "base64url...",
        "publicKey": "base64url..."
      }
    }
  ],
  "authentication": ["did:sonr:alice123#webauthn-1"],
  "service": [
    {
      "id": "did:sonr:alice123#vault",
      "type": "DWNVault",
      "serviceEndpoint": "https://vault.sonr.id/alice123"
    }
  ]
}

DWN Vault ServiceWorker

Implements decentralized storage as a ServiceWorker:

Background Processing

Runs independently of UI thread

Offline Operation

Functions without network connectivity

Persistent Storage

IndexedDB for local data persistence
class DWNVaultServiceWorker {
  private ipfsClient: IPFSClient;
  private storage: VaultStorage;
  private mpcEngine: MPCEngine;

  async handleVaultRequest(request: VaultRequest): Promise<VaultResponse> {
    switch (request.type) {
      case "store":
        return this.storeData(request.data, request.policy);
      case "retrieve":
        return this.retrieveData(request.cid, request.requester);
      case "authorize":
        return this.processAuthorization(request.ucanToken);
      case "execute":
        return this.executeCapability(request.capability, request.params);
    }
  }

  async storeData(data: any, policy: StoragePolicy): Promise<string> {
    // Encrypt data
    const encrypted = await this.encrypt(data);

    // Store locally
    const localCID = await this.storage.store(encrypted, policy);

    // Replicate to IPFS
    const ipfsCID = await this.ipfsClient.add(encrypted);
    await this.storage.updateReplication(localCID, ipfsCID);

    return localCID;
  }

  async executeTransaction(
    tx: CrossChainTransaction,
  ): Promise<TransactionResult> {
    // Validate capabilities
    if (!(await this.validateCapability(tx))) {
      throw new Error("Unauthorized transaction");
    }

    // Plan execution
    const plan = await this.planExecution(tx);

    // Execute steps
    const results = await Promise.all(
      plan.steps.map((step) => this.executeStep(step)),
    );

    // Store proof
    await this.storeExecutionProof(tx, results);

    return this.aggregateResults(results);
  }
}

ServiceWorker lifecycle management:

export class SonrWallet {
  private serviceWorker: ServiceWorkerRegistration;
  private didController: DIDController;
  private motrEnclave: MotrEnclave;
  private ica: InterchainAccount;

  async initialize(): Promise<void> {
    // Register ServiceWorker
    this.serviceWorker =
      await navigator.serviceWorker.register("/vault-worker.js");

    // Initialize DID Controller
    this.didController = await DIDController.create({
      webauthn: true,
      biometric: true,
    });

    // Start Motr Enclave
    this.motrEnclave = await MotrEnclave.load({
      wasmModule: "/motr.wasm",
      mpcConfig: await this.getMPCConfig(),
    });

    // Initialize ICA
    this.ica = await InterchainAccount.create({
      controller: this.didController.did,
    });

    // Connect components
    await this.connectComponents();
  }

  async performAction(action: WalletAction): Promise<ActionResult> {
    switch (action.domain) {
      case "identity":
        return this.didController.handle(action);
      case "storage":
        return this.sendToServiceWorker(action);
      case "computation":
        return this.motrEnclave.execute(action);
      case "transaction":
        return this.ica.execute(action);
    }
  }
}

InterchainAccount

Enables cross-chain operations via IBC:

interface InterchainAccount {
  // Account management
  createAccount(chainId: string): Promise<string>;
  getAccount(chainId: string): Promise<AccountInfo>;

  // Transactions
  executeRemoteTransaction(
    targetChain: string,
    transaction: Transaction,
  ): Promise<TransactionResult>;

  // Asset operations
  transferAssets(transfer: CrossChainTransfer): Promise<TransferResult>;
  queryBalance(chainId: string, denom: string): Promise<Balance>;

  // IBC operations
  createChannel(counterpartyChain: string): Promise<Channel>;
  sendPacket(packet: IBCPacket): Promise<PacketResult>;
}

Cross-chain transaction flow:

Wallet Operations

Account Creation

Wallet creation process:

export async function createSonrWallet(): Promise<SonrWallet> {
  // Create WebAuthn credential
  const credential = (await navigator.credentials.create({
    publicKey: {
      challenge: crypto.getRandomValues(new Uint8Array(32)),
      rp: { name: "Sonr Wallet" },
      user: {
        id: crypto.getRandomValues(new Uint8Array(32)),
        name: "user@example.com",
        displayName: "User",
      },
      pubKeyCredParams: [{ alg: -7, type: "public-key" }],
    },
  })) as PublicKeyCredential;

  // Generate DID
  const did = await generateDIDFromWebAuthn(credential);

  // Configure Vault
  const vaultConfig = await generateVaultConfig({
    did: did,
    mpcThreshold: 3,
    replicationFactor: 5,
  });

  // Submit claim transaction
  await submitClaimTransaction({
    creator: did,
    credential: credential,
    vaultCID: vaultConfig.cid,
  });

  // Initialize wallet
  const wallet = new SonrWallet();
  await wallet.initialize();

  return wallet;
}

Authorization Model

Capability-based permissions replace transaction signing:

interface ServiceAuthRequest {
  service: string;
  capabilities: {
    resource: string;
    actions: string[];
    constraints?: {
      amount?: string;
      frequency?: string;
      expires?: number;
    };
  }[];
}

// Request permission for DeFi operations
const defiAuth: ServiceAuthRequest = {
  service: "defi.example.com",
  capabilities: [
    {
      resource: "sonr://vault/alice123",
      actions: ["bank:send", "defi:lend", "defi:withdraw"],
      constraints: {
        amount: "10000000000uusdc", // 10,000 USDC limit
        frequency: "daily",
        expires: Date.now() + 30 * 24 * 60 * 60 * 1000, // 30 days
      },
    },
  ],
};

// User sees readable permission dialog
function presentAuthRequest(request: ServiceAuthRequest): UserDialog {
  const cap = request.capabilities[0];
  return {
    title: `${request.service} requests permissions`,
    description: `Access to ${cap.actions.join(", ")}`,
    limits: [
      `Maximum amount: ${formatAmount(cap.constraints.amount)}`,
      `Frequency: ${cap.constraints.frequency}`,
      `Expires: ${formatDate(cap.constraints.expires)}`,
    ],
  };
}

Advanced Features

Multi-Chain Operations

Unified asset management across chains:

class AssetManager {
  async getPortfolio(): Promise<Portfolio> {
    const chains = ["cosmos-hub", "osmosis", "ethereum"];

    const balances = await Promise.all(
      chains.map((chain) => this.getChainBalances(chain)),
    );

    return {
      totalValue: this.calculateTotalValue(balances),
      chains: balances,
      allocation: this.calculateAllocation(balances),
    };
  }

  async executeCrossChainTrade(trade: CrossChainTrade): Promise<void> {
    const sourceAccount = await this.ica.getAccount(trade.sourceChain);
    const targetAccount = await this.ica.getAccount(trade.targetChain);

    await this.ica.executeRemoteTransaction(trade.targetChain, {
      type: "swap",
      from: sourceAccount.address,
      to: targetAccount.address,
      amount: trade.amount,
      denom: trade.denom,
    });
  }
}

Smart Contract Interaction

Automated contract operations:

class ContractManager {
  async deployContract(
    chainId: string,
    bytecode: Uint8Array,
    constructor: any[],
  ): Promise<string> {
    const account = await this.ica.getAccount(chainId);

    const deployment = await this.ica.executeRemoteTransaction(chainId, {
      type: "deploy",
      from: account.address,
      bytecode: bytecode,
      constructor: constructor,
    });

    return deployment.contractAddress;
  }

  async scheduleContractCall(
    contract: string,
    method: string,
    params: any[],
    schedule: CallSchedule,
  ): Promise<void> {
    await this.vault.store({
      type: "scheduled_call",
      contract,
      method,
      params,
      schedule,
    });

    await this.serviceWorker.scheduleExecution(schedule);
  }
}

Privacy Features

Zero-knowledge proof integration:

class PrivacyManager {
  async createZKProof(statement: string, witness: any): Promise<ZKProof> {
    return this.motrEnclave.executeContract(this.zkProofWasm, {
      statement,
      witness,
    });
  }

  async proveBalance(minBalance: string, denom: string): Promise<BalanceProof> {
    const balance = await this.getBalance(denom);

    return this.createZKProof(`balance >= ${minBalance}`, {
      balance: balance.amount,
    });
  }
}

Integration Patterns

SDK Usage

Wallet SDK provides unified interface:

import { SonrWallet } from "@sonr/wallet-sdk";

// Connect wallet
const wallet = await SonrWallet.connect({
  autoConnect: true,
  preferredChains: ["cosmos-hub", "osmosis"],
});

// Request capabilities
const auth = await wallet.requestAuth({
  service: "app.example.com",
  capabilities: [
    {
      action: "bank:send",
      resource: "cosmos-hub",
      constraints: { maxAmount: "1000000uatom" },
    },
  ],
});

if (auth.approved) {
  // Execute transaction
  const result = await wallet.send({
    to: "cosmos1abc...",
    amount: "100000uatom",
    denom: "uatom",
    chain: "cosmos-hub",
  });
}

// Event handling
wallet.on("transaction", (tx) => {
  console.log("Transaction:", tx);
});

Platform Support

Consistent API across platforms:

// Web
import { SonrWallet } from "@sonr/wallet-web";

// React Native
import { SonrWallet } from "@sonr/wallet-react-native";

// Flutter
import "package:sonr_wallet/sonr_wallet.dart";

// iOS/Android native
// Swift: import SonrWallet
// Kotlin: import io.sonr.wallet.SonrWallet

Security Architecture

Security Layers

Multiple protection mechanisms:

Hardware Security

WebAuthn biometrics and hardware keys

MPC Protection

Distributed key management

Capability Limits

Time-bound permissions

Audit Trails

Cryptographic transaction logs

Threat Protection

interface SecurityFeatures {
  // Device security
  biometricAuth: boolean;
  hardwareKeys: boolean;
  deviceBinding: boolean;

  // Network security
  mpcKeySharding: boolean;
  encryptedComms: boolean;
  replayProtection: boolean;

  // User protection
  transactionLimits: boolean;
  cooldownPeriods: boolean;
  multiFactorAuth: boolean;

  // Service protection
  capabilityLimits: boolean;
  autoRevocation: boolean;
  emergencyFreeze: boolean;
}

Recovery Mechanisms

Migration from Existing Wallets

Migrate assets from traditional wallets:

class WalletMigration {
  async migrateFromMetaMask(): Promise<MigrationResult> {
    // Connect to source wallet
    const metamask = await this.connectMetaMask();

    // Inventory assets
    const assets = await this.inventoryAssets(metamask);

    // Create Sonr accounts
    const accounts = await this.createSonrAccounts(assets.chains);

    // Plan transfers
    const transfers = await this.planTransfers(assets, accounts);

    // Execute migration
    return this.executeMigration(transfers);
  }

  async recoverFromBackup(backup: WalletBackup): Promise<void> {
    // Verify backup
    if (!(await this.verifyBackup(backup))) {
      throw new Error("Invalid backup");
    }

    // Restore components
    await this.restoreDID(backup.did, backup.credentials);
    await this.restoreVault(backup.vaultConfig);
    await this.restoreMPCShares(backup.mpcShares);

    // Sync with network
    await this.syncWithNetwork();
  }
}

Social Recovery

Recover through trusted contacts:

interface SocialRecovery {
  guardians: Guardian[];
  threshold: number; // Required signatures
  recoveryDelay: number; // Time delay
}

class RecoveryManager {
  async initiateRecovery(lostDID: string): Promise<RecoverySession> {
    // Create session
    const session = await this.createRecoverySession(lostDID);

    // Notify guardians
    await this.notifyGuardians(session);

    // Start timer
    await this.startRecoveryCountdown(session);

    return session;
  }

  async completeRecovery(
    session: RecoverySession,
    signatures: Signature[],
  ): Promise<void> {
    // Verify signatures
    if (!(await this.verifyGuardianSignatures(session, signatures))) {
      throw new Error("Invalid signatures");
    }

    // Wait for delay
    await this.waitForRecoveryDelay(session);

    // Create new credentials
    const credentials = await this.createNewCredentials();

    // Update DID
    await this.updateDIDDocument(session.did, credentials);

    // Restore access
    await this.restoreWalletAccess(session.did, credentials);
  }
}

Performance Optimization

Batch Operations

Optimize transaction execution:

class PerformanceManager {
  async executeBatch(transactions: Transaction[]): Promise<BatchResult> {
    // Group by chain
    const chainGroups = this.groupByChain(transactions);

    // Parallel execution
    const results = await Promise.all(
      Object.entries(chainGroups).map(([chain, txs]) =>
        this.executeChainBatch(chain, txs),
      ),
    );

    return this.aggregateResults(results);
  }

  // Transaction templates
  async createTemplate(
    type: string,
    params: TemplateParams,
  ): Promise<TransactionTemplate> {
    const template = await this.motrEnclave.executeContract(this.templateWasm, {
      type,
      params,
    });

    await this.vault.store(`template_${type}`, template);
    return template;
  }
}

Caching Strategy

Intelligent data caching:

class CacheManager {
  private cache = new Map<string, CacheEntry>();

  async getCachedOrCompute<T>(
    key: string,
    computeFn: () => Promise<T>,
    ttl: number = 300000,
  ): Promise<T> {
    const cached = this.cache.get(key);

    if (cached && cached.expires > Date.now()) {
      return cached.value;
    }

    const value = await computeFn();

    this.cache.set(key, {
      value,
      expires: Date.now() + ttl,
    });

    return value;
  }
}

Best Practices

For Developers

  1. Use component abstractions: Leverage SDK instead of direct component access
  2. Handle capability denials: Gracefully manage permission rejections
  3. Batch operations: Group transactions for efficiency
  4. Monitor events: Listen for wallet state changes
  5. Test recovery flows: Ensure backup/recovery procedures work

For Security Engineers

  1. Audit permissions: Review capability requests carefully
  2. Monitor anomalies: Track unusual transaction patterns
  3. Implement rate limits: Prevent automated attacks
  4. Verify integrations: Audit third-party service connections

For Users

  1. Enable biometrics: Use hardware security features
  2. Set up guardians: Configure social recovery contacts
  3. Review permissions: Regularly audit granted capabilities
  4. Keep devices secure: Protect WebAuthn credentials

Next Steps

Ready to Integrate?

Developers: Start with the Wallet SDK Reference for implementation details.

Architects: Explore Integration Patterns for system design.

Security Engineers: Review Security Best Practices for deployment guidelines.