@reown/appkit-core-react-native 2.0.0-alpha.0 → 2.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/lib/commonjs/controllers/ApiController.js +16 -5
  2. package/lib/commonjs/controllers/ApiController.js.map +1 -1
  3. package/lib/commonjs/controllers/AssetController.js.map +1 -1
  4. package/lib/commonjs/controllers/BlockchainApiController.js +103 -111
  5. package/lib/commonjs/controllers/BlockchainApiController.js.map +1 -1
  6. package/lib/commonjs/controllers/ConnectionController.js +1 -10
  7. package/lib/commonjs/controllers/ConnectionController.js.map +1 -1
  8. package/lib/commonjs/controllers/ConnectionsController.js +313 -52
  9. package/lib/commonjs/controllers/ConnectionsController.js.map +1 -1
  10. package/lib/commonjs/controllers/EnsController.js +4 -4
  11. package/lib/commonjs/controllers/EnsController.js.map +1 -1
  12. package/lib/commonjs/controllers/EventsController.js +4 -4
  13. package/lib/commonjs/controllers/EventsController.js.map +1 -1
  14. package/lib/commonjs/controllers/ModalController.js +6 -7
  15. package/lib/commonjs/controllers/ModalController.js.map +1 -1
  16. package/lib/commonjs/controllers/OnRampController.js +117 -53
  17. package/lib/commonjs/controllers/OnRampController.js.map +1 -1
  18. package/lib/commonjs/controllers/OptionsController.js +14 -0
  19. package/lib/commonjs/controllers/OptionsController.js.map +1 -1
  20. package/lib/commonjs/controllers/PublicStateController.js.map +1 -1
  21. package/lib/commonjs/controllers/RouterController.js +1 -22
  22. package/lib/commonjs/controllers/RouterController.js.map +1 -1
  23. package/lib/commonjs/controllers/SendController.js +101 -101
  24. package/lib/commonjs/controllers/SendController.js.map +1 -1
  25. package/lib/commonjs/controllers/SnackController.js +29 -5
  26. package/lib/commonjs/controllers/SnackController.js.map +1 -1
  27. package/lib/commonjs/controllers/SwapController.js +140 -147
  28. package/lib/commonjs/controllers/SwapController.js.map +1 -1
  29. package/lib/commonjs/controllers/ThemeController.js.map +1 -1
  30. package/lib/commonjs/controllers/TransactionsController.js +23 -19
  31. package/lib/commonjs/controllers/TransactionsController.js.map +1 -1
  32. package/lib/commonjs/index.js +0 -35
  33. package/lib/commonjs/index.js.map +1 -1
  34. package/lib/commonjs/package.json +1 -0
  35. package/lib/commonjs/utils/ApiUtil.js.map +1 -1
  36. package/lib/commonjs/utils/AssetUtil.js +3 -14
  37. package/lib/commonjs/utils/AssetUtil.js.map +1 -1
  38. package/lib/commonjs/utils/ConstantsUtil.js +122 -426
  39. package/lib/commonjs/utils/ConstantsUtil.js.map +1 -1
  40. package/lib/commonjs/utils/CoreHelperUtil.js +13 -8
  41. package/lib/commonjs/utils/CoreHelperUtil.js.map +1 -1
  42. package/lib/commonjs/utils/EventUtil.js.map +1 -1
  43. package/lib/commonjs/utils/FetchUtil.js +34 -10
  44. package/lib/commonjs/utils/FetchUtil.js.map +1 -1
  45. package/lib/commonjs/utils/RouterUtil.js.map +1 -1
  46. package/lib/commonjs/utils/StorageUtil.js +86 -92
  47. package/lib/commonjs/utils/StorageUtil.js.map +1 -1
  48. package/lib/commonjs/utils/SwapApiUtil.js +11 -22
  49. package/lib/commonjs/utils/SwapApiUtil.js.map +1 -1
  50. package/lib/commonjs/utils/SwapCalculationUtil.js.map +1 -1
  51. package/lib/commonjs/utils/TypeUtil.js +25 -0
  52. package/lib/commonjs/utils/TypeUtil.js.map +1 -1
  53. package/lib/module/controllers/ApiController.js +18 -6
  54. package/lib/module/controllers/ApiController.js.map +1 -1
  55. package/lib/module/controllers/AssetController.js +2 -0
  56. package/lib/module/controllers/AssetController.js.map +1 -1
  57. package/lib/module/controllers/BlockchainApiController.js +104 -110
  58. package/lib/module/controllers/BlockchainApiController.js.map +1 -1
  59. package/lib/module/controllers/ConnectionController.js +3 -10
  60. package/lib/module/controllers/ConnectionController.js.map +1 -1
  61. package/lib/module/controllers/ConnectionsController.js +314 -51
  62. package/lib/module/controllers/ConnectionsController.js.map +1 -1
  63. package/lib/module/controllers/EnsController.js +4 -2
  64. package/lib/module/controllers/EnsController.js.map +1 -1
  65. package/lib/module/controllers/EventsController.js +3 -1
  66. package/lib/module/controllers/EventsController.js.map +1 -1
  67. package/lib/module/controllers/ModalController.js +8 -7
  68. package/lib/module/controllers/ModalController.js.map +1 -1
  69. package/lib/module/controllers/OnRampController.js +118 -52
  70. package/lib/module/controllers/OnRampController.js.map +1 -1
  71. package/lib/module/controllers/OptionsController.js +16 -0
  72. package/lib/module/controllers/OptionsController.js.map +1 -1
  73. package/lib/module/controllers/PublicStateController.js +2 -0
  74. package/lib/module/controllers/PublicStateController.js.map +1 -1
  75. package/lib/module/controllers/RouterController.js +3 -22
  76. package/lib/module/controllers/RouterController.js.map +1 -1
  77. package/lib/module/controllers/SendController.js +100 -98
  78. package/lib/module/controllers/SendController.js.map +1 -1
  79. package/lib/module/controllers/SnackController.js +31 -5
  80. package/lib/module/controllers/SnackController.js.map +1 -1
  81. package/lib/module/controllers/SwapController.js +142 -147
  82. package/lib/module/controllers/SwapController.js.map +1 -1
  83. package/lib/module/controllers/ThemeController.js +2 -0
  84. package/lib/module/controllers/ThemeController.js.map +1 -1
  85. package/lib/module/controllers/TransactionsController.js +23 -17
  86. package/lib/module/controllers/TransactionsController.js.map +1 -1
  87. package/lib/module/index.js +2 -5
  88. package/lib/module/index.js.map +1 -1
  89. package/lib/module/utils/ApiUtil.js +2 -0
  90. package/lib/module/utils/ApiUtil.js.map +1 -1
  91. package/lib/module/utils/AssetUtil.js +5 -14
  92. package/lib/module/utils/AssetUtil.js.map +1 -1
  93. package/lib/module/utils/ConstantsUtil.js +124 -426
  94. package/lib/module/utils/ConstantsUtil.js.map +1 -1
  95. package/lib/module/utils/CoreHelperUtil.js +14 -6
  96. package/lib/module/utils/CoreHelperUtil.js.map +1 -1
  97. package/lib/module/utils/EventUtil.js +2 -0
  98. package/lib/module/utils/EventUtil.js.map +1 -1
  99. package/lib/module/utils/FetchUtil.js +36 -10
  100. package/lib/module/utils/FetchUtil.js.map +1 -1
  101. package/lib/module/utils/RouterUtil.js +2 -0
  102. package/lib/module/utils/RouterUtil.js.map +1 -1
  103. package/lib/module/utils/StorageUtil.js +89 -91
  104. package/lib/module/utils/StorageUtil.js.map +1 -1
  105. package/lib/module/utils/SwapApiUtil.js +13 -22
  106. package/lib/module/utils/SwapApiUtil.js.map +1 -1
  107. package/lib/module/utils/SwapCalculationUtil.js +2 -0
  108. package/lib/module/utils/SwapCalculationUtil.js.map +1 -1
  109. package/lib/module/utils/TypeUtil.js +25 -1
  110. package/lib/module/utils/TypeUtil.js.map +1 -1
  111. package/lib/typescript/controllers/ApiController.d.ts +2 -1
  112. package/lib/typescript/controllers/ApiController.d.ts.map +1 -1
  113. package/lib/typescript/controllers/BlockchainApiController.d.ts +20 -13
  114. package/lib/typescript/controllers/BlockchainApiController.d.ts.map +1 -1
  115. package/lib/typescript/controllers/ConnectionController.d.ts +3 -16
  116. package/lib/typescript/controllers/ConnectionController.d.ts.map +1 -1
  117. package/lib/typescript/controllers/ConnectionsController.d.ts +26 -22
  118. package/lib/typescript/controllers/ConnectionsController.d.ts.map +1 -1
  119. package/lib/typescript/controllers/ModalController.d.ts +1 -1
  120. package/lib/typescript/controllers/ModalController.d.ts.map +1 -1
  121. package/lib/typescript/controllers/OnRampController.d.ts +3 -2
  122. package/lib/typescript/controllers/OnRampController.d.ts.map +1 -1
  123. package/lib/typescript/controllers/OptionsController.d.ts +7 -2
  124. package/lib/typescript/controllers/OptionsController.d.ts.map +1 -1
  125. package/lib/typescript/controllers/RouterController.d.ts +4 -17
  126. package/lib/typescript/controllers/RouterController.d.ts.map +1 -1
  127. package/lib/typescript/controllers/SendController.d.ts +5 -7
  128. package/lib/typescript/controllers/SendController.d.ts.map +1 -1
  129. package/lib/typescript/controllers/SnackController.d.ts +3 -3
  130. package/lib/typescript/controllers/SnackController.d.ts.map +1 -1
  131. package/lib/typescript/controllers/SwapController.d.ts +12 -11
  132. package/lib/typescript/controllers/SwapController.d.ts.map +1 -1
  133. package/lib/typescript/controllers/TransactionsController.d.ts +3 -3
  134. package/lib/typescript/controllers/TransactionsController.d.ts.map +1 -1
  135. package/lib/typescript/index.d.ts +0 -5
  136. package/lib/typescript/index.d.ts.map +1 -1
  137. package/lib/typescript/utils/AssetUtil.d.ts +2 -3
  138. package/lib/typescript/utils/AssetUtil.d.ts.map +1 -1
  139. package/lib/typescript/utils/ConstantsUtil.d.ts +7 -414
  140. package/lib/typescript/utils/ConstantsUtil.d.ts.map +1 -1
  141. package/lib/typescript/utils/CoreHelperUtil.d.ts +5 -4
  142. package/lib/typescript/utils/CoreHelperUtil.d.ts.map +1 -1
  143. package/lib/typescript/utils/FetchUtil.d.ts.map +1 -1
  144. package/lib/typescript/utils/StorageUtil.d.ts +11 -15
  145. package/lib/typescript/utils/StorageUtil.d.ts.map +1 -1
  146. package/lib/typescript/utils/SwapApiUtil.d.ts +3 -3
  147. package/lib/typescript/utils/SwapApiUtil.d.ts.map +1 -1
  148. package/lib/typescript/utils/TypeUtil.d.ts +54 -177
  149. package/lib/typescript/utils/TypeUtil.d.ts.map +1 -1
  150. package/package.json +9 -23
  151. package/src/controllers/ApiController.ts +17 -4
  152. package/src/controllers/BlockchainApiController.ts +74 -119
  153. package/src/controllers/ConnectionController.ts +5 -28
  154. package/src/controllers/ConnectionsController.ts +399 -92
  155. package/src/controllers/EnsController.ts +2 -2
  156. package/src/controllers/EventsController.ts +1 -1
  157. package/src/controllers/ModalController.ts +7 -9
  158. package/src/controllers/OnRampController.ts +178 -81
  159. package/src/controllers/OptionsController.ts +22 -9
  160. package/src/controllers/RouterController.ts +4 -54
  161. package/src/controllers/SendController.ts +124 -113
  162. package/src/controllers/SnackController.ts +31 -5
  163. package/src/controllers/SwapController.ts +165 -181
  164. package/src/controllers/TransactionsController.ts +24 -18
  165. package/src/index.ts +0 -15
  166. package/src/utils/AssetUtil.ts +4 -18
  167. package/src/utils/ConstantsUtil.ts +125 -428
  168. package/src/utils/CoreHelperUtil.ts +30 -8
  169. package/src/utils/FetchUtil.ts +37 -10
  170. package/src/utils/StorageUtil.ts +165 -106
  171. package/src/utils/SwapApiUtil.ts +25 -42
  172. package/src/utils/TypeUtil.ts +64 -171
  173. package/lib/commonjs/controllers/AccountController.js +0 -93
  174. package/lib/commonjs/controllers/AccountController.js.map +0 -1
  175. package/lib/commonjs/controllers/ConnectorController.js +0 -50
  176. package/lib/commonjs/controllers/ConnectorController.js.map +0 -1
  177. package/lib/commonjs/controllers/NetworkController.js +0 -90
  178. package/lib/commonjs/controllers/NetworkController.js.map +0 -1
  179. package/lib/commonjs/controllers/WebviewController.js +0 -52
  180. package/lib/commonjs/controllers/WebviewController.js.map +0 -1
  181. package/lib/commonjs/utils/NetworkUtil.js +0 -46
  182. package/lib/commonjs/utils/NetworkUtil.js.map +0 -1
  183. package/lib/module/controllers/AccountController.js +0 -88
  184. package/lib/module/controllers/AccountController.js.map +0 -1
  185. package/lib/module/controllers/ConnectorController.js +0 -45
  186. package/lib/module/controllers/ConnectorController.js.map +0 -1
  187. package/lib/module/controllers/NetworkController.js +0 -85
  188. package/lib/module/controllers/NetworkController.js.map +0 -1
  189. package/lib/module/controllers/WebviewController.js +0 -47
  190. package/lib/module/controllers/WebviewController.js.map +0 -1
  191. package/lib/module/utils/NetworkUtil.js +0 -40
  192. package/lib/module/utils/NetworkUtil.js.map +0 -1
  193. package/lib/typescript/controllers/AccountController.d.ts +0 -33
  194. package/lib/typescript/controllers/AccountController.d.ts.map +0 -1
  195. package/lib/typescript/controllers/ConnectorController.d.ts +0 -18
  196. package/lib/typescript/controllers/ConnectorController.d.ts.map +0 -1
  197. package/lib/typescript/controllers/NetworkController.d.ts +0 -34
  198. package/lib/typescript/controllers/NetworkController.d.ts.map +0 -1
  199. package/lib/typescript/controllers/WebviewController.d.ts +0 -21
  200. package/lib/typescript/controllers/WebviewController.d.ts.map +0 -1
  201. package/lib/typescript/utils/NetworkUtil.d.ts +0 -8
  202. package/lib/typescript/utils/NetworkUtil.d.ts.map +0 -1
  203. package/src/controllers/AccountController.ts +0 -128
  204. package/src/controllers/ConnectorController.ts +0 -64
  205. package/src/controllers/NetworkController.ts +0 -120
  206. package/src/controllers/WebviewController.ts +0 -63
  207. package/src/utils/NetworkUtil.ts +0 -33
@@ -1,119 +1,221 @@
1
1
  import { proxy, ref } from 'valtio';
2
- import { derive } from 'valtio/utils';
3
- import type {
4
- AppKitNetwork,
5
- BlockchainAdapter,
6
- CaipAddress,
7
- CaipNetworkId,
8
- ChainNamespace,
9
- GetBalanceResponse,
10
- WalletInfo
2
+ import { derive } from 'derive-valtio';
3
+ import {
4
+ EVMAdapter,
5
+ type AppKitNetwork,
6
+ type BlockchainAdapter,
7
+ type CaipAddress,
8
+ type CaipNetworkId,
9
+ type ChainNamespace,
10
+ type Balance,
11
+ type WalletInfo,
12
+ type ConnectionProperties,
13
+ type AccountType,
14
+ type Connection,
15
+ SolanaBaseAdapter,
16
+ type Identity
11
17
  } from '@reown/appkit-common-react-native';
12
18
  import { StorageUtil } from '../utils/StorageUtil';
19
+ import { BlockchainApiController } from './BlockchainApiController';
20
+ import { SnackController } from './SnackController';
21
+ import { OptionsController } from './OptionsController';
22
+ import { CoreHelperUtil } from '../utils/CoreHelperUtil';
13
23
 
14
24
  // -- Types --------------------------------------------- //
15
- type Balance = GetBalanceResponse;
16
-
17
- //TODO: balance could be elsewhere
18
- interface Connection {
19
- accounts: CaipAddress[];
20
- balances: Record<CaipAddress, Balance>; //TODO: make this an array of balances
21
- adapter: BlockchainAdapter;
22
- chains: CaipNetworkId[];
23
- activeChain: CaipNetworkId;
24
- wallet?: WalletInfo;
25
- }
26
-
27
25
  export interface ConnectionsControllerState {
28
26
  activeNamespace?: ChainNamespace;
29
- connections: Record<string, Connection>;
27
+ connections: Map<ChainNamespace, Connection>;
30
28
  networks: AppKitNetwork[];
31
29
  }
32
30
 
33
31
  // -- State --------------------------------------------- //
34
32
  const baseState = proxy<ConnectionsControllerState>({
35
33
  activeNamespace: undefined,
36
- connections: {},
34
+ connections: new Map<ChainNamespace, Connection>(),
37
35
  networks: []
38
36
  });
39
37
 
38
+ // -- Helper Functions --------------------------------------------- //
39
+ const getActiveConnection = (snap: ConnectionsControllerState): Connection | undefined => {
40
+ if (!snap.activeNamespace) return undefined;
41
+
42
+ return snap.connections.get(snap.activeNamespace);
43
+ };
44
+
45
+ const hasValidAccounts = (connection: Connection): boolean => {
46
+ return connection?.accounts && connection.accounts.length > 0;
47
+ };
48
+
49
+ const findSmartAccountForNetwork = (connection: Connection): CaipAddress | undefined => {
50
+ return connection.properties?.smartAccounts?.find(account =>
51
+ account.startsWith(connection.caipNetwork)
52
+ );
53
+ };
54
+
55
+ const findEOAForNetwork = (connection: Connection): CaipAddress | undefined => {
56
+ const smartAccounts = connection.properties?.smartAccounts || [];
57
+
58
+ return connection.accounts.find(
59
+ account => account.startsWith(connection.caipNetwork) && !smartAccounts.includes(account)
60
+ );
61
+ };
62
+
63
+ const getActiveAddress = (connection: Connection): CaipAddress | undefined => {
64
+ if (!hasValidAccounts(connection)) {
65
+ return undefined;
66
+ }
67
+
68
+ // For smart accounts, prioritize smart account addresses
69
+ if (connection.type === 'smartAccount') {
70
+ const smartAccount = findSmartAccountForNetwork(connection);
71
+ if (smartAccount) {
72
+ return smartAccount;
73
+ }
74
+ }
75
+
76
+ // Fall back to EOA or any account that matches the network
77
+ return findEOAForNetwork(connection);
78
+ };
79
+
80
+ const updateConnection = (
81
+ namespace: ChainNamespace,
82
+ connection: Connection,
83
+ updates: Partial<Connection>
84
+ ) => {
85
+ if (!connection) return;
86
+ const newConnectionsMap = new Map(baseState.connections);
87
+ newConnectionsMap.set(namespace, { ...connection, ...updates });
88
+ baseState.connections = newConnectionsMap;
89
+ };
90
+
91
+ const getActiveIdentity = (connection: Connection): Identity | undefined => {
92
+ const activeAddress = getActiveAddress(connection);
93
+ if (!activeAddress) return undefined;
94
+
95
+ return connection.identities?.get(activeAddress);
96
+ };
97
+
40
98
  const derivedState = derive(
41
99
  {
42
- activeAddress: (get): CaipAddress | undefined => {
100
+ isConnected: (get): boolean => {
43
101
  const snap = get(baseState);
44
102
 
45
- if (!snap.activeNamespace) return undefined;
46
-
47
- const connection = snap.connections[snap.activeNamespace];
48
-
49
- if (!connection || !connection.accounts || connection.accounts.length === 0) {
50
- return undefined;
51
- }
103
+ return !!snap.activeNamespace && !!snap.connections.size;
104
+ },
105
+ activeAddress: (get): CaipAddress | undefined => {
106
+ const snap = get(baseState);
107
+ const connection = getActiveConnection(snap);
52
108
 
53
- //TODO: what happens if there are several accounts on the same chain?
54
- const activeAccount = connection.accounts.find(account =>
55
- account.startsWith(connection.activeChain)
56
- );
109
+ return connection ? getActiveAddress(connection) : undefined;
110
+ },
111
+ identity: (get): Identity | undefined => {
112
+ const snap = get(baseState);
113
+ const connection = getActiveConnection(snap);
57
114
 
58
- return activeAccount;
115
+ return connection ? getActiveIdentity(connection) : undefined;
59
116
  },
60
117
  activeBalance: (get): Balance | undefined => {
61
118
  const snap = get(baseState);
119
+ const connection = getActiveConnection(snap);
62
120
 
63
- if (!snap.activeNamespace) return undefined;
64
- const connection = snap.connections[snap.activeNamespace];
121
+ if (!connection) {
122
+ return undefined;
123
+ }
65
124
 
66
- if (!connection || !connection.accounts || connection.accounts.length === 0) {
125
+ const activeAddress = getActiveAddress(connection);
126
+ if (!activeAddress || !connection.balances || connection.balances.size === 0) {
67
127
  return undefined;
68
128
  }
69
129
 
70
- const activeAccount = connection.accounts.find(account =>
71
- account.startsWith(connection.activeChain)
130
+ const addressBalances = connection.balances.get(activeAddress);
131
+ if (!addressBalances || addressBalances.length === 0) {
132
+ return undefined;
133
+ }
134
+
135
+ // Check if there's a specific token configured in OptionsController
136
+ const configuredTokens = OptionsController.state.tokens;
137
+ const activeNetwork = snap.networks.find(
138
+ network =>
139
+ network.chainNamespace === snap.activeNamespace &&
140
+ network.id?.toString() === connection.caipNetwork?.split(':')[1]
72
141
  );
73
142
 
74
- if (
75
- !connection ||
76
- !connection.balances ||
77
- !activeAccount ||
78
- Object.keys(connection.balances).length === 0
79
- ) {
80
- return undefined;
143
+ if (configuredTokens && activeNetwork) {
144
+ const configuredToken = configuredTokens[activeNetwork.caipNetworkId];
145
+ if (configuredToken) {
146
+ // Find the configured token in the balances
147
+ const specificToken = addressBalances.find(
148
+ balance => balance.address === configuredToken.address
149
+ );
150
+ if (specificToken) {
151
+ return specificToken;
152
+ }
153
+ }
81
154
  }
82
155
 
83
- return connection.balances[activeAccount];
156
+ // Return the native token (first balance without address)
157
+ const nativeToken = addressBalances.find(balance => !balance.address);
158
+ if (nativeToken) {
159
+ return nativeToken;
160
+ }
161
+
162
+ // Fallback to first available balance
163
+ return addressBalances[0];
84
164
  },
85
165
  activeNetwork: (get): AppKitNetwork | undefined => {
86
166
  const snap = get(baseState);
87
-
88
- if (!snap.activeNamespace) return undefined;
89
-
90
- const connection = snap.connections[snap.activeNamespace];
167
+ const connection = getActiveConnection(snap);
91
168
 
92
169
  if (!connection) return undefined;
93
170
 
94
171
  return snap.networks.find(
95
172
  network =>
96
173
  network.chainNamespace === snap.activeNamespace &&
97
- network.id?.toString() === connection.activeChain?.split(':')[1]
174
+ network.id?.toString() === connection.caipNetwork?.split(':')[1]
98
175
  );
99
176
  },
100
177
  activeCaipNetworkId: (get): CaipNetworkId | undefined => {
101
178
  const snap = get(baseState);
179
+ const connection = getActiveConnection(snap);
102
180
 
103
- if (!snap.activeNamespace) return undefined;
181
+ return connection?.caipNetwork;
182
+ },
183
+ accountType: (get): AccountType | undefined => {
184
+ const snap = get(baseState);
185
+ const connection = getActiveConnection(snap);
104
186
 
105
- const connection = snap.connections[snap.activeNamespace];
187
+ return connection?.type;
188
+ },
189
+ connection: (get): Connection | undefined => {
190
+ const snap = get(baseState);
106
191
 
107
- if (!connection) return undefined;
192
+ return getActiveConnection(snap);
193
+ },
194
+ balances: (get): Balance[] | undefined => {
195
+ const snap = get(baseState);
196
+
197
+ const _connection = getActiveConnection(snap);
198
+
199
+ if (!_connection) {
200
+ return undefined;
201
+ }
202
+
203
+ const _activeAddress = getActiveAddress(_connection);
108
204
 
109
- return connection.activeChain;
205
+ if (!_activeAddress) return [];
206
+
207
+ return (
208
+ _connection?.balances
209
+ .get(_activeAddress)
210
+ // Filter out tokens with no quantity
211
+ ?.filter(balance => balance?.quantity?.numeric)
212
+ );
110
213
  },
111
214
  walletInfo: (get): WalletInfo | undefined => {
112
215
  const snap = get(baseState);
216
+ const connection = getActiveConnection(snap);
113
217
 
114
- if (!snap.activeNamespace) return undefined;
115
-
116
- return snap.connections[snap.activeNamespace]?.wallet;
218
+ return connection?.wallet;
117
219
  }
118
220
  },
119
221
  {
@@ -130,55 +232,127 @@ export const ConnectionsController = {
130
232
  StorageUtil.setActiveNamespace(namespace);
131
233
  },
132
234
 
133
- storeConnection({
134
- namespace,
135
- adapter,
235
+ setConnection({
136
236
  accounts,
137
- chains,
138
- wallet,
139
- activeChain
237
+ adapter,
238
+ caipNetwork,
239
+ namespace,
240
+ properties,
241
+ wallet
140
242
  }: {
141
- namespace: string;
142
- adapter: BlockchainAdapter;
143
243
  accounts: CaipAddress[];
144
- chains: CaipNetworkId[];
244
+ adapter: BlockchainAdapter;
245
+ caipNetwork: CaipNetworkId;
246
+ namespace: ChainNamespace;
247
+ properties?: ConnectionProperties;
145
248
  wallet?: WalletInfo;
146
- activeChain?: CaipNetworkId;
147
249
  }) {
148
- baseState.connections[namespace] = {
149
- balances: {},
150
- activeChain: activeChain ?? chains[0]!,
250
+ const type: AccountType =
251
+ properties?.smartAccounts?.length &&
252
+ properties.smartAccounts.find(account => account.startsWith(caipNetwork))
253
+ ? 'smartAccount'
254
+ : 'eoa';
255
+
256
+ const newConnectionEntry: Connection = {
257
+ balances: new Map<CaipAddress, Balance[]>(),
258
+ caipNetwork,
151
259
  adapter: ref(adapter),
152
260
  accounts,
153
- chains,
154
- wallet
261
+ wallet,
262
+ properties,
263
+ type
155
264
  };
265
+
266
+ // Create a new Map to ensure Valtio detects the change
267
+ const newConnectionsMap = new Map(baseState.connections);
268
+ newConnectionsMap.set(namespace, newConnectionEntry);
269
+ baseState.connections = newConnectionsMap;
156
270
  },
157
271
 
158
- updateAccounts(namespace: string, accounts: CaipAddress[]) {
159
- const connection = baseState.connections[namespace];
272
+ updateAccounts(namespace: ChainNamespace, accounts: CaipAddress[]) {
273
+ const connection = baseState.connections.get(namespace);
160
274
  if (!connection) {
161
275
  return;
162
276
  }
163
- connection.accounts = accounts;
277
+
278
+ const newConnectionsMap = new Map(baseState.connections);
279
+ const updatedConnection = { ...connection, accounts };
280
+ newConnectionsMap.set(namespace, updatedConnection);
281
+ baseState.connections = newConnectionsMap;
164
282
  },
165
283
 
166
- updateBalance(namespace: string, address: CaipAddress, balance: Balance) {
167
- const connection = baseState.connections[namespace];
284
+ updateBalance(namespace: ChainNamespace, address: CaipAddress, balance: Balance) {
285
+ const connection = baseState.connections.get(namespace);
168
286
  if (!connection) {
287
+ console.warn(`No connection found for namespace: ${namespace}`);
288
+
169
289
  return;
170
290
  }
171
- connection.balances[address] = balance;
291
+ const newBalances = new Map(connection.balances);
292
+ const existingBalances = connection.balances.get(address) || [];
293
+ // Check if this token already exists by contract address or symbol
294
+ const existingIndex = existingBalances.findIndex(existingBalance => {
295
+ if (balance.address) {
296
+ return existingBalance.address === balance.address;
297
+ }
298
+
299
+ return existingBalance.symbol === balance.symbol;
300
+ });
301
+ let updatedBalances: Balance[];
302
+ if (existingIndex >= 0) {
303
+ // Update existing token
304
+ updatedBalances = [...existingBalances];
305
+ updatedBalances[existingIndex] = {
306
+ ...updatedBalances[existingIndex],
307
+ ...balance
308
+ };
309
+ } else {
310
+ // Add new token
311
+ updatedBalances = [...existingBalances, balance];
312
+ }
313
+ newBalances.set(address, updatedBalances);
314
+ updateConnection(namespace, connection, { balances: newBalances });
172
315
  },
173
316
 
174
- setActiveChain(namespace: string, chain: CaipNetworkId) {
175
- const connection = baseState.connections[namespace];
317
+ updateIdentity(
318
+ namespace: ChainNamespace,
319
+ connection: Connection,
320
+ plainAddress: string,
321
+ identity: Identity
322
+ ) {
323
+ const accounts = connection.accounts.filter(
324
+ account => CoreHelperUtil.getPlainAddress(account) === plainAddress
325
+ );
326
+
327
+ if (accounts.length > 0) {
328
+ const newIdentities = new Map(connection.identities || []);
329
+ let hasChanges = false;
330
+
331
+ accounts.forEach(account => {
332
+ const existingIdentity = newIdentities.get(account);
333
+ if (!existingIdentity || existingIdentity.name !== identity.name) {
334
+ newIdentities.set(account, identity);
335
+ hasChanges = true;
336
+ }
337
+ });
338
+
339
+ if (hasChanges) {
340
+ updateConnection(namespace, connection, { identities: newIdentities });
341
+ }
342
+ }
343
+ },
344
+
345
+ setActiveNetwork(namespace: ChainNamespace, networkId: CaipNetworkId) {
346
+ const connection = baseState.connections.get(namespace);
176
347
 
177
348
  if (!connection) {
178
349
  return;
179
350
  }
180
351
 
181
- connection.activeChain = chain;
352
+ baseState.connections.set(namespace, {
353
+ ...connection,
354
+ caipNetwork: networkId
355
+ });
182
356
  },
183
357
 
184
358
  setNetworks(networks: AppKitNetwork[]) {
@@ -188,12 +362,24 @@ export const ConnectionsController = {
188
362
  getConnectedNetworks() {
189
363
  return baseState.networks.filter(
190
364
  network =>
191
- baseState.connections[network.chainNamespace]?.chains.includes(network.caipNetworkId)
365
+ baseState.connections
366
+ .get(network.chainNamespace)
367
+ ?.accounts.some(account => account.startsWith(network.caipNetworkId))
192
368
  );
193
369
  },
194
370
 
195
- async disconnect(namespace: string, isInternal = true) {
196
- const connection = baseState.connections[namespace];
371
+ setAccountType(namespace: ChainNamespace, type: AccountType) {
372
+ const connection = baseState.connections.get(namespace);
373
+ if (!connection) return;
374
+
375
+ const newConnectionsMap = new Map(baseState.connections);
376
+ const newConnection = { ...connection, type };
377
+ newConnectionsMap.set(namespace, newConnection);
378
+ baseState.connections = newConnectionsMap;
379
+ },
380
+
381
+ async disconnect(namespace: ChainNamespace, isInternal = true) {
382
+ const connection = baseState.connections.get(namespace);
197
383
  if (!connection) return;
198
384
 
199
385
  // Get the current connector from the adapter
@@ -201,13 +387,13 @@ export const ConnectionsController = {
201
387
  if (!connector) return;
202
388
 
203
389
  // Find all namespaces that use the same connector
204
- const namespacesUsingConnector = Object.keys(baseState.connections).filter(
205
- ns => baseState.connections[ns]?.adapter.connector === connector
390
+ const namespacesUsingConnector = Array.from(baseState.connections.keys()).filter(
391
+ ns => baseState.connections.get(ns)?.adapter.connector === connector
206
392
  );
207
393
 
208
394
  // Unsubscribe all event listeners from the adapter
209
395
  namespacesUsingConnector.forEach(ns => {
210
- const _connection = baseState.connections[ns];
396
+ const _connection = baseState.connections.get(ns);
211
397
  if (_connection?.adapter) {
212
398
  _connection.adapter.removeAllListeners();
213
399
  }
@@ -219,9 +405,11 @@ export const ConnectionsController = {
219
405
  }
220
406
 
221
407
  // Remove all namespaces that used this connector
408
+ const newConnectionsMap = new Map(baseState.connections);
222
409
  namespacesUsingConnector.forEach(ns => {
223
- delete baseState.connections[ns];
410
+ newConnectionsMap.delete(ns);
224
411
  });
412
+ baseState.connections = newConnectionsMap;
225
413
 
226
414
  // Remove activeNamespace if it is in the list of namespaces using the connector
227
415
  if (
@@ -232,5 +420,124 @@ export const ConnectionsController = {
232
420
  baseState.activeNamespace = undefined;
233
421
  StorageUtil.setActiveNamespace(undefined);
234
422
  }
423
+ },
424
+
425
+ parseUnits(value: string, decimals: number) {
426
+ if (!baseState.activeNamespace) return undefined;
427
+
428
+ return baseState.connections
429
+ .get(baseState.activeNamespace)
430
+ ?.adapter.parseUnits(value, decimals);
431
+ },
432
+
433
+ async signMessage(address: CaipAddress, message: string) {
434
+ if (!baseState.activeNamespace) return undefined;
435
+
436
+ const [namespace, chainId, plainAddress] = address.split(':');
437
+
438
+ if (!namespace || namespace !== baseState.activeNamespace || !chainId || !plainAddress) {
439
+ return undefined;
440
+ }
441
+
442
+ const adapter = baseState.connections.get(baseState.activeNamespace)?.adapter;
443
+
444
+ if (adapter instanceof EVMAdapter && plainAddress && chainId) {
445
+ return adapter.signMessage(plainAddress, message, chainId);
446
+ }
447
+
448
+ return undefined;
449
+ },
450
+
451
+ async sendTransaction(args: any) {
452
+ if (!baseState.activeNamespace) return undefined;
453
+
454
+ const adapter = baseState.connections.get(baseState.activeNamespace)?.adapter;
455
+ if (adapter instanceof EVMAdapter || adapter instanceof SolanaBaseAdapter) {
456
+ return adapter.sendTransaction(args);
457
+ }
458
+
459
+ return undefined;
460
+ },
461
+
462
+ async estimateGas(args: any) {
463
+ if (!baseState.activeNamespace || baseState.activeNamespace !== 'eip155') return undefined;
464
+
465
+ const adapter = baseState.connections.get(baseState.activeNamespace)?.adapter;
466
+ if (adapter instanceof EVMAdapter) {
467
+ return adapter.estimateGas(args);
468
+ }
469
+
470
+ return undefined;
471
+ },
472
+
473
+ async writeContract(args: any) {
474
+ if (!baseState.activeNamespace) return undefined;
475
+
476
+ const adapter = baseState.connections.get(baseState.activeNamespace)?.adapter;
477
+ if (adapter instanceof EVMAdapter) {
478
+ return adapter.writeContract(args);
479
+ }
480
+
481
+ return undefined;
482
+ },
483
+
484
+ async fetchBalance(forceUpdateAddresses?: CaipAddress[]) {
485
+ const connection = getActiveConnection(baseState);
486
+ if (!connection) {
487
+ throw new Error('No active connection found for balance fetch');
488
+ }
489
+
490
+ const chainId = connection.caipNetwork;
491
+ const address = getActiveAddress(connection);
492
+ const namespace = baseState.activeNamespace;
493
+ if (!namespace || !address || !chainId) {
494
+ throw new Error('Missing required data for balance fetch');
495
+ }
496
+
497
+ try {
498
+ const response = await BlockchainApiController.getBalance(address, forceUpdateAddresses);
499
+ if (!response) {
500
+ throw new Error('Failed to fetch token balance');
501
+ }
502
+ // Update balances for each token in the response
503
+ response.balances.forEach(balance => {
504
+ this.updateBalance(namespace, address, {
505
+ name: balance.name,
506
+ symbol: balance.symbol,
507
+ amount: balance.quantity.numeric,
508
+ address: balance.address,
509
+ quantity: balance.quantity,
510
+ price: balance.price,
511
+ value: balance.value,
512
+ iconUrl: balance.iconUrl
513
+ });
514
+ });
515
+ } catch (error) {
516
+ SnackController.showError('Failed to get account balance');
517
+ }
518
+ },
519
+
520
+ getSmartAccountEnabledNetworks(): AppKitNetwork[] {
521
+ const activeConnection = getActiveConnection(baseState);
522
+ if (!activeConnection) {
523
+ return [];
524
+ }
525
+ if (!activeConnection.properties?.smartAccounts?.length) {
526
+ return [];
527
+ }
528
+ const smartAccountNetworks = new Set<CaipNetworkId>();
529
+ activeConnection.properties.smartAccounts.forEach(smartAccount => {
530
+ const parts = smartAccount.split(':');
531
+ if (parts.length >= 2) {
532
+ const networkId: CaipNetworkId = `${parts[0]}:${parts[1]}`;
533
+ smartAccountNetworks.add(networkId);
534
+ }
535
+ });
536
+
537
+ return baseState.networks.filter(network => {
538
+ const networkId: CaipNetworkId = `${network.chainNamespace}:${network.id}`;
539
+
540
+ return smartAccountNetworks.has(networkId);
541
+ });
235
542
  }
236
543
  };
@@ -1,5 +1,5 @@
1
- import { subscribeKey as subKey } from 'valtio/vanilla/utils';
2
- import { proxy, subscribe as sub } from 'valtio/vanilla';
1
+ import { subscribeKey as subKey } from 'valtio/utils';
2
+ import { proxy, subscribe as sub } from 'valtio';
3
3
  import { BlockchainApiController } from './BlockchainApiController';
4
4
  import type { BlockchainApiEnsError } from '../utils/TypeUtil';
5
5
 
@@ -1,4 +1,4 @@
1
- import { proxy, subscribe as sub } from 'valtio/vanilla';
1
+ import { proxy, subscribe as sub } from 'valtio';
2
2
  import { ApiController } from './ApiController';
3
3
  import { OptionsController } from './OptionsController';
4
4
  import { CoreHelperUtil } from '../utils/CoreHelperUtil';
@@ -1,11 +1,9 @@
1
1
  import { proxy } from 'valtio';
2
- import { AccountController } from './AccountController';
3
- import type { RouterControllerState } from './RouterController';
4
- import { RouterController } from './RouterController';
2
+ import { RouterController, type RouterControllerState } from './RouterController';
5
3
  import { PublicStateController } from './PublicStateController';
6
4
  import { EventsController } from './EventsController';
7
5
  import { ApiController } from './ApiController';
8
- import { ConnectorController } from './ConnectorController';
6
+ import { ConnectionsController } from './ConnectionsController';
9
7
 
10
8
  // -- Types --------------------------------------------- //
11
9
  export interface ModalControllerState {
@@ -31,11 +29,11 @@ export const ModalController = {
31
29
 
32
30
  async open(options?: ModalControllerArguments['open']) {
33
31
  await ApiController.state.prefetchPromise;
34
- const connected = AccountController.state.isConnected;
32
+ const isConnected = ConnectionsController.state.isConnected;
35
33
  if (options?.view) {
36
34
  RouterController.reset(options.view);
37
- } else if (AccountController.state.isConnected) {
38
- const isUniversalWallet = ConnectorController.state.connectedConnector === 'AUTH';
35
+ } else if (isConnected) {
36
+ const isUniversalWallet = !!ConnectionsController.state.connection?.properties?.provider;
39
37
  RouterController.reset(isUniversalWallet ? 'Account' : 'AccountDefault');
40
38
  } else {
41
39
  RouterController.reset('Connect');
@@ -45,12 +43,12 @@ export const ModalController = {
45
43
  EventsController.sendEvent({
46
44
  type: 'track',
47
45
  event: 'MODAL_OPEN',
48
- properties: { connected }
46
+ properties: { connected: isConnected }
49
47
  });
50
48
  },
51
49
 
52
50
  close() {
53
- const connected = AccountController.state.isConnected;
51
+ const connected = ConnectionsController.state.isConnected;
54
52
  state.open = false;
55
53
  PublicStateController.set({ open: false });
56
54
  EventsController.sendEvent({