@metamask/snaps-controllers 18.0.4 → 19.0.1

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 (288) hide show
  1. package/CHANGELOG.md +108 -1
  2. package/dist/cronjob/CronjobController-method-action-types.cjs +7 -0
  3. package/dist/cronjob/CronjobController-method-action-types.cjs.map +1 -0
  4. package/dist/cronjob/CronjobController-method-action-types.d.cts +51 -0
  5. package/dist/cronjob/CronjobController-method-action-types.d.cts.map +1 -0
  6. package/dist/cronjob/CronjobController-method-action-types.d.mts +51 -0
  7. package/dist/cronjob/CronjobController-method-action-types.d.mts.map +1 -0
  8. package/dist/cronjob/CronjobController-method-action-types.mjs +6 -0
  9. package/dist/cronjob/CronjobController-method-action-types.mjs.map +1 -0
  10. package/dist/cronjob/CronjobController.cjs +7 -4
  11. package/dist/cronjob/CronjobController.cjs.map +1 -1
  12. package/dist/cronjob/CronjobController.d.cts +8 -25
  13. package/dist/cronjob/CronjobController.d.cts.map +1 -1
  14. package/dist/cronjob/CronjobController.d.mts +8 -25
  15. package/dist/cronjob/CronjobController.d.mts.map +1 -1
  16. package/dist/cronjob/CronjobController.mjs +7 -4
  17. package/dist/cronjob/CronjobController.mjs.map +1 -1
  18. package/dist/cronjob/index.cjs +3 -15
  19. package/dist/cronjob/index.cjs.map +1 -1
  20. package/dist/cronjob/index.d.cts +3 -1
  21. package/dist/cronjob/index.d.cts.map +1 -1
  22. package/dist/cronjob/index.d.mts +3 -1
  23. package/dist/cronjob/index.d.mts.map +1 -1
  24. package/dist/cronjob/index.mjs +1 -1
  25. package/dist/cronjob/index.mjs.map +1 -1
  26. package/dist/insights/SnapInsightsController.cjs +1 -3
  27. package/dist/insights/SnapInsightsController.cjs.map +1 -1
  28. package/dist/insights/SnapInsightsController.d.cts +9 -9
  29. package/dist/insights/SnapInsightsController.d.cts.map +1 -1
  30. package/dist/insights/SnapInsightsController.d.mts +9 -9
  31. package/dist/insights/SnapInsightsController.d.mts.map +1 -1
  32. package/dist/insights/SnapInsightsController.mjs +1 -3
  33. package/dist/insights/SnapInsightsController.mjs.map +1 -1
  34. package/dist/insights/index.cjs +3 -15
  35. package/dist/insights/index.cjs.map +1 -1
  36. package/dist/insights/index.d.cts +2 -1
  37. package/dist/insights/index.d.cts.map +1 -1
  38. package/dist/insights/index.d.mts +2 -1
  39. package/dist/insights/index.d.mts.map +1 -1
  40. package/dist/insights/index.mjs +1 -1
  41. package/dist/insights/index.mjs.map +1 -1
  42. package/dist/interface/SnapInterfaceController-method-action-types.cjs +7 -0
  43. package/dist/interface/SnapInterfaceController-method-action-types.cjs.map +1 -0
  44. package/dist/interface/SnapInterfaceController-method-action-types.d.cts +99 -0
  45. package/dist/interface/SnapInterfaceController-method-action-types.d.cts.map +1 -0
  46. package/dist/interface/SnapInterfaceController-method-action-types.d.mts +99 -0
  47. package/dist/interface/SnapInterfaceController-method-action-types.d.mts.map +1 -0
  48. package/dist/interface/SnapInterfaceController-method-action-types.mjs +6 -0
  49. package/dist/interface/SnapInterfaceController-method-action-types.mjs.map +1 -0
  50. package/dist/interface/SnapInterfaceController.cjs +12 -16
  51. package/dist/interface/SnapInterfaceController.cjs.map +1 -1
  52. package/dist/interface/SnapInterfaceController.d.cts +10 -40
  53. package/dist/interface/SnapInterfaceController.d.cts.map +1 -1
  54. package/dist/interface/SnapInterfaceController.d.mts +10 -40
  55. package/dist/interface/SnapInterfaceController.d.mts.map +1 -1
  56. package/dist/interface/SnapInterfaceController.mjs +12 -16
  57. package/dist/interface/SnapInterfaceController.mjs.map +1 -1
  58. package/dist/interface/index.cjs +3 -15
  59. package/dist/interface/index.cjs.map +1 -1
  60. package/dist/interface/index.d.cts +3 -1
  61. package/dist/interface/index.d.cts.map +1 -1
  62. package/dist/interface/index.d.mts +3 -1
  63. package/dist/interface/index.d.mts.map +1 -1
  64. package/dist/interface/index.mjs +1 -1
  65. package/dist/interface/index.mjs.map +1 -1
  66. package/dist/multichain/MultichainRoutingService-method-action-types.cjs +7 -0
  67. package/dist/multichain/MultichainRoutingService-method-action-types.cjs.map +1 -0
  68. package/dist/multichain/MultichainRoutingService-method-action-types.d.cts +61 -0
  69. package/dist/multichain/MultichainRoutingService-method-action-types.d.cts.map +1 -0
  70. package/dist/multichain/MultichainRoutingService-method-action-types.d.mts +61 -0
  71. package/dist/multichain/MultichainRoutingService-method-action-types.d.mts.map +1 -0
  72. package/dist/multichain/MultichainRoutingService-method-action-types.mjs +6 -0
  73. package/dist/multichain/MultichainRoutingService-method-action-types.mjs.map +1 -0
  74. package/dist/multichain/{MultichainRouter.cjs → MultichainRoutingService.cjs} +14 -13
  75. package/dist/multichain/MultichainRoutingService.cjs.map +1 -0
  76. package/dist/multichain/{MultichainRouter.d.mts → MultichainRoutingService.d.cts} +14 -29
  77. package/dist/multichain/MultichainRoutingService.d.cts.map +1 -0
  78. package/dist/multichain/{MultichainRouter.d.cts → MultichainRoutingService.d.mts} +14 -29
  79. package/dist/multichain/MultichainRoutingService.d.mts.map +1 -0
  80. package/dist/multichain/{MultichainRouter.mjs → MultichainRoutingService.mjs} +12 -11
  81. package/dist/multichain/MultichainRoutingService.mjs.map +1 -0
  82. package/dist/multichain/index.cjs +3 -15
  83. package/dist/multichain/index.cjs.map +1 -1
  84. package/dist/multichain/index.d.cts +3 -1
  85. package/dist/multichain/index.d.cts.map +1 -1
  86. package/dist/multichain/index.d.mts +3 -1
  87. package/dist/multichain/index.d.mts.map +1 -1
  88. package/dist/multichain/index.mjs +1 -1
  89. package/dist/multichain/index.mjs.map +1 -1
  90. package/dist/services/ExecutionService-method-action-types.cjs +7 -0
  91. package/dist/services/ExecutionService-method-action-types.cjs.map +1 -0
  92. package/dist/services/ExecutionService-method-action-types.d.cts +50 -0
  93. package/dist/services/ExecutionService-method-action-types.d.cts.map +1 -0
  94. package/dist/services/ExecutionService-method-action-types.d.mts +50 -0
  95. package/dist/services/ExecutionService-method-action-types.d.mts.map +1 -0
  96. package/dist/services/ExecutionService-method-action-types.mjs +6 -0
  97. package/dist/services/ExecutionService-method-action-types.mjs.map +1 -0
  98. package/dist/services/ExecutionService.cjs +287 -0
  99. package/dist/services/ExecutionService.cjs.map +1 -1
  100. package/dist/services/ExecutionService.d.cts +100 -46
  101. package/dist/services/ExecutionService.d.cts.map +1 -1
  102. package/dist/services/ExecutionService.d.mts +100 -46
  103. package/dist/services/ExecutionService.d.mts.map +1 -1
  104. package/dist/services/ExecutionService.mjs +285 -1
  105. package/dist/services/ExecutionService.mjs.map +1 -1
  106. package/dist/services/browser.cjs +5 -2
  107. package/dist/services/browser.cjs.map +1 -1
  108. package/dist/services/browser.d.cts +4 -2
  109. package/dist/services/browser.d.cts.map +1 -1
  110. package/dist/services/browser.d.mts +4 -2
  111. package/dist/services/browser.d.mts.map +1 -1
  112. package/dist/services/browser.mjs +2 -2
  113. package/dist/services/browser.mjs.map +1 -1
  114. package/dist/services/iframe/IframeExecutionService.cjs +2 -2
  115. package/dist/services/iframe/IframeExecutionService.cjs.map +1 -1
  116. package/dist/services/iframe/IframeExecutionService.d.cts +3 -3
  117. package/dist/services/iframe/IframeExecutionService.d.cts.map +1 -1
  118. package/dist/services/iframe/IframeExecutionService.d.mts +3 -3
  119. package/dist/services/iframe/IframeExecutionService.d.mts.map +1 -1
  120. package/dist/services/iframe/IframeExecutionService.mjs +2 -2
  121. package/dist/services/iframe/IframeExecutionService.mjs.map +1 -1
  122. package/dist/services/index.cjs +5 -1
  123. package/dist/services/index.cjs.map +1 -1
  124. package/dist/services/index.d.cts +4 -2
  125. package/dist/services/index.d.cts.map +1 -1
  126. package/dist/services/index.d.mts +4 -2
  127. package/dist/services/index.d.mts.map +1 -1
  128. package/dist/services/index.mjs +2 -1
  129. package/dist/services/index.mjs.map +1 -1
  130. package/dist/services/multiplex.cjs +27 -0
  131. package/dist/services/multiplex.cjs.map +1 -0
  132. package/dist/services/multiplex.d.cts +11 -0
  133. package/dist/services/multiplex.d.cts.map +1 -0
  134. package/dist/services/multiplex.d.mts +11 -0
  135. package/dist/services/multiplex.d.mts.map +1 -0
  136. package/dist/services/multiplex.mjs +27 -0
  137. package/dist/services/multiplex.mjs.map +1 -0
  138. package/dist/services/node-js/NodeProcessExecutionService.cjs +2 -2
  139. package/dist/services/node-js/NodeProcessExecutionService.cjs.map +1 -1
  140. package/dist/services/node-js/NodeProcessExecutionService.d.cts +3 -3
  141. package/dist/services/node-js/NodeProcessExecutionService.d.cts.map +1 -1
  142. package/dist/services/node-js/NodeProcessExecutionService.d.mts +3 -3
  143. package/dist/services/node-js/NodeProcessExecutionService.d.mts.map +1 -1
  144. package/dist/services/node-js/NodeProcessExecutionService.mjs +2 -2
  145. package/dist/services/node-js/NodeProcessExecutionService.mjs.map +1 -1
  146. package/dist/services/node-js/NodeThreadExecutionService.cjs +2 -5
  147. package/dist/services/node-js/NodeThreadExecutionService.cjs.map +1 -1
  148. package/dist/services/node-js/NodeThreadExecutionService.d.cts +3 -3
  149. package/dist/services/node-js/NodeThreadExecutionService.d.cts.map +1 -1
  150. package/dist/services/node-js/NodeThreadExecutionService.d.mts +3 -3
  151. package/dist/services/node-js/NodeThreadExecutionService.d.mts.map +1 -1
  152. package/dist/services/node-js/NodeThreadExecutionService.mjs +2 -5
  153. package/dist/services/node-js/NodeThreadExecutionService.mjs.map +1 -1
  154. package/dist/services/offscreen/OffscreenExecutionService.cjs.map +1 -1
  155. package/dist/services/offscreen/OffscreenExecutionService.d.cts +1 -1
  156. package/dist/services/offscreen/OffscreenExecutionService.d.cts.map +1 -1
  157. package/dist/services/offscreen/OffscreenExecutionService.d.mts +1 -1
  158. package/dist/services/offscreen/OffscreenExecutionService.d.mts.map +1 -1
  159. package/dist/services/offscreen/OffscreenExecutionService.mjs.map +1 -1
  160. package/dist/services/proxy/ProxyExecutionService.cjs +2 -5
  161. package/dist/services/proxy/ProxyExecutionService.cjs.map +1 -1
  162. package/dist/services/proxy/ProxyExecutionService.d.cts +3 -3
  163. package/dist/services/proxy/ProxyExecutionService.d.cts.map +1 -1
  164. package/dist/services/proxy/ProxyExecutionService.d.mts +3 -3
  165. package/dist/services/proxy/ProxyExecutionService.d.mts.map +1 -1
  166. package/dist/services/proxy/ProxyExecutionService.mjs +2 -5
  167. package/dist/services/proxy/ProxyExecutionService.mjs.map +1 -1
  168. package/dist/services/webview/WebViewExecutionService.cjs +2 -2
  169. package/dist/services/webview/WebViewExecutionService.cjs.map +1 -1
  170. package/dist/services/webview/WebViewExecutionService.d.cts +3 -3
  171. package/dist/services/webview/WebViewExecutionService.d.cts.map +1 -1
  172. package/dist/services/webview/WebViewExecutionService.d.mts +3 -3
  173. package/dist/services/webview/WebViewExecutionService.d.mts.map +1 -1
  174. package/dist/services/webview/WebViewExecutionService.mjs +2 -2
  175. package/dist/services/webview/WebViewExecutionService.mjs.map +1 -1
  176. package/dist/snaps/SnapController-method-action-types.cjs +7 -0
  177. package/dist/snaps/SnapController-method-action-types.cjs.map +1 -0
  178. package/dist/snaps/SnapController-method-action-types.d.cts +284 -0
  179. package/dist/snaps/SnapController-method-action-types.d.cts.map +1 -0
  180. package/dist/snaps/SnapController-method-action-types.d.mts +284 -0
  181. package/dist/snaps/SnapController-method-action-types.d.mts.map +1 -0
  182. package/dist/snaps/SnapController-method-action-types.mjs +6 -0
  183. package/dist/snaps/SnapController-method-action-types.mjs.map +1 -0
  184. package/dist/snaps/SnapController.cjs +118 -113
  185. package/dist/snaps/SnapController.cjs.map +1 -1
  186. package/dist/snaps/SnapController.d.cts +33 -190
  187. package/dist/snaps/SnapController.d.cts.map +1 -1
  188. package/dist/snaps/SnapController.d.mts +33 -190
  189. package/dist/snaps/SnapController.d.mts.map +1 -1
  190. package/dist/snaps/SnapController.mjs +119 -114
  191. package/dist/snaps/SnapController.mjs.map +1 -1
  192. package/dist/snaps/index.cjs +3 -1
  193. package/dist/snaps/index.cjs.map +1 -1
  194. package/dist/snaps/index.d.cts +3 -1
  195. package/dist/snaps/index.d.cts.map +1 -1
  196. package/dist/snaps/index.d.mts +3 -1
  197. package/dist/snaps/index.d.mts.map +1 -1
  198. package/dist/snaps/index.mjs +1 -1
  199. package/dist/snaps/index.mjs.map +1 -1
  200. package/dist/snaps/registry/SnapRegistryController-method-action-types.cjs +7 -0
  201. package/dist/snaps/registry/SnapRegistryController-method-action-types.cjs.map +1 -0
  202. package/dist/snaps/registry/SnapRegistryController-method-action-types.d.cts +46 -0
  203. package/dist/snaps/registry/SnapRegistryController-method-action-types.d.cts.map +1 -0
  204. package/dist/snaps/registry/SnapRegistryController-method-action-types.d.mts +46 -0
  205. package/dist/snaps/registry/SnapRegistryController-method-action-types.d.mts.map +1 -0
  206. package/dist/snaps/registry/SnapRegistryController-method-action-types.mjs +6 -0
  207. package/dist/snaps/registry/SnapRegistryController-method-action-types.mjs.map +1 -0
  208. package/dist/snaps/registry/{json.cjs → SnapRegistryController.cjs} +27 -24
  209. package/dist/snaps/registry/SnapRegistryController.cjs.map +1 -0
  210. package/dist/snaps/registry/SnapRegistryController.d.cts +67 -0
  211. package/dist/snaps/registry/SnapRegistryController.d.cts.map +1 -0
  212. package/dist/snaps/registry/SnapRegistryController.d.mts +67 -0
  213. package/dist/snaps/registry/SnapRegistryController.d.mts.map +1 -0
  214. package/dist/snaps/registry/{json.mjs → SnapRegistryController.mjs} +25 -22
  215. package/dist/snaps/registry/SnapRegistryController.mjs.map +1 -0
  216. package/dist/snaps/registry/index.cjs +5 -16
  217. package/dist/snaps/registry/index.cjs.map +1 -1
  218. package/dist/snaps/registry/index.d.cts +5 -2
  219. package/dist/snaps/registry/index.d.cts.map +1 -1
  220. package/dist/snaps/registry/index.d.mts +5 -2
  221. package/dist/snaps/registry/index.d.mts.map +1 -1
  222. package/dist/snaps/registry/index.mjs +2 -2
  223. package/dist/snaps/registry/index.mjs.map +1 -1
  224. package/dist/snaps/registry/types.cjs +11 -0
  225. package/dist/snaps/registry/types.cjs.map +1 -0
  226. package/dist/snaps/registry/types.d.cts +20 -0
  227. package/dist/snaps/registry/types.d.cts.map +1 -0
  228. package/dist/snaps/registry/types.d.mts +20 -0
  229. package/dist/snaps/registry/types.d.mts.map +1 -0
  230. package/dist/snaps/registry/types.mjs +8 -0
  231. package/dist/snaps/registry/types.mjs.map +1 -0
  232. package/dist/types/controllers.cjs.map +1 -1
  233. package/dist/types/controllers.d.cts +1 -1
  234. package/dist/types/controllers.d.cts.map +1 -1
  235. package/dist/types/controllers.d.mts +1 -1
  236. package/dist/types/controllers.d.mts.map +1 -1
  237. package/dist/types/controllers.mjs.map +1 -1
  238. package/dist/websocket/WebSocketService-method-action-types.cjs +7 -0
  239. package/dist/websocket/WebSocketService-method-action-types.cjs.map +1 -0
  240. package/dist/websocket/WebSocketService-method-action-types.d.cts +54 -0
  241. package/dist/websocket/WebSocketService-method-action-types.d.cts.map +1 -0
  242. package/dist/websocket/WebSocketService-method-action-types.d.mts +54 -0
  243. package/dist/websocket/WebSocketService-method-action-types.d.mts.map +1 -0
  244. package/dist/websocket/WebSocketService-method-action-types.mjs +6 -0
  245. package/dist/websocket/WebSocketService-method-action-types.mjs.map +1 -0
  246. package/dist/websocket/WebSocketService.cjs +14 -11
  247. package/dist/websocket/WebSocketService.cjs.map +1 -1
  248. package/dist/websocket/WebSocketService.d.cts +43 -22
  249. package/dist/websocket/WebSocketService.d.cts.map +1 -1
  250. package/dist/websocket/WebSocketService.d.mts +43 -22
  251. package/dist/websocket/WebSocketService.d.mts.map +1 -1
  252. package/dist/websocket/WebSocketService.mjs +14 -11
  253. package/dist/websocket/WebSocketService.mjs.map +1 -1
  254. package/dist/websocket/index.cjs +3 -15
  255. package/dist/websocket/index.cjs.map +1 -1
  256. package/dist/websocket/index.d.cts +3 -1
  257. package/dist/websocket/index.d.cts.map +1 -1
  258. package/dist/websocket/index.d.mts +3 -1
  259. package/dist/websocket/index.d.mts.map +1 -1
  260. package/dist/websocket/index.mjs +1 -1
  261. package/dist/websocket/index.mjs.map +1 -1
  262. package/package.json +12 -11
  263. package/dist/multichain/MultichainRouter.cjs.map +0 -1
  264. package/dist/multichain/MultichainRouter.d.cts.map +0 -1
  265. package/dist/multichain/MultichainRouter.d.mts.map +0 -1
  266. package/dist/multichain/MultichainRouter.mjs.map +0 -1
  267. package/dist/services/AbstractExecutionService.cjs +0 -314
  268. package/dist/services/AbstractExecutionService.cjs.map +0 -1
  269. package/dist/services/AbstractExecutionService.d.cts +0 -107
  270. package/dist/services/AbstractExecutionService.d.cts.map +0 -1
  271. package/dist/services/AbstractExecutionService.d.mts +0 -107
  272. package/dist/services/AbstractExecutionService.d.mts.map +0 -1
  273. package/dist/services/AbstractExecutionService.mjs +0 -313
  274. package/dist/services/AbstractExecutionService.mjs.map +0 -1
  275. package/dist/snaps/registry/json.cjs.map +0 -1
  276. package/dist/snaps/registry/json.d.cts +0 -58
  277. package/dist/snaps/registry/json.d.cts.map +0 -1
  278. package/dist/snaps/registry/json.d.mts +0 -58
  279. package/dist/snaps/registry/json.d.mts.map +0 -1
  280. package/dist/snaps/registry/json.mjs.map +0 -1
  281. package/dist/snaps/registry/registry.cjs +0 -11
  282. package/dist/snaps/registry/registry.cjs.map +0 -1
  283. package/dist/snaps/registry/registry.d.cts +0 -41
  284. package/dist/snaps/registry/registry.d.cts.map +0 -1
  285. package/dist/snaps/registry/registry.d.mts +0 -41
  286. package/dist/snaps/registry/registry.d.mts.map +0 -1
  287. package/dist/snaps/registry/registry.mjs +0 -8
  288. package/dist/snaps/registry/registry.mjs.map +0 -1
