Describe the bug
When a player explicitly taps Logout in my Unity Android game (SolRacer) and then relaunches the app, adapter restores Account state without restoring authorization state. Logout is supposed to end the session, but the wallet acts as if it never happened.
While investigating I found three related lifecycle inconsistencies in SolanaMobileWalletAdapter:
-
Logout() does not clear the in-memory _authToken, so within the same session subsequent signing operations may still attempt Reauthorize() using a token the player intended to revoke.
-
Logout() does not clearly define whether wallet-side authorization is revoked when keepConnectionAlive is enabled, which creates ambiguity between local adapter logout and transport-level session termination.
-
keepConnectionAlive = true restores PlayerPrefs["pk"] but does not restore _authToken, so on restart _Login() returns a cached account silently, while the first SignTransaction() call triggers a full Authorize() popup mid-gameplay instead of at login time.
To Reproduce
- Build a Unity Android game using
SolanaWalletAdapter with keepConnectionAlive = true
- Launch on an Android device with Phantom or Seeker installed
- Connect the wallet, complete the full
Authorize() flow, tap Approve in the wallet
- Tap Logout inside the game
- Kill the app completely and relaunch it
- Observe: the wallet reconnects silently with no authorization prompt shown
To reproduce the mid-gameplay popup (the keepConnectionAlive half-reconnect bug):
- Same setup, but skip the logout step, just kill and relaunch after connecting
- The app appears connected (no login prompt is shown)
- Trigger any on-chain transaction (e.g. submitting a race result)
- Observe: a full
Authorize() wallet approval sheet appears in the middle of gameplay
Expected behavior
After an explicit Logout, the next app launch should show the wallet authorization prompt. The player made an active choice to log out, the game should not silently reconnect them.
For the keepConnectionAlive case: if a cached session exists and is still valid, the reconnect should be fully silent including signing (via reauthorize). If it is not valid or was explicitly revoked, the full Authorize() prompt should appear at login time, not mid-session during a transaction.
Adapter lifecycle invariant:
If Account is restored from cached state when keepConnectionAlive = true,
then authorization state should also be restored (via reauthorize),
or the adapter should trigger authorization during login instead of deferring it
until the first signing request.
Screenshots
N/A, the issue is a missing wallet approval prompt that should appear but does not.
Smartphone
- Device: Solana Seeker (Android)
- OS: Android 14
- Wallet: Seeker Wallet / Phantom for Android
- Unity version: 2022.3 LTS
- Solana Unity SDK:
com.solana.unity_sdk (PackageCache hash cedf547211d1)
Additional context
The root cause is that IAdapterOperations and MobileWalletAdapterClient have no deauthorize RPC implementation. The Mobile Wallet Adapter spec defines authorize, reauthorize, and deauthorize as three distinct operations, the SDK only implements the first two. Without deauthorize, there is no way to implement correct logout behavior in a Unity game on top of this SDK without reimplementing the MWA transport layer yourself.
The specific lines where the gaps are:
// SolanaMobileWalletAdapter.cs Logout() never clears _authToken
public override void Logout()
{
base.Logout();
PlayerPrefs.DeleteKey("pk");
PlayerPrefs.Save();
// _authToken is never set to null here
}
// _Login() returns cached account but _authToken is null on restart
if (_walletOptions.keepConnectionAlive)
{
string pk = PlayerPrefs.GetString("pk", null);
if (!pk.IsNullOrEmpty()) return new Account(string.Empty, new PublicKey(pk));
// auth token is not restored first sign op will trigger full Authorize() again
}
// IAdapterOperations.cs no Deauthorize() method exists
public interface IAdapterOperations
{
Task<AuthorizationResult> Authorize(...);
Task<AuthorizationResult> Reauthorize(...);
Task<SignedResult> SignTransactions(...);
Task<SignedResult> SignMessages(...);
// Deauthorize() is missing
}
This affects any Unity game on Solana Mobile / Seeker that needs logout, player account switching, or multi-user device support.
Describe the bug
When a player explicitly taps Logout in my Unity Android game (SolRacer) and then relaunches the app, adapter restores Account state without restoring authorization state. Logout is supposed to end the session, but the wallet acts as if it never happened.
While investigating I found three related lifecycle inconsistencies in SolanaMobileWalletAdapter:
Logout() does not clear the in-memory _authToken, so within the same session subsequent signing operations may still attempt Reauthorize() using a token the player intended to revoke.
Logout() does not clearly define whether wallet-side authorization is revoked when keepConnectionAlive is enabled, which creates ambiguity between local adapter logout and transport-level session termination.
keepConnectionAlive = true restores PlayerPrefs["pk"] but does not restore _authToken, so on restart _Login() returns a cached account silently, while the first SignTransaction() call triggers a full Authorize() popup mid-gameplay instead of at login time.
To Reproduce
SolanaWalletAdapterwithkeepConnectionAlive = trueAuthorize()flow, tap Approve in the walletTo reproduce the mid-gameplay popup (the
keepConnectionAlivehalf-reconnect bug):Authorize()wallet approval sheet appears in the middle of gameplayExpected behavior
After an explicit Logout, the next app launch should show the wallet authorization prompt. The player made an active choice to log out, the game should not silently reconnect them.
For the
keepConnectionAlivecase: if a cached session exists and is still valid, the reconnect should be fully silent including signing (viareauthorize). If it is not valid or was explicitly revoked, the fullAuthorize()prompt should appear at login time, not mid-session during a transaction.Adapter lifecycle invariant:
If Account is restored from cached state when keepConnectionAlive = true,
then authorization state should also be restored (via reauthorize),
or the adapter should trigger authorization during login instead of deferring it
until the first signing request.
Screenshots
N/A, the issue is a missing wallet approval prompt that should appear but does not.
Smartphone
com.solana.unity_sdk(PackageCache hashcedf547211d1)Additional context
The root cause is that
IAdapterOperationsandMobileWalletAdapterClienthave nodeauthorizeRPC implementation. The Mobile Wallet Adapter spec definesauthorize,reauthorize, anddeauthorizeas three distinct operations, the SDK only implements the first two. Withoutdeauthorize, there is no way to implement correct logout behavior in a Unity game on top of this SDK without reimplementing the MWA transport layer yourself.The specific lines where the gaps are:
This affects any Unity game on Solana Mobile / Seeker that needs logout, player account switching, or multi-user device support.