feat: add GetCapabilities MWA 2.0 method#277
feat: add GetCapabilities MWA 2.0 method#277mstevens843 wants to merge 1 commit intomagicblock-labs:mainfrom
Conversation
The MWA 2.0 spec defines get_capabilities as a non-privileged method that queries wallet capabilities. This method did not exist in the SDK. Added GetCapabilities() to the MWA client layer: - IAdapterOperations.cs: added GetCapabilities() interface method - MobileWalletAdapterClient.cs: sends get_capabilities JSON-RPC request - SolanaMobileWalletAdapter.cs: async wrapper via LocalAssociationScenario - CapabilitiesResult.cs: response model (MaxTransactionsPerRequest, MaxMessagesPerRequest, SupportedTransactionVersions, Features) Tested on Solana Seeker with Phantom — returns real values: maxTransactions=10, maxMessages=1, supportedVersions=[legacy, 0], features=[supports_sign_and_send_transactions] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
WalkthroughA new Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@Runtime/codebase/SolanaMobileStack/JsonRpcClient/Responses/CapabilitiesResult.cs`:
- Around line 18-24: CapabilitiesResult's collection properties
SupportedTransactionVersions and Features can be deserialized as null and cause
NREs; update the property declarations in the CapabilitiesResult class to
initialize both SupportedTransactionVersions and Features to empty List<string>
instances (e.g., new List<string>()) so consumers can safely iterate without
null checks and keep the existing JsonProperty/RequiredMember attributes intact.
In `@Runtime/codebase/SolanaMobileStack/SolanaMobileWalletAdapter.cs`:
- Around line 191-208: The method captures a CapabilitiesResult into the local
variable capabilities via LocalAssociationScenario.StartAndExecute/
GetCapabilities but may return null even when result.WasSuccessful; after the
call to StartAndExecute and the success check, add a null guard for the
capabilities variable (from this method's local “capabilities”) and handle it
consistently—either throw a descriptive Exception or log an error with
Debug.LogError and throw (e.g., "Capabilities payload was null after successful
association")—so callers never receive a null CapabilitiesResult.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 4e9512e0-7855-4ee6-a1a5-218cc1c3b5a7
📒 Files selected for processing (5)
Runtime/codebase/SolanaMobileStack/Interfaces/IAdapterOperations.csRuntime/codebase/SolanaMobileStack/JsonRpcClient/Responses/CapabilitiesResult.csRuntime/codebase/SolanaMobileStack/JsonRpcClient/Responses/CapabilitiesResult.cs.metaRuntime/codebase/SolanaMobileStack/MobileWalletAdapterClient.csRuntime/codebase/SolanaMobileStack/SolanaMobileWalletAdapter.cs
| [JsonProperty("supported_transaction_versions")] | ||
| [RequiredMember] | ||
| public List<string> SupportedTransactionVersions { get; set; } | ||
|
|
||
| [JsonProperty("features", NullValueHandling = NullValueHandling.Ignore)] | ||
| [RequiredMember] | ||
| public List<string> Features { get; set; } |
There was a problem hiding this comment.
Initialize collection properties to avoid null-driven crashes.
On Line 20 and Line 24, both lists can deserialize as null, which makes downstream iteration fragile. Prefer non-null defaults.
💡 Proposed fix
[JsonProperty("supported_transaction_versions")]
[RequiredMember]
- public List<string> SupportedTransactionVersions { get; set; }
+ public List<string> SupportedTransactionVersions { get; set; } = new();
[JsonProperty("features", NullValueHandling = NullValueHandling.Ignore)]
[RequiredMember]
- public List<string> Features { get; set; }
+ public List<string> Features { get; set; } = new();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| [JsonProperty("supported_transaction_versions")] | |
| [RequiredMember] | |
| public List<string> SupportedTransactionVersions { get; set; } | |
| [JsonProperty("features", NullValueHandling = NullValueHandling.Ignore)] | |
| [RequiredMember] | |
| public List<string> Features { get; set; } | |
| [JsonProperty("supported_transaction_versions")] | |
| [RequiredMember] | |
| public List<string> SupportedTransactionVersions { get; set; } = new(); | |
| [JsonProperty("features", NullValueHandling = NullValueHandling.Ignore)] | |
| [RequiredMember] | |
| public List<string> Features { get; set; } = new(); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@Runtime/codebase/SolanaMobileStack/JsonRpcClient/Responses/CapabilitiesResult.cs`
around lines 18 - 24, CapabilitiesResult's collection properties
SupportedTransactionVersions and Features can be deserialized as null and cause
NREs; update the property declarations in the CapabilitiesResult class to
initialize both SupportedTransactionVersions and Features to empty List<string>
instances (e.g., new List<string>()) so consumers can safely iterate without
null checks and keep the existing JsonProperty/RequiredMember attributes intact.
| CapabilitiesResult capabilities = null; | ||
| var localAssociationScenario = new LocalAssociationScenario(); | ||
| var result = await localAssociationScenario.StartAndExecute( | ||
| new List<Action<IAdapterOperations>> | ||
| { | ||
| async client => | ||
| { | ||
| capabilities = await client.GetCapabilities(); | ||
| } | ||
| } | ||
| ); | ||
| if (!result.WasSuccessful) | ||
| { | ||
| Debug.LogError(result.Error.Message); | ||
| throw new Exception(result.Error.Message); | ||
| } | ||
| return capabilities; | ||
| } |
There was a problem hiding this comment.
Guard against null capabilities payload before returning.
On Line 207, capabilities may still be null even when the scenario itself reports success, which can lead to downstream null dereferences.
🛡️ Proposed fix
if (!result.WasSuccessful)
{
Debug.LogError(result.Error.Message);
throw new Exception(result.Error.Message);
}
+ if (capabilities == null)
+ {
+ throw new Exception("get_capabilities returned an empty result.");
+ }
return capabilities;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| CapabilitiesResult capabilities = null; | |
| var localAssociationScenario = new LocalAssociationScenario(); | |
| var result = await localAssociationScenario.StartAndExecute( | |
| new List<Action<IAdapterOperations>> | |
| { | |
| async client => | |
| { | |
| capabilities = await client.GetCapabilities(); | |
| } | |
| } | |
| ); | |
| if (!result.WasSuccessful) | |
| { | |
| Debug.LogError(result.Error.Message); | |
| throw new Exception(result.Error.Message); | |
| } | |
| return capabilities; | |
| } | |
| CapabilitiesResult capabilities = null; | |
| var localAssociationScenario = new LocalAssociationScenario(); | |
| var result = await localAssociationScenario.StartAndExecute( | |
| new List<Action<IAdapterOperations>> | |
| { | |
| async client => | |
| { | |
| capabilities = await client.GetCapabilities(); | |
| } | |
| } | |
| ); | |
| if (!result.WasSuccessful) | |
| { | |
| Debug.LogError(result.Error.Message); | |
| throw new Exception(result.Error.Message); | |
| } | |
| if (capabilities == null) | |
| { | |
| throw new Exception("get_capabilities returned an empty result."); | |
| } | |
| return capabilities; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Runtime/codebase/SolanaMobileStack/SolanaMobileWalletAdapter.cs` around lines
191 - 208, The method captures a CapabilitiesResult into the local variable
capabilities via LocalAssociationScenario.StartAndExecute/ GetCapabilities but
may return null even when result.WasSuccessful; after the call to
StartAndExecute and the success check, add a null guard for the capabilities
variable (from this method's local “capabilities”) and handle it
consistently—either throw a descriptive Exception or log an error with
Debug.LogError and throw (e.g., "Capabilities payload was null after successful
association")—so callers never receive a null CapabilitiesResult.
The MWA 2.0 spec defines get_capabilities as a non-privileged method that queries wallet capabilities. This method did not exist in the SDK.
Added GetCapabilities() to the MWA client layer:
Tested on Solana Seeker with Phantom — returns real values: maxTransactions=10, maxMessages=1, supportedVersions=[legacy, 0], features=[supports_sign_and_send_transactions]
Problem
The MWA 2.0 spec defines get_capabilities as a non-privileged method for querying wallet limits and supported features. Without it, developers have no way to check how many transactions or messages a wallet can handle per request. Sending more than the wallet supports fails the entire request with
ERROR_TOO_MANY_PAYLOADS and there is no way to prevent it ahead of time.
Solution
Added GetCapabilities() across the MWA client layer following the same pattern as existing methods (authorize, signTransactions, signMessages):
Before & After Screenshots
BEFORE:
No method exists to query wallet capabilities. Developers must guess batch sizes or hardcode limits.
AFTER:
Tested on Solana Seeker with Phantom wallet:
Other changes (e.g. bug fixes, small refactors)
None. Self-contained addition.
Deploy Notes
No new dependencies, scripts, or configuration changes. Pure C# addition to the existing MWA client layer.
New scripts:
New dependencies:
Summary by CodeRabbit