@@ -7,6 +7,12 @@ const utils_1 = require("@metamask/utils");
7
7
  const nanoid_1 = require("nanoid");
8
8
  const snaps_1 = require("../snaps/index.cjs");
9
9
  const serviceName = 'WebSocketService';
10
+ const MESSENGER_EXPOSED_METHODS = [
11
+ 'open',
12
+ 'close',
13
+ 'sendMessage',
14
+ 'getAll',
15
+ ];
10
16
  class WebSocketService {
11
17
  name = serviceName;
12
18
  state = null;
@@ -15,10 +21,7 @@ class WebSocketService {
15
21
  constructor({ messenger }) {
16
22
  this.#messenger = messenger;
17
23
  this.#sockets = new Map();
18
- this.#messenger.registerActionHandler(`${serviceName}:open`, async (...args) => this.#open(...args));
19
- this.#messenger.registerActionHandler(`${serviceName}:close`, (...args) => this.#close(...args));
20
- this.#messenger.registerActionHandler(`${serviceName}:sendMessage`, async (...args) => this.#sendMessage(...args));
21
- this.#messenger.registerActionHandler(`${serviceName}:getAll`, (...args) => this.#getAll(...args));
24
+ this.#messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
22
25
  this.#messenger.subscribe('SnapController:snapUpdated', (snap) => {
23
26
  this.#closeAll(snap.id);
24
27
  });
@@ -53,7 +56,7 @@ class WebSocketService {
53
56
  * @returns True if a matching connection already exists, otherwise false.
54
57
  */
55
58
  #exists(snapId, url, protocols) {
56
- return this.#getAll(snapId).some((socket) => socket.url === url && (0, snaps_utils_1.isEqual)(socket.protocols, protocols));
59
+ return this.getAll(snapId).some((socket) => socket.url === url && (0, snaps_utils_1.isEqual)(socket.protocols, protocols));
57
60
  }
58
61
  /**
59
62
  * Handle sending a specific WebSocketEvent to a Snap.
@@ -82,7 +85,7 @@ class WebSocketService {
82
85
  * @returns The identifier for the opened connection.
83
86
  * @throws If the connection fails.
84
87
  */
85
- async #open(snapId, url, protocols = []) {
88
+ async open(snapId, url, protocols = []) {
86
89
  (0, utils_1.assert)(!this.#exists(snapId, url, protocols), `An open WebSocket connection to ${url} already exists.`);
87
90
  const parsedUrl = new URL(url);
88
91
  const { origin } = parsedUrl;
@@ -149,7 +152,7 @@ class WebSocketService {
149
152
  * @param snapId - The Snap ID.
150
153
  * @param id - The identifier for the WebSocket connection.
151
154
  */
152
- #close(snapId, id) {
155
+ close(snapId, id) {
153
156
  const { socket } = this.#get(snapId, id);
154
157
  socket.close();
155
158
  }
@@ -159,8 +162,8 @@ class WebSocketService {
159
162
  * @param snapId - The Snap ID.
160
163
  */
161
164
  #closeAll(snapId) {
162
- for (const socket of this.#getAll(snapId)) {
163
- this.#close(snapId, socket.id);
165
+ for (const socket of this.getAll(snapId)) {
166
+ this.close(snapId, socket.id);
164
167
  }
165
168
  }
166
169
  /**
@@ -170,7 +173,7 @@ class WebSocketService {
170
173
  * @param id - The identifier for the WebSocket connection.
171
174
  * @param data - The message to send.
172
175
  */
173
- async #sendMessage(snapId, id, data) {
176
+ async sendMessage(snapId, id, data) {
174
177
  const { socket, openPromise } = this.#get(snapId, id);
175
178
  await openPromise;
176
179
  const wrappedData = Array.isArray(data) ? new Uint8Array(data) : data;
@@ -182,7 +185,7 @@ class WebSocketService {
182
185
  * @param snapId - The Snap ID.
183
186
  * @returns A list of WebSocket connections.
184
187
  */
185
- #getAll(snapId) {
188
+ getAll(snapId) {
186
189
  return [...this.#sockets.values()]
187
190
  .filter((socket) => socket.snapId === snapId)
188
191
  .map((socket) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"WebSocketService.cjs","sourceRoot":"","sources":["../../src/websocket/WebSocketService.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Messenger } from '@metamask/messenger';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type {\n GetWebSocketsResult,\n SnapId,\n WebSocketEvent,\n} from '@metamask/snaps-sdk';\nimport { HandlerType, isEqual, logError } from '@metamask/snaps-utils';\nimport { assert, createDeferredPromise } from '@metamask/utils';\nimport { nanoid } from 'nanoid';\n\nimport type {\n HandleSnapRequest,\n SnapInstalled,\n SnapUninstalled,\n SnapUpdated,\n} from '../snaps';\nimport { METAMASK_ORIGIN } from '../snaps';\n\nconst serviceName = 'WebSocketService';\n\nexport type WebSocketServiceOpenAction = {\n type: `${typeof serviceName}:open`;\n handler: (\n snapId: SnapId,\n url: string,\n protocols?: string[],\n ) => Promise<string>;\n};\n\nexport type WebSocketServiceCloseAction = {\n type: `${typeof serviceName}:close`;\n handler: (snapId: SnapId, id: string) => void;\n};\n\nexport type WebSocketServiceSendMessageAction = {\n type: `${typeof serviceName}:sendMessage`;\n handler: (\n snapId: SnapId,\n id: string,\n data: string | number[],\n ) => Promise<void>;\n};\n\nexport type WebSocketServiceGetAllAction = {\n type: `${typeof serviceName}:getAll`;\n handler: (snapId: SnapId) => GetWebSocketsResult;\n};\n\nexport type WebSocketServiceActions =\n | WebSocketServiceOpenAction\n | WebSocketServiceCloseAction\n | WebSocketServiceSendMessageAction\n | WebSocketServiceGetAllAction;\n\nexport type WebSocketServiceAllowedActions = HandleSnapRequest;\n\nexport type WebSocketServiceEvents =\n | SnapUninstalled\n | SnapUpdated\n | SnapInstalled;\n\nexport type WebSocketServiceMessenger = Messenger<\n 'WebSocketService',\n WebSocketServiceActions | WebSocketServiceAllowedActions,\n WebSocketServiceEvents\n>;\n\ntype WebSocketServiceArgs = {\n messenger: WebSocketServiceMessenger;\n};\n\ntype InternalSocket = {\n id: string;\n snapId: SnapId;\n url: string;\n protocols: string[];\n openPromise: Promise<void>;\n // eslint-disable-next-line no-restricted-globals\n socket: WebSocket;\n};\n\nexport class WebSocketService {\n name: typeof serviceName = serviceName;\n\n state = null;\n\n readonly #messenger: WebSocketServiceMessenger;\n\n readonly #sockets: Map<string, InternalSocket>;\n\n constructor({ messenger }: WebSocketServiceArgs) {\n this.#messenger = messenger;\n this.#sockets = new Map();\n\n this.#messenger.registerActionHandler(\n `${serviceName}:open`,\n async (...args) => this.#open(...args),\n );\n\n this.#messenger.registerActionHandler(`${serviceName}:close`, (...args) =>\n this.#close(...args),\n );\n\n this.#messenger.registerActionHandler(\n `${serviceName}:sendMessage`,\n async (...args) => this.#sendMessage(...args),\n );\n\n this.#messenger.registerActionHandler(`${serviceName}:getAll`, (...args) =>\n this.#getAll(...args),\n );\n\n this.#messenger.subscribe('SnapController:snapUpdated', (snap) => {\n this.#closeAll(snap.id);\n });\n\n this.#messenger.subscribe('SnapController:snapUninstalled', (snap) => {\n this.#closeAll(snap.id);\n });\n\n // Due to local Snaps not currently emitting snapUninstalled we also have to\n // listen to snapInstalled.\n this.#messenger.subscribe('SnapController:snapInstalled', (snap) => {\n this.#closeAll(snap.id);\n });\n }\n\n /**\n * Get information about a given WebSocket connection with an ID.\n *\n * @param snapId - The Snap ID.\n * @param id - The identifier for the WebSocket connection.\n * @returns Information about the WebSocket connection.\n * @throws If the WebSocket connection cannot be found.\n */\n #get(snapId: SnapId, id: string) {\n const socket = this.#sockets.get(id);\n\n assert(\n socket && socket.snapId === snapId,\n `Socket with ID \"${id}\" not found.`,\n );\n\n return socket;\n }\n\n /**\n * Check whether a given Snap ID already has an open connection for a URL and protocol.\n *\n * @param snapId - The Snap ID.\n * @param url - The URL.\n * @param protocols - A protocols parameter.\n * @returns True if a matching connection already exists, otherwise false.\n */\n #exists(snapId: SnapId, url: string, protocols: string[]) {\n return this.#getAll(snapId).some(\n (socket) => socket.url === url && isEqual(socket.protocols, protocols),\n );\n }\n\n /**\n * Handle sending a specific WebSocketEvent to a Snap.\n *\n * @param snapId - The Snap ID.\n * @param event - The WebSocketEvent.\n */\n #handleEvent(snapId: SnapId, event: WebSocketEvent) {\n this.#messenger\n .call('SnapController:handleRequest', {\n origin: METAMASK_ORIGIN,\n snapId,\n handler: HandlerType.OnWebSocketEvent,\n request: { method: '', params: { event } },\n })\n .catch((error) => {\n logError(\n `An error occurred while handling a WebSocket message for Snap \"${snapId}\":`,\n error,\n );\n });\n }\n\n /**\n * Open a WebSocket connection.\n *\n * @param snapId - The Snap ID.\n * @param url - The URL for the WebSocket connection.\n * @param protocols - An optional parameter for protocols.\n * @returns The identifier for the opened connection.\n * @throws If the connection fails.\n */\n async #open(snapId: SnapId, url: string, protocols: string[] = []) {\n assert(\n !this.#exists(snapId, url, protocols),\n `An open WebSocket connection to ${url} already exists.`,\n );\n\n const parsedUrl = new URL(url);\n const { origin } = parsedUrl;\n\n const id = nanoid();\n\n // eslint-disable-next-line no-restricted-globals\n const socket = new WebSocket(url, protocols);\n socket.binaryType = 'arraybuffer';\n\n const { promise, resolve, reject } = createDeferredPromise();\n\n socket.addEventListener('open', () => {\n resolve();\n this.#handleEvent(snapId, {\n type: 'open',\n id,\n origin,\n });\n });\n\n socket.addEventListener('close', (event) => {\n this.#sockets.delete(id);\n\n this.#handleEvent(snapId, {\n type: 'close',\n id,\n origin,\n code: event.code,\n reason: event.reason,\n // wasClean is not available on mobile.\n wasClean: event.wasClean ?? null,\n });\n });\n\n const errorListener = () => {\n reject(\n rpcErrors.resourceUnavailable(\n 'An error occurred while opening the WebSocket.',\n ),\n );\n };\n\n socket.addEventListener('error', errorListener);\n\n socket.addEventListener('message', (event) => {\n const isText = typeof event.data === 'string';\n const data = isText\n ? { type: 'text' as const, message: event.data }\n : {\n type: 'binary' as const,\n // We request that the WebSocket gives us an array buffer.\n message: Array.from(new Uint8Array(event.data)),\n };\n\n this.#handleEvent(snapId, {\n type: 'message',\n id,\n origin,\n data,\n });\n });\n\n this.#sockets.set(id, {\n id,\n snapId,\n url,\n protocols,\n socket,\n openPromise: promise,\n });\n\n await promise;\n\n socket.removeEventListener('error', errorListener);\n\n return id;\n }\n\n /**\n * Close a given WebSocket connection.\n *\n * @param snapId - The Snap ID.\n * @param id - The identifier for the WebSocket connection.\n */\n #close(snapId: SnapId, id: string) {\n const { socket } = this.#get(snapId, id);\n\n socket.close();\n }\n\n /**\n * Close all open connections for a given Snap ID.\n *\n * @param snapId - The Snap ID.\n */\n #closeAll(snapId: SnapId) {\n for (const socket of this.#getAll(snapId)) {\n this.#close(snapId, socket.id);\n }\n }\n\n /**\n * Send a message from a given Snap ID to a WebSocket connection.\n *\n * @param snapId - The Snap ID.\n * @param id - The identifier for the WebSocket connection.\n * @param data - The message to send.\n */\n async #sendMessage(snapId: SnapId, id: string, data: string | number[]) {\n const { socket, openPromise } = this.#get(snapId, id);\n\n await openPromise;\n\n const wrappedData = Array.isArray(data) ? new Uint8Array(data) : data;\n\n socket.send(wrappedData);\n }\n\n /**\n * Get a list of all open WebSocket connections for a Snap ID.\n *\n * @param snapId - The Snap ID.\n * @returns A list of WebSocket connections.\n */\n #getAll(snapId: SnapId) {\n return [...this.#sockets.values()]\n .filter((socket) => socket.snapId === snapId)\n .map((socket) => ({\n id: socket.id,\n url: socket.url,\n protocols: socket.protocols,\n }));\n }\n}\n"]}
1
+ {"version":3,"file":"WebSocketService.cjs","sourceRoot":"","sources":["../../src/websocket/WebSocketService.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Messenger } from '@metamask/messenger';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { SnapId, WebSocketEvent } from '@metamask/snaps-sdk';\nimport { HandlerType, isEqual, logError } from '@metamask/snaps-utils';\nimport { assert, createDeferredPromise } from '@metamask/utils';\nimport { nanoid } from 'nanoid';\n\nimport type { WebSocketServiceMethodActions } from './WebSocketService-method-action-types';\nimport type {\n SnapControllerHandleRequestAction,\n SnapControllerSnapInstalledEvent,\n SnapControllerSnapUninstalledEvent,\n SnapControllerSnapUpdatedEvent,\n} from '../snaps';\nimport { METAMASK_ORIGIN } from '../snaps';\n\nconst serviceName = 'WebSocketService';\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'open',\n 'close',\n 'sendMessage',\n 'getAll',\n] as const;\n\nexport type WebSocketServiceActions = WebSocketServiceMethodActions;\n\ntype AllowedActions = SnapControllerHandleRequestAction;\n\ntype AllowedEvents =\n | SnapControllerSnapUninstalledEvent\n | SnapControllerSnapUpdatedEvent\n | SnapControllerSnapInstalledEvent;\n\nexport type WebSocketServiceMessenger = Messenger<\n 'WebSocketService',\n WebSocketServiceActions | AllowedActions,\n AllowedEvents\n>;\n\ntype WebSocketServiceArgs = {\n messenger: WebSocketServiceMessenger;\n};\n\ntype InternalSocket = {\n id: string;\n snapId: SnapId;\n url: string;\n protocols: string[];\n openPromise: Promise<void>;\n // eslint-disable-next-line no-restricted-globals\n socket: WebSocket;\n};\n\nexport class WebSocketService {\n name: typeof serviceName = serviceName;\n\n state = null;\n\n readonly #messenger: WebSocketServiceMessenger;\n\n readonly #sockets: Map<string, InternalSocket>;\n\n constructor({ messenger }: WebSocketServiceArgs) {\n this.#messenger = messenger;\n this.#sockets = new Map();\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n this.#messenger.subscribe('SnapController:snapUpdated', (snap) => {\n this.#closeAll(snap.id);\n });\n\n this.#messenger.subscribe('SnapController:snapUninstalled', (snap) => {\n this.#closeAll(snap.id);\n });\n\n // Due to local Snaps not currently emitting snapUninstalled we also have to\n // listen to snapInstalled.\n this.#messenger.subscribe('SnapController:snapInstalled', (snap) => {\n this.#closeAll(snap.id);\n });\n }\n\n /**\n * Get information about a given WebSocket connection with an ID.\n *\n * @param snapId - The Snap ID.\n * @param id - The identifier for the WebSocket connection.\n * @returns Information about the WebSocket connection.\n * @throws If the WebSocket connection cannot be found.\n */\n #get(snapId: SnapId, id: string) {\n const socket = this.#sockets.get(id);\n\n assert(\n socket && socket.snapId === snapId,\n `Socket with ID \"${id}\" not found.`,\n );\n\n return socket;\n }\n\n /**\n * Check whether a given Snap ID already has an open connection for a URL and protocol.\n *\n * @param snapId - The Snap ID.\n * @param url - The URL.\n * @param protocols - A protocols parameter.\n * @returns True if a matching connection already exists, otherwise false.\n */\n #exists(snapId: SnapId, url: string, protocols: string[]) {\n return this.getAll(snapId).some(\n (socket) => socket.url === url && isEqual(socket.protocols, protocols),\n );\n }\n\n /**\n * Handle sending a specific WebSocketEvent to a Snap.\n *\n * @param snapId - The Snap ID.\n * @param event - The WebSocketEvent.\n */\n #handleEvent(snapId: SnapId, event: WebSocketEvent) {\n this.#messenger\n .call('SnapController:handleRequest', {\n origin: METAMASK_ORIGIN,\n snapId,\n handler: HandlerType.OnWebSocketEvent,\n request: { method: '', params: { event } },\n })\n .catch((error) => {\n logError(\n `An error occurred while handling a WebSocket message for Snap \"${snapId}\":`,\n error,\n );\n });\n }\n\n /**\n * Open a WebSocket connection.\n *\n * @param snapId - The Snap ID.\n * @param url - The URL for the WebSocket connection.\n * @param protocols - An optional parameter for protocols.\n * @returns The identifier for the opened connection.\n * @throws If the connection fails.\n */\n async open(snapId: SnapId, url: string, protocols: string[] = []) {\n assert(\n !this.#exists(snapId, url, protocols),\n `An open WebSocket connection to ${url} already exists.`,\n );\n\n const parsedUrl = new URL(url);\n const { origin } = parsedUrl;\n\n const id = nanoid();\n\n // eslint-disable-next-line no-restricted-globals\n const socket = new WebSocket(url, protocols);\n socket.binaryType = 'arraybuffer';\n\n const { promise, resolve, reject } = createDeferredPromise();\n\n socket.addEventListener('open', () => {\n resolve();\n this.#handleEvent(snapId, {\n type: 'open',\n id,\n origin,\n });\n });\n\n socket.addEventListener('close', (event) => {\n this.#sockets.delete(id);\n\n this.#handleEvent(snapId, {\n type: 'close',\n id,\n origin,\n code: event.code,\n reason: event.reason,\n // wasClean is not available on mobile.\n wasClean: event.wasClean ?? null,\n });\n });\n\n const errorListener = () => {\n reject(\n rpcErrors.resourceUnavailable(\n 'An error occurred while opening the WebSocket.',\n ),\n );\n };\n\n socket.addEventListener('error', errorListener);\n\n socket.addEventListener('message', (event) => {\n const isText = typeof event.data === 'string';\n const data = isText\n ? { type: 'text' as const, message: event.data }\n : {\n type: 'binary' as const,\n // We request that the WebSocket gives us an array buffer.\n message: Array.from(new Uint8Array(event.data)),\n };\n\n this.#handleEvent(snapId, {\n type: 'message',\n id,\n origin,\n data,\n });\n });\n\n this.#sockets.set(id, {\n id,\n snapId,\n url,\n protocols,\n socket,\n openPromise: promise,\n });\n\n await promise;\n\n socket.removeEventListener('error', errorListener);\n\n return id;\n }\n\n /**\n * Close a given WebSocket connection.\n *\n * @param snapId - The Snap ID.\n * @param id - The identifier for the WebSocket connection.\n */\n close(snapId: SnapId, id: string) {\n const { socket } = this.#get(snapId, id);\n\n socket.close();\n }\n\n /**\n * Close all open connections for a given Snap ID.\n *\n * @param snapId - The Snap ID.\n */\n #closeAll(snapId: SnapId) {\n for (const socket of this.getAll(snapId)) {\n this.close(snapId, socket.id);\n }\n }\n\n /**\n * Send a message from a given Snap ID to a WebSocket connection.\n *\n * @param snapId - The Snap ID.\n * @param id - The identifier for the WebSocket connection.\n * @param data - The message to send.\n */\n async sendMessage(snapId: SnapId, id: string, data: string | number[]) {\n const { socket, openPromise } = this.#get(snapId, id);\n\n await openPromise;\n\n const wrappedData = Array.isArray(data) ? new Uint8Array(data) : data;\n\n socket.send(wrappedData);\n }\n\n /**\n * Get a list of all open WebSocket connections for a Snap ID.\n *\n * @param snapId - The Snap ID.\n * @returns A list of WebSocket connections.\n */\n getAll(snapId: SnapId) {\n return [...this.#sockets.values()]\n .filter((socket) => socket.snapId === snapId)\n .map((socket) => ({\n id: socket.id,\n url: socket.url,\n protocols: socket.protocols,\n }));\n }\n}\n"]}
@@ -1,27 +1,12 @@
1
1
  import type { Messenger } from "@metamask/messenger";
2
- import type { GetWebSocketsResult, SnapId } from "@metamask/snaps-sdk";
3
- import type { HandleSnapRequest, SnapInstalled, SnapUninstalled, SnapUpdated } from "../snaps/index.cjs";
2
+ import type { SnapId } from "@metamask/snaps-sdk";
3
+ import type { WebSocketServiceMethodActions } from "./WebSocketService-method-action-types.cjs";
4
+ import type { SnapControllerHandleRequestAction, SnapControllerSnapInstalledEvent, SnapControllerSnapUninstalledEvent, SnapControllerSnapUpdatedEvent } from "../snaps/index.cjs";
4
5
  declare const serviceName = "WebSocketService";
5
- export type WebSocketServiceOpenAction = {
6
- type: `${typeof serviceName}:open`;
7
- handler: (snapId: SnapId, url: string, protocols?: string[]) => Promise<string>;
8
- };
9
- export type WebSocketServiceCloseAction = {
10
- type: `${typeof serviceName}:close`;
11
- handler: (snapId: SnapId, id: string) => void;
12
- };
13
- export type WebSocketServiceSendMessageAction = {
14
- type: `${typeof serviceName}:sendMessage`;
15
- handler: (snapId: SnapId, id: string, data: string | number[]) => Promise<void>;
16
- };
17
- export type WebSocketServiceGetAllAction = {
18
- type: `${typeof serviceName}:getAll`;
19
- handler: (snapId: SnapId) => GetWebSocketsResult;
20
- };
21
- export type WebSocketServiceActions = WebSocketServiceOpenAction | WebSocketServiceCloseAction | WebSocketServiceSendMessageAction | WebSocketServiceGetAllAction;
22
- export type WebSocketServiceAllowedActions = HandleSnapRequest;
23
- export type WebSocketServiceEvents = SnapUninstalled | SnapUpdated | SnapInstalled;
24
- export type WebSocketServiceMessenger = Messenger<'WebSocketService', WebSocketServiceActions | WebSocketServiceAllowedActions, WebSocketServiceEvents>;
6
+ export type WebSocketServiceActions = WebSocketServiceMethodActions;
7
+ type AllowedActions = SnapControllerHandleRequestAction;
8
+ type AllowedEvents = SnapControllerSnapUninstalledEvent | SnapControllerSnapUpdatedEvent | SnapControllerSnapInstalledEvent;
9
+ export type WebSocketServiceMessenger = Messenger<'WebSocketService', WebSocketServiceActions | AllowedActions, AllowedEvents>;
25
10
  type WebSocketServiceArgs = {
26
11
  messenger: WebSocketServiceMessenger;
27
12
  };
@@ -30,6 +15,42 @@ export declare class WebSocketService {
30
15
  name: typeof serviceName;
31
16
  state: null;
32
17
  constructor({ messenger }: WebSocketServiceArgs);
18
+ /**
19
+ * Open a WebSocket connection.
20
+ *
21
+ * @param snapId - The Snap ID.
22
+ * @param url - The URL for the WebSocket connection.
23
+ * @param protocols - An optional parameter for protocols.
24
+ * @returns The identifier for the opened connection.
25
+ * @throws If the connection fails.
26
+ */
27
+ open(snapId: SnapId, url: string, protocols?: string[]): Promise<string>;
28
+ /**
29
+ * Close a given WebSocket connection.
30
+ *
31
+ * @param snapId - The Snap ID.
32
+ * @param id - The identifier for the WebSocket connection.
33
+ */
34
+ close(snapId: SnapId, id: string): void;
35
+ /**
36
+ * Send a message from a given Snap ID to a WebSocket connection.
37
+ *
38
+ * @param snapId - The Snap ID.
39
+ * @param id - The identifier for the WebSocket connection.
40
+ * @param data - The message to send.
41
+ */
42
+ sendMessage(snapId: SnapId, id: string, data: string | number[]): Promise<void>;
43
+ /**
44
+ * Get a list of all open WebSocket connections for a Snap ID.
45
+ *
46
+ * @param snapId - The Snap ID.
47
+ * @returns A list of WebSocket connections.
48
+ */
49
+ getAll(snapId: SnapId): {
50
+ id: string;
51
+ url: string;
52
+ protocols: string[];
53
+ }[];
33
54
  }
34
55
  export {};
35
56
  //# sourceMappingURL=WebSocketService.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WebSocketService.d.cts","sourceRoot":"","sources":["../../src/websocket/WebSocketService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,KAAK,EACV,mBAAmB,EACnB,MAAM,EAEP,4BAA4B;AAK7B,OAAO,KAAK,EACV,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,WAAW,EACZ,2BAAiB;AAGlB,QAAA,MAAM,WAAW,qBAAqB,CAAC;AAEvC,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,GAAG,OAAO,WAAW,OAAO,CAAC;IACnC,OAAO,EAAE,CACP,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAAE,KACjB,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,GAAG,OAAO,WAAW,QAAQ,CAAC;IACpC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/C,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,IAAI,EAAE,GAAG,OAAO,WAAW,cAAc,CAAC;IAC1C,OAAO,EAAE,CACP,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,KACpB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,IAAI,EAAE,GAAG,OAAO,WAAW,SAAS,CAAC;IACrC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,mBAAmB,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAC/B,0BAA0B,GAC1B,2BAA2B,GAC3B,iCAAiC,GACjC,4BAA4B,CAAC;AAEjC,MAAM,MAAM,8BAA8B,GAAG,iBAAiB,CAAC;AAE/D,MAAM,MAAM,sBAAsB,GAC9B,eAAe,GACf,WAAW,GACX,aAAa,CAAC;AAElB,MAAM,MAAM,yBAAyB,GAAG,SAAS,CAC/C,kBAAkB,EAClB,uBAAuB,GAAG,8BAA8B,EACxD,sBAAsB,CACvB,CAAC;AAEF,KAAK,oBAAoB,GAAG;IAC1B,SAAS,EAAE,yBAAyB,CAAC;CACtC,CAAC;AAYF,qBAAa,gBAAgB;;IAC3B,IAAI,EAAE,OAAO,WAAW,CAAe;IAEvC,KAAK,OAAQ;gBAMD,EAAE,SAAS,EAAE,EAAE,oBAAoB;CAgPhD"}
1
+ {"version":3,"file":"WebSocketService.d.cts","sourceRoot":"","sources":["../../src/websocket/WebSocketService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,KAAK,EAAE,MAAM,EAAkB,4BAA4B;AAKlE,OAAO,KAAK,EAAE,6BAA6B,EAAE,mDAA+C;AAC5F,OAAO,KAAK,EACV,iCAAiC,EACjC,gCAAgC,EAChC,kCAAkC,EAClC,8BAA8B,EAC/B,2BAAiB;AAGlB,QAAA,MAAM,WAAW,qBAAqB,CAAC;AASvC,MAAM,MAAM,uBAAuB,GAAG,6BAA6B,CAAC;AAEpE,KAAK,cAAc,GAAG,iCAAiC,CAAC;AAExD,KAAK,aAAa,GACd,kCAAkC,GAClC,8BAA8B,GAC9B,gCAAgC,CAAC;AAErC,MAAM,MAAM,yBAAyB,GAAG,SAAS,CAC/C,kBAAkB,EAClB,uBAAuB,GAAG,cAAc,EACxC,aAAa,CACd,CAAC;AAEF,KAAK,oBAAoB,GAAG;IAC1B,SAAS,EAAE,yBAAyB,CAAC;CACtC,CAAC;AAYF,qBAAa,gBAAgB;;IAC3B,IAAI,EAAE,OAAO,WAAW,CAAe;IAEvC,KAAK,OAAQ;gBAMD,EAAE,SAAS,EAAE,EAAE,oBAAoB;IA+E/C;;;;;;;;OAQG;IACG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,GAAE,MAAM,EAAO;IAoFhE;;;;;OAKG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAiBhC;;;;;;OAMG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAUrE;;;;;OAKG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM;;;;;CAStB"}
@@ -1,27 +1,12 @@
1
1
  import type { Messenger } from "@metamask/messenger";
2
- import type { GetWebSocketsResult, SnapId } from "@metamask/snaps-sdk";
3
- import type { HandleSnapRequest, SnapInstalled, SnapUninstalled, SnapUpdated } from "../snaps/index.mjs";
2
+ import type { SnapId } from "@metamask/snaps-sdk";
3
+ import type { WebSocketServiceMethodActions } from "./WebSocketService-method-action-types.mjs";
4
+ import type { SnapControllerHandleRequestAction, SnapControllerSnapInstalledEvent, SnapControllerSnapUninstalledEvent, SnapControllerSnapUpdatedEvent } from "../snaps/index.mjs";
4
5
  declare const serviceName = "WebSocketService";
5
- export type WebSocketServiceOpenAction = {
6
- type: `${typeof serviceName}:open`;
7
- handler: (snapId: SnapId, url: string, protocols?: string[]) => Promise<string>;
8
- };
9
- export type WebSocketServiceCloseAction = {
10
- type: `${typeof serviceName}:close`;
11
- handler: (snapId: SnapId, id: string) => void;
12
- };
13
- export type WebSocketServiceSendMessageAction = {
14
- type: `${typeof serviceName}:sendMessage`;
15
- handler: (snapId: SnapId, id: string, data: string | number[]) => Promise<void>;
16
- };
17
- export type WebSocketServiceGetAllAction = {
18
- type: `${typeof serviceName}:getAll`;
19
- handler: (snapId: SnapId) => GetWebSocketsResult;
20
- };
21
- export type WebSocketServiceActions = WebSocketServiceOpenAction | WebSocketServiceCloseAction | WebSocketServiceSendMessageAction | WebSocketServiceGetAllAction;
22
- export type WebSocketServiceAllowedActions = HandleSnapRequest;
23
- export type WebSocketServiceEvents = SnapUninstalled | SnapUpdated | SnapInstalled;
24
- export type WebSocketServiceMessenger = Messenger<'WebSocketService', WebSocketServiceActions | WebSocketServiceAllowedActions, WebSocketServiceEvents>;
6
+ export type WebSocketServiceActions = WebSocketServiceMethodActions;
7
+ type AllowedActions = SnapControllerHandleRequestAction;
8
+ type AllowedEvents = SnapControllerSnapUninstalledEvent | SnapControllerSnapUpdatedEvent | SnapControllerSnapInstalledEvent;
9
+ export type WebSocketServiceMessenger = Messenger<'WebSocketService', WebSocketServiceActions | AllowedActions, AllowedEvents>;
25
10
  type WebSocketServiceArgs = {
26
11
  messenger: WebSocketServiceMessenger;
27
12
  };
@@ -30,6 +15,42 @@ export declare class WebSocketService {
30
15
  name: typeof serviceName;
31
16
  state: null;
32
17
  constructor({ messenger }: WebSocketServiceArgs);
18
+ /**
19
+ * Open a WebSocket connection.
20
+ *
21
+ * @param snapId - The Snap ID.
22
+ * @param url - The URL for the WebSocket connection.
23
+ * @param protocols - An optional parameter for protocols.
24
+ * @returns The identifier for the opened connection.
25
+ * @throws If the connection fails.
26
+ */
27
+ open(snapId: SnapId, url: string, protocols?: string[]): Promise<string>;
28
+ /**
29
+ * Close a given WebSocket connection.
30
+ *
31
+ * @param snapId - The Snap ID.
32
+ * @param id - The identifier for the WebSocket connection.
33
+ */
34
+ close(snapId: SnapId, id: string): void;
35
+ /**
36
+ * Send a message from a given Snap ID to a WebSocket connection.
37
+ *
38
+ * @param snapId - The Snap ID.
39
+ * @param id - The identifier for the WebSocket connection.
40
+ * @param data - The message to send.
41
+ */
42
+ sendMessage(snapId: SnapId, id: string, data: string | number[]): Promise<void>;
43
+ /**
44
+ * Get a list of all open WebSocket connections for a Snap ID.
45
+ *
46
+ * @param snapId - The Snap ID.
47
+ * @returns A list of WebSocket connections.
48
+ */
49
+ getAll(snapId: SnapId): {
50
+ id: string;
51
+ url: string;
52
+ protocols: string[];
53
+ }[];
33
54
  }
34
55
  export {};
35
56
  //# sourceMappingURL=WebSocketService.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WebSocketService.d.mts","sourceRoot":"","sources":["../../src/websocket/WebSocketService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,KAAK,EACV,mBAAmB,EACnB,MAAM,EAEP,4BAA4B;AAK7B,OAAO,KAAK,EACV,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,WAAW,EACZ,2BAAiB;AAGlB,QAAA,MAAM,WAAW,qBAAqB,CAAC;AAEvC,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,GAAG,OAAO,WAAW,OAAO,CAAC;IACnC,OAAO,EAAE,CACP,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAAE,KACjB,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,GAAG,OAAO,WAAW,QAAQ,CAAC;IACpC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/C,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,IAAI,EAAE,GAAG,OAAO,WAAW,cAAc,CAAC;IAC1C,OAAO,EAAE,CACP,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,KACpB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,IAAI,EAAE,GAAG,OAAO,WAAW,SAAS,CAAC;IACrC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,mBAAmB,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAC/B,0BAA0B,GAC1B,2BAA2B,GAC3B,iCAAiC,GACjC,4BAA4B,CAAC;AAEjC,MAAM,MAAM,8BAA8B,GAAG,iBAAiB,CAAC;AAE/D,MAAM,MAAM,sBAAsB,GAC9B,eAAe,GACf,WAAW,GACX,aAAa,CAAC;AAElB,MAAM,MAAM,yBAAyB,GAAG,SAAS,CAC/C,kBAAkB,EAClB,uBAAuB,GAAG,8BAA8B,EACxD,sBAAsB,CACvB,CAAC;AAEF,KAAK,oBAAoB,GAAG;IAC1B,SAAS,EAAE,yBAAyB,CAAC;CACtC,CAAC;AAYF,qBAAa,gBAAgB;;IAC3B,IAAI,EAAE,OAAO,WAAW,CAAe;IAEvC,KAAK,OAAQ;gBAMD,EAAE,SAAS,EAAE,EAAE,oBAAoB;CAgPhD"}
1
+ {"version":3,"file":"WebSocketService.d.mts","sourceRoot":"","sources":["../../src/websocket/WebSocketService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,KAAK,EAAE,MAAM,EAAkB,4BAA4B;AAKlE,OAAO,KAAK,EAAE,6BAA6B,EAAE,mDAA+C;AAC5F,OAAO,KAAK,EACV,iCAAiC,EACjC,gCAAgC,EAChC,kCAAkC,EAClC,8BAA8B,EAC/B,2BAAiB;AAGlB,QAAA,MAAM,WAAW,qBAAqB,CAAC;AASvC,MAAM,MAAM,uBAAuB,GAAG,6BAA6B,CAAC;AAEpE,KAAK,cAAc,GAAG,iCAAiC,CAAC;AAExD,KAAK,aAAa,GACd,kCAAkC,GAClC,8BAA8B,GAC9B,gCAAgC,CAAC;AAErC,MAAM,MAAM,yBAAyB,GAAG,SAAS,CAC/C,kBAAkB,EAClB,uBAAuB,GAAG,cAAc,EACxC,aAAa,CACd,CAAC;AAEF,KAAK,oBAAoB,GAAG;IAC1B,SAAS,EAAE,yBAAyB,CAAC;CACtC,CAAC;AAYF,qBAAa,gBAAgB;;IAC3B,IAAI,EAAE,OAAO,WAAW,CAAe;IAEvC,KAAK,OAAQ;gBAMD,EAAE,SAAS,EAAE,EAAE,oBAAoB;IA+E/C;;;;;;;;OAQG;IACG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,GAAE,MAAM,EAAO;IAoFhE;;;;;OAKG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAiBhC;;;;;;OAMG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAUrE;;;;;OAKG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM;;;;;CAStB"}
@@ -4,6 +4,12 @@ import { assert, createDeferredPromise } from "@metamask/utils";
4
4
  import { nanoid } from "nanoid";
5
5
  import { METAMASK_ORIGIN } from "../snaps/index.mjs";
6
6
  const serviceName = 'WebSocketService';
7
+ const MESSENGER_EXPOSED_METHODS = [
8
+ 'open',
9
+ 'close',
10
+ 'sendMessage',
11
+ 'getAll',
12
+ ];
7
13
  export class WebSocketService {
8
14
  name = serviceName;
9
15
  state = null;
@@ -12,10 +18,7 @@ export class WebSocketService {
12
18
  constructor({ messenger }) {
13
19
  this.#messenger = messenger;
14
20
  this.#sockets = new Map();
15
- this.#messenger.registerActionHandler(`${serviceName}:open`, async (...args) => this.#open(...args));
16
- this.#messenger.registerActionHandler(`${serviceName}:close`, (...args) => this.#close(...args));
17
- this.#messenger.registerActionHandler(`${serviceName}:sendMessage`, async (...args) => this.#sendMessage(...args));
18
- this.#messenger.registerActionHandler(`${serviceName}:getAll`, (...args) => this.#getAll(...args));
21
+ this.#messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
19
22
  this.#messenger.subscribe('SnapController:snapUpdated', (snap) => {
20
23
  this.#closeAll(snap.id);
21
24
  });
@@ -50,7 +53,7 @@ export class WebSocketService {
50
53
  * @returns True if a matching connection already exists, otherwise false.
51
54
  */
52
55
  #exists(snapId, url, protocols) {
53
- return this.#getAll(snapId).some((socket) => socket.url === url && isEqual(socket.protocols, protocols));
56
+ return this.getAll(snapId).some((socket) => socket.url === url && isEqual(socket.protocols, protocols));
54
57
  }
55
58
  /**
56
59
  * Handle sending a specific WebSocketEvent to a Snap.
@@ -79,7 +82,7 @@ export class WebSocketService {
79
82
  * @returns The identifier for the opened connection.
80
83
  * @throws If the connection fails.
81
84
  */
82
- async #open(snapId, url, protocols = []) {
85
+ async open(snapId, url, protocols = []) {
83
86
  assert(!this.#exists(snapId, url, protocols), `An open WebSocket connection to ${url} already exists.`);
84
87
  const parsedUrl = new URL(url);
85
88
  const { origin } = parsedUrl;
@@ -146,7 +149,7 @@ export class WebSocketService {
146
149
  * @param snapId - The Snap ID.
147
150
  * @param id - The identifier for the WebSocket connection.
148
151
  */
149
- #close(snapId, id) {
152
+ close(snapId, id) {
150
153
  const { socket } = this.#get(snapId, id);
151
154
  socket.close();
152
155
  }
@@ -156,8 +159,8 @@ export class WebSocketService {
156
159
  * @param snapId - The Snap ID.
157
160
  */
158
161
  #closeAll(snapId) {
159
- for (const socket of this.#getAll(snapId)) {
160
- this.#close(snapId, socket.id);
162
+ for (const socket of this.getAll(snapId)) {
163
+ this.close(snapId, socket.id);
161
164
  }
162
165
  }
163
166
  /**
@@ -167,7 +170,7 @@ export class WebSocketService {
167
170
  * @param id - The identifier for the WebSocket connection.
168
171
  * @param data - The message to send.
169
172
  */
170
- async #sendMessage(snapId, id, data) {
173
+ async sendMessage(snapId, id, data) {
171
174
  const { socket, openPromise } = this.#get(snapId, id);
172
175
  await openPromise;
173
176
  const wrappedData = Array.isArray(data) ? new Uint8Array(data) : data;
@@ -179,7 +182,7 @@ export class WebSocketService {
179
182
  * @param snapId - The Snap ID.
180
183
  * @returns A list of WebSocket connections.
181
184
  */
182
- #getAll(snapId) {
185
+ getAll(snapId) {
183
186
  return [...this.#sockets.values()]
184
187
  .filter((socket) => socket.snapId === snapId)
185
188
  .map((socket) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"WebSocketService.mjs","sourceRoot":"","sources":["../../src/websocket/WebSocketService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,6BAA6B;AAMjD,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,8BAA8B;AACvE,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,wBAAwB;AAChE,OAAO,EAAE,MAAM,EAAE,eAAe;AAQhC,OAAO,EAAE,eAAe,EAAE,2BAAiB;AAE3C,MAAM,WAAW,GAAG,kBAAkB,CAAC;AA+DvC,MAAM,OAAO,gBAAgB;IAC3B,IAAI,GAAuB,WAAW,CAAC;IAEvC,KAAK,GAAG,IAAI,CAAC;IAEJ,UAAU,CAA4B;IAEtC,QAAQ,CAA8B;IAE/C,YAAY,EAAE,SAAS,EAAwB;QAC7C,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;QAE1B,IAAI,CAAC,UAAU,CAAC,qBAAqB,CACnC,GAAG,WAAW,OAAO,EACrB,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CACvC,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,qBAAqB,CAAC,GAAG,WAAW,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CACxE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CACrB,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,qBAAqB,CACnC,GAAG,WAAW,cAAc,EAC5B,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,CAC9C,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,qBAAqB,CAAC,GAAG,WAAW,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CACzE,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CACtB,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,4BAA4B,EAAE,CAAC,IAAI,EAAE,EAAE;YAC/D,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,gCAAgC,EAAE,CAAC,IAAI,EAAE,EAAE;YACnE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,4EAA4E;QAC5E,2BAA2B;QAC3B,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,8BAA8B,EAAE,CAAC,IAAI,EAAE,EAAE;YACjE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,IAAI,CAAC,MAAc,EAAE,EAAU;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAErC,MAAM,CACJ,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAClC,mBAAmB,EAAE,cAAc,CACpC,CAAC;QAEF,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;OAOG;IACH,OAAO,CAAC,MAAc,EAAE,GAAW,EAAE,SAAmB;QACtD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAC9B,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,KAAK,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CACvE,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,MAAc,EAAE,KAAqB;QAChD,IAAI,CAAC,UAAU;aACZ,IAAI,CAAC,8BAA8B,EAAE;YACpC,MAAM,EAAE,eAAe;YACvB,MAAM;YACN,OAAO,EAAE,WAAW,CAAC,gBAAgB;YACrC,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE;SAC3C,CAAC;aACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACf,QAAQ,CACN,kEAAkE,MAAM,IAAI,EAC5E,KAAK,CACN,CAAC;QACJ,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,KAAK,CAAC,MAAc,EAAE,GAAW,EAAE,YAAsB,EAAE;QAC/D,MAAM,CACJ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,CAAC,EACrC,mCAAmC,GAAG,kBAAkB,CACzD,CAAC;QAEF,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;QAE7B,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;QAEpB,iDAAiD;QACjD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC7C,MAAM,CAAC,UAAU,GAAG,aAAa,CAAC;QAElC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,qBAAqB,EAAE,CAAC;QAE7D,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;YACnC,OAAO,EAAE,CAAC;YACV,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;gBACxB,IAAI,EAAE,MAAM;gBACZ,EAAE;gBACF,MAAM;aACP,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACzC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAEzB,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;gBACxB,IAAI,EAAE,OAAO;gBACb,EAAE;gBACF,MAAM;gBACN,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,uCAAuC;gBACvC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;aACjC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,MAAM,CACJ,SAAS,CAAC,mBAAmB,CAC3B,gDAAgD,CACjD,CACF,CAAC;QACJ,CAAC,CAAC;QAEF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QAEhD,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;YAC3C,MAAM,MAAM,GAAG,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;YAC9C,MAAM,IAAI,GAAG,MAAM;gBACjB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE;gBAChD,CAAC,CAAC;oBACE,IAAI,EAAE,QAAiB;oBACvB,0DAA0D;oBAC1D,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;iBAChD,CAAC;YAEN,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;gBACxB,IAAI,EAAE,SAAS;gBACf,EAAE;gBACF,MAAM;gBACN,IAAI;aACL,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE;YACpB,EAAE;YACF,MAAM;YACN,GAAG;YACH,SAAS;YACT,MAAM;YACN,WAAW,EAAE,OAAO;SACrB,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC;QAEd,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QAEnD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,MAAc,EAAE,EAAU;QAC/B,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAEzC,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,MAAc;QACtB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,YAAY,CAAC,MAAc,EAAE,EAAU,EAAE,IAAuB;QACpE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAEtD,MAAM,WAAW,CAAC;QAElB,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAEtE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3B,CAAC;IAED;;;;;OAKG;IACH,OAAO,CAAC,MAAc;QACpB,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;aAC/B,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC;aAC5C,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAChB,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B,CAAC,CAAC,CAAC;IACR,CAAC;CACF","sourcesContent":["import type { Messenger } from '@metamask/messenger';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type {\n GetWebSocketsResult,\n SnapId,\n WebSocketEvent,\n} from '@metamask/snaps-sdk';\nimport { HandlerType, isEqual, logError } from '@metamask/snaps-utils';\nimport { assert, createDeferredPromise } from '@metamask/utils';\nimport { nanoid } from 'nanoid';\n\nimport type {\n HandleSnapRequest,\n SnapInstalled,\n SnapUninstalled,\n SnapUpdated,\n} from '../snaps';\nimport { METAMASK_ORIGIN } from '../snaps';\n\nconst serviceName = 'WebSocketService';\n\nexport type WebSocketServiceOpenAction = {\n type: `${typeof serviceName}:open`;\n handler: (\n snapId: SnapId,\n url: string,\n protocols?: string[],\n ) => Promise<string>;\n};\n\nexport type WebSocketServiceCloseAction = {\n type: `${typeof serviceName}:close`;\n handler: (snapId: SnapId, id: string) => void;\n};\n\nexport type WebSocketServiceSendMessageAction = {\n type: `${typeof serviceName}:sendMessage`;\n handler: (\n snapId: SnapId,\n id: string,\n data: string | number[],\n ) => Promise<void>;\n};\n\nexport type WebSocketServiceGetAllAction = {\n type: `${typeof serviceName}:getAll`;\n handler: (snapId: SnapId) => GetWebSocketsResult;\n};\n\nexport type WebSocketServiceActions =\n | WebSocketServiceOpenAction\n | WebSocketServiceCloseAction\n | WebSocketServiceSendMessageAction\n | WebSocketServiceGetAllAction;\n\nexport type WebSocketServiceAllowedActions = HandleSnapRequest;\n\nexport type WebSocketServiceEvents =\n | SnapUninstalled\n | SnapUpdated\n | SnapInstalled;\n\nexport type WebSocketServiceMessenger = Messenger<\n 'WebSocketService',\n WebSocketServiceActions | WebSocketServiceAllowedActions,\n WebSocketServiceEvents\n>;\n\ntype WebSocketServiceArgs = {\n messenger: WebSocketServiceMessenger;\n};\n\ntype InternalSocket = {\n id: string;\n snapId: SnapId;\n url: string;\n protocols: string[];\n openPromise: Promise<void>;\n // eslint-disable-next-line no-restricted-globals\n socket: WebSocket;\n};\n\nexport class WebSocketService {\n name: typeof serviceName = serviceName;\n\n state = null;\n\n readonly #messenger: WebSocketServiceMessenger;\n\n readonly #sockets: Map<string, InternalSocket>;\n\n constructor({ messenger }: WebSocketServiceArgs) {\n this.#messenger = messenger;\n this.#sockets = new Map();\n\n this.#messenger.registerActionHandler(\n `${serviceName}:open`,\n async (...args) => this.#open(...args),\n );\n\n this.#messenger.registerActionHandler(`${serviceName}:close`, (...args) =>\n this.#close(...args),\n );\n\n this.#messenger.registerActionHandler(\n `${serviceName}:sendMessage`,\n async (...args) => this.#sendMessage(...args),\n );\n\n this.#messenger.registerActionHandler(`${serviceName}:getAll`, (...args) =>\n this.#getAll(...args),\n );\n\n this.#messenger.subscribe('SnapController:snapUpdated', (snap) => {\n this.#closeAll(snap.id);\n });\n\n this.#messenger.subscribe('SnapController:snapUninstalled', (snap) => {\n this.#closeAll(snap.id);\n });\n\n // Due to local Snaps not currently emitting snapUninstalled we also have to\n // listen to snapInstalled.\n this.#messenger.subscribe('SnapController:snapInstalled', (snap) => {\n this.#closeAll(snap.id);\n });\n }\n\n /**\n * Get information about a given WebSocket connection with an ID.\n *\n * @param snapId - The Snap ID.\n * @param id - The identifier for the WebSocket connection.\n * @returns Information about the WebSocket connection.\n * @throws If the WebSocket connection cannot be found.\n */\n #get(snapId: SnapId, id: string) {\n const socket = this.#sockets.get(id);\n\n assert(\n socket && socket.snapId === snapId,\n `Socket with ID \"${id}\" not found.`,\n );\n\n return socket;\n }\n\n /**\n * Check whether a given Snap ID already has an open connection for a URL and protocol.\n *\n * @param snapId - The Snap ID.\n * @param url - The URL.\n * @param protocols - A protocols parameter.\n * @returns True if a matching connection already exists, otherwise false.\n */\n #exists(snapId: SnapId, url: string, protocols: string[]) {\n return this.#getAll(snapId).some(\n (socket) => socket.url === url && isEqual(socket.protocols, protocols),\n );\n }\n\n /**\n * Handle sending a specific WebSocketEvent to a Snap.\n *\n * @param snapId - The Snap ID.\n * @param event - The WebSocketEvent.\n */\n #handleEvent(snapId: SnapId, event: WebSocketEvent) {\n this.#messenger\n .call('SnapController:handleRequest', {\n origin: METAMASK_ORIGIN,\n snapId,\n handler: HandlerType.OnWebSocketEvent,\n request: { method: '', params: { event } },\n })\n .catch((error) => {\n logError(\n `An error occurred while handling a WebSocket message for Snap \"${snapId}\":`,\n error,\n );\n });\n }\n\n /**\n * Open a WebSocket connection.\n *\n * @param snapId - The Snap ID.\n * @param url - The URL for the WebSocket connection.\n * @param protocols - An optional parameter for protocols.\n * @returns The identifier for the opened connection.\n * @throws If the connection fails.\n */\n async #open(snapId: SnapId, url: string, protocols: string[] = []) {\n assert(\n !this.#exists(snapId, url, protocols),\n `An open WebSocket connection to ${url} already exists.`,\n );\n\n const parsedUrl = new URL(url);\n const { origin } = parsedUrl;\n\n const id = nanoid();\n\n // eslint-disable-next-line no-restricted-globals\n const socket = new WebSocket(url, protocols);\n socket.binaryType = 'arraybuffer';\n\n const { promise, resolve, reject } = createDeferredPromise();\n\n socket.addEventListener('open', () => {\n resolve();\n this.#handleEvent(snapId, {\n type: 'open',\n id,\n origin,\n });\n });\n\n socket.addEventListener('close', (event) => {\n this.#sockets.delete(id);\n\n this.#handleEvent(snapId, {\n type: 'close',\n id,\n origin,\n code: event.code,\n reason: event.reason,\n // wasClean is not available on mobile.\n wasClean: event.wasClean ?? null,\n });\n });\n\n const errorListener = () => {\n reject(\n rpcErrors.resourceUnavailable(\n 'An error occurred while opening the WebSocket.',\n ),\n );\n };\n\n socket.addEventListener('error', errorListener);\n\n socket.addEventListener('message', (event) => {\n const isText = typeof event.data === 'string';\n const data = isText\n ? { type: 'text' as const, message: event.data }\n : {\n type: 'binary' as const,\n // We request that the WebSocket gives us an array buffer.\n message: Array.from(new Uint8Array(event.data)),\n };\n\n this.#handleEvent(snapId, {\n type: 'message',\n id,\n origin,\n data,\n });\n });\n\n this.#sockets.set(id, {\n id,\n snapId,\n url,\n protocols,\n socket,\n openPromise: promise,\n });\n\n await promise;\n\n socket.removeEventListener('error', errorListener);\n\n return id;\n }\n\n /**\n * Close a given WebSocket connection.\n *\n * @param snapId - The Snap ID.\n * @param id - The identifier for the WebSocket connection.\n */\n #close(snapId: SnapId, id: string) {\n const { socket } = this.#get(snapId, id);\n\n socket.close();\n }\n\n /**\n * Close all open connections for a given Snap ID.\n *\n * @param snapId - The Snap ID.\n */\n #closeAll(snapId: SnapId) {\n for (const socket of this.#getAll(snapId)) {\n this.#close(snapId, socket.id);\n }\n }\n\n /**\n * Send a message from a given Snap ID to a WebSocket connection.\n *\n * @param snapId - The Snap ID.\n * @param id - The identifier for the WebSocket connection.\n * @param data - The message to send.\n */\n async #sendMessage(snapId: SnapId, id: string, data: string | number[]) {\n const { socket, openPromise } = this.#get(snapId, id);\n\n await openPromise;\n\n const wrappedData = Array.isArray(data) ? new Uint8Array(data) : data;\n\n socket.send(wrappedData);\n }\n\n /**\n * Get a list of all open WebSocket connections for a Snap ID.\n *\n * @param snapId - The Snap ID.\n * @returns A list of WebSocket connections.\n */\n #getAll(snapId: SnapId) {\n return [...this.#sockets.values()]\n .filter((socket) => socket.snapId === snapId)\n .map((socket) => ({\n id: socket.id,\n url: socket.url,\n protocols: socket.protocols,\n }));\n }\n}\n"]}
1
+ {"version":3,"file":"WebSocketService.mjs","sourceRoot":"","sources":["../../src/websocket/WebSocketService.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Messenger } from '@metamask/messenger';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { SnapId, WebSocketEvent } from '@metamask/snaps-sdk';\nimport { HandlerType, isEqual, logError } from '@metamask/snaps-utils';\nimport { assert, createDeferredPromise } from '@metamask/utils';\nimport { nanoid } from 'nanoid';\n\nimport type { WebSocketServiceMethodActions } from './WebSocketService-method-action-types';\nimport type {\n SnapControllerHandleRequestAction,\n SnapControllerSnapInstalledEvent,\n SnapControllerSnapUninstalledEvent,\n SnapControllerSnapUpdatedEvent,\n} from '../snaps';\nimport { METAMASK_ORIGIN } from '../snaps';\n\nconst serviceName = 'WebSocketService';\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'open',\n 'close',\n 'sendMessage',\n 'getAll',\n] as const;\n\nexport type WebSocketServiceActions = WebSocketServiceMethodActions;\n\ntype AllowedActions = SnapControllerHandleRequestAction;\n\ntype AllowedEvents =\n | SnapControllerSnapUninstalledEvent\n | SnapControllerSnapUpdatedEvent\n | SnapControllerSnapInstalledEvent;\n\nexport type WebSocketServiceMessenger = Messenger<\n 'WebSocketService',\n WebSocketServiceActions | AllowedActions,\n AllowedEvents\n>;\n\ntype WebSocketServiceArgs = {\n messenger: WebSocketServiceMessenger;\n};\n\ntype InternalSocket = {\n id: string;\n snapId: SnapId;\n url: string;\n protocols: string[];\n openPromise: Promise<void>;\n // eslint-disable-next-line no-restricted-globals\n socket: WebSocket;\n};\n\nexport class WebSocketService {\n name: typeof serviceName = serviceName;\n\n state = null;\n\n readonly #messenger: WebSocketServiceMessenger;\n\n readonly #sockets: Map<string, InternalSocket>;\n\n constructor({ messenger }: WebSocketServiceArgs) {\n this.#messenger = messenger;\n this.#sockets = new Map();\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n this.#messenger.subscribe('SnapController:snapUpdated', (snap) => {\n this.#closeAll(snap.id);\n });\n\n this.#messenger.subscribe('SnapController:snapUninstalled', (snap) => {\n this.#closeAll(snap.id);\n });\n\n // Due to local Snaps not currently emitting snapUninstalled we also have to\n // listen to snapInstalled.\n this.#messenger.subscribe('SnapController:snapInstalled', (snap) => {\n this.#closeAll(snap.id);\n });\n }\n\n /**\n * Get information about a given WebSocket connection with an ID.\n *\n * @param snapId - The Snap ID.\n * @param id - The identifier for the WebSocket connection.\n * @returns Information about the WebSocket connection.\n * @throws If the WebSocket connection cannot be found.\n */\n #get(snapId: SnapId, id: string) {\n const socket = this.#sockets.get(id);\n\n assert(\n socket && socket.snapId === snapId,\n `Socket with ID \"${id}\" not found.`,\n );\n\n return socket;\n }\n\n /**\n * Check whether a given Snap ID already has an open connection for a URL and protocol.\n *\n * @param snapId - The Snap ID.\n * @param url - The URL.\n * @param protocols - A protocols parameter.\n * @returns True if a matching connection already exists, otherwise false.\n */\n #exists(snapId: SnapId, url: string, protocols: string[]) {\n return this.getAll(snapId).some(\n (socket) => socket.url === url && isEqual(socket.protocols, protocols),\n );\n }\n\n /**\n * Handle sending a specific WebSocketEvent to a Snap.\n *\n * @param snapId - The Snap ID.\n * @param event - The WebSocketEvent.\n */\n #handleEvent(snapId: SnapId, event: WebSocketEvent) {\n this.#messenger\n .call('SnapController:handleRequest', {\n origin: METAMASK_ORIGIN,\n snapId,\n handler: HandlerType.OnWebSocketEvent,\n request: { method: '', params: { event } },\n })\n .catch((error) => {\n logError(\n `An error occurred while handling a WebSocket message for Snap \"${snapId}\":`,\n error,\n );\n });\n }\n\n /**\n * Open a WebSocket connection.\n *\n * @param snapId - The Snap ID.\n * @param url - The URL for the WebSocket connection.\n * @param protocols - An optional parameter for protocols.\n * @returns The identifier for the opened connection.\n * @throws If the connection fails.\n */\n async open(snapId: SnapId, url: string, protocols: string[] = []) {\n assert(\n !this.#exists(snapId, url, protocols),\n `An open WebSocket connection to ${url} already exists.`,\n );\n\n const parsedUrl = new URL(url);\n const { origin } = parsedUrl;\n\n const id = nanoid();\n\n // eslint-disable-next-line no-restricted-globals\n const socket = new WebSocket(url, protocols);\n socket.binaryType = 'arraybuffer';\n\n const { promise, resolve, reject } = createDeferredPromise();\n\n socket.addEventListener('open', () => {\n resolve();\n this.#handleEvent(snapId, {\n type: 'open',\n id,\n origin,\n });\n });\n\n socket.addEventListener('close', (event) => {\n this.#sockets.delete(id);\n\n this.#handleEvent(snapId, {\n type: 'close',\n id,\n origin,\n code: event.code,\n reason: event.reason,\n // wasClean is not available on mobile.\n wasClean: event.wasClean ?? null,\n });\n });\n\n const errorListener = () => {\n reject(\n rpcErrors.resourceUnavailable(\n 'An error occurred while opening the WebSocket.',\n ),\n );\n };\n\n socket.addEventListener('error', errorListener);\n\n socket.addEventListener('message', (event) => {\n const isText = typeof event.data === 'string';\n const data = isText\n ? { type: 'text' as const, message: event.data }\n : {\n type: 'binary' as const,\n // We request that the WebSocket gives us an array buffer.\n message: Array.from(new Uint8Array(event.data)),\n };\n\n this.#handleEvent(snapId, {\n type: 'message',\n id,\n origin,\n data,\n });\n });\n\n this.#sockets.set(id, {\n id,\n snapId,\n url,\n protocols,\n socket,\n openPromise: promise,\n });\n\n await promise;\n\n socket.removeEventListener('error', errorListener);\n\n return id;\n }\n\n /**\n * Close a given WebSocket connection.\n *\n * @param snapId - The Snap ID.\n * @param id - The identifier for the WebSocket connection.\n */\n close(snapId: SnapId, id: string) {\n const { socket } = this.#get(snapId, id);\n\n socket.close();\n }\n\n /**\n * Close all open connections for a given Snap ID.\n *\n * @param snapId - The Snap ID.\n */\n #closeAll(snapId: SnapId) {\n for (const socket of this.getAll(snapId)) {\n this.close(snapId, socket.id);\n }\n }\n\n /**\n * Send a message from a given Snap ID to a WebSocket connection.\n *\n * @param snapId - The Snap ID.\n * @param id - The identifier for the WebSocket connection.\n * @param data - The message to send.\n */\n async sendMessage(snapId: SnapId, id: string, data: string | number[]) {\n const { socket, openPromise } = this.#get(snapId, id);\n\n await openPromise;\n\n const wrappedData = Array.isArray(data) ? new Uint8Array(data) : data;\n\n socket.send(wrappedData);\n }\n\n /**\n * Get a list of all open WebSocket connections for a Snap ID.\n *\n * @param snapId - The Snap ID.\n * @returns A list of WebSocket connections.\n */\n getAll(snapId: SnapId) {\n return [...this.#sockets.values()]\n .filter((socket) => socket.snapId === snapId)\n .map((socket) => ({\n id: socket.id,\n url: socket.url,\n protocols: socket.protocols,\n }));\n }\n}\n"]}
@@ -1,18 +1,6 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
2
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./WebSocketService.cjs"), exports);
3
+ exports.WebSocketService = void 0;
4
+ var WebSocketService_1 = require("./WebSocketService.cjs");
5
+ Object.defineProperty(exports, "WebSocketService", { enumerable: true, get: function () { return WebSocketService_1.WebSocketService; } });
18
6
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../src/websocket/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAmC","sourcesContent":["export * from './WebSocketService';\n"]}
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../src/websocket/index.ts"],"names":[],"mappings":";;;AAIA,2DAAsD;AAA7C,oHAAA,gBAAgB,OAAA","sourcesContent":["export type {\n WebSocketServiceActions,\n WebSocketServiceMessenger,\n} from './WebSocketService';\nexport { WebSocketService } from './WebSocketService';\nexport type {\n WebSocketServiceCloseAction,\n WebSocketServiceGetAllAction,\n WebSocketServiceOpenAction,\n WebSocketServiceSendMessageAction,\n} from './WebSocketService-method-action-types';\n"]}
@@ -1,2 +1,4 @@
1
- export * from "./WebSocketService.cjs";
1
+ export type { WebSocketServiceActions, WebSocketServiceMessenger, } from "./WebSocketService.cjs";
2
+ export { WebSocketService } from "./WebSocketService.cjs";
3
+ export type { WebSocketServiceCloseAction, WebSocketServiceGetAllAction, WebSocketServiceOpenAction, WebSocketServiceSendMessageAction, } from "./WebSocketService-method-action-types.cjs";
2
4
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../src/websocket/index.ts"],"names":[],"mappings":"AAAA,uCAAmC"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../src/websocket/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,uBAAuB,EACvB,yBAAyB,GAC1B,+BAA2B;AAC5B,OAAO,EAAE,gBAAgB,EAAE,+BAA2B;AACtD,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,EAC5B,0BAA0B,EAC1B,iCAAiC,GAClC,mDAA+C"}
@@ -1,2 +1,4 @@
1
- export * from "./WebSocketService.mjs";
1
+ export type { WebSocketServiceActions, WebSocketServiceMessenger, } from "./WebSocketService.mjs";
2
+ export { WebSocketService } from "./WebSocketService.mjs";
3
+ export type { WebSocketServiceCloseAction, WebSocketServiceGetAllAction, WebSocketServiceOpenAction, WebSocketServiceSendMessageAction, } from "./WebSocketService-method-action-types.mjs";
2
4
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/websocket/index.ts"],"names":[],"mappings":"AAAA,uCAAmC"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/websocket/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,uBAAuB,EACvB,yBAAyB,GAC1B,+BAA2B;AAC5B,OAAO,EAAE,gBAAgB,EAAE,+BAA2B;AACtD,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,EAC5B,0BAA0B,EAC1B,iCAAiC,GAClC,mDAA+C"}
@@ -1,2 +1,2 @@
1
- export * from "./WebSocketService.mjs";
1
+ export { WebSocketService } from "./WebSocketService.mjs";
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../src/websocket/index.ts"],"names":[],"mappings":"AAAA,uCAAmC","sourcesContent":["export * from './WebSocketService';\n"]}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../src/websocket/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,+BAA2B","sourcesContent":["export type {\n WebSocketServiceActions,\n WebSocketServiceMessenger,\n} from './WebSocketService';\nexport { WebSocketService } from './WebSocketService';\nexport type {\n WebSocketServiceCloseAction,\n WebSocketServiceGetAllAction,\n WebSocketServiceOpenAction,\n WebSocketServiceSendMessageAction,\n} from './WebSocketService-method-action-types';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/snaps-controllers",
3
- "version": "18.0.4",
3
+ "version": "19.0.1",
4
4
  "description": "Controllers for MetaMask Snaps",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -62,6 +62,7 @@
62
62
  "build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references",
63
63
  "changelog:update": "../../scripts/update-changelog.sh @metamask/snaps-controllers",
64
64
  "changelog:validate": "../../scripts/validate-changelog.sh @metamask/snaps-controllers",
65
+ "generate-method-action-types": "messenger-generate-action-types",
65
66
  "lint": "yarn lint:eslint && yarn lint:misc --check && yarn changelog:validate && yarn lint:dependencies",
66
67
  "lint:ci": "yarn lint",
67
68
  "lint:dependencies": "depcheck",
@@ -79,21 +80,21 @@
79
80
  "test:watch": "jest --watch"
80
81
  },
81
82
  "dependencies": {
82
- "@metamask/approval-controller": "^8.0.0",
83
- "@metamask/base-controller": "^9.0.0",
84
- "@metamask/json-rpc-engine": "^10.2.3",
83
+ "@metamask/approval-controller": "^9.0.1",
84
+ "@metamask/base-controller": "^9.0.1",
85
+ "@metamask/json-rpc-engine": "^10.2.4",
85
86
  "@metamask/json-rpc-middleware-stream": "^8.0.8",
86
87
  "@metamask/key-tree": "^10.1.1",
87
- "@metamask/messenger": "^0.3.0",
88
+ "@metamask/messenger": "^1.1.0",
88
89
  "@metamask/object-multiplex": "^2.1.0",
89
- "@metamask/permission-controller": "^12.2.0",
90
+ "@metamask/permission-controller": "^12.3.0",
90
91
  "@metamask/post-message-stream": "^10.0.0",
91
92
  "@metamask/rpc-errors": "^7.0.3",
92
93
  "@metamask/snaps-registry": "^4.0.0",
93
- "@metamask/snaps-rpc-methods": "^15.0.0",
94
+ "@metamask/snaps-rpc-methods": "^15.0.2",
94
95
  "@metamask/snaps-sdk": "^11.0.0",
95
- "@metamask/snaps-utils": "^12.1.1",
96
- "@metamask/storage-service": "^1.0.0",
96
+ "@metamask/snaps-utils": "^12.1.3",
97
+ "@metamask/storage-service": "^1.0.1",
97
98
  "@metamask/superstruct": "^3.2.1",
98
99
  "@metamask/utils": "^11.10.0",
99
100
  "@xstate/fsm": "^2.0.0",
@@ -111,7 +112,7 @@
111
112
  "tar-stream": "^3.1.7"
112
113
  },
113
114
  "devDependencies": {
114
- "@lavamoat/allow-scripts": "^3.4.3",
115
+ "@lavamoat/allow-scripts": "^4.0.0",
115
116
  "@metamask/auto-changelog": "^5.3.2",
116
117
  "@metamask/browser-passworder": "^6.0.0",
117
118
  "@noble/hashes": "^1.7.1",
@@ -148,7 +149,7 @@
148
149
  "vitest": "^3.1.1"
149
150
  },
150
151
  "peerDependencies": {
151
- "@metamask/snaps-execution-environments": "^11.0.1"
152
+ "@metamask/snaps-execution-environments": "^11.0.2"
152
153
  },
153
154
  "peerDependenciesMeta": {
154
155
  "@metamask/snaps-execution-environments": {