Skip to main content

App Session Methods

App sessions enable multi-party applications with custom governance rules, allowing complex interactions on top of payment channels.


Overview

App sessions are off-chain channels built on top of the unified balance, intended for app developers to create application-specific interactions. They act as a "box" or shared account where multiple participants can transfer funds and execute custom logic with governance rules.

Key Features

Multi-Party Governance: Define custom voting weights and quorum rules for state updates.

Application-Specific State: Store arbitrary application data (game state, escrow conditions, etc.).

Flexible Fund Management: Transfer, redistribute, add, or withdraw funds during session lifecycle.

Instant Updates: All state changes happen off-chain with zero gas fees.

For App Developers

App sessions are specifically designed for app developers building trustless multi-party applications like games, prediction markets, escrow, and collaborative finance.


Protocol Versions

App sessions support multiple protocol versions for backward compatibility.

Version Comparison

FeatureNitroRPC/0.2 (Legacy)NitroRPC/0.4 (Current)
State UpdatesBasic onlyIntent-based (OPERATE, DEPOSIT, WITHDRAW)
Add Funds to Active Session❌ No✅ Yes (DEPOSIT intent)
Remove Funds from Active Session❌ No✅ Yes (WITHDRAW intent)
Fund Redistribution✅ Yes✅ Yes (OPERATE intent)
Error HandlingBasicEnhanced validation
Modify Total FundsMust close & recreateCan update during session
Recommended ForLegacy support onlyAll new implementations
Protocol Version Selection

The protocol version is specified in the app definition during creation and cannot be changed for an existing session. Always use NitroRPC/0.4 for new app sessions.


create_app_session

Name

create_app_session

Usage

Creates a new virtual application session on top of the unified balance. An app session is a "box" or shared account where multiple participants can transfer funds and execute application-specific logic with custom governance rules. The app definition specifies participants, their voting weights, quorum requirements for state updates, and the protocol version. Funds are transferred from participants' unified balance accounts to a dedicated App Session Account for the duration of the session. App sessions enable complex multi-party applications like games, prediction markets, escrow, and collaborative finance—all operating off-chain with instant state updates and zero gas fees.

When to Use

When multiple participants need to interact with shared funds and application state in a trustless manner. Examples include turn-based games, betting pools, escrow arrangements, DAOs, prediction markets, and any application requiring multi-signature state management.

Prerequisites

  • All participants with non-zero initial allocations must be authenticated
  • All such participants must have sufficient available balance
  • All such participants must sign the creation request
  • Protocol version must be supported (NitroRPC/0.2 or NitroRPC/0.4)

Request

Quick Reference

Common structures: AppDefinitionAllocation

ParameterTypeRequiredDescriptionSee Also
definitionAppDefinitionYesConfiguration defining the app session rules and participants↓ Structure
allocationsAllocation[]YesInitial funds to transfer from participants' unified balance accounts↓ Structure
session_datastringNoApplication-specific initial state (JSON string, max 64KB recommended)
This is application-specific; protocol doesn't validate content

Session Identifier

app_session_id is derived deterministically from the entire App definition:

appSessionId = keccak256(JSON.stringify({
application: "...",
protocol: "NitroRPC/0.4",
participants: [...],
weights: [...],
quorum: 100,
challenge: 86400,
nonce: 123456
}))
  • Includes application, protocol, participants, weights, quorum, challenge, and nonce
  • Does not include chainId because sessions live entirely off-chain
  • Client can recompute locally to verify clearnode responses
  • nonce uniqueness is critical: same definition ⇒ same ID

Implementation reference: clearnode/app_session_service.go.

AppDefinition

FieldTypeRequiredDescriptionDefaultAllowed ValuesNotes
protocolstringYesProtocol version for this app session"NitroRPC/0.2" | "NitroRPC/0.4"Version cannot be changed after creation; use 0.4 for new sessions
participantsaddress[]YesArray of all participant wallet addressesMin: 2 participantsOrder is important - indices used for signatures and weights
Last participant often represents the application/judge
weightsint64[]YesVoting power for each participantLength must match participants array
Order corresponds to participants array
Absolute values matter for quorum; don't need to sum to 100
quorumuint64YesMinimum total weight required to approve state updatesSum of signers' weights must be ≥ quorum
challengeuint64NoChallenge period in seconds for disputes86400 (24 hours)Only relevant if app session state is ever checkpointed on-chain
nonceuint64YesUnique identifierTypically timestamp; ensures uniqueness

Example:

{
"protocol": "NitroRPC/0.4",
"participants": ["0x742d35Cc...", "0x8B3192f2...", "0x456789ab..."],
"weights": [50, 50, 100],
"quorum": 100,
"challenge": 3600,
"nonce": 1699123456789
}

Allocation

FieldTypeRequiredDescription
participantaddressYesParticipant wallet address (must be in definition.participants)
assetstringYesAsset identifier (e.g., "usdc")
amountstringYesAmount in human-readable format (e.g., "100.0")

Example:

[
{"participant": "0x742d35Cc...", "asset": "usdc", "amount": "100.0"},
{"participant": "0x8B3192f2...", "asset": "usdc", "amount": "100.0"},
{"participant": "0x456789ab...", "asset": "usdc", "amount": "0.0"}
]

Note: Participants with zero allocation don't need to sign creation.

Response

ParameterTypeDescriptionFormat/StructureExampleNotes
app_session_idstringUnique identifier for the created app session0x-prefixed hex string (32 bytes)"0x9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba"Use this for all subsequent operations on this session
statusstringApp session status"open""open"Values: "open" or "closed"
versionnumberCurrent state version11Always starts at 1

The Go service returns only these fields on creation. To fetch full metadata (application, participants, quorum, weights, session_data, protocol, challenge, nonce, timestamps), call get_app_sessions after creation.


Governance Models

App sessions support flexible governance through custom weights and quorum configurations.

Example 1: Simple Two-Player Game

Participants: [Alice, Bob]
Weights: [1, 1]
Quorum: 2

Result: Both players must sign every state update
Use case: Chess, poker, betting between two parties

Governance: Cooperative - both parties must agree to all changes.

Example 2: Game with Judge

Participants: [Alice, Bob, Judge]
Weights: [0, 0, 100]
Quorum: 100

Result: Only judge can update state
Use case: Games where application determines outcome

Governance: Authoritative - application/judge has full control.

Example 3: Multi-Party Escrow

Participants: [Buyer, Seller, Arbiter]
Weights: [40, 40, 50]
Quorum: 80

Result: Any 2 parties can approve
- Buyer + Seller (80)
- Buyer + Arbiter (90)
- Seller + Arbiter (90)
Use case: Escrowed transactions with dispute resolution

Governance: Flexible 2-of-3 - any two can proceed, preventing single-party blocking.

Example 4: DAO-like Voting

Participants: [User1, User2, User3, User4, Contract]
Weights: [20, 25, 30, 25, 0]
Quorum: 51

Result: Majority of weighted votes required (51 out of 100)
Use case: Collaborative funds management

Governance: Weighted majority - decisions require majority approval by stake.

Example 5: Watch Tower

Participants: [Alice, Bob, WatchTower]
Weights: [40, 40, 100]
Quorum: 80

Result:
- Normal operation: Alice + Bob (80)
- Emergency: WatchTower alone (100)
Use case: Automated monitoring and intervention

Governance: Dual-mode - normal requires cooperation, emergency allows automated action.

Governance Flexibility

By adjusting weights and quorum, you can implement any governance model from fully cooperative (all must sign) to fully authoritative (single party controls) to complex weighted voting systems.


Fund Transfer Mechanics

When an app session is created, funds are transferred from the unified balance account to a dedicated App Session Account:

Balance State Changes:

Before Creation:
Alice's Unified Account:
Balance: 200 USDC

After Creating Session with 100 USDC:
Alice's Unified Account:
Balance: 100 USDC

App Session Account:
Balance: 100 USDC (Beneficiary: Alice)

Signature Requirements

All participants with non-zero initial allocations MUST sign the create_app_session request. The clearnode validates that:

  1. All required signatures are present
  2. Signatures are valid for respective participants
  3. Total weight of signers >= quorum (must be met for creation)

submit_app_state

Name

submit_app_state

Usage

Submits a state update for an active app session. State updates can redistribute funds between participants (OPERATE intent), add funds to the session (DEPOSIT intent), or remove funds from the session (WITHDRAW intent). The intent system is only available in NitroRPC/0.4; version 0.2 sessions only support fund redistribution without explicit intent. Each state update increments the version number, and must be signed by participants whose combined weights meet the quorum requirement. The allocations field always represents the FINAL state after the operation, not the delta.

When to Use

During app session lifecycle to update the state based on application logic. Examples include recording game moves, updating scores, reallocating funds based on outcomes, adding stakes, or partially withdrawing winnings.

Prerequisites

  • App session must exist and be in "open" status
  • Signers must meet quorum requirement
  • For DEPOSIT intent: Depositing participant must sign (in addition to quorum)
  • For DEPOSIT intent: Depositing participant must have sufficient available balance
  • For WITHDRAW intent: Session must have sufficient funds to withdraw
  • NitroRPC/0.4: version must be exactly current_version + 1
  • NitroRPC/0.2: omit intent and version (service rejects them); only OPERATE-style redistribution is supported
  • If using a session key, spending allowances for that key are enforced

Request

ParameterTypeRequiredDescriptionFormatExampleNotes / See Also
app_session_idstringYesIdentifier of the app session to update0x-prefixed hex string (32 bytes)"0x9876543210fedcba..."-
intentstringYes for v0.4, No for v0.2Type of operation (NitroRPC/0.4 only)Allowed: "operate" | "deposit" | "withdraw""operate"Omit for NitroRPC/0.2 sessions (treated as operate)
versionnumberYesExpected next version number-2Must be exactly currentVersion + 1; prevents conflicts
allocationsAllocation[]YesFINAL allocation state after this update

⚠️ IMPORTANT: This is the target state, NOT the delta
See Allocation aboveAfter operate from [100, 100] where Alice loses 25 to Bob:
[{"participant": "0xAlice", "asset": "usdc", "amount": "75.0"}, {"participant": "0xBob", "asset": "usdc", "amount": "125.0"}]
Clearnode validates based on intent rules (see below)
session_datastringNoUpdated application-specific stateJSON string"{\"currentMove\":\"e2e4\",\"turn\":\"black\"}"Can be updated independently of allocations

Response

ParameterTypeDescriptionFormat/StructureExampleNotes
app_session_idstringSession identifier (echoed)---
versionnumberConfirmed new version number-2-
statusstringUpdated session status"open""open"Minimal response (no metadata echoed)

The Go handler returns an AppSessionResponse type, but for state submissions it only includes app_session_id, version, and status (and does not echo session metadata). Use get_app_sessions to read the full session record.


Intent System (NitroRPC/0.4)

The intent system defines the type of operation being performed. Each intent has specific validation rules.

Intent: OPERATE (Redistribute Existing Funds)

Purpose: Move funds between participants without changing total amount in session.

Rules:

  • Sum of allocations MUST equal sum before operation
  • No funds added or removed from session
  • Quorum requirement MUST be met
  • Depositing participant signature NOT required

Example:

Current state (version 1):
Alice: 100 USDC
Bob: 100 USDC
Total: 200 USDC

Update (version 2, intent: "operate"):
Allocations: [
{"participant": "0xAlice", "asset": "usdc", "amount": "75.0"},
{"participant": "0xBob", "asset": "usdc", "amount": "125.0"}
]

Result:
Alice: 75 USDC (-25)
Bob: 125 USDC (+25)
Total: 200 USDC (unchanged)

Validation: Sum before (200) == Sum after (200)

Use Cases:

  • Record game outcome (winner gets opponent's stake)
  • Update prediction market positions
  • Rebalance shared pool
  • Penalize or reward participants
OPERATE Intent

Use OPERATE for simple fund redistributions within the session. The total amount remains constant—funds just move between participants.


Intent: DEPOSIT (Add Funds to Session)

Purpose: Add funds from a participant's unified balance into the session.

Rules:

  • Sum of allocations MUST be greater or equal to sum before operation
  • Increase MUST come from available balance of depositing participant
  • Depositing participant MUST sign (even if quorum is met without them)
  • Quorum requirement MUST still be met
  • Allocations show FINAL amounts (not delta)
  • If signed via a session key, spending caps for that key are enforced

Example:

Current state (version 1):
Alice: 100 USDC
Bob: 100 USDC
Total: 200 USDC

Alice's Unified Balance:
Available: 50 USDC

Update (version 2, intent: "deposit"):
Allocations: [
{"participant": "0xAlice", "asset": "usdc", "amount": "150.0"},
{"participant": "0xBob", "asset": "usdc", "amount": "100.0"}
]
Signatures: [AliceSig, QuorumSigs...]

Calculation:
Alice deposit amount = 150 (new) - 100 (old) = 50 USDC

Result:
Alice: 150 USDC (100 + 50 deposited)
Bob: 100 USDC (unchanged)
Total: 250 USDC (+50)

Alice's Unified Balance After:
Available: 0 USDC (50 transferred to App Session Account)

App Session Account After:
Balance: 250 USDC (increased by 50)

Validation:
- Sum after (250) > Sum before (200)
- Alice signed ✓
- Alice had 50 available ✓

Use Cases:

  • Top up game stake mid-game
  • Add collateral to escrow
  • Increase position in prediction market
  • Buy into ongoing game
DEPOSIT Intent

Critical Understanding: The allocations array shows FINAL amounts, not the deposit amount. The clearnode calculates the deposit by comparing previous and new allocations for each participant.


Intent: WITHDRAW (Remove Funds from Session)

Purpose: Remove funds from session back to a participant's unified balance.

Rules:

  • Sum of allocations MUST be less or equal to sum before operation
  • Decrease is returned to participant's available balance
  • Withdrawing participant signature NOT specifically required (quorum sufficient)
  • Quorum requirement MUST be met
  • Allocations show FINAL amounts (not delta)

Example:

Current state (version 1):
Alice: 150 USDC
Bob: 100 USDC
Total: 250 USDC

Update (version 2, intent: "withdraw"):
Allocations: [
{"participant": "0xAlice", "asset": "usdc", "amount": "150.0"},
{"participant": "0xBob", "asset": "usdc", "amount": "75.0"}
]
Signatures: [QuorumSigs...]

Calculation:
Bob withdrawal amount = 100 (old) - 75 (new) = 25 USDC

Result:
Alice: 150 USDC (unchanged)
Bob: 75 USDC (100 - 25 withdrawn)
Total: 225 USDC (-25)

Bob's Unified Balance After:
Available: +25 USDC

App Session Account After:
Balance: 225 USDC (decreased by 25)

Validation:
- Sum after (225) < Sum before (250)
- Quorum met ✓

Use Cases:

  • Cash out partial winnings mid-game
  • Remove collateral when no longer needed
  • Take profits from shared investment
  • Reduce stake in ongoing game

Version Management

  • NitroRPC/0.4: each update MUST be exactly previous_version + 1, or it is rejected.
  • NitroRPC/0.2: omit intent and version; providing either results in "incorrect request: specified parameters are not supported in this protocol".

Quorum Validation

For every update, the clearnode validates quorum:

Validation Logic:

totalWeight = sum of weights for all signers
if (totalWeight >= definition.quorum) {
Update accepted
} else {
Reject: "Quorum not met"
}

Example (using Game with Judge scenario):

Participants: [Alice, Bob, Judge]
Weights: [0, 0, 100]
Quorum: 100

Valid signature combinations:
- Judge alone: weight = 100 >= 100
- Alice + Bob: weight = 0 >= 100
- Alice + Bob + Judge: weight = 100 >= 100

close_app_session

Name

close_app_session

Usage

Closes an active app session and distributes all funds from the App Session Account according to the final allocations. Once closed, the app session cannot be reopened; participants must create a new session if they want to continue. The final allocations determine how funds are returned to each participant's unified balance account. Closing requires quorum signatures. The final session_data can record the outcome or final state of the application. All funds in the App Session Account are released immediately.

When to Use

When application logic has completed and participants want to finalize the outcome and retrieve their funds. Examples include game ending, escrow condition met, prediction market settled, or any application reaching its natural conclusion.

Prerequisites

  • App session must exist and be in "open" status
  • Signers must meet quorum requirement
  • Final allocations must not exceed total funds in session
  • Sum of final allocations must equal total session funds

Request

ParameterTypeRequiredDescriptionFormat/StructureExampleNotes
app_session_idstringYesIdentifier of the app session to close0x-prefixed hex string (32 bytes)"0x9876543210fedcba..."-
allocationsAllocation[]YesFinal distribution of all funds in the session

IMPORTANT: Must account for ALL funds; sum must equal session total

Structure (per allocation):
participant (address) - Participant wallet address
asset (string) - Asset identifier
amount (string) - Final amount for this participant
See structure200 USDC total, winner takes most:
[{"participant": "0xAlice", "asset": "usdc", "amount": "180.0"}, {"participant": "0xBob", "asset": "usdc", "amount": "15.0"}, {"participant": "0xJudge", "asset": "usdc", "amount": "5.0"}]
Can allocate zero to participants (they get nothing)
session_datastringNoFinal application state or outcome recordJSON string"{\"result\":\"Alice wins\",\"finalScore\":\"3-1\"}"Useful for recording outcome for history/analytics

Response

ParameterTypeDescriptionFormat/StructureExampleNotes
app_session_idstringSession identifier (echoed)---
statusstringFinal statusValue: "closed""closed"Minimal response
versionnumberNew session version-2Incremented on close
close_app_session response

The handler returns an AppSessionResponse type in Go, but on close it only populates app_session_id, status, and version. For full metadata after closure, query get_app_sessions.


Fund Distribution on Closure

When an app session closes, funds return to participants' unified balances:

Before Closure:
Alice's Unified Account:
Balance: 100 USDC

App Session Account 0x98765:
Alice: 100 USDC
Bob: 100 USDC
Total: 200 USDC

Close with final allocations:
Alice: 180 USDC
Bob: 20 USDC

After Closure:
Alice's Unified Account:
Balance: 280 USDC (100 + 180 received from session)

Bob's Unified Account:
Balance: 20 USDC (received from session)

App Session Account 0x98765:
Closed (Balance: 0 USDC)

Allocation Rules

  1. Must Sum to Total:

    • sum(final_allocations) MUST equal sum(current_allocations)
    • Clearnode validates this; cannot create or destroy funds during close
  2. Can Be Zero:

    • Participants can receive zero in final allocation (lost everything)
    • Example: Losing player in a winner-takes-all game
  3. Accounting for Participants:

    • It is recommended to include an entry for every participant (use zero for losers).
    • If you omit a participant, the service treats them as receiving zero, as long as per-asset totals still match the session balance.
  4. Can Include Non-Financial Participants:

    • Example: Judge/application can receive commission
    • {"participant": "0xJudge", "asset": "usdc", "amount": "5.0"}

Closure Examples

Example 1: Chess Game

Initial:
White: 100 USDC
Black: 100 USDC
Judge: 0 USDC
Total: 200 USDC

Final (White wins):
White: 190 USDC (won 90)
Black: 0 USDC (lost 100)
Judge: 10 USDC (5% commission)
Total: 200 USDC

Example 2: Escrow (Buyer Satisfied)

Initial:
Buyer: 100 USDC
Seller: 0 USDC
Arbiter: 0 USDC
Total: 100 USDC

Final (Successful delivery):
Buyer: 0 USDC
Seller: 99 USDC (payment)
Arbiter: 1 USDC (fee)
Total: 100 USDC

Example 3: Escrow (Dispute, Buyer Refunded)

Initial:
Buyer: 100 USDC
Seller: 0 USDC
Arbiter: 0 USDC
Total: 100 USDC

Final (Arbiter ruled for buyer):
Buyer: 95 USDC (refund minus fee)
Seller: 0 USDC
Arbiter: 5 USDC (dispute fee)
Total: 100 USDC

Example 4: Prediction Market

Initial:
User1: 50 USDC (bet YES)
User2: 50 USDC (bet YES)
User3: 40 USDC (bet NO)
Oracle: 0 USDC
Total: 140 USDC

Final (Outcome: YES):
User1: 68.25 USDC (split pot proportionally)
User2: 68.25 USDC
User3: 0 USDC (lost)
Oracle: 3.50 USDC (2.5% fee)
Total: 140 USDC
Final Distribution

All participants receive funds according to the final allocations, whether they won, lost, or served as neutral parties (judges, arbiters, oracles). The total is always preserved.



Implementation Notes

State Management:

  • Always use intent: "operate" for simple redistributions
  • Always specify FINAL allocations, never deltas
  • The clearnode computes deltas internally by comparing with previous state
  • Version numbers must be strictly sequential
  • The session_data field can be updated in any intent

Performance:

  • Updates are instant (< 1 second) and off-chain
  • Zero gas fees for all operations
  • All updates are logged for audit trail

Notifications:

  • Participants are notified on all active connections of state changes
  • Closed sessions remain queryable for history

Irreversibility:

  • Closure is instant and atomic
  • All funds released simultaneously
  • Once closed, cannot be reopened
  • To continue, create a new session

Next Steps

Explore other protocol features:

For foundational concepts: