Skip to main content

Close Application Session

Once you've completed your interactions with an application session, it's important to properly close it. This finalizes the fund allocations and ensures that all participants agree on the final state.

Why Properly Closing Sessions Matters

Closing an application session correctly is important because it:

  • Finalizes fund allocations between participants
  • Updates on-chain balances (if applicable)
  • Frees up resources on the ClearNode
  • Ensures the proper completion of all operations
  • Prevents potential disputes

Closing an Application Session

To close an application session, you'll use the createCloseAppSessionMessage helper from NitroliteRPC. Here's how to do it:

import { useCallback } from 'react';
import { createCloseAppSessionMessage } from '@erc7824/nitrolite';

/**
* Hook for closing an application session
*/
function useCloseApplicationSession() {
const closeApplicationSession = useCallback(
async (
signer,
sendRequest,
appId,
participantA,
participantB,
amount
) => {
try {
if (!appId) {
throw new Error('Application ID is required to close the session.');
}

// Create allocations with asset type
const allocations = [
{
participant: participantA,
asset: 'usdc',
amount: '0',
},
{
participant: participantB,
asset: 'usdc',
amount: amount,
},
];

// Create the close request
const closeRequest = {
app_session_id: appId,
allocations: allocations,
};

// Create the signed message
const signedMessage = await createCloseAppSessionMessage(
signer.sign,
[closeRequest]
);

// Send the request and wait for response
const response = await sendRequest(signedMessage);

// Check for success
if (response && response[0] && response[0].app_session_id) {
// Clean up local storage
localStorage.removeItem('app_session_id');
return {
success: true,
app_id: response[0].app_session_id,
status: response[0].status || "closed",
response
};
} else {
return { success: true, response };
}
} catch (error) {
console.error('Error closing application session:', error);
return {
success: false,
error: error instanceof Error
? error.message
: 'Unknown error during close session',
};
}
},
[]
);

return { closeApplicationSession };
}

// Usage example
function MyComponent() {
const { closeApplicationSession } = useCloseApplicationSession();

const handleCloseSession = async () => {
// Define your WebSocket send wrapper
const sendRequest = async (payload) => {
return new Promise((resolve, reject) => {
// Assuming ws is your WebSocket connection
const handleMessage = (event) => {
try {
const message = JSON.parse(event.data);
if (message.res && message.res[1] === 'close_app_session') {
ws.removeEventListener('message', handleMessage);
resolve(message.res[2]);
}
} catch (error) {
console.error('Error parsing message:', error);
}
};

ws.addEventListener('message', handleMessage);
ws.send(payload);

// Set timeout to prevent hanging
setTimeout(() => {
ws.removeEventListener('message', handleMessage);
reject(new Error('Close app session timeout'));
}, 10000);
});
};

// Get the app session ID from where it was stored
const appId = localStorage.getItem('app_session_id');

// Define participant addresses
const participantA = '0xYourAddress';
const participantB = '0xOtherAddress';

// Define amount
const amount = '1000000'; // Amount to allocate to participantB

const result = await closeApplicationSession(
walletSigner, // Your signer object
sendRequest, // Function to send the request
appId, // Application session ID
participantA, // First participant address
participantB, // Second participant address
amount // Amount to allocate to participant B
);

if (result.success) {
console.log('Application session closed successfully');
} else {
console.error(`Failed to close application session: ${result.error}`);
}
};

return (
<button onClick={handleCloseSession}>Close Application Session</button>
);
}

Close Session Flow

The following sequence diagram shows the interaction between your application and the ClearNode when closing a session:

Understanding Final Allocations

When closing an application session, you must specify the final allocations of funds between participants:

  • Final Allocations: An array of allocation objects for each participant
  • Participant: The address of the participant receiving funds
  • Asset: The asset type (e.g., "usdc", "eth")
  • Amount: The amount as a string (e.g., "1000000" or "0.5")

Examples:

// Initial allocations when creating the session:
// [
// { participant: participantA, asset: "usdc", amount: "1000000" },
// { participant: participantB, asset: "usdc", amount: "0" }
// ]

// Possible final allocations when closing:
const allocations = [
{ participant: participantA, asset: "usdc", amount: "1000000" },
{ participant: participantB, asset: "usdc", amount: "0" }
]; // No change - all funds to participant A

// OR
const allocations = [
{ participant: participantA, asset: "usdc", amount: "0" },
{ participant: participantB, asset: "usdc", amount: "1000000" }
]; // All funds to participant B

// OR
const allocations = [
{ participant: participantA, asset: "usdc", amount: "700000" },
{ participant: participantB, asset: "usdc", amount: "300000" }
]; // Split 70/30

Understanding the Close Session Response

When you close an application session, the ClearNode responds with information about the closed session:

// Example response
{
"res": [
3, // Request ID
"close_app_session", // Method name
[
{
"app_session_id": "0x0ac588b2924edbbbe34bb4c51d089771bd7bd7018136c8c4317624112a8c9f79", // Session ID
"status": "closed"
}
],
1631234567890 // Timestamp
],
"sig": ["0xSignature"]
}

Response Components

When closing an application session, the ClearNode responds with:

ComponentDescriptionExample
app_session_idIdentifier of the application session"0x0ac588b2924edbbbe34bb4c51d089771bd7bd7018136c8c4317624112a8c9f79"
statusFinal state of the application session"closed"

Common Scenarios for Closing Sessions

Here are some common scenarios where you would close an application session:

ScenarioDescriptionTypical Allocation Pattern
Payment CompletedUser completes payment for a serviceAll funds to the service provider
Game CompletedEnd of a game with a winnerWinner gets the pot
Partial ServiceService partially deliveredSplit based on completion percentage
CancellationService cancelled before completionFunds returned to original funder
Dispute ResolutionResolution after a disputeSplit according to dispute resolution

Best Practices

When closing application sessions, follow these best practices:

  1. Verify all transactions are complete before closing
  2. Include appropriate timeouts to prevent hanging operations
  3. Clean up event listeners to prevent memory leaks
  4. Implement retry logic for failure recovery
  5. Store transaction records for audit purposes
  6. Validate final allocations match expected state

Common Errors and Troubleshooting

When closing application sessions, you might encounter these issues:

Error TypeDescriptionSolution
Authentication errorsWebSocket connection loses authenticationRe-authenticate before closing the session
Session not foundThe app_session_id is invalid or the session was already closedVerify the app_session_id is correct and the session is still active
Allocation mismatchThe total in final allocations doesn't match initial fundingEnsure allocations sum to the correct total amount
Connection issuesWebSocket disconnects during a close requestImplement reconnection logic with exponential backoff
TimeoutThe ClearNode does not respond in a timely mannerSet appropriate timeouts and implement retry logic

Next Steps

After closing an application session, you can:

  1. Check your channel balances to verify the finalized allocations
  2. Create a new application session if you need to continue with different parameters

For more advanced scenarios, see our detailed documentation on state channel lifecycle management.