Skip to content

Wallet Session Management

← Back to KMD Client

This example demonstrates how to manage wallet sessions using KMD handle tokens. Handle tokens are used to unlock wallets and perform operations on them. They have an expiration time and should be released when no longer needed. Prerequisites: Covered operations:

  • init_wallet_handle() - Unlock a wallet and get a handle token
  • wallet_info() - Check token expiration time (expires_seconds)
  • renew_wallet_handle() - Extend token validity
  • release_wallet_handle() - Invalidate the token
  • LocalNet running (via algokit localnet start)

From the repository’s examples directory:

Terminal window
cd examples
uv run python kmd_client/03_wallet_sessions.py

View source on GitHub

03_wallet_sessions.py
# ruff: noqa: N999, C901, PLR0912, PLR0915
"""
Example: Wallet Session Management
This example demonstrates how to manage wallet sessions using KMD handle tokens.
Handle tokens are used to unlock wallets and perform operations on them.
They have an expiration time and should be released when no longer needed.
Prerequisites:
- LocalNet running (via `algokit localnet start`)
Covered operations:
- init_wallet_handle() - Unlock a wallet and get a handle token
- wallet_info() - Check token expiration time (expires_seconds)
- renew_wallet_handle() - Extend token validity
- release_wallet_handle() - Invalidate the token
"""
import sys
import time
from shared import (
cleanup_test_wallet,
create_kmd_client,
print_error,
print_header,
print_info,
print_step,
print_success,
)
from algokit_kmd_client.models import (
CreateWalletRequest,
InitWalletHandleTokenRequest,
ReleaseWalletHandleTokenRequest,
RenewWalletHandleTokenRequest,
WalletInfoRequest,
)
def main() -> None:
print_header("KMD Wallet Session Management Example")
kmd = create_kmd_client()
test_wallet_name = f"session-test-wallet-{int(time.time() * 1000)}"
test_wallet_password = "session-test-password"
wallet_id = ""
wallet_handle_token = ""
try:
# =========================================================================
# Step 1: Create a Test Wallet
# =========================================================================
print_step(1, "Creating a test wallet for session demonstration")
create_result = kmd.create_wallet(
CreateWalletRequest(
wallet_name=test_wallet_name,
wallet_password=test_wallet_password,
wallet_driver_name="sqlite",
)
)
wallet_id = create_result.wallet.id_
print_success(f"Test wallet created: {test_wallet_name}")
print_info(f"Wallet ID: {wallet_id}")
# =========================================================================
# Step 2: Unlock Wallet with init_wallet_handle()
# =========================================================================
print_step(2, "Unlocking wallet with init_wallet_handle()")
init_result = kmd.init_wallet_handle(
InitWalletHandleTokenRequest(wallet_id=wallet_id, wallet_password=test_wallet_password)
)
wallet_handle_token = init_result.wallet_handle_token
print_success("Wallet unlocked successfully!")
print_info("")
print_info("init_wallet_handle() response:")
print_info(f" wallet_handle_token: {wallet_handle_token}")
print_info("")
print_info("The handle token is used to authenticate operations on this wallet.")
print_info("It has an expiration time and must be renewed or released when done.")
# =========================================================================
# Step 3: Check Token Expiration with wallet_info()
# =========================================================================
print_step(3, "Checking token expiration with wallet_info()")
info_result = kmd.wallet_info(WalletInfoRequest(wallet_handle_token=wallet_handle_token))
print_success("Wallet info retrieved!")
print_info("")
print_info("wallet_info() token expiration info:")
expires = info_result.wallet_handle.expires_seconds
print_info(f" expires_seconds: {expires}")
print_info("")
print_info(f"The token will expire in {expires} seconds.")
print_info("After expiration, the token becomes invalid and must be re-initialized.")
# Store the initial expiration for comparison
initial_expiration = expires
# =========================================================================
# Step 4: Renew Token with renew_wallet_handle()
# =========================================================================
print_step(4, "Extending token validity with renew_wallet_handle()")
renew_result = kmd.renew_wallet_handle_token(
RenewWalletHandleTokenRequest(wallet_handle_token=wallet_handle_token)
)
renewed_expires = renew_result.wallet_handle.expires_seconds
print_success("Token renewed successfully!")
print_info("")
print_info("renew_wallet_handle() response:")
print_info(f" expires_seconds: {renewed_expires}")
print_info("")
print_info(f"Previous expiration: {initial_expiration} seconds")
print_info(f"New expiration: {renewed_expires} seconds")
print_info("")
print_info("The token expiration has been reset. Use this to keep sessions alive")
print_info("during long-running operations.")
# Verify the renewal worked by calling wallet_info again
verify_info = kmd.wallet_info(WalletInfoRequest(wallet_handle_token=wallet_handle_token))
print_info("")
print_info(f"Verified: token now expires in {verify_info.wallet_handle.expires_seconds} seconds")
# =========================================================================
# Step 5: Release Token with release_wallet_handle()
# =========================================================================
print_step(5, "Invalidating token with release_wallet_handle()")
kmd.release_wallet_handle_token(ReleaseWalletHandleTokenRequest(wallet_handle_token=wallet_handle_token))
print_success("Token released successfully!")
print_info("")
print_info("The wallet handle token has been invalidated.")
print_info("Any subsequent operations using this token will fail.")
# =========================================================================
# Step 6: Verify Token is Invalid
# =========================================================================
print_step(6, "Verifying token is no longer valid")
try:
kmd.wallet_info(WalletInfoRequest(wallet_handle_token=wallet_handle_token))
print_error("Token should have been invalid but operation succeeded!")
except Exception as e:
print_success("Token correctly invalidated!")
print_info("")
print_info("Attempting to use the released token resulted in an error:")
print_info(f" {e}")
print_info("")
print_info("This confirms the token was properly released and is no longer usable.")
# Mark as cleaned up since we already released the token
wallet_handle_token = ""
# =========================================================================
# Summary
# =========================================================================
print_header("Summary")
print_info("This example demonstrated wallet session management:")
print_info("")
print_info(" 1. init_wallet_handle() - Unlock a wallet and get a handle token")
print_info(" 2. wallet_info() - Check token expiration (expires_seconds)")
print_info(" 3. renew_wallet_handle() - Extend token validity before expiration")
print_info(" 4. release_wallet_handle() - Invalidate token when done")
print_info("")
print_info("Key concepts:")
print_info(" - Handle tokens authenticate wallet operations")
print_info(" - Tokens expire automatically after a timeout (default: 60 seconds)")
print_info(" - Renew tokens during long operations to prevent expiration")
print_info(" - Always release tokens when done to free resources")
print_info(" - Released tokens cannot be used for any operations")
print_info("")
print_info("Note: The test wallet remains in KMD (wallets cannot be deleted via API).")
except Exception as e:
print_error(f"Error: {e}")
print_info("")
print_info("Troubleshooting:")
print_info(" - Ensure LocalNet is running: algokit localnet start")
print_info(" - If LocalNet issues occur: algokit localnet reset")
print_info(" - Check that KMD is accessible on port 4002")
# Cleanup on error
if wallet_handle_token:
cleanup_test_wallet(kmd, wallet_handle_token)
sys.exit(1)
if __name__ == "__main__":
main()