Skip to main content

Auto-Sign: Eliminating Wallet Pop-ups for Real-Time Applications

4 min read

Every blockchain interaction that requires a wallet signature creates friction. In a turn-based game, you might tolerate one pop-up per move. But in a real-time game, you need dozens of signatures per minute, and each pop-up breaks the flow completely. Auto-sign fixes this by delegating non-financial signing to a session key: your wallet approves once, then the app signs on your behalf for the rest of the session.

On-chain chess game requiring wallet signature to play

The problem with wallet pop-ups

Blockchain games need cryptographic signatures to prove that a player authorized each action. Without auto-sign, every game move triggers a wallet confirmation dialog ("Sign this transaction?"). The result is an experience that feels nothing like a game and everything like filling out forms. Real-time gameplay is basically impossible under these conditions.

How auto-sign works

The core insight is separating two types of blockchain interactions:

  • Financial transactions (asset transfers, token minting, contract calls with value) always require explicit wallet approval
  • Non-financial data submissions (game moves, messages, state updates) can be safely delegated to a session key

When a player starts a session, their wallet generates a temporary key pair and signs a delegation certificate. This certificate authorizes the session key to submit non-financial data on the player's behalf. The session key is scoped (can only submit game data, never move funds), time-bounded (expires when the session ends), and revocable (the player can cancel delegation at any time).

This preserves the security guarantees players expect: nobody can move their assets without explicit approval. It just removes the friction that makes real-time apps unusable.

Implementation in @effectstream/wallets

Auto-sign lives in the @effectstream/wallets package, which provides multi-chain wallet support for EffectStream applications. The package handles the full delegation lifecycle: key generation, certificate signing, session management, and automatic signing of non-financial transactions.

The wallet layer supports multiple chains (EVM via injected providers and Ethers, Cardano, Midnight, Polkadot, Algorand, and Mina), and auto-sign works across all of them through a unified API. Developers don't need chain-specific signing logic; the framework handles the differences. Full reference is in the wallets documentation.

The three-step flow in Safe Solver is representative of every game on midnight.fun:

import {
WalletMode,
walletLogin,
allInjectedWallets,
} from "@effectstream/wallets";

// 1. Initialize a local session wallet, silent and persisted in
// encrypted browser storage. preferBatchedMode enables auto-sign.
const localWalletResult = await walletLogin({
mode: WalletMode.EvmEthers,
preferBatchedMode: true,
connection: {
metadata: { name: "session", displayName: "Session Wallet" },
api: await getLocalSignerFromStorage(),
},
});

// 2. Let the user connect their real wallet (Midnight Lace in this
// example) — this is the only step that shows a pop-up.
const injected = await allInjectedWallets({
signatureSupport: false,
transactionSupport: false,
});
const midnightWallet = injected[WalletMode.Midnight][0];
const realWalletResult = await walletLogin({
mode: WalletMode.Midnight,
preference: { name: midnightWallet.metadata.name },
});

// 3. One-time delegation: the real wallet signs a message
// authorising the session wallet to submit non-financial inputs
// on its behalf. After this point, gameplay is silent.
await effectStreamService.connectWallets(
localWalletResult.result,
realWalletResult.result,
);

// 4. Every subsequent game input is signed by the session wallet —
// no pop-ups for the rest of the session.
await sendGameMove({ move: "x10y20" });

The signing model is uniform regardless of chain: WalletMode.Midnight could be swapped for WalletMode.EvmInjected, WalletMode.Cardano, or any other supported chain and the rest of the flow stays the same.

Live on midnight.fun

Auto-sign is live and in production on midnight.fun, powering three games:

  • Safe Solver - a puzzle game where auto-sign lets you submit moves rapidly
  • Kachina Kolosseum - PvP combat where timing matters and pop-ups would ruin the experience
  • Block Kart Legends - racing where dozens of state updates happen per session

midnight.fun games portal showing Safe Solver, Kachina, and Block Kart with achievements and leaderboards

The difference is immediately noticeable. Players approve wallet access once when connecting, then play freely. A typical Safe Solver session generates 20-30 signatures, all handled by the session key in the background.

Before and after

Without auto-sign: Connect wallet → Start game → Pop-up → Approve → Make move → Pop-up → Approve → Make move → Pop-up → Approve → ... (player gives up after 3 moves)

With auto-sign: Connect wallet → Approve delegation → Play freely for the entire session → Done

The gameplay goes from "blockchain app with constant interruptions" to "normal game that happens to be on-chain." And it's not just games: chat apps, collaborative tools, IoT dashboards, anything that needs rapid interaction benefits from session key delegation. The security model (limited scope, time-bounded, revocable) applies to all of them.