Skip to content

Commit 413330e

Browse files
Improve Unity AppKit events documentation
- Add comprehensive coverage of all 5 main AppKit events - Include SignClient Unity events for advanced use cases - Document all event argument types and their properties - Add best practices for event subscription and cleanup - Include platform considerations for WebGL vs native - Provide practical code examples with proper error handling - Fix ChainChanged event example to use correct NewChain property - Add common use cases for UI updates and connection management Co-Authored-By: gleb@reown.com <gleb@skibitsky.com>
1 parent fadd8a0 commit 413330e

File tree

1 file changed

+243
-6
lines changed

1 file changed

+243
-6
lines changed

appkit/unity/core/events.mdx

Lines changed: 243 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,265 @@
22
title: Events
33
---
44

5+
AppKit Unity provides a comprehensive event system that allows you to respond to various state changes in your application. All events are automatically dispatched on Unity's main thread, making them safe to use for UI updates.
6+
57
## AppKit Events
68

9+
### Core Events
10+
711
```csharp
8-
//Invoked after successful initialization of AppKit
9-
AppKit.Initialized += (sender, eventArgs) => { };
12+
// Invoked after successful initialization of AppKit
13+
AppKit.Initialized += (sender, eventArgs) => {
14+
Debug.Log("AppKit initialized successfully");
15+
};
1016

1117
// Invoked after successful connection of an account
1218
AppKit.AccountConnected += (sender, eventArgs) => {
13-
Account activeAccount = eventArgs.GetAccount();
19+
Account activeAccount = eventArgs.Account;
20+
Debug.Log($"Account connected: {activeAccount.Address}");
21+
22+
// Access all connected accounts
23+
foreach (var account in eventArgs.Accounts)
24+
{
25+
Debug.Log($"Available account: {account.Address} on {account.ChainId}");
26+
}
1427
};
1528

1629
// Invoked after successful disconnection of an account
17-
AppKit.AccountDisconnected += (sender, eventArgs) => { };
30+
AppKit.AccountDisconnected += (sender, eventArgs) => {
31+
Debug.Log("Account disconnected");
32+
};
1833

1934
// Invoked after account has changed
20-
// This happens when the wallet updates a session or the user changes the active chain.
35+
// This happens when the wallet updates a session or the user changes the active account
2136
AppKit.AccountChanged += (sender, eventArgs) => {
2237
Account newAccount = eventArgs.Account;
38+
Debug.Log($"Account changed to: {newAccount.Address}");
2339
};
2440

2541
// Invoked after active chain has changed
2642
AppKit.ChainChanged += (sender, eventArgs) => {
27-
Chain newChain = eventArgs.Chain;
43+
Chain previousChain = eventArgs.PreviousChain;
44+
Chain newChain = eventArgs.NewChain;
45+
46+
Debug.Log($"Chain changed from {previousChain?.Name} to {newChain?.Name}");
47+
Debug.Log($"New chain ID: {newChain?.ChainId}");
48+
};
49+
```
50+
51+
## SignClient Unity Events
52+
53+
For advanced use cases, you can also subscribe to lower-level SignClient events through `AppKit.Instance.SignClient`:
54+
55+
```csharp
56+
// Subscribe to SignClient Unity events
57+
AppKit.Instance.SignClient.SessionConnectedUnity += (sender, session) => {
58+
Debug.Log($"Session connected: {session.Topic}");
59+
};
60+
61+
AppKit.Instance.SignClient.SessionUpdatedUnity += (sender, session) => {
62+
Debug.Log($"Session updated: {session.Topic}");
63+
};
64+
65+
AppKit.Instance.SignClient.SessionDisconnectedUnity += (sender, eventArgs) => {
66+
Debug.Log("Session disconnected");
67+
};
68+
69+
AppKit.Instance.SignClient.SessionRequestSentUnity += (sender, sessionRequest) => {
70+
Debug.Log($"Session request sent: {sessionRequest.Id}");
71+
};
72+
```
73+
74+
## Event Arguments
75+
76+
### InitializeEventArgs
77+
Empty event arguments indicating successful initialization.
78+
79+
### AccountConnectedEventArgs
80+
- `Account Account` - The currently active connected account
81+
- `IEnumerable<Account> Accounts` - All connected accounts
82+
- `Func<Task<Account>> GetAccountAsync` - (Deprecated) Use Account property instead
83+
- `Func<Task<Account[]>> GetAccountsAsync` - (Deprecated) Use Accounts property instead
84+
85+
### AccountDisconnectedEventArgs
86+
Empty event arguments indicating account disconnection.
87+
88+
### AccountChangedEventArgs
89+
- `Account Account` - The new active account
90+
91+
### ChainChangedEventArgs
92+
- `Chain PreviousChain` - The previously active chain (can be null)
93+
- `Chain NewChain` - The newly active chain
94+
95+
## Best Practices
96+
97+
### Event Subscription and Cleanup
98+
99+
Always unsubscribe from events to prevent memory leaks:
100+
101+
```csharp
102+
public class WalletManager : MonoBehaviour
103+
{
104+
private void OnEnable()
105+
{
106+
// Subscribe to events
107+
AppKit.AccountConnected += OnAccountConnected;
108+
AppKit.AccountDisconnected += OnAccountDisconnected;
109+
AppKit.ChainChanged += OnChainChanged;
110+
}
111+
112+
private void OnDisable()
113+
{
114+
// Unsubscribe from events
115+
AppKit.AccountConnected -= OnAccountConnected;
116+
AppKit.AccountDisconnected -= OnAccountDisconnected;
117+
AppKit.ChainChanged -= OnChainChanged;
118+
}
119+
120+
private void OnAccountConnected(object sender, Connector.AccountConnectedEventArgs e)
121+
{
122+
// Handle account connection
123+
UpdateUI(e.Account);
124+
}
125+
126+
private void OnAccountDisconnected(object sender, Connector.AccountDisconnectedEventArgs e)
127+
{
128+
// Handle account disconnection
129+
ClearUI();
130+
}
131+
132+
private void OnChainChanged(object sender, NetworkController.ChainChangedEventArgs e)
133+
{
134+
// Handle chain change
135+
UpdateChainUI(e.NewChain);
136+
}
137+
}
138+
```
139+
140+
### Error Handling
141+
142+
Always wrap event handlers in try-catch blocks to prevent exceptions from breaking the event chain:
143+
144+
```csharp
145+
AppKit.AccountConnected += (sender, eventArgs) => {
146+
try
147+
{
148+
// Your event handling code
149+
UpdateAccountUI(eventArgs.Account);
150+
}
151+
catch (Exception ex)
152+
{
153+
Debug.LogError($"Error handling AccountConnected event: {ex.Message}");
154+
}
28155
};
29156
```
157+
158+
### Thread Safety
159+
160+
All AppKit events are automatically dispatched on Unity's main thread, making them safe for:
161+
- UI updates
162+
- GameObject manipulation
163+
- Component access
164+
165+
No additional thread synchronization is required.
166+
167+
## Platform Considerations
168+
169+
### WebGL vs Native
170+
171+
- **Native platforms** (iOS, Android, Desktop): Full event support with persistent storage
172+
- **WebGL**: All events work the same way, but storage is handled differently using PlayerPrefs
173+
174+
### SignClient Storage
175+
176+
The SignClient automatically handles storage differences between platforms:
177+
- **Native**: Uses file system storage at `Application.persistentDataPath/Reown/storage.json`
178+
- **WebGL**: Uses PlayerPrefs with Unity's synchronization context
179+
180+
## Common Use Cases
181+
182+
### Updating UI on Account Changes
183+
184+
```csharp
185+
public class AccountDisplay : MonoBehaviour
186+
{
187+
[SerializeField] private Text accountText;
188+
[SerializeField] private Text chainText;
189+
190+
private void OnEnable()
191+
{
192+
AppKit.AccountConnected += UpdateAccountDisplay;
193+
AppKit.AccountChanged += UpdateAccountDisplay;
194+
AppKit.ChainChanged += UpdateChainDisplay;
195+
AppKit.AccountDisconnected += ClearDisplay;
196+
}
197+
198+
private void OnDisable()
199+
{
200+
AppKit.AccountConnected -= UpdateAccountDisplay;
201+
AppKit.AccountChanged -= UpdateAccountDisplay;
202+
AppKit.ChainChanged -= UpdateChainDisplay;
203+
AppKit.AccountDisconnected -= ClearDisplay;
204+
}
205+
206+
private void UpdateAccountDisplay(object sender, Connector.AccountConnectedEventArgs e)
207+
{
208+
accountText.text = $"Account: {e.Account.Address}";
209+
}
210+
211+
private void UpdateChainDisplay(object sender, NetworkController.ChainChangedEventArgs e)
212+
{
213+
chainText.text = $"Chain: {e.NewChain?.Name ?? "Unknown"}";
214+
}
215+
216+
private void ClearDisplay(object sender, Connector.AccountDisconnectedEventArgs e)
217+
{
218+
accountText.text = "No account connected";
219+
chainText.text = "No chain selected";
220+
}
221+
}
222+
```
223+
224+
### Handling Connection State
225+
226+
```csharp
227+
public class ConnectionManager : MonoBehaviour
228+
{
229+
[SerializeField] private Button connectButton;
230+
[SerializeField] private Button disconnectButton;
231+
232+
private void OnEnable()
233+
{
234+
AppKit.AccountConnected += OnAccountConnected;
235+
AppKit.AccountDisconnected += OnAccountDisconnected;
236+
237+
// Set initial state
238+
UpdateButtonStates();
239+
}
240+
241+
private void OnDisable()
242+
{
243+
AppKit.AccountConnected -= OnAccountConnected;
244+
AppKit.AccountDisconnected -= OnAccountDisconnected;
245+
}
246+
247+
private void OnAccountConnected(object sender, Connector.AccountConnectedEventArgs e)
248+
{
249+
UpdateButtonStates();
250+
Debug.Log("Wallet connected successfully!");
251+
}
252+
253+
private void OnAccountDisconnected(object sender, Connector.AccountDisconnectedEventArgs e)
254+
{
255+
UpdateButtonStates();
256+
Debug.Log("Wallet disconnected");
257+
}
258+
259+
private void UpdateButtonStates()
260+
{
261+
bool isConnected = AppKit.IsAccountConnected;
262+
connectButton.gameObject.SetActive(!isConnected);
263+
disconnectButton.gameObject.SetActive(isConnected);
264+
}
265+
}
266+
```

0 commit comments

Comments
 (0)