|
2 | 2 | title: Events
|
3 | 3 | ---
|
4 | 4 |
|
| 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 | + |
5 | 7 | ## AppKit Events
|
6 | 8 |
|
| 9 | +### Core Events |
| 10 | + |
7 | 11 | ```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 | +}; |
10 | 16 |
|
11 | 17 | // Invoked after successful connection of an account
|
12 | 18 | 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 | + } |
14 | 27 | };
|
15 | 28 |
|
16 | 29 | // Invoked after successful disconnection of an account
|
17 |
| -AppKit.AccountDisconnected += (sender, eventArgs) => { }; |
| 30 | +AppKit.AccountDisconnected += (sender, eventArgs) => { |
| 31 | + Debug.Log("Account disconnected"); |
| 32 | +}; |
18 | 33 |
|
19 | 34 | // 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 |
21 | 36 | AppKit.AccountChanged += (sender, eventArgs) => {
|
22 | 37 | Account newAccount = eventArgs.Account;
|
| 38 | + Debug.Log($"Account changed to: {newAccount.Address}"); |
23 | 39 | };
|
24 | 40 |
|
25 | 41 | // Invoked after active chain has changed
|
26 | 42 | 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 | + } |
28 | 155 | };
|
29 | 156 | ```
|
| 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