Delegation
ship opens it. undelegate unlocks the app; releaseStake frees the bond after the challenge window.
Until you delegate, the engine has nothing to write. The contract is a normal Monad contract. Delegation is the one on-chain transaction that opens the fast path. undelegate is the one that closes it.
import { keyOf } from "@interludelayer-sdk/sdk";
await interlude.delegateAll(ownerWallet);
// One instance on the engine, everyone else stays on Monad.
await interlude.delegateKey(ownerWallet, keyOf(userAddress));ship already sent delegateAll(). You only call it yourself for a second partition. The owner wallet is the contract owner, not the player.
When the session is done
Call undelegate on that partition. The lock lifts. The contract is ordinary Monad again, same address, with the settled state. The validator’s stake stays reserved through the challenge window (~1 hour on the deployed terms) so a bad batch and an immediate exit cannot walk away with the bond.
That reservation does not clear itself. After stakeUnlockAt, call releaseStake on the Hub (permissionless; anyone may send it). Before that time the call reverts with StakeStillLocked. The SDK does not wait out the window — use a keeper, or call it once the window has passed.
import { keyOf } from "@interludelayer-sdk/sdk";
await interlude.undelegate(ownerWallet); // whole contract
await interlude.undelegate(ownerWallet, keyOf(userAddress));
// After the challenge window (stakeUnlockAt):
await interlude.releaseStake(anyWallet);
await interlude.releaseStake(anyWallet, keyOf(userAddress));If the engine stops committing, anyone can forceClose the session. Silence cannot freeze the app. forceClose also enters the challenge window — it does not skip releaseStake.
