@towns-labs/sdk 2.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 (978) hide show
  1. package/README.md +29 -0
  2. package/dist/appRegistryService.d.ts +17 -0
  3. package/dist/appRegistryService.d.ts.map +1 -0
  4. package/dist/appRegistryService.js +48 -0
  5. package/dist/appRegistryService.js.map +1 -0
  6. package/dist/check.d.ts +31 -0
  7. package/dist/check.d.ts.map +1 -0
  8. package/dist/check.js +44 -0
  9. package/dist/check.js.map +1 -0
  10. package/dist/client-v2.d.ts +89 -0
  11. package/dist/client-v2.d.ts.map +1 -0
  12. package/dist/client-v2.js +293 -0
  13. package/dist/client-v2.js.map +1 -0
  14. package/dist/client.d.ts +390 -0
  15. package/dist/client.d.ts.map +1 -0
  16. package/dist/client.js +2135 -0
  17. package/dist/client.js.map +1 -0
  18. package/dist/clientDecryptionExtensions.d.ts +50 -0
  19. package/dist/clientDecryptionExtensions.d.ts.map +1 -0
  20. package/dist/clientDecryptionExtensions.js +319 -0
  21. package/dist/clientDecryptionExtensions.js.map +1 -0
  22. package/dist/createApp.d.ts +31 -0
  23. package/dist/createApp.d.ts.map +1 -0
  24. package/dist/createApp.js +77 -0
  25. package/dist/createApp.js.map +1 -0
  26. package/dist/createBot.d.ts +159 -0
  27. package/dist/createBot.d.ts.map +1 -0
  28. package/dist/createBot.js +206 -0
  29. package/dist/createBot.js.map +1 -0
  30. package/dist/decryptionExtensions.d.ts +214 -0
  31. package/dist/decryptionExtensions.d.ts.map +1 -0
  32. package/dist/decryptionExtensions.js +883 -0
  33. package/dist/decryptionExtensions.js.map +1 -0
  34. package/dist/encryptedContentTypes.d.ts +35 -0
  35. package/dist/encryptedContentTypes.d.ts.map +1 -0
  36. package/dist/encryptedContentTypes.js +86 -0
  37. package/dist/encryptedContentTypes.js.map +1 -0
  38. package/dist/id.d.ts +77 -0
  39. package/dist/id.d.ts.map +1 -0
  40. package/dist/id.js +224 -0
  41. package/dist/id.js.map +1 -0
  42. package/dist/index.d.ts +131 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +131 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/makeAppRegistryRpcClient.d.ts +8 -0
  47. package/dist/makeAppRegistryRpcClient.d.ts.map +1 -0
  48. package/dist/makeAppRegistryRpcClient.js +40 -0
  49. package/dist/makeAppRegistryRpcClient.js.map +1 -0
  50. package/dist/makeAuthenticationRpcClient.d.ts +8 -0
  51. package/dist/makeAuthenticationRpcClient.d.ts.map +1 -0
  52. package/dist/makeAuthenticationRpcClient.js +39 -0
  53. package/dist/makeAuthenticationRpcClient.js.map +1 -0
  54. package/dist/makeNotificationRpcClient.d.ts +8 -0
  55. package/dist/makeNotificationRpcClient.d.ts.map +1 -0
  56. package/dist/makeNotificationRpcClient.js +40 -0
  57. package/dist/makeNotificationRpcClient.js.map +1 -0
  58. package/dist/makeRiverRpcClient.d.ts +6 -0
  59. package/dist/makeRiverRpcClient.d.ts.map +1 -0
  60. package/dist/makeRiverRpcClient.js +9 -0
  61. package/dist/makeRiverRpcClient.js.map +1 -0
  62. package/dist/makeStreamRpcClient.d.ts +21 -0
  63. package/dist/makeStreamRpcClient.d.ts.map +1 -0
  64. package/dist/makeStreamRpcClient.js +110 -0
  65. package/dist/makeStreamRpcClient.js.map +1 -0
  66. package/dist/memberMetadata_DisplayNames.d.ts +26 -0
  67. package/dist/memberMetadata_DisplayNames.d.ts.map +1 -0
  68. package/dist/memberMetadata_DisplayNames.js +95 -0
  69. package/dist/memberMetadata_DisplayNames.js.map +1 -0
  70. package/dist/memberMetadata_EnsAddresses.d.ts +25 -0
  71. package/dist/memberMetadata_EnsAddresses.d.ts.map +1 -0
  72. package/dist/memberMetadata_EnsAddresses.js +86 -0
  73. package/dist/memberMetadata_EnsAddresses.js.map +1 -0
  74. package/dist/memberMetadata_Nft.d.ts +31 -0
  75. package/dist/memberMetadata_Nft.d.ts.map +1 -0
  76. package/dist/memberMetadata_Nft.js +95 -0
  77. package/dist/memberMetadata_Nft.js.map +1 -0
  78. package/dist/memberMetadata_Usernames.d.ts +35 -0
  79. package/dist/memberMetadata_Usernames.d.ts.map +1 -0
  80. package/dist/memberMetadata_Usernames.js +162 -0
  81. package/dist/memberMetadata_Usernames.js.map +1 -0
  82. package/dist/migrations/migrateSnapshot.d.ts +3 -0
  83. package/dist/migrations/migrateSnapshot.d.ts.map +1 -0
  84. package/dist/migrations/migrateSnapshot.js +29 -0
  85. package/dist/migrations/migrateSnapshot.js.map +1 -0
  86. package/dist/migrations/snapshotMigration0000.d.ts +3 -0
  87. package/dist/migrations/snapshotMigration0000.d.ts.map +1 -0
  88. package/dist/migrations/snapshotMigration0000.js +5 -0
  89. package/dist/migrations/snapshotMigration0000.js.map +1 -0
  90. package/dist/migrations/snapshotMigration0001.d.ts +3 -0
  91. package/dist/migrations/snapshotMigration0001.d.ts.map +1 -0
  92. package/dist/migrations/snapshotMigration0001.js +40 -0
  93. package/dist/migrations/snapshotMigration0001.js.map +1 -0
  94. package/dist/migrations/snapshotMigration0002.d.ts +3 -0
  95. package/dist/migrations/snapshotMigration0002.d.ts.map +1 -0
  96. package/dist/migrations/snapshotMigration0002.js +23 -0
  97. package/dist/migrations/snapshotMigration0002.js.map +1 -0
  98. package/dist/migrations/snapshotMigration0003.d.ts +6 -0
  99. package/dist/migrations/snapshotMigration0003.d.ts.map +1 -0
  100. package/dist/migrations/snapshotMigration0003.js +15 -0
  101. package/dist/migrations/snapshotMigration0003.js.map +1 -0
  102. package/dist/migrations/snapshotMigration0004.d.ts +9 -0
  103. package/dist/migrations/snapshotMigration0004.d.ts.map +1 -0
  104. package/dist/migrations/snapshotMigration0004.js +93 -0
  105. package/dist/migrations/snapshotMigration0004.js.map +1 -0
  106. package/dist/migrations/snapshotMigration0005.d.ts +9 -0
  107. package/dist/migrations/snapshotMigration0005.d.ts.map +1 -0
  108. package/dist/migrations/snapshotMigration0005.js +89 -0
  109. package/dist/migrations/snapshotMigration0005.js.map +1 -0
  110. package/dist/migrations/snapshotMigration0006.d.ts +9 -0
  111. package/dist/migrations/snapshotMigration0006.d.ts.map +1 -0
  112. package/dist/migrations/snapshotMigration0006.js +33 -0
  113. package/dist/migrations/snapshotMigration0006.js.map +1 -0
  114. package/dist/notificationService.d.ts +17 -0
  115. package/dist/notificationService.d.ts.map +1 -0
  116. package/dist/notificationService.js +49 -0
  117. package/dist/notificationService.js.map +1 -0
  118. package/dist/notificationsClient.d.ts +48 -0
  119. package/dist/notificationsClient.d.ts.map +1 -0
  120. package/dist/notificationsClient.js +302 -0
  121. package/dist/notificationsClient.js.map +1 -0
  122. package/dist/observable/combine.d.ts +44 -0
  123. package/dist/observable/combine.d.ts.map +1 -0
  124. package/dist/observable/combine.js +67 -0
  125. package/dist/observable/combine.js.map +1 -0
  126. package/dist/observable/constant.d.ts +7 -0
  127. package/dist/observable/constant.d.ts.map +1 -0
  128. package/dist/observable/constant.js +13 -0
  129. package/dist/observable/constant.js.map +1 -0
  130. package/dist/observable/observable.d.ts +33 -0
  131. package/dist/observable/observable.d.ts.map +1 -0
  132. package/dist/observable/observable.js +109 -0
  133. package/dist/observable/observable.js.map +1 -0
  134. package/dist/observable/observableRecord.d.ts +18 -0
  135. package/dist/observable/observableRecord.d.ts.map +1 -0
  136. package/dist/observable/observableRecord.js +71 -0
  137. package/dist/observable/observableRecord.js.map +1 -0
  138. package/dist/observable/persistedObservable.d.ts +39 -0
  139. package/dist/observable/persistedObservable.d.ts.map +1 -0
  140. package/dist/observable/persistedObservable.js +77 -0
  141. package/dist/observable/persistedObservable.js.map +1 -0
  142. package/dist/observable/utils.d.ts +2 -0
  143. package/dist/observable/utils.d.ts.map +1 -0
  144. package/dist/observable/utils.js +12 -0
  145. package/dist/observable/utils.js.map +1 -0
  146. package/dist/persistenceStore.d.ts +112 -0
  147. package/dist/persistenceStore.d.ts.map +1 -0
  148. package/dist/persistenceStore.js +465 -0
  149. package/dist/persistenceStore.js.map +1 -0
  150. package/dist/riverDbManager.d.ts +5 -0
  151. package/dist/riverDbManager.d.ts.map +1 -0
  152. package/dist/riverDbManager.js +7 -0
  153. package/dist/riverDbManager.js.map +1 -0
  154. package/dist/rpcCommon.d.ts +7 -0
  155. package/dist/rpcCommon.d.ts.map +1 -0
  156. package/dist/rpcCommon.js +2 -0
  157. package/dist/rpcCommon.js.map +1 -0
  158. package/dist/rpcInterceptors.d.ts +21 -0
  159. package/dist/rpcInterceptors.d.ts.map +1 -0
  160. package/dist/rpcInterceptors.js +376 -0
  161. package/dist/rpcInterceptors.js.map +1 -0
  162. package/dist/sign.d.ts +59 -0
  163. package/dist/sign.d.ts.map +1 -0
  164. package/dist/sign.js +363 -0
  165. package/dist/sign.js.map +1 -0
  166. package/dist/signerContext.d.ts +62 -0
  167. package/dist/signerContext.d.ts.map +1 -0
  168. package/dist/signerContext.js +103 -0
  169. package/dist/signerContext.js.map +1 -0
  170. package/dist/store/store.d.ts +22 -0
  171. package/dist/store/store.d.ts.map +1 -0
  172. package/dist/store/store.js +165 -0
  173. package/dist/store/store.js.map +1 -0
  174. package/dist/stream.d.ts +49 -0
  175. package/dist/stream.d.ts.map +1 -0
  176. package/dist/stream.js +112 -0
  177. package/dist/stream.js.map +1 -0
  178. package/dist/streamEvents.d.ts +96 -0
  179. package/dist/streamEvents.d.ts.map +1 -0
  180. package/dist/streamEvents.js +2 -0
  181. package/dist/streamEvents.js.map +1 -0
  182. package/dist/streamStateView.d.ts +87 -0
  183. package/dist/streamStateView.d.ts.map +1 -0
  184. package/dist/streamStateView.js +596 -0
  185. package/dist/streamStateView.js.map +1 -0
  186. package/dist/streamStateView_AbstractContent.d.ts +15 -0
  187. package/dist/streamStateView_AbstractContent.d.ts.map +1 -0
  188. package/dist/streamStateView_AbstractContent.js +24 -0
  189. package/dist/streamStateView_AbstractContent.js.map +1 -0
  190. package/dist/streamStateView_Channel.d.ts +16 -0
  191. package/dist/streamStateView_Channel.d.ts.map +1 -0
  192. package/dist/streamStateView_Channel.js +76 -0
  193. package/dist/streamStateView_Channel.js.map +1 -0
  194. package/dist/streamStateView_ChannelMetadata.d.ts +22 -0
  195. package/dist/streamStateView_ChannelMetadata.d.ts.map +1 -0
  196. package/dist/streamStateView_ChannelMetadata.js +77 -0
  197. package/dist/streamStateView_ChannelMetadata.js.map +1 -0
  198. package/dist/streamStateView_DMChannel.d.ts +25 -0
  199. package/dist/streamStateView_DMChannel.d.ts.map +1 -0
  200. package/dist/streamStateView_DMChannel.js +114 -0
  201. package/dist/streamStateView_DMChannel.js.map +1 -0
  202. package/dist/streamStateView_GDMChannel.d.ts +27 -0
  203. package/dist/streamStateView_GDMChannel.d.ts.map +1 -0
  204. package/dist/streamStateView_GDMChannel.js +160 -0
  205. package/dist/streamStateView_GDMChannel.js.map +1 -0
  206. package/dist/streamStateView_Media.d.ts +22 -0
  207. package/dist/streamStateView_Media.d.ts.map +1 -0
  208. package/dist/streamStateView_Media.js +60 -0
  209. package/dist/streamStateView_Media.js.map +1 -0
  210. package/dist/streamStateView_MemberMetadata.d.ts +59 -0
  211. package/dist/streamStateView_MemberMetadata.d.ts.map +1 -0
  212. package/dist/streamStateView_MemberMetadata.js +113 -0
  213. package/dist/streamStateView_MemberMetadata.js.map +1 -0
  214. package/dist/streamStateView_Members.d.ts +101 -0
  215. package/dist/streamStateView_Members.d.ts.map +1 -0
  216. package/dist/streamStateView_Members.js +582 -0
  217. package/dist/streamStateView_Members.js.map +1 -0
  218. package/dist/streamStateView_Members_Solicitations.d.ts +15 -0
  219. package/dist/streamStateView_Members_Solicitations.d.ts.map +1 -0
  220. package/dist/streamStateView_Members_Solicitations.js +48 -0
  221. package/dist/streamStateView_Members_Solicitations.js.map +1 -0
  222. package/dist/streamStateView_Space.d.ts +31 -0
  223. package/dist/streamStateView_Space.d.ts.map +1 -0
  224. package/dist/streamStateView_Space.js +193 -0
  225. package/dist/streamStateView_Space.js.map +1 -0
  226. package/dist/streamStateView_UnknownContent.d.ts +11 -0
  227. package/dist/streamStateView_UnknownContent.d.ts.map +1 -0
  228. package/dist/streamStateView_UnknownContent.js +15 -0
  229. package/dist/streamStateView_UnknownContent.js.map +1 -0
  230. package/dist/streamStateView_User.d.ts +27 -0
  231. package/dist/streamStateView_User.d.ts.map +1 -0
  232. package/dist/streamStateView_User.js +200 -0
  233. package/dist/streamStateView_User.js.map +1 -0
  234. package/dist/streamStateView_UserInbox.d.ts +21 -0
  235. package/dist/streamStateView_UserInbox.d.ts.map +1 -0
  236. package/dist/streamStateView_UserInbox.js +85 -0
  237. package/dist/streamStateView_UserInbox.js.map +1 -0
  238. package/dist/streamStateView_UserMetadata.d.ts +31 -0
  239. package/dist/streamStateView_UserMetadata.d.ts.map +1 -0
  240. package/dist/streamStateView_UserMetadata.js +160 -0
  241. package/dist/streamStateView_UserMetadata.js.map +1 -0
  242. package/dist/streamStateView_UserSettings.d.ts +24 -0
  243. package/dist/streamStateView_UserSettings.d.ts.map +1 -0
  244. package/dist/streamStateView_UserSettings.js +125 -0
  245. package/dist/streamStateView_UserSettings.js.map +1 -0
  246. package/dist/streamUtils.d.ts +49 -0
  247. package/dist/streamUtils.d.ts.map +1 -0
  248. package/dist/streamUtils.js +220 -0
  249. package/dist/streamUtils.js.map +1 -0
  250. package/dist/sync/ISyncedStreamsController.d.ts +17 -0
  251. package/dist/sync/ISyncedStreamsController.d.ts.map +1 -0
  252. package/dist/sync/ISyncedStreamsController.js +2 -0
  253. package/dist/sync/ISyncedStreamsController.js.map +1 -0
  254. package/dist/sync/SyncedStreamsControllerLite.d.ts +32 -0
  255. package/dist/sync/SyncedStreamsControllerLite.d.ts.map +1 -0
  256. package/dist/sync/SyncedStreamsControllerLite.js +183 -0
  257. package/dist/sync/SyncedStreamsControllerLite.js.map +1 -0
  258. package/dist/sync-agent/constants.d.ts +2 -0
  259. package/dist/sync-agent/constants.d.ts.map +1 -0
  260. package/dist/sync-agent/constants.js +2 -0
  261. package/dist/sync-agent/constants.js.map +1 -0
  262. package/dist/sync-agent/db.d.ts +18 -0
  263. package/dist/sync-agent/db.d.ts.map +1 -0
  264. package/dist/sync-agent/db.js +34 -0
  265. package/dist/sync-agent/db.js.map +1 -0
  266. package/dist/sync-agent/dms/dms.d.ts +24 -0
  267. package/dist/sync-agent/dms/dms.d.ts.map +1 -0
  268. package/dist/sync-agent/dms/dms.js +60 -0
  269. package/dist/sync-agent/dms/dms.js.map +1 -0
  270. package/dist/sync-agent/dms/models/dm.d.ts +76 -0
  271. package/dist/sync-agent/dms/models/dm.d.ts.map +1 -0
  272. package/dist/sync-agent/dms/models/dm.js +177 -0
  273. package/dist/sync-agent/dms/models/dm.js.map +1 -0
  274. package/dist/sync-agent/entitlements/entitlements.d.ts +10 -0
  275. package/dist/sync-agent/entitlements/entitlements.d.ts.map +1 -0
  276. package/dist/sync-agent/entitlements/entitlements.js +20 -0
  277. package/dist/sync-agent/entitlements/entitlements.js.map +1 -0
  278. package/dist/sync-agent/gdms/gdms.d.ts +23 -0
  279. package/dist/sync-agent/gdms/gdms.d.ts.map +1 -0
  280. package/dist/sync-agent/gdms/gdms.js +56 -0
  281. package/dist/sync-agent/gdms/gdms.js.map +1 -0
  282. package/dist/sync-agent/gdms/models/gdm.d.ts +76 -0
  283. package/dist/sync-agent/gdms/models/gdm.d.ts.map +1 -0
  284. package/dist/sync-agent/gdms/models/gdm.js +176 -0
  285. package/dist/sync-agent/gdms/models/gdm.js.map +1 -0
  286. package/dist/sync-agent/members/members.d.ts +32 -0
  287. package/dist/sync-agent/members/members.d.ts.map +1 -0
  288. package/dist/sync-agent/members/members.js +143 -0
  289. package/dist/sync-agent/members/members.js.map +1 -0
  290. package/dist/sync-agent/members/models/member.d.ts +68 -0
  291. package/dist/sync-agent/members/models/member.d.ts.map +1 -0
  292. package/dist/sync-agent/members/models/member.js +134 -0
  293. package/dist/sync-agent/members/models/member.js.map +1 -0
  294. package/dist/sync-agent/members/models/myself.d.ts +20 -0
  295. package/dist/sync-agent/members/models/myself.d.ts.map +1 -0
  296. package/dist/sync-agent/members/models/myself.js +97 -0
  297. package/dist/sync-agent/members/models/myself.js.map +1 -0
  298. package/dist/sync-agent/river-connection/models/authStatus.d.ts +18 -0
  299. package/dist/sync-agent/river-connection/models/authStatus.d.ts.map +1 -0
  300. package/dist/sync-agent/river-connection/models/authStatus.js +19 -0
  301. package/dist/sync-agent/river-connection/models/authStatus.js.map +1 -0
  302. package/dist/sync-agent/river-connection/models/riverChain.d.ts +24 -0
  303. package/dist/sync-agent/river-connection/models/riverChain.d.ts.map +1 -0
  304. package/dist/sync-agent/river-connection/models/riverChain.js +66 -0
  305. package/dist/sync-agent/river-connection/models/riverChain.js.map +1 -0
  306. package/dist/sync-agent/river-connection/models/transactionalClient.d.ts +11 -0
  307. package/dist/sync-agent/river-connection/models/transactionalClient.d.ts.map +1 -0
  308. package/dist/sync-agent/river-connection/models/transactionalClient.js +14 -0
  309. package/dist/sync-agent/river-connection/models/transactionalClient.js.map +1 -0
  310. package/dist/sync-agent/river-connection/riverConnection.d.ts +66 -0
  311. package/dist/sync-agent/river-connection/riverConnection.d.ts.map +1 -0
  312. package/dist/sync-agent/river-connection/riverConnection.js +222 -0
  313. package/dist/sync-agent/river-connection/riverConnection.js.map +1 -0
  314. package/dist/sync-agent/spaces/models/channel.d.ts +124 -0
  315. package/dist/sync-agent/spaces/models/channel.d.ts.map +1 -0
  316. package/dist/sync-agent/spaces/models/channel.js +254 -0
  317. package/dist/sync-agent/spaces/models/channel.js.map +1 -0
  318. package/dist/sync-agent/spaces/models/space.d.ts +57 -0
  319. package/dist/sync-agent/spaces/models/space.d.ts.map +1 -0
  320. package/dist/sync-agent/spaces/models/space.js +147 -0
  321. package/dist/sync-agent/spaces/models/space.js.map +1 -0
  322. package/dist/sync-agent/spaces/spaces.d.ts +29 -0
  323. package/dist/sync-agent/spaces/spaces.d.ts.map +1 -0
  324. package/dist/sync-agent/spaces/spaces.js +90 -0
  325. package/dist/sync-agent/spaces/spaces.js.map +1 -0
  326. package/dist/sync-agent/syncAgent.d.ts +66 -0
  327. package/dist/sync-agent/syncAgent.d.ts.map +1 -0
  328. package/dist/sync-agent/syncAgent.js +102 -0
  329. package/dist/sync-agent/syncAgent.js.map +1 -0
  330. package/dist/sync-agent/timeline/timeline.d.ts +26 -0
  331. package/dist/sync-agent/timeline/timeline.d.ts.map +1 -0
  332. package/dist/sync-agent/timeline/timeline.js +56 -0
  333. package/dist/sync-agent/timeline/timeline.js.map +1 -0
  334. package/dist/sync-agent/user/models/userInbox.d.ts +21 -0
  335. package/dist/sync-agent/user/models/userInbox.d.ts.map +1 -0
  336. package/dist/sync-agent/user/models/userInbox.js +68 -0
  337. package/dist/sync-agent/user/models/userInbox.js.map +1 -0
  338. package/dist/sync-agent/user/models/userMemberships.d.ts +28 -0
  339. package/dist/sync-agent/user/models/userMemberships.d.ts.map +1 -0
  340. package/dist/sync-agent/user/models/userMemberships.js +83 -0
  341. package/dist/sync-agent/user/models/userMemberships.js.map +1 -0
  342. package/dist/sync-agent/user/models/userMetadata.d.ts +21 -0
  343. package/dist/sync-agent/user/models/userMetadata.d.ts.map +1 -0
  344. package/dist/sync-agent/user/models/userMetadata.js +68 -0
  345. package/dist/sync-agent/user/models/userMetadata.js.map +1 -0
  346. package/dist/sync-agent/user/models/userSettings.d.ts +17 -0
  347. package/dist/sync-agent/user/models/userSettings.d.ts.map +1 -0
  348. package/dist/sync-agent/user/models/userSettings.js +48 -0
  349. package/dist/sync-agent/user/models/userSettings.js.map +1 -0
  350. package/dist/sync-agent/user/user.d.ts +18 -0
  351. package/dist/sync-agent/user/user.d.ts.map +1 -0
  352. package/dist/sync-agent/user/user.js +30 -0
  353. package/dist/sync-agent/user/user.js.map +1 -0
  354. package/dist/sync-agent/utils/bot.d.ts +16 -0
  355. package/dist/sync-agent/utils/bot.d.ts.map +1 -0
  356. package/dist/sync-agent/utils/bot.js +39 -0
  357. package/dist/sync-agent/utils/bot.js.map +1 -0
  358. package/dist/sync-agent/utils/promiseQueue.d.ts +6 -0
  359. package/dist/sync-agent/utils/promiseQueue.d.ts.map +1 -0
  360. package/dist/sync-agent/utils/promiseQueue.js +20 -0
  361. package/dist/sync-agent/utils/promiseQueue.js.map +1 -0
  362. package/dist/sync-agent/utils/providers.d.ts +5 -0
  363. package/dist/sync-agent/utils/providers.d.ts.map +1 -0
  364. package/dist/sync-agent/utils/providers.js +16 -0
  365. package/dist/sync-agent/utils/providers.js.map +1 -0
  366. package/dist/sync-agent/utils/spaceUtils.d.ts +3 -0
  367. package/dist/sync-agent/utils/spaceUtils.d.ts.map +1 -0
  368. package/dist/sync-agent/utils/spaceUtils.js +31 -0
  369. package/dist/sync-agent/utils/spaceUtils.js.map +1 -0
  370. package/dist/syncEvents.d.ts +9 -0
  371. package/dist/syncEvents.d.ts.map +1 -0
  372. package/dist/syncEvents.js +2 -0
  373. package/dist/syncEvents.js.map +1 -0
  374. package/dist/syncedStream.d.ts +24 -0
  375. package/dist/syncedStream.d.ts.map +1 -0
  376. package/dist/syncedStream.js +119 -0
  377. package/dist/syncedStream.js.map +1 -0
  378. package/dist/syncedStreams.d.ts +43 -0
  379. package/dist/syncedStreams.d.ts.map +1 -0
  380. package/dist/syncedStreams.js +115 -0
  381. package/dist/syncedStreams.js.map +1 -0
  382. package/dist/syncedStreamsExtension.d.ts +45 -0
  383. package/dist/syncedStreamsExtension.d.ts.map +1 -0
  384. package/dist/syncedStreamsExtension.js +295 -0
  385. package/dist/syncedStreamsExtension.js.map +1 -0
  386. package/dist/syncedStreamsLoop.d.ts +132 -0
  387. package/dist/syncedStreamsLoop.d.ts.map +1 -0
  388. package/dist/syncedStreamsLoop.js +922 -0
  389. package/dist/syncedStreamsLoop.js.map +1 -0
  390. package/dist/tags.d.ts +12 -0
  391. package/dist/tags.d.ts.map +1 -0
  392. package/dist/tags.js +160 -0
  393. package/dist/tags.js.map +1 -0
  394. package/dist/tests/bob_testUtils.d.ts +4 -0
  395. package/dist/tests/bob_testUtils.d.ts.map +1 -0
  396. package/dist/tests/bob_testUtils.js +161 -0
  397. package/dist/tests/bob_testUtils.js.map +1 -0
  398. package/dist/tests/multi/appRegistryService.test.d.ts +2 -0
  399. package/dist/tests/multi/appRegistryService.test.d.ts.map +1 -0
  400. package/dist/tests/multi/appRegistryService.test.js +41 -0
  401. package/dist/tests/multi/appRegistryService.test.js.map +1 -0
  402. package/dist/tests/multi/botEntitlements.test.d.ts +5 -0
  403. package/dist/tests/multi/botEntitlements.test.d.ts.map +1 -0
  404. package/dist/tests/multi/botEntitlements.test.js +178 -0
  405. package/dist/tests/multi/botEntitlements.test.js.map +1 -0
  406. package/dist/tests/multi/botMembership.test.d.ts +5 -0
  407. package/dist/tests/multi/botMembership.test.d.ts.map +1 -0
  408. package/dist/tests/multi/botMembership.test.js +295 -0
  409. package/dist/tests/multi/botMembership.test.js.map +1 -0
  410. package/dist/tests/multi/botStreamCreation.test.d.ts +5 -0
  411. package/dist/tests/multi/botStreamCreation.test.d.ts.map +1 -0
  412. package/dist/tests/multi/botStreamCreation.test.js +60 -0
  413. package/dist/tests/multi/botStreamCreation.test.js.map +1 -0
  414. package/dist/tests/multi/channelScrubbing.test.d.ts +5 -0
  415. package/dist/tests/multi/channelScrubbing.test.d.ts.map +1 -0
  416. package/dist/tests/multi/channelScrubbing.test.js +102 -0
  417. package/dist/tests/multi/channelScrubbing.test.js.map +1 -0
  418. package/dist/tests/multi/channelSpaceSettings.test.d.ts +5 -0
  419. package/dist/tests/multi/channelSpaceSettings.test.d.ts.map +1 -0
  420. package/dist/tests/multi/channelSpaceSettings.test.js +204 -0
  421. package/dist/tests/multi/channelSpaceSettings.test.js.map +1 -0
  422. package/dist/tests/multi/disableChannel.test.d.ts +5 -0
  423. package/dist/tests/multi/disableChannel.test.d.ts.map +1 -0
  424. package/dist/tests/multi/disableChannel.test.js +30 -0
  425. package/dist/tests/multi/disableChannel.test.js.map +1 -0
  426. package/dist/tests/multi/disableSpace.test.d.ts +5 -0
  427. package/dist/tests/multi/disableSpace.test.d.ts.map +1 -0
  428. package/dist/tests/multi/disableSpace.test.js +37 -0
  429. package/dist/tests/multi/disableSpace.test.js.map +1 -0
  430. package/dist/tests/multi/entitlements/channelEntitlementPermissions.test.d.ts +5 -0
  431. package/dist/tests/multi/entitlements/channelEntitlementPermissions.test.d.ts.map +1 -0
  432. package/dist/tests/multi/entitlements/channelEntitlementPermissions.test.js +129 -0
  433. package/dist/tests/multi/entitlements/channelEntitlementPermissions.test.js.map +1 -0
  434. package/dist/tests/multi/entitlements/channelWithThreeNestedEntitlement.test.d.ts +5 -0
  435. package/dist/tests/multi/entitlements/channelWithThreeNestedEntitlement.test.d.ts.map +1 -0
  436. package/dist/tests/multi/entitlements/channelWithThreeNestedEntitlement.test.js +44 -0
  437. package/dist/tests/multi/entitlements/channelWithThreeNestedEntitlement.test.js.map +1 -0
  438. package/dist/tests/multi/entitlements/channelsWithComplexEntitlements.test.d.ts +5 -0
  439. package/dist/tests/multi/entitlements/channelsWithComplexEntitlements.test.d.ts.map +1 -0
  440. package/dist/tests/multi/entitlements/channelsWithComplexEntitlements.test.js +125 -0
  441. package/dist/tests/multi/entitlements/channelsWithComplexEntitlements.test.js.map +1 -0
  442. package/dist/tests/multi/entitlements/channelsWithEntitlementLoss.test.d.ts +5 -0
  443. package/dist/tests/multi/entitlements/channelsWithEntitlementLoss.test.d.ts.map +1 -0
  444. package/dist/tests/multi/entitlements/channelsWithEntitlementLoss.test.js +72 -0
  445. package/dist/tests/multi/entitlements/channelsWithEntitlementLoss.test.js.map +1 -0
  446. package/dist/tests/multi/entitlements/channelsWithEntitlements.test.d.ts +5 -0
  447. package/dist/tests/multi/entitlements/channelsWithEntitlements.test.d.ts.map +1 -0
  448. package/dist/tests/multi/entitlements/channelsWithEntitlements.test.js +57 -0
  449. package/dist/tests/multi/entitlements/channelsWithEntitlements.test.js.map +1 -0
  450. package/dist/tests/multi/entitlements/channelsWithErc20Entitlements.test.d.ts +5 -0
  451. package/dist/tests/multi/entitlements/channelsWithErc20Entitlements.test.d.ts.map +1 -0
  452. package/dist/tests/multi/entitlements/channelsWithErc20Entitlements.test.js +86 -0
  453. package/dist/tests/multi/entitlements/channelsWithErc20Entitlements.test.js.map +1 -0
  454. package/dist/tests/multi/entitlements/channelsWithErc721Entitlements.test.d.ts +5 -0
  455. package/dist/tests/multi/entitlements/channelsWithErc721Entitlements.test.d.ts.map +1 -0
  456. package/dist/tests/multi/entitlements/channelsWithErc721Entitlements.test.js +69 -0
  457. package/dist/tests/multi/entitlements/channelsWithErc721Entitlements.test.js.map +1 -0
  458. package/dist/tests/multi/entitlements/channelsWithEthBalanceEntitlements.test.d.ts +5 -0
  459. package/dist/tests/multi/entitlements/channelsWithEthBalanceEntitlements.test.d.ts.map +1 -0
  460. package/dist/tests/multi/entitlements/channelsWithEthBalanceEntitlements.test.js +145 -0
  461. package/dist/tests/multi/entitlements/channelsWithEthBalanceEntitlements.test.js.map +1 -0
  462. package/dist/tests/multi/entitlements/channelsWithUserEntitlements.test.d.ts +5 -0
  463. package/dist/tests/multi/entitlements/channelsWithUserEntitlements.test.d.ts.map +1 -0
  464. package/dist/tests/multi/entitlements/channelsWithUserEntitlements.test.js +53 -0
  465. package/dist/tests/multi/entitlements/channelsWithUserEntitlements.test.js.map +1 -0
  466. package/dist/tests/multi/entitlements/membershipRenewals.test.d.ts +5 -0
  467. package/dist/tests/multi/entitlements/membershipRenewals.test.d.ts.map +1 -0
  468. package/dist/tests/multi/entitlements/membershipRenewals.test.js +150 -0
  469. package/dist/tests/multi/entitlements/membershipRenewals.test.js.map +1 -0
  470. package/dist/tests/multi/entitlements/spaceWithComplexEntitlements.test.d.ts +5 -0
  471. package/dist/tests/multi/entitlements/spaceWithComplexEntitlements.test.d.ts.map +1 -0
  472. package/dist/tests/multi/entitlements/spaceWithComplexEntitlements.test.js +131 -0
  473. package/dist/tests/multi/entitlements/spaceWithComplexEntitlements.test.js.map +1 -0
  474. package/dist/tests/multi/entitlements/spaceWithEntitlements.test.d.ts +5 -0
  475. package/dist/tests/multi/entitlements/spaceWithEntitlements.test.d.ts.map +1 -0
  476. package/dist/tests/multi/entitlements/spaceWithEntitlements.test.js +109 -0
  477. package/dist/tests/multi/entitlements/spaceWithEntitlements.test.js.map +1 -0
  478. package/dist/tests/multi/entitlements/spaceWithErc20Entitlements.test.d.ts +5 -0
  479. package/dist/tests/multi/entitlements/spaceWithErc20Entitlements.test.d.ts.map +1 -0
  480. package/dist/tests/multi/entitlements/spaceWithErc20Entitlements.test.js +103 -0
  481. package/dist/tests/multi/entitlements/spaceWithErc20Entitlements.test.js.map +1 -0
  482. package/dist/tests/multi/entitlements/spaceWithErc721Entitlements.test.d.ts +5 -0
  483. package/dist/tests/multi/entitlements/spaceWithErc721Entitlements.test.d.ts.map +1 -0
  484. package/dist/tests/multi/entitlements/spaceWithErc721Entitlements.test.js +84 -0
  485. package/dist/tests/multi/entitlements/spaceWithErc721Entitlements.test.js.map +1 -0
  486. package/dist/tests/multi/entitlements/spaceWithEthBalanceEntitlements.test.d.ts +5 -0
  487. package/dist/tests/multi/entitlements/spaceWithEthBalanceEntitlements.test.d.ts.map +1 -0
  488. package/dist/tests/multi/entitlements/spaceWithEthBalanceEntitlements.test.js +168 -0
  489. package/dist/tests/multi/entitlements/spaceWithEthBalanceEntitlements.test.js.map +1 -0
  490. package/dist/tests/multi/entitlements/spaceWithThreeNestedEntitlement.test.d.ts +5 -0
  491. package/dist/tests/multi/entitlements/spaceWithThreeNestedEntitlement.test.d.ts.map +1 -0
  492. package/dist/tests/multi/entitlements/spaceWithThreeNestedEntitlement.test.js +45 -0
  493. package/dist/tests/multi/entitlements/spaceWithThreeNestedEntitlement.test.js.map +1 -0
  494. package/dist/tests/multi/entitlements/spaceWithUserEntitlements.test.d.ts +5 -0
  495. package/dist/tests/multi/entitlements/spaceWithUserEntitlements.test.d.ts.map +1 -0
  496. package/dist/tests/multi/entitlements/spaceWithUserEntitlements.test.js +79 -0
  497. package/dist/tests/multi/entitlements/spaceWithUserEntitlements.test.js.map +1 -0
  498. package/dist/tests/multi/legacySpace.test.d.ts +5 -0
  499. package/dist/tests/multi/legacySpace.test.d.ts.map +1 -0
  500. package/dist/tests/multi/legacySpace.test.js +48 -0
  501. package/dist/tests/multi/legacySpace.test.js.map +1 -0
  502. package/dist/tests/multi/mediaWithEntitlements.test.d.ts +5 -0
  503. package/dist/tests/multi/mediaWithEntitlements.test.d.ts.map +1 -0
  504. package/dist/tests/multi/mediaWithEntitlements.test.js +152 -0
  505. package/dist/tests/multi/mediaWithEntitlements.test.js.map +1 -0
  506. package/dist/tests/multi/membershipManagement.test.d.ts +5 -0
  507. package/dist/tests/multi/membershipManagement.test.d.ts.map +1 -0
  508. package/dist/tests/multi/membershipManagement.test.js +76 -0
  509. package/dist/tests/multi/membershipManagement.test.js.map +1 -0
  510. package/dist/tests/multi/notificationService.test.d.ts +2 -0
  511. package/dist/tests/multi/notificationService.test.d.ts.map +1 -0
  512. package/dist/tests/multi/notificationService.test.js +51 -0
  513. package/dist/tests/multi/notificationService.test.js.map +1 -0
  514. package/dist/tests/multi/riverAirdropDapp.test.d.ts +5 -0
  515. package/dist/tests/multi/riverAirdropDapp.test.d.ts.map +1 -0
  516. package/dist/tests/multi/riverAirdropDapp.test.js +43 -0
  517. package/dist/tests/multi/riverAirdropDapp.test.js.map +1 -0
  518. package/dist/tests/multi/spaceDapp.test.d.ts +5 -0
  519. package/dist/tests/multi/spaceDapp.test.d.ts.map +1 -0
  520. package/dist/tests/multi/spaceDapp.test.js +61 -0
  521. package/dist/tests/multi/spaceDapp.test.js.map +1 -0
  522. package/dist/tests/multi/spaceWithVariousPriceConfigurations.test.d.ts +2 -0
  523. package/dist/tests/multi/spaceWithVariousPriceConfigurations.test.d.ts.map +1 -0
  524. package/dist/tests/multi/spaceWithVariousPriceConfigurations.test.js +63 -0
  525. package/dist/tests/multi/spaceWithVariousPriceConfigurations.test.js.map +1 -0
  526. package/dist/tests/multi/sync-agent/member-queue.test.d.ts +2 -0
  527. package/dist/tests/multi/sync-agent/member-queue.test.d.ts.map +1 -0
  528. package/dist/tests/multi/sync-agent/member-queue.test.js +54 -0
  529. package/dist/tests/multi/sync-agent/member-queue.test.js.map +1 -0
  530. package/dist/tests/multi/sync-agent/member.test.d.ts +2 -0
  531. package/dist/tests/multi/sync-agent/member.test.d.ts.map +1 -0
  532. package/dist/tests/multi/sync-agent/member.test.js +45 -0
  533. package/dist/tests/multi/sync-agent/member.test.js.map +1 -0
  534. package/dist/tests/multi/sync-agent/members.test.d.ts +2 -0
  535. package/dist/tests/multi/sync-agent/members.test.d.ts.map +1 -0
  536. package/dist/tests/multi/sync-agent/members.test.js +35 -0
  537. package/dist/tests/multi/sync-agent/members.test.js.map +1 -0
  538. package/dist/tests/multi/sync-agent/riverConnection.test.d.ts +5 -0
  539. package/dist/tests/multi/sync-agent/riverConnection.test.d.ts.map +1 -0
  540. package/dist/tests/multi/sync-agent/riverConnection.test.js +39 -0
  541. package/dist/tests/multi/sync-agent/riverConnection.test.js.map +1 -0
  542. package/dist/tests/multi/sync-agent/spaces.test.d.ts +2 -0
  543. package/dist/tests/multi/sync-agent/spaces.test.d.ts.map +1 -0
  544. package/dist/tests/multi/sync-agent/spaces.test.js +33 -0
  545. package/dist/tests/multi/sync-agent/spaces.test.js.map +1 -0
  546. package/dist/tests/multi/sync-agent/streams.test.d.ts +2 -0
  547. package/dist/tests/multi/sync-agent/streams.test.d.ts.map +1 -0
  548. package/dist/tests/multi/sync-agent/streams.test.js +27 -0
  549. package/dist/tests/multi/sync-agent/streams.test.js.map +1 -0
  550. package/dist/tests/multi/sync-agent/syncAgent.test.d.ts +2 -0
  551. package/dist/tests/multi/sync-agent/syncAgent.test.d.ts.map +1 -0
  552. package/dist/tests/multi/sync-agent/syncAgent.test.js +68 -0
  553. package/dist/tests/multi/sync-agent/syncAgent.test.js.map +1 -0
  554. package/dist/tests/multi/sync-agent/syncAgents.test.d.ts +2 -0
  555. package/dist/tests/multi/sync-agent/syncAgents.test.d.ts.map +1 -0
  556. package/dist/tests/multi/sync-agent/syncAgents.test.js +163 -0
  557. package/dist/tests/multi/sync-agent/syncAgents.test.js.map +1 -0
  558. package/dist/tests/multi/sync-agent/timeline.test.d.ts +2 -0
  559. package/dist/tests/multi/sync-agent/timeline.test.d.ts.map +1 -0
  560. package/dist/tests/multi/sync-agent/timeline.test.js +232 -0
  561. package/dist/tests/multi/sync-agent/timeline.test.js.map +1 -0
  562. package/dist/tests/multi/sync-agent/user.test.d.ts +5 -0
  563. package/dist/tests/multi/sync-agent/user.test.d.ts.map +1 -0
  564. package/dist/tests/multi/sync-agent/user.test.js +55 -0
  565. package/dist/tests/multi/sync-agent/user.test.js.map +1 -0
  566. package/dist/tests/multi/transactions.test.d.ts +5 -0
  567. package/dist/tests/multi/transactions.test.d.ts.map +1 -0
  568. package/dist/tests/multi/transactions.test.js +153 -0
  569. package/dist/tests/multi/transactions.test.js.map +1 -0
  570. package/dist/tests/multi/transactions_SpaceReview.test.d.ts +2 -0
  571. package/dist/tests/multi/transactions_SpaceReview.test.d.ts.map +1 -0
  572. package/dist/tests/multi/transactions_SpaceReview.test.js +278 -0
  573. package/dist/tests/multi/transactions_SpaceReview.test.js.map +1 -0
  574. package/dist/tests/multi/transactions_Tip.test.d.ts +5 -0
  575. package/dist/tests/multi/transactions_Tip.test.d.ts.map +1 -0
  576. package/dist/tests/multi/transactions_Tip.test.js +379 -0
  577. package/dist/tests/multi/transactions_Tip.test.js.map +1 -0
  578. package/dist/tests/multi/withEntitlements.test.d.ts +5 -0
  579. package/dist/tests/multi/withEntitlements.test.d.ts.map +1 -0
  580. package/dist/tests/multi/withEntitlements.test.js +125 -0
  581. package/dist/tests/multi/withEntitlements.test.js.map +1 -0
  582. package/dist/tests/multi_ne/aliceAndFriends.test.d.ts +5 -0
  583. package/dist/tests/multi_ne/aliceAndFriends.test.d.ts.map +1 -0
  584. package/dist/tests/multi_ne/aliceAndFriends.test.js +20 -0
  585. package/dist/tests/multi_ne/aliceAndFriends.test.js.map +1 -0
  586. package/dist/tests/multi_ne/aliceAndFriends10for10.test.d.ts +5 -0
  587. package/dist/tests/multi_ne/aliceAndFriends10for10.test.d.ts.map +1 -0
  588. package/dist/tests/multi_ne/aliceAndFriends10for10.test.js +23 -0
  589. package/dist/tests/multi_ne/aliceAndFriends10for10.test.js.map +1 -0
  590. package/dist/tests/multi_ne/aliceAndFriends3for8.test.d.ts +5 -0
  591. package/dist/tests/multi_ne/aliceAndFriends3for8.test.d.ts.map +1 -0
  592. package/dist/tests/multi_ne/aliceAndFriends3for8.test.js +22 -0
  593. package/dist/tests/multi_ne/aliceAndFriends3for8.test.js.map +1 -0
  594. package/dist/tests/multi_ne/aliceAndFriendslongAndRandom.test.d.ts +5 -0
  595. package/dist/tests/multi_ne/aliceAndFriendslongAndRandom.test.d.ts.map +1 -0
  596. package/dist/tests/multi_ne/aliceAndFriendslongAndRandom.test.js +28 -0
  597. package/dist/tests/multi_ne/aliceAndFriendslongAndRandom.test.js.map +1 -0
  598. package/dist/tests/multi_ne/bobFlushes.test.d.ts +5 -0
  599. package/dist/tests/multi_ne/bobFlushes.test.d.ts.map +1 -0
  600. package/dist/tests/multi_ne/bobFlushes.test.js +20 -0
  601. package/dist/tests/multi_ne/bobFlushes.test.js.map +1 -0
  602. package/dist/tests/multi_ne/channels.test.d.ts +5 -0
  603. package/dist/tests/multi_ne/channels.test.d.ts.map +1 -0
  604. package/dist/tests/multi_ne/channels.test.js +45 -0
  605. package/dist/tests/multi_ne/channels.test.js.map +1 -0
  606. package/dist/tests/multi_ne/client.test.d.ts +5 -0
  607. package/dist/tests/multi_ne/client.test.d.ts.map +1 -0
  608. package/dist/tests/multi_ne/client.test.js +821 -0
  609. package/dist/tests/multi_ne/client.test.js.map +1 -0
  610. package/dist/tests/multi_ne/clientCrypto.test.d.ts +5 -0
  611. package/dist/tests/multi_ne/clientCrypto.test.d.ts.map +1 -0
  612. package/dist/tests/multi_ne/clientCrypto.test.js +78 -0
  613. package/dist/tests/multi_ne/clientCrypto.test.js.map +1 -0
  614. package/dist/tests/multi_ne/clientDecryptionExtensions.test.d.ts +5 -0
  615. package/dist/tests/multi_ne/clientDecryptionExtensions.test.d.ts.map +1 -0
  616. package/dist/tests/multi_ne/clientDecryptionExtensions.test.js +176 -0
  617. package/dist/tests/multi_ne/clientDecryptionExtensions.test.js.map +1 -0
  618. package/dist/tests/multi_ne/deviceKeyMessage.test.d.ts +5 -0
  619. package/dist/tests/multi_ne/deviceKeyMessage.test.d.ts.map +1 -0
  620. package/dist/tests/multi_ne/deviceKeyMessage.test.js +156 -0
  621. package/dist/tests/multi_ne/deviceKeyMessage.test.js.map +1 -0
  622. package/dist/tests/multi_ne/dms.test.d.ts +5 -0
  623. package/dist/tests/multi_ne/dms.test.d.ts.map +1 -0
  624. package/dist/tests/multi_ne/dms.test.js +131 -0
  625. package/dist/tests/multi_ne/dms.test.js.map +1 -0
  626. package/dist/tests/multi_ne/ephemeralEvents.test.d.ts +5 -0
  627. package/dist/tests/multi_ne/ephemeralEvents.test.d.ts.map +1 -0
  628. package/dist/tests/multi_ne/ephemeralEvents.test.js +125 -0
  629. package/dist/tests/multi_ne/ephemeralEvents.test.js.map +1 -0
  630. package/dist/tests/multi_ne/gdms.test.d.ts +5 -0
  631. package/dist/tests/multi_ne/gdms.test.d.ts.map +1 -0
  632. package/dist/tests/multi_ne/gdms.test.js +302 -0
  633. package/dist/tests/multi_ne/gdms.test.js.map +1 -0
  634. package/dist/tests/multi_ne/id.test.d.ts +5 -0
  635. package/dist/tests/multi_ne/id.test.d.ts.map +1 -0
  636. package/dist/tests/multi_ne/id.test.js +70 -0
  637. package/dist/tests/multi_ne/id.test.js.map +1 -0
  638. package/dist/tests/multi_ne/makeStreamRpcClient.test.d.ts +5 -0
  639. package/dist/tests/multi_ne/makeStreamRpcClient.test.d.ts.map +1 -0
  640. package/dist/tests/multi_ne/makeStreamRpcClient.test.js +80 -0
  641. package/dist/tests/multi_ne/makeStreamRpcClient.test.js.map +1 -0
  642. package/dist/tests/multi_ne/media.test.d.ts +5 -0
  643. package/dist/tests/multi_ne/media.test.d.ts.map +1 -0
  644. package/dist/tests/multi_ne/media.test.js +220 -0
  645. package/dist/tests/multi_ne/media.test.js.map +1 -0
  646. package/dist/tests/multi_ne/memberMetadata.test.d.ts +5 -0
  647. package/dist/tests/multi_ne/memberMetadata.test.d.ts.map +1 -0
  648. package/dist/tests/multi_ne/memberMetadata.test.js +622 -0
  649. package/dist/tests/multi_ne/memberMetadata.test.js.map +1 -0
  650. package/dist/tests/multi_ne/memberMetadata_DisplayNames.test.d.ts +5 -0
  651. package/dist/tests/multi_ne/memberMetadata_DisplayNames.test.d.ts.map +1 -0
  652. package/dist/tests/multi_ne/memberMetadata_DisplayNames.test.js +54 -0
  653. package/dist/tests/multi_ne/memberMetadata_DisplayNames.test.js.map +1 -0
  654. package/dist/tests/multi_ne/memberMetadata_EnsAddresses.test.d.ts +5 -0
  655. package/dist/tests/multi_ne/memberMetadata_EnsAddresses.test.d.ts.map +1 -0
  656. package/dist/tests/multi_ne/memberMetadata_EnsAddresses.test.js +37 -0
  657. package/dist/tests/multi_ne/memberMetadata_EnsAddresses.test.js.map +1 -0
  658. package/dist/tests/multi_ne/memberMetadata_Nft.test.d.ts +5 -0
  659. package/dist/tests/multi_ne/memberMetadata_Nft.test.d.ts.map +1 -0
  660. package/dist/tests/multi_ne/memberMetadata_Nft.test.js +49 -0
  661. package/dist/tests/multi_ne/memberMetadata_Nft.test.js.map +1 -0
  662. package/dist/tests/multi_ne/memberMetadata_Usernames.test.d.ts +5 -0
  663. package/dist/tests/multi_ne/memberMetadata_Usernames.test.d.ts.map +1 -0
  664. package/dist/tests/multi_ne/memberMetadata_Usernames.test.js +126 -0
  665. package/dist/tests/multi_ne/memberMetadata_Usernames.test.js.map +1 -0
  666. package/dist/tests/multi_ne/nodeSelection.test.d.ts +5 -0
  667. package/dist/tests/multi_ne/nodeSelection.test.d.ts.map +1 -0
  668. package/dist/tests/multi_ne/nodeSelection.test.js +41 -0
  669. package/dist/tests/multi_ne/nodeSelection.test.js.map +1 -0
  670. package/dist/tests/multi_ne/outboundGroupSession.test.d.ts +5 -0
  671. package/dist/tests/multi_ne/outboundGroupSession.test.d.ts.map +1 -0
  672. package/dist/tests/multi_ne/outboundGroupSession.test.js +107 -0
  673. package/dist/tests/multi_ne/outboundGroupSession.test.js.map +1 -0
  674. package/dist/tests/multi_ne/persistenceStore.test.d.ts +5 -0
  675. package/dist/tests/multi_ne/persistenceStore.test.d.ts.map +1 -0
  676. package/dist/tests/multi_ne/persistenceStore.test.js +27 -0
  677. package/dist/tests/multi_ne/persistenceStore.test.js.map +1 -0
  678. package/dist/tests/multi_ne/restart.test.d.ts +4 -0
  679. package/dist/tests/multi_ne/restart.test.d.ts.map +1 -0
  680. package/dist/tests/multi_ne/restart.test.js +160 -0
  681. package/dist/tests/multi_ne/restart.test.js.map +1 -0
  682. package/dist/tests/multi_ne/sign.test.d.ts +5 -0
  683. package/dist/tests/multi_ne/sign.test.d.ts.map +1 -0
  684. package/dist/tests/multi_ne/sign.test.js +218 -0
  685. package/dist/tests/multi_ne/sign.test.js.map +1 -0
  686. package/dist/tests/multi_ne/space.test.d.ts +5 -0
  687. package/dist/tests/multi_ne/space.test.d.ts.map +1 -0
  688. package/dist/tests/multi_ne/space.test.js +284 -0
  689. package/dist/tests/multi_ne/space.test.js.map +1 -0
  690. package/dist/tests/multi_ne/streamMembershipHardening.test.d.ts +5 -0
  691. package/dist/tests/multi_ne/streamMembershipHardening.test.d.ts.map +1 -0
  692. package/dist/tests/multi_ne/streamMembershipHardening.test.js +30 -0
  693. package/dist/tests/multi_ne/streamMembershipHardening.test.js.map +1 -0
  694. package/dist/tests/multi_ne/streamRpcClient.test.d.ts +5 -0
  695. package/dist/tests/multi_ne/streamRpcClient.test.d.ts.map +1 -0
  696. package/dist/tests/multi_ne/streamRpcClient.test.js +554 -0
  697. package/dist/tests/multi_ne/streamRpcClient.test.js.map +1 -0
  698. package/dist/tests/multi_ne/streamRpcClientGetSince.test.d.ts +2 -0
  699. package/dist/tests/multi_ne/streamRpcClientGetSince.test.d.ts.map +1 -0
  700. package/dist/tests/multi_ne/streamRpcClientGetSince.test.js +120 -0
  701. package/dist/tests/multi_ne/streamRpcClientGetSince.test.js.map +1 -0
  702. package/dist/tests/multi_ne/streamRpcClientSync.test.d.ts +5 -0
  703. package/dist/tests/multi_ne/streamRpcClientSync.test.d.ts.map +1 -0
  704. package/dist/tests/multi_ne/streamRpcClientSync.test.js +201 -0
  705. package/dist/tests/multi_ne/streamRpcClientSync.test.js.map +1 -0
  706. package/dist/tests/multi_ne/streamRpcClientSyncSnapshots.test.d.ts +2 -0
  707. package/dist/tests/multi_ne/streamRpcClientSyncSnapshots.test.d.ts.map +1 -0
  708. package/dist/tests/multi_ne/streamRpcClientSyncSnapshots.test.js +96 -0
  709. package/dist/tests/multi_ne/streamRpcClientSyncSnapshots.test.js.map +1 -0
  710. package/dist/tests/multi_ne/streamStateView_User.test.d.ts +5 -0
  711. package/dist/tests/multi_ne/streamStateView_User.test.d.ts.map +1 -0
  712. package/dist/tests/multi_ne/streamStateView_User.test.js +31 -0
  713. package/dist/tests/multi_ne/streamStateView_User.test.js.map +1 -0
  714. package/dist/tests/multi_ne/syncWithBlocks.test.d.ts +2 -0
  715. package/dist/tests/multi_ne/syncWithBlocks.test.d.ts.map +1 -0
  716. package/dist/tests/multi_ne/syncWithBlocks.test.js +157 -0
  717. package/dist/tests/multi_ne/syncWithBlocks.test.js.map +1 -0
  718. package/dist/tests/multi_ne/syncedStream.test.d.ts +5 -0
  719. package/dist/tests/multi_ne/syncedStream.test.d.ts.map +1 -0
  720. package/dist/tests/multi_ne/syncedStream.test.js +98 -0
  721. package/dist/tests/multi_ne/syncedStream.test.js.map +1 -0
  722. package/dist/tests/multi_ne/syncedStreams.test.d.ts +5 -0
  723. package/dist/tests/multi_ne/syncedStreams.test.d.ts.map +1 -0
  724. package/dist/tests/multi_ne/syncedStreams.test.js +158 -0
  725. package/dist/tests/multi_ne/syncedStreams.test.js.map +1 -0
  726. package/dist/tests/multi_ne/trading.solana.test.d.ts +2 -0
  727. package/dist/tests/multi_ne/trading.solana.test.d.ts.map +1 -0
  728. package/dist/tests/multi_ne/trading.solana.test.js +229 -0
  729. package/dist/tests/multi_ne/trading.solana.test.js.map +1 -0
  730. package/dist/tests/multi_ne/trading.test.d.ts +2 -0
  731. package/dist/tests/multi_ne/trading.test.d.ts.map +1 -0
  732. package/dist/tests/multi_ne/trading.test.js +243 -0
  733. package/dist/tests/multi_ne/trading.test.js.map +1 -0
  734. package/dist/tests/multi_ne/userInboxMessage.test.d.ts +5 -0
  735. package/dist/tests/multi_ne/userInboxMessage.test.d.ts.map +1 -0
  736. package/dist/tests/multi_ne/userInboxMessage.test.js +201 -0
  737. package/dist/tests/multi_ne/userInboxMessage.test.js.map +1 -0
  738. package/dist/tests/multi_ne/userSettings.test.d.ts +5 -0
  739. package/dist/tests/multi_ne/userSettings.test.d.ts.map +1 -0
  740. package/dist/tests/multi_ne/userSettings.test.js +116 -0
  741. package/dist/tests/multi_ne/userSettings.test.js.map +1 -0
  742. package/dist/tests/multi_ne/workflows.test.d.ts +5 -0
  743. package/dist/tests/multi_ne/workflows.test.d.ts.map +1 -0
  744. package/dist/tests/multi_ne/workflows.test.js +87 -0
  745. package/dist/tests/multi_ne/workflows.test.js.map +1 -0
  746. package/dist/tests/multi_v2/entitlements/channelsWithCrossChainEntitlements.test.d.ts +6 -0
  747. package/dist/tests/multi_v2/entitlements/channelsWithCrossChainEntitlements.test.d.ts.map +1 -0
  748. package/dist/tests/multi_v2/entitlements/channelsWithCrossChainEntitlements.test.js +78 -0
  749. package/dist/tests/multi_v2/entitlements/channelsWithCrossChainEntitlements.test.js.map +1 -0
  750. package/dist/tests/multi_v2/entitlements/channelsWithErc1155Entitlement.test.d.ts +6 -0
  751. package/dist/tests/multi_v2/entitlements/channelsWithErc1155Entitlement.test.d.ts.map +1 -0
  752. package/dist/tests/multi_v2/entitlements/channelsWithErc1155Entitlement.test.js +89 -0
  753. package/dist/tests/multi_v2/entitlements/channelsWithErc1155Entitlement.test.js.map +1 -0
  754. package/dist/tests/multi_v2/entitlements/spaceWithCrossChainEntitlements.test.d.ts +6 -0
  755. package/dist/tests/multi_v2/entitlements/spaceWithCrossChainEntitlements.test.d.ts.map +1 -0
  756. package/dist/tests/multi_v2/entitlements/spaceWithCrossChainEntitlements.test.js +88 -0
  757. package/dist/tests/multi_v2/entitlements/spaceWithCrossChainEntitlements.test.js.map +1 -0
  758. package/dist/tests/multi_v2/entitlements/spaceWithErc1155Entitlements.test.d.ts +6 -0
  759. package/dist/tests/multi_v2/entitlements/spaceWithErc1155Entitlements.test.d.ts.map +1 -0
  760. package/dist/tests/multi_v2/entitlements/spaceWithErc1155Entitlements.test.js +105 -0
  761. package/dist/tests/multi_v2/entitlements/spaceWithErc1155Entitlements.test.js.map +1 -0
  762. package/dist/tests/multi_v2/updateRole.test.d.ts +5 -0
  763. package/dist/tests/multi_v2/updateRole.test.d.ts.map +1 -0
  764. package/dist/tests/multi_v2/updateRole.test.js +25 -0
  765. package/dist/tests/multi_v2/updateRole.test.js.map +1 -0
  766. package/dist/tests/syncAgent_testUtils.d.ts +9 -0
  767. package/dist/tests/syncAgent_testUtils.d.ts.map +1 -0
  768. package/dist/tests/syncAgent_testUtils.js +39 -0
  769. package/dist/tests/syncAgent_testUtils.js.map +1 -0
  770. package/dist/tests/testDriver_testUtils.d.ts +2 -0
  771. package/dist/tests/testDriver_testUtils.d.ts.map +1 -0
  772. package/dist/tests/testDriver_testUtils.js +154 -0
  773. package/dist/tests/testDriver_testUtils.js.map +1 -0
  774. package/dist/tests/testUtils.d.ts +197 -0
  775. package/dist/tests/testUtils.d.ts.map +1 -0
  776. package/dist/tests/testUtils.js +1086 -0
  777. package/dist/tests/testUtils.js.map +1 -0
  778. package/dist/tests/unit/crypto.test.d.ts +5 -0
  779. package/dist/tests/unit/crypto.test.d.ts.map +1 -0
  780. package/dist/tests/unit/crypto.test.js +116 -0
  781. package/dist/tests/unit/crypto.test.js.map +1 -0
  782. package/dist/tests/unit/crypto_utils.test.d.ts +5 -0
  783. package/dist/tests/unit/crypto_utils.test.d.ts.map +1 -0
  784. package/dist/tests/unit/crypto_utils.test.js +36 -0
  785. package/dist/tests/unit/crypto_utils.test.js.map +1 -0
  786. package/dist/tests/unit/decorators.test.d.ts +2 -0
  787. package/dist/tests/unit/decorators.test.d.ts.map +1 -0
  788. package/dist/tests/unit/decorators.test.js +76 -0
  789. package/dist/tests/unit/decorators.test.js.map +1 -0
  790. package/dist/tests/unit/decryptionExtensions.test.d.ts +2 -0
  791. package/dist/tests/unit/decryptionExtensions.test.d.ts.map +1 -0
  792. package/dist/tests/unit/decryptionExtensions.test.js +341 -0
  793. package/dist/tests/unit/decryptionExtensions.test.js.map +1 -0
  794. package/dist/tests/unit/helpers/ConversationBuilder.d.ts +39 -0
  795. package/dist/tests/unit/helpers/ConversationBuilder.d.ts.map +1 -0
  796. package/dist/tests/unit/helpers/ConversationBuilder.js +171 -0
  797. package/dist/tests/unit/helpers/ConversationBuilder.js.map +1 -0
  798. package/dist/tests/unit/observable/combine.test.d.ts +2 -0
  799. package/dist/tests/unit/observable/combine.test.d.ts.map +1 -0
  800. package/dist/tests/unit/observable/combine.test.js +282 -0
  801. package/dist/tests/unit/observable/combine.test.js.map +1 -0
  802. package/dist/tests/unit/observable/observable.test.d.ts +2 -0
  803. package/dist/tests/unit/observable/observable.test.d.ts.map +1 -0
  804. package/dist/tests/unit/observable/observable.test.js +321 -0
  805. package/dist/tests/unit/observable/observable.test.js.map +1 -0
  806. package/dist/tests/unit/snapshotMigration0000.test.d.ts +2 -0
  807. package/dist/tests/unit/snapshotMigration0000.test.d.ts.map +1 -0
  808. package/dist/tests/unit/snapshotMigration0000.test.js +12 -0
  809. package/dist/tests/unit/snapshotMigration0000.test.js.map +1 -0
  810. package/dist/tests/unit/snapshotMigration0001.test.d.ts +2 -0
  811. package/dist/tests/unit/snapshotMigration0001.test.d.ts.map +1 -0
  812. package/dist/tests/unit/snapshotMigration0001.test.js +63 -0
  813. package/dist/tests/unit/snapshotMigration0001.test.js.map +1 -0
  814. package/dist/tests/unit/snapshotMigration0002.test.d.ts +2 -0
  815. package/dist/tests/unit/snapshotMigration0002.test.d.ts.map +1 -0
  816. package/dist/tests/unit/snapshotMigration0002.test.js +31 -0
  817. package/dist/tests/unit/snapshotMigration0002.test.js.map +1 -0
  818. package/dist/tests/unit/snapshotMigration0003.test.d.ts +2 -0
  819. package/dist/tests/unit/snapshotMigration0003.test.d.ts.map +1 -0
  820. package/dist/tests/unit/snapshotMigration0003.test.js +28 -0
  821. package/dist/tests/unit/snapshotMigration0003.test.js.map +1 -0
  822. package/dist/tests/unit/snapshotMigration0004.test.d.ts +2 -0
  823. package/dist/tests/unit/snapshotMigration0004.test.d.ts.map +1 -0
  824. package/dist/tests/unit/snapshotMigration0004.test.js +112 -0
  825. package/dist/tests/unit/snapshotMigration0004.test.js.map +1 -0
  826. package/dist/tests/unit/snapshotMigration0005.test.d.ts +2 -0
  827. package/dist/tests/unit/snapshotMigration0005.test.d.ts.map +1 -0
  828. package/dist/tests/unit/snapshotMigration0005.test.js +124 -0
  829. package/dist/tests/unit/snapshotMigration0005.test.js.map +1 -0
  830. package/dist/tests/unit/store.test.d.ts +2 -0
  831. package/dist/tests/unit/store.test.d.ts.map +1 -0
  832. package/dist/tests/unit/store.test.js +47 -0
  833. package/dist/tests/unit/store.test.js.map +1 -0
  834. package/dist/tests/unit/streamUtils.test.d.ts +2 -0
  835. package/dist/tests/unit/streamUtils.test.d.ts.map +1 -0
  836. package/dist/tests/unit/streamUtils.test.js +383 -0
  837. package/dist/tests/unit/streamUtils.test.js.map +1 -0
  838. package/dist/tests/unit/tags.test.d.ts +2 -0
  839. package/dist/tests/unit/tags.test.d.ts.map +1 -0
  840. package/dist/tests/unit/tags.test.js +154 -0
  841. package/dist/tests/unit/tags.test.js.map +1 -0
  842. package/dist/tests/unit/testUtils.test.d.ts +5 -0
  843. package/dist/tests/unit/testUtils.test.d.ts.map +1 -0
  844. package/dist/tests/unit/testUtils.test.js +86 -0
  845. package/dist/tests/unit/testUtils.test.js.map +1 -0
  846. package/dist/tests/unit/timelineStoreInterface.test.d.ts +5 -0
  847. package/dist/tests/unit/timelineStoreInterface.test.d.ts.map +1 -0
  848. package/dist/tests/unit/timelineStoreInterface.test.js +343 -0
  849. package/dist/tests/unit/timelineStoreInterface.test.js.map +1 -0
  850. package/dist/townsEnv.d.ts +47 -0
  851. package/dist/townsEnv.d.ts.map +1 -0
  852. package/dist/townsEnv.js +248 -0
  853. package/dist/townsEnv.js.map +1 -0
  854. package/dist/types.d.ts +200 -0
  855. package/dist/types.d.ts.map +1 -0
  856. package/dist/types.js +765 -0
  857. package/dist/types.js.map +1 -0
  858. package/dist/unauthenticatedClient.d.ts +25 -0
  859. package/dist/unauthenticatedClient.d.ts.map +1 -0
  860. package/dist/unauthenticatedClient.js +133 -0
  861. package/dist/unauthenticatedClient.js.map +1 -0
  862. package/dist/utils.d.ts +33 -0
  863. package/dist/utils.d.ts.map +1 -0
  864. package/dist/utils.js +119 -0
  865. package/dist/utils.js.map +1 -0
  866. package/dist/views/models/timelineEvent.d.ts +11 -0
  867. package/dist/views/models/timelineEvent.d.ts.map +1 -0
  868. package/dist/views/models/timelineEvent.js +1063 -0
  869. package/dist/views/models/timelineEvent.js.map +1 -0
  870. package/dist/views/models/timelineTypes.d.ts +412 -0
  871. package/dist/views/models/timelineTypes.d.ts.map +1 -0
  872. package/dist/views/models/timelineTypes.js +224 -0
  873. package/dist/views/models/timelineTypes.js.map +1 -0
  874. package/dist/views/streams/channelStreams.d.ts +8 -0
  875. package/dist/views/streams/channelStreams.d.ts.map +1 -0
  876. package/dist/views/streams/channelStreams.js +9 -0
  877. package/dist/views/streams/channelStreams.js.map +1 -0
  878. package/dist/views/streams/dmStreams.d.ts +13 -0
  879. package/dist/views/streams/dmStreams.d.ts.map +1 -0
  880. package/dist/views/streams/dmStreams.js +33 -0
  881. package/dist/views/streams/dmStreams.js.map +1 -0
  882. package/dist/views/streams/gdmStreams.d.ts +16 -0
  883. package/dist/views/streams/gdmStreams.d.ts.map +1 -0
  884. package/dist/views/streams/gdmStreams.js +40 -0
  885. package/dist/views/streams/gdmStreams.js.map +1 -0
  886. package/dist/views/streams/notificationSettings.d.ts +14 -0
  887. package/dist/views/streams/notificationSettings.d.ts.map +1 -0
  888. package/dist/views/streams/notificationSettings.js +32 -0
  889. package/dist/views/streams/notificationSettings.js.map +1 -0
  890. package/dist/views/streams/spaceStreams.d.ts +17 -0
  891. package/dist/views/streams/spaceStreams.d.ts.map +1 -0
  892. package/dist/views/streams/spaceStreams.js +52 -0
  893. package/dist/views/streams/spaceStreams.js.map +1 -0
  894. package/dist/views/streams/streamMemberIds.d.ts +8 -0
  895. package/dist/views/streams/streamMemberIds.d.ts.map +1 -0
  896. package/dist/views/streams/streamMemberIds.js +34 -0
  897. package/dist/views/streams/streamMemberIds.js.map +1 -0
  898. package/dist/views/streams/streamStatus.d.ts +12 -0
  899. package/dist/views/streams/streamStatus.d.ts.map +1 -0
  900. package/dist/views/streams/streamStatus.js +25 -0
  901. package/dist/views/streams/streamStatus.js.map +1 -0
  902. package/dist/views/streams/timelines.d.ts +25 -0
  903. package/dist/views/streams/timelines.d.ts.map +1 -0
  904. package/dist/views/streams/timelines.js +108 -0
  905. package/dist/views/streams/timelines.js.map +1 -0
  906. package/dist/views/streams/timelinesModel.d.ts +32 -0
  907. package/dist/views/streams/timelinesModel.d.ts.map +1 -0
  908. package/dist/views/streams/timelinesModel.js +656 -0
  909. package/dist/views/streams/timelinesModel.js.map +1 -0
  910. package/dist/views/streams/userInboxStreams.d.ts +10 -0
  911. package/dist/views/streams/userInboxStreams.d.ts.map +1 -0
  912. package/dist/views/streams/userInboxStreams.js +24 -0
  913. package/dist/views/streams/userInboxStreams.js.map +1 -0
  914. package/dist/views/streams/userMetadataStreams.d.ts +10 -0
  915. package/dist/views/streams/userMetadataStreams.d.ts.map +1 -0
  916. package/dist/views/streams/userMetadataStreams.js +25 -0
  917. package/dist/views/streams/userMetadataStreams.js.map +1 -0
  918. package/dist/views/streams/userSettingsStreams.d.ts +16 -0
  919. package/dist/views/streams/userSettingsStreams.d.ts.map +1 -0
  920. package/dist/views/streams/userSettingsStreams.js +74 -0
  921. package/dist/views/streams/userSettingsStreams.js.map +1 -0
  922. package/dist/views/streams/userStreamsView.d.ts +28 -0
  923. package/dist/views/streams/userStreamsView.d.ts.map +1 -0
  924. package/dist/views/streams/userStreamsView.js +119 -0
  925. package/dist/views/streams/userStreamsView.js.map +1 -0
  926. package/dist/views/streamsView.d.ts +58 -0
  927. package/dist/views/streamsView.d.ts.map +1 -0
  928. package/dist/views/streamsView.js +172 -0
  929. package/dist/views/streamsView.js.map +1 -0
  930. package/dist/views/transforms/blockedUserIdsTransform.d.ts +5 -0
  931. package/dist/views/transforms/blockedUserIdsTransform.d.ts.map +1 -0
  932. package/dist/views/transforms/blockedUserIdsTransform.js +12 -0
  933. package/dist/views/transforms/blockedUserIdsTransform.js.map +1 -0
  934. package/dist/views/transforms/dmsAndGdmsTransform.d.ts +23 -0
  935. package/dist/views/transforms/dmsAndGdmsTransform.d.ts.map +1 -0
  936. package/dist/views/transforms/dmsAndGdmsTransform.js +73 -0
  937. package/dist/views/transforms/dmsAndGdmsTransform.js.map +1 -0
  938. package/dist/views/transforms/dmsAndGdmsUnreadIdsTransform.d.ts +13 -0
  939. package/dist/views/transforms/dmsAndGdmsUnreadIdsTransform.d.ts.map +1 -0
  940. package/dist/views/transforms/dmsAndGdmsUnreadIdsTransform.js +22 -0
  941. package/dist/views/transforms/dmsAndGdmsUnreadIdsTransform.js.map +1 -0
  942. package/dist/views/transforms/logObservable.d.ts +2 -0
  943. package/dist/views/transforms/logObservable.d.ts.map +1 -0
  944. package/dist/views/transforms/logObservable.js +10 -0
  945. package/dist/views/transforms/logObservable.js.map +1 -0
  946. package/dist/views/transforms/membersNotInDmsTransform.d.ts +17 -0
  947. package/dist/views/transforms/membersNotInDmsTransform.d.ts.map +1 -0
  948. package/dist/views/transforms/membersNotInDmsTransform.js +39 -0
  949. package/dist/views/transforms/membersNotInDmsTransform.js.map +1 -0
  950. package/dist/views/transforms/membershipsTransform.d.ts +4 -0
  951. package/dist/views/transforms/membershipsTransform.d.ts.map +1 -0
  952. package/dist/views/transforms/membershipsTransform.js +16 -0
  953. package/dist/views/transforms/membershipsTransform.js.map +1 -0
  954. package/dist/views/transforms/mutedStreamIdsTransform.d.ts +5 -0
  955. package/dist/views/transforms/mutedStreamIdsTransform.d.ts.map +1 -0
  956. package/dist/views/transforms/mutedStreamIdsTransform.js +11 -0
  957. package/dist/views/transforms/mutedStreamIdsTransform.js.map +1 -0
  958. package/dist/views/transforms/spaceIdsTransform.d.ts +3 -0
  959. package/dist/views/transforms/spaceIdsTransform.d.ts.map +1 -0
  960. package/dist/views/transforms/spaceIdsTransform.js +14 -0
  961. package/dist/views/transforms/spaceIdsTransform.js.map +1 -0
  962. package/dist/views/transforms/spaceMentionsTransform.d.ts +17 -0
  963. package/dist/views/transforms/spaceMentionsTransform.d.ts.map +1 -0
  964. package/dist/views/transforms/spaceMentionsTransform.js +79 -0
  965. package/dist/views/transforms/spaceMentionsTransform.js.map +1 -0
  966. package/dist/views/transforms/spaceUnreadsTransform.d.ts +15 -0
  967. package/dist/views/transforms/spaceUnreadsTransform.d.ts.map +1 -0
  968. package/dist/views/transforms/spaceUnreadsTransform.js +83 -0
  969. package/dist/views/transforms/spaceUnreadsTransform.js.map +1 -0
  970. package/dist/views/transforms/streamMemberIdsSansUserTransform.d.ts +7 -0
  971. package/dist/views/transforms/streamMemberIdsSansUserTransform.d.ts.map +1 -0
  972. package/dist/views/transforms/streamMemberIdsSansUserTransform.js +23 -0
  973. package/dist/views/transforms/streamMemberIdsSansUserTransform.js.map +1 -0
  974. package/dist/views/transforms/unreadMarkersTransform.d.ts +13 -0
  975. package/dist/views/transforms/unreadMarkersTransform.d.ts.map +1 -0
  976. package/dist/views/transforms/unreadMarkersTransform.js +246 -0
  977. package/dist/views/transforms/unreadMarkersTransform.js.map +1 -0
  978. package/package.json +69 -0
package/dist/client.js ADDED
@@ -0,0 +1,2135 @@
1
+ import { create, toBinary, toJsonString } from '@bufbuild/protobuf';
2
+ import { SpaceAddressFromSpaceId, SpaceReviewAction, } from '@towns-labs/web3';
3
+ import { MembershipOp, ChannelOp, Err, BlockchainTransactionReceipt_LogSchema, BlockchainTransactionReceiptSchema, ChannelPropertiesSchema, FullyReadMarkersSchema, ChunkedMediaSchema, EncryptedDataSchema, UserBioSchema, MemberPayload_NftSchema, ChannelMessageSchema, SolanaBlockchainTransactionReceiptSchema, SessionKeysSchema, EnvelopeSchema, MessageInteractionType, InteractionRequestPayloadSchema, InteractionResponsePayloadSchema, EncryptedDataVersion, } from '@towns-labs/proto';
4
+ import { bin_fromHexString, bin_toHexString, shortenHexString, check, dlog, dlogError, bin_fromString, bin_toBase64, } from '@towns-labs/utils';
5
+ import { AES_GCM_DERIVED_ALGORITHM, EncryptionAlgorithmId, GroupEncryptionAlgorithmId, GroupEncryptionCrypto, } from '@towns-labs/encryption';
6
+ import { makeSessionKeys, } from './decryptionExtensions';
7
+ import { ClientDecryptionExtensions } from './clientDecryptionExtensions';
8
+ import { getMaxTimeoutMs, getMiniblocks } from './makeStreamRpcClient';
9
+ import { errorContains, errorContainsMessage, getRpcErrorProperty } from './rpcInterceptors';
10
+ import { assert, isDefined, logNever } from './check';
11
+ import EventEmitter from 'events';
12
+ import { isChannelStreamId, isDMChannelStreamId, isGDMChannelStreamId, isSpaceStreamId, makeDMStreamId, makeUniqueGDMChannelStreamId, makeUniqueMediaStreamId, makeUserMetadataStreamId, makeUserSettingsStreamId, makeUserStreamId, makeUserInboxStreamId, userIdFromAddress, addressFromUserId, streamIdAsBytes, streamIdAsString, makeSpaceStreamId, STREAM_ID_STRING_LENGTH, contractAddressFromSpaceId, isUserId, spaceIdFromChannelId, } from './id';
13
+ import { makeEvent, unpackStream, unpackStreamEx, waitForStreamEx, } from './sign';
14
+ import { StreamStateView } from './streamStateView';
15
+ import { make_UserMetadataPayload_Inception, make_ChannelPayload_Inception, make_ChannelPayload_Message, make_MemberPayload_Membership2, make_SpacePayload_Inception, make_UserPayload_Inception, make_SpacePayload_ChannelUpdate, make_UserSettingsPayload_FullyReadMarkers, make_UserSettingsPayload_UserBlock, make_UserSettingsPayload_Inception, make_MediaPayload_Inception, make_MediaPayload_Chunk, make_DMChannelPayload_Inception, make_DMChannelPayload_Message, make_GDMChannelPayload_Inception, make_GDMChannelPayload_Message, make_UserInboxPayload_Ack, make_UserInboxPayload_Inception, make_UserMetadataPayload_EncryptionDevice, make_UserInboxPayload_GroupEncryptionSessions, make_GDMChannelPayload_ChannelProperties, make_UserPayload_UserMembershipAction, make_UserPayload_UserMembership, make_MemberPayload_DisplayName, make_MemberPayload_Username, getRefEventIdFromChannelMessage, make_payload_Redaction, make_MemberPayload_EnsAddress, make_MemberPayload_Nft, make_MemberPayload_Pin, make_MemberPayload_Unpin, make_SpacePayload_UpdateChannelAutojoin, make_SpacePayload_UpdateChannelHideUserJoinLeaveEvents, make_SpacePayload_SpaceImage, make_UserMetadataPayload_ProfileImage, make_UserMetadataPayload_Bio, make_UserPayload_BlockchainTransaction, make_MemberPayload_EncryptionAlgorithm, isSolanaTransactionReceipt, make_payload_InteractionRequest, make_payload_InteractionResponse, } from './types';
16
+ import { applyExclusionFilterToMiniblocks } from './streamUtils';
17
+ import debug from 'debug';
18
+ import { ethereumAddressAsBytes, getTime, isEthereumAddress, stripUndefinedMetadata, usernameChecksum, } from './utils';
19
+ import { isEncryptedContentKind, toDecryptedContent } from './encryptedContentTypes';
20
+ import { PersistenceStore, StubPersistenceStore, } from './persistenceStore';
21
+ import { SyncedStreams } from './syncedStreams';
22
+ import { SyncState } from './syncedStreamsLoop';
23
+ import { SyncedStream } from './syncedStream';
24
+ import { SyncedStreamsExtension } from './syncedStreamsExtension';
25
+ import { decryptAESGCM, deriveKeyAndIV, encryptAESGCM, uint8ArrayToBase64, } from '@towns-labs/sdk-crypto';
26
+ import { makeTags, makeTipTags, makeTransferTags } from './tags';
27
+ import { StreamsView } from './views/streamsView';
28
+ import { NotificationsClient } from './notificationsClient';
29
+ import { SyncedStreamsControllerLite } from './sync/SyncedStreamsControllerLite';
30
+ export var SyncMode;
31
+ (function (SyncMode) {
32
+ SyncMode[SyncMode["Full"] = 0] = "Full";
33
+ SyncMode[SyncMode["Lite"] = 1] = "Lite";
34
+ })(SyncMode || (SyncMode = {}));
35
+ const defaultExcludeEventsInScrollback = [
36
+ {
37
+ payload: 'memberPayload',
38
+ content: 'keySolicitation',
39
+ },
40
+ {
41
+ payload: 'memberPayload',
42
+ content: 'keyFulfillment',
43
+ },
44
+ ];
45
+ export class Client extends EventEmitter {
46
+ opts;
47
+ signerContext;
48
+ rpcClient;
49
+ userId;
50
+ appAddress;
51
+ streams;
52
+ streamsView;
53
+ logId;
54
+ notifications;
55
+ excludeEventsInScrollback;
56
+ userStreamId;
57
+ userSettingsStreamId;
58
+ userMetadataStreamId;
59
+ userInboxStreamId;
60
+ logCall;
61
+ logSync;
62
+ logEmitFromStream;
63
+ logEmitFromClient;
64
+ logEvent;
65
+ logError;
66
+ logInfo;
67
+ logDebug;
68
+ cryptoBackend;
69
+ cryptoStore;
70
+ getStreamRequests = new Map();
71
+ getStreamExRequests = new Map();
72
+ initStreamRequests = new Map();
73
+ getScrollbackRequests = new Map();
74
+ creatingStreamIds = new Set();
75
+ decryptionExtensions;
76
+ syncedStreamsExtensions;
77
+ persistenceStore;
78
+ defaultGroupEncryptionAlgorithm;
79
+ pendingUsernames = new Map();
80
+ pendingUsernameTimeouts = new Map();
81
+ constructor(signerContext, appAddress, rpcClient, cryptoStore, opts) {
82
+ super();
83
+ this.opts = opts;
84
+ if (opts?.logNamespaceFilter) {
85
+ debug.enable(opts.logNamespaceFilter);
86
+ }
87
+ assert(isDefined(signerContext.creatorAddress) && signerContext.creatorAddress.length === 20, 'creatorAddress must be set');
88
+ assert(isDefined(signerContext.signerPrivateKey()) &&
89
+ signerContext.signerPrivateKey().length === 64, 'signerPrivateKey must be set');
90
+ assert(!isDefined(appAddress) || isEthereumAddress(appAddress), 'appAddress must be an ethereum address');
91
+ this.signerContext = signerContext;
92
+ this.rpcClient = rpcClient;
93
+ this.userId = userIdFromAddress(signerContext.creatorAddress);
94
+ this.appAddress = appAddress;
95
+ this.streamsView = new StreamsView(this.userId, {
96
+ isDMMessageEventBlocked: (event) => {
97
+ if (!this?.userSettingsStreamId) {
98
+ return false;
99
+ }
100
+ const stream = this.stream(this.userSettingsStreamId);
101
+ check(isDefined(stream), 'stream must be defined');
102
+ return stream.view.userSettingsContent.isUserBlockedAt(event.sender.id, event.eventNum);
103
+ },
104
+ });
105
+ this.defaultGroupEncryptionAlgorithm =
106
+ opts?.defaultGroupEncryptionAlgorithm ??
107
+ GroupEncryptionAlgorithmId.HybridGroupEncryption;
108
+ this.logId =
109
+ opts?.logId ??
110
+ shortenHexString(this.userId.startsWith('0x') ? this.userId.slice(2) : this.userId);
111
+ this.logCall = dlog('csb:cl:call').extend(this.logId);
112
+ this.logSync = dlog('csb:cl:sync').extend(this.logId);
113
+ this.logEmitFromStream = dlog('csb:cl:stream').extend(this.logId);
114
+ this.logEmitFromClient = dlog('csb:cl:emit').extend(this.logId);
115
+ this.logEvent = dlog('csb:cl:event').extend(this.logId);
116
+ this.logError = dlogError('csb:cl:error').extend(this.logId);
117
+ this.logInfo = dlog('csb:cl:info', { defaultEnabled: true }).extend(this.logId);
118
+ this.logDebug = dlog('csb:cl:debug').extend(this.logId);
119
+ this.cryptoStore = cryptoStore;
120
+ if (opts?.persistenceStoreName) {
121
+ this.persistenceStore = new PersistenceStore(opts.persistenceStoreName);
122
+ }
123
+ else {
124
+ this.persistenceStore = new StubPersistenceStore();
125
+ }
126
+ this.streams = new SyncedStreams(this.userId, this.rpcClient, this, opts?.unpackEnvelopeOpts, this.logId, opts?.highPriorityStreamIds);
127
+ const syncedStreamsControllerDelegate = {
128
+ startSyncStreams: async (lastAccessedAt) => {
129
+ this.streamsView.setLastAccessedAt(lastAccessedAt);
130
+ this.streams.startSyncStreams(lastAccessedAt);
131
+ this.decryptionExtensions?.start();
132
+ },
133
+ initStream: (streamId, allowGetStream, persistedData) => this.initStream(streamId, allowGetStream, persistedData),
134
+ emitClientInitStatus: (status) => this.emit('clientInitStatusUpdated', status),
135
+ };
136
+ if (opts?.syncMode === SyncMode.Lite) {
137
+ this.syncedStreamsExtensions = new SyncedStreamsControllerLite(opts?.highPriorityStreamIds, syncedStreamsControllerDelegate, this.persistenceStore, this.logId);
138
+ }
139
+ else {
140
+ this.syncedStreamsExtensions = new SyncedStreamsExtension(opts?.highPriorityStreamIds, syncedStreamsControllerDelegate, this.persistenceStore, this.logId);
141
+ }
142
+ // Initialize notifications client if options are provided
143
+ if (opts?.notifications) {
144
+ this.notifications = new NotificationsClient(signerContext, opts.notifications.url, opts.notifications.store, opts.notifications.rpcOptions, this.streamsView);
145
+ }
146
+ this.excludeEventsInScrollback = defaultExcludeEventsInScrollback;
147
+ if (opts?.excludeEventsInScrollback !== undefined) {
148
+ this.excludeEventsInScrollback = opts.excludeEventsInScrollback;
149
+ }
150
+ this.logCall('new Client');
151
+ }
152
+ get streamSyncActive() {
153
+ return this.streams.syncState === SyncState.Syncing;
154
+ }
155
+ get clientInitStatus() {
156
+ return this.syncedStreamsExtensions.initStatus;
157
+ }
158
+ get cryptoInitialized() {
159
+ return this.cryptoBackend !== undefined;
160
+ }
161
+ async stop() {
162
+ this.logCall('stop');
163
+ await this.decryptionExtensions?.stop();
164
+ await this.syncedStreamsExtensions.stop();
165
+ await this.stopSync();
166
+ }
167
+ stream(streamId) {
168
+ return this.streams.get(streamId);
169
+ }
170
+ createSyncedStream(streamId) {
171
+ check(!this.streams.has(streamId), 'stream already exists');
172
+ const stream = new SyncedStream(this.userId, streamIdAsString(streamId), this.streamsView, this, this.logEmitFromStream, this.persistenceStore);
173
+ this.streams.set(streamId, stream);
174
+ return stream;
175
+ }
176
+ initUserJoinedStreams() {
177
+ assert(isDefined(this.userStreamId), 'userStreamId must be set');
178
+ const stream = this.stream(this.userStreamId);
179
+ assert(isDefined(stream), 'userStream must be set');
180
+ stream.on('userJoinedStream', (s) => void this.onJoinedStream(s));
181
+ stream.on('userInvitedToStream', (s) => void this.onInvitedToStream(s));
182
+ stream.on('userLeftStream', (s) => void this.onLeftStream(s));
183
+ this.on('streamUpToDate', (s) => void this.onStreamUpToDate(s));
184
+ const streamIds = Object.entries(stream.view.userContent.streamMemberships).reduce((acc, [streamId, payload]) => {
185
+ if (payload?.op === MembershipOp.SO_JOIN ||
186
+ (payload?.op === MembershipOp.SO_INVITE &&
187
+ (isDMChannelStreamId(streamId) || isGDMChannelStreamId(streamId)))) {
188
+ acc.push(streamId);
189
+ }
190
+ return acc;
191
+ }, []);
192
+ this.syncedStreamsExtensions.setStreamIds(streamIds);
193
+ }
194
+ /// get or create user streams, if first time creating an app, appOwnerAddress must be set
195
+ async initializeUser(opts) {
196
+ if (opts?.appOwnerAddress && !isEthereumAddress(opts.appOwnerAddress)) {
197
+ throw Error('appOwnerAddress must be an ethereum address');
198
+ }
199
+ const appOwnerAddress = opts?.appOwnerAddress
200
+ ? ethereumAddressAsBytes(opts.appOwnerAddress)
201
+ : undefined;
202
+ if (opts?.installedAppAddress && !isEthereumAddress(opts.installedAppAddress)) {
203
+ throw Error('installedAppAddress must be an ethereum address');
204
+ }
205
+ const spaceId = opts?.spaceId ? streamIdAsBytes(opts?.spaceId) : undefined;
206
+ const installedAppAddress = opts?.installedAppAddress
207
+ ? ethereumAddressAsBytes(opts.installedAppAddress)
208
+ : undefined;
209
+ const initMetadata = {
210
+ spaceId,
211
+ installedAppAddress,
212
+ };
213
+ const initializeUserStartTime = performance.now();
214
+ this.logCall('initializeUser', this.userId);
215
+ assert(this.userStreamId === undefined, 'already initialized');
216
+ const initCrypto = await getTime(() => this.initCrypto(opts?.encryptionDeviceInit));
217
+ check(isDefined(this.decryptionExtensions), 'decryptionExtensions must be defined');
218
+ const [initUserStream, initUserInboxStream, initUserMetadataStream, initUserSettingsStream,] = await Promise.all([
219
+ getTime(() => this.initUserStream(initMetadata, appOwnerAddress)),
220
+ getTime(() => this.initUserInboxStream(initMetadata, appOwnerAddress)),
221
+ getTime(() => this.initUserMetadataStream(initMetadata, appOwnerAddress)),
222
+ getTime(() => this.initUserSettingsStream(initMetadata, appOwnerAddress)),
223
+ ]);
224
+ this.initUserJoinedStreams();
225
+ if (!opts?.skipSync) {
226
+ this.syncedStreamsExtensions.start();
227
+ }
228
+ const initializeUserEndTime = performance.now();
229
+ const executionTime = initializeUserEndTime - initializeUserStartTime;
230
+ this.logCall('initializeUser::executionTime', executionTime);
231
+ // all of these init calls follow a similar pattern and call highly similar functions
232
+ // so just tracking more granular times for a single one of these as a start, so there's not too much data to digest
233
+ const initUserMetadataTimes = initUserMetadataStream.result;
234
+ return {
235
+ initCryptoTime: initCrypto.time,
236
+ initUserStreamTime: initUserStream.time,
237
+ initUserInboxStreamTime: initUserInboxStream.time,
238
+ initUserMetadataStreamTime: initUserMetadataStream.time,
239
+ initUserSettingsStreamTime: initUserSettingsStream.time,
240
+ ...initUserMetadataTimes,
241
+ };
242
+ }
243
+ onNetworkStatusChanged(isOnline) {
244
+ this.streams.onNetworkStatusChanged(isOnline);
245
+ }
246
+ async initUserStream(metadata, appOwnerAddress) {
247
+ this.userStreamId = makeUserStreamId(this.userId);
248
+ const userStream = this.createSyncedStream(this.userStreamId);
249
+ if (!(await userStream.initializeFromPersistence())) {
250
+ const response = (await this.getUserStream(this.userStreamId)) ??
251
+ (await this.createUserStream(this.userStreamId, metadata, appOwnerAddress));
252
+ await userStream.initializeFromResponse(response);
253
+ }
254
+ check(userStream.view.userContent.appAddress === this.appAddress, 'appAddress mismatch after initializing user stream');
255
+ }
256
+ async initUserInboxStream(metadata, appOwnerAddress) {
257
+ this.userInboxStreamId = makeUserInboxStreamId(this.userId);
258
+ const userInboxStream = this.createSyncedStream(this.userInboxStreamId);
259
+ if (!(await userInboxStream.initializeFromPersistence())) {
260
+ const response = (await this.getUserStream(this.userInboxStreamId)) ??
261
+ (await this.createUserInboxStream(this.userInboxStreamId, metadata, appOwnerAddress));
262
+ await userInboxStream.initializeFromResponse(response);
263
+ }
264
+ check(userInboxStream.view.userInboxContent.appAddress === this.appAddress, 'appAddress mismatch after initializing user inbox stream');
265
+ }
266
+ async initUserMetadataStream(metadata, appOwnerAddress) {
267
+ this.userMetadataStreamId = makeUserMetadataStreamId(this.userId);
268
+ const userMetadataStream = this.createSyncedStream(this.userMetadataStreamId);
269
+ let initUserMetadataStreamInitFromPersistenceTime = 0;
270
+ let initUserMetadataStreamGetUserStreamTime = 0;
271
+ let initUserMetadataStreamCreateUserMetadataStreamTime = 0;
272
+ let initUserMetadataStreamInitFromResponseTime = 0;
273
+ const initFromPersistence = await getTime(() => userMetadataStream.initializeFromPersistence());
274
+ initUserMetadataStreamInitFromPersistenceTime = initFromPersistence.time;
275
+ if (!initFromPersistence.result) {
276
+ const getUserStreamResponse = await getTime(() => {
277
+ check(!!this.userMetadataStreamId, 'userMetadataStreamId must be set');
278
+ return this.getUserStream(this.userMetadataStreamId);
279
+ });
280
+ initUserMetadataStreamGetUserStreamTime = getUserStreamResponse.time;
281
+ let response;
282
+ if (getUserStreamResponse.result) {
283
+ response = getUserStreamResponse.result;
284
+ }
285
+ else {
286
+ const createUserMetadataStreamResponse = await getTime(() => {
287
+ check(!!this.userMetadataStreamId, 'userMetadataStreamId must be set');
288
+ return this.createUserMetadataStream(this.userMetadataStreamId, metadata, appOwnerAddress);
289
+ });
290
+ initUserMetadataStreamCreateUserMetadataStreamTime =
291
+ createUserMetadataStreamResponse.time;
292
+ response = createUserMetadataStreamResponse.result;
293
+ }
294
+ const initializeFromResponse = await getTime(() => userMetadataStream.initializeFromResponse(response));
295
+ initUserMetadataStreamInitFromResponseTime = initializeFromResponse.time;
296
+ }
297
+ check(userMetadataStream.view.userMetadataContent.appAddress === this.appAddress, 'appAddress mismatch after initializing user metadata stream');
298
+ const times = {
299
+ ...(initUserMetadataStreamInitFromPersistenceTime
300
+ ? { initUserMetadataStreamInitFromPersistenceTime }
301
+ : {}),
302
+ ...(initUserMetadataStreamGetUserStreamTime
303
+ ? { initUserMetadataStreamGetUserStreamTime }
304
+ : {}),
305
+ ...(initUserMetadataStreamCreateUserMetadataStreamTime
306
+ ? {
307
+ initUserMetadataStreamCreateUserMetadataStreamTime,
308
+ }
309
+ : {}),
310
+ ...(initUserMetadataStreamInitFromResponseTime
311
+ ? { initUserMetadataStreamInitFromResponseTime }
312
+ : {}),
313
+ };
314
+ return times;
315
+ }
316
+ async initUserSettingsStream(metadata, appOwnerAddress) {
317
+ this.userSettingsStreamId = makeUserSettingsStreamId(this.userId);
318
+ const userSettingsStream = this.createSyncedStream(this.userSettingsStreamId);
319
+ if (!(await userSettingsStream.initializeFromPersistence())) {
320
+ const response = (await this.getUserStream(this.userSettingsStreamId)) ??
321
+ (await this.createUserSettingsStream(this.userSettingsStreamId, metadata, appOwnerAddress));
322
+ await userSettingsStream.initializeFromResponse(response);
323
+ }
324
+ check(userSettingsStream.view.userSettingsContent.appAddress === this.appAddress, 'appAddress mismatch after initializing user settings stream');
325
+ }
326
+ async getUserStream(streamId) {
327
+ const response = await this.rpcClient.getStream({
328
+ streamId: streamIdAsBytes(streamId),
329
+ optional: true,
330
+ });
331
+ if (response.stream) {
332
+ return unpackStream(response.stream, this.opts?.unpackEnvelopeOpts);
333
+ }
334
+ else {
335
+ return undefined;
336
+ }
337
+ }
338
+ async createUserStream(userStreamId, metadata, appOwnerAddress) {
339
+ check(isDefined(this.appAddress) == isDefined(appOwnerAddress), 'appAddress and appOwnerAddress must both be set or both be undefined');
340
+ const userEvents = [
341
+ await makeEvent(this.signerContext, make_UserPayload_Inception({
342
+ streamId: streamIdAsBytes(userStreamId),
343
+ appAddress: this.appAddress ? bin_fromHexString(this.appAddress) : undefined,
344
+ appOwnerAddress,
345
+ })),
346
+ ];
347
+ const encoded = metadata ? stripUndefinedMetadata(metadata) : metadata;
348
+ const response = await this.rpcClient.createStream({
349
+ events: userEvents,
350
+ streamId: streamIdAsBytes(userStreamId),
351
+ metadata: encoded,
352
+ });
353
+ return unpackStream(response.stream, this.opts?.unpackEnvelopeOpts);
354
+ }
355
+ async createUserMetadataStream(userMetadataStreamId, metadata, appOwnerAddress) {
356
+ check(isDefined(this.appAddress) == isDefined(appOwnerAddress), 'appAddress and appOwnerAddress must both be set or both be undefined');
357
+ const userDeviceKeyEvents = [
358
+ await makeEvent(this.signerContext, make_UserMetadataPayload_Inception({
359
+ streamId: streamIdAsBytes(userMetadataStreamId),
360
+ appAddress: this.appAddress ? bin_fromHexString(this.appAddress) : undefined,
361
+ appOwnerAddress,
362
+ })),
363
+ ];
364
+ const encoded = metadata ? stripUndefinedMetadata(metadata) : metadata;
365
+ const response = await this.rpcClient.createStream({
366
+ events: userDeviceKeyEvents,
367
+ streamId: streamIdAsBytes(userMetadataStreamId),
368
+ metadata: encoded,
369
+ });
370
+ return unpackStream(response.stream, this.opts?.unpackEnvelopeOpts);
371
+ }
372
+ async createUserInboxStream(userInboxStreamId, metadata, appOwnerAddress) {
373
+ check(isDefined(this.appAddress) == isDefined(appOwnerAddress), 'appAddress and appOwnerAddress must both be set or both be undefined');
374
+ const userInboxEvents = [
375
+ await makeEvent(this.signerContext, make_UserInboxPayload_Inception({
376
+ streamId: streamIdAsBytes(userInboxStreamId),
377
+ appAddress: this.appAddress ? bin_fromHexString(this.appAddress) : undefined,
378
+ appOwnerAddress,
379
+ })),
380
+ ];
381
+ const encoded = metadata ? stripUndefinedMetadata(metadata) : metadata;
382
+ const response = await this.rpcClient.createStream({
383
+ events: userInboxEvents,
384
+ streamId: streamIdAsBytes(userInboxStreamId),
385
+ metadata: encoded,
386
+ });
387
+ return unpackStream(response.stream, this.opts?.unpackEnvelopeOpts);
388
+ }
389
+ async createUserSettingsStream(inUserSettingsStreamId, metadata, appOwnerAddress) {
390
+ check(isDefined(this.appAddress) == isDefined(appOwnerAddress), 'appAddress and appOwnerAddress must both be set or both be undefined');
391
+ const userSettingsStreamId = streamIdAsBytes(inUserSettingsStreamId);
392
+ const userSettingsEvents = [
393
+ await makeEvent(this.signerContext, make_UserSettingsPayload_Inception({
394
+ streamId: userSettingsStreamId,
395
+ appAddress: this.appAddress ? bin_fromHexString(this.appAddress) : undefined,
396
+ appOwnerAddress,
397
+ })),
398
+ ];
399
+ const encoded = metadata ? stripUndefinedMetadata(metadata) : metadata;
400
+ const response = await this.rpcClient.createStream({
401
+ events: userSettingsEvents,
402
+ streamId: userSettingsStreamId,
403
+ metadata: encoded,
404
+ });
405
+ return unpackStream(response.stream, this.opts?.unpackEnvelopeOpts);
406
+ }
407
+ async createStreamAndSync(request) {
408
+ const streamId = streamIdAsString(request.streamId);
409
+ try {
410
+ this.creatingStreamIds.add(streamId);
411
+ let response = await this.rpcClient.createStream(request);
412
+ const stream = this.createSyncedStream(streamId);
413
+ if (!response.stream) {
414
+ // if a stream already exists it will return a nil stream in the response, but no error
415
+ // fetch the stream to get the client in the right state
416
+ response = await this.rpcClient.getStream({ streamId: request.streamId });
417
+ }
418
+ const unpacked = await unpackStream(response.stream, this.opts?.unpackEnvelopeOpts);
419
+ await stream.initializeFromResponse(unpacked);
420
+ if (stream.view.syncCookie) {
421
+ this.streams.addStreamToSync(streamId, stream.view.syncCookie);
422
+ }
423
+ }
424
+ catch (err) {
425
+ this.logError('Failed to create stream', streamId);
426
+ this.streams.delete(streamId);
427
+ this.creatingStreamIds.delete(streamId);
428
+ throw err;
429
+ }
430
+ return { streamId: streamId };
431
+ }
432
+ // createSpace
433
+ // param spaceAddress: address of the space contract, or address made with makeSpaceStreamId
434
+ async createSpace(spaceAddressOrId) {
435
+ const oSpaceId = spaceAddressOrId.length === STREAM_ID_STRING_LENGTH
436
+ ? spaceAddressOrId
437
+ : makeSpaceStreamId(spaceAddressOrId);
438
+ const spaceId = streamIdAsBytes(oSpaceId);
439
+ this.logCall('createSpace', spaceId);
440
+ assert(this.userStreamId !== undefined, 'streamId must be set');
441
+ assert(isSpaceStreamId(spaceId), 'spaceId must be a valid streamId');
442
+ // create utf8 encoder
443
+ const inceptionEvent = await makeEvent(this.signerContext, make_SpacePayload_Inception({
444
+ streamId: spaceId,
445
+ }));
446
+ const joinEvent = await makeEvent(this.signerContext, make_MemberPayload_Membership2({
447
+ userId: this.userId,
448
+ op: MembershipOp.SO_JOIN,
449
+ initiatorId: this.userId,
450
+ }));
451
+ return this.createStreamAndSync({
452
+ events: [inceptionEvent, joinEvent],
453
+ streamId: spaceId,
454
+ metadata: {},
455
+ });
456
+ }
457
+ async createChannel(spaceId, _channelName, _channelTopic, inChannelId, streamSettings, channelSettings) {
458
+ const channelId = streamIdAsBytes(inChannelId);
459
+ const channelIdStr = streamIdAsString(inChannelId);
460
+ const spaceIdstr = streamIdAsString(spaceId);
461
+ this.logCall('createChannel', channelId, spaceId);
462
+ const derivedSpaceId = spaceIdFromChannelId(channelIdStr);
463
+ assert(derivedSpaceId === spaceIdstr, 'derivedSpaceId must be the same as spaceId');
464
+ assert(this.userStreamId !== undefined, 'userStreamId must be set');
465
+ assert(isSpaceStreamId(spaceId), 'spaceId must be a valid streamId');
466
+ assert(isChannelStreamId(channelId), 'channelId must be a valid streamId');
467
+ const inceptionEvent = await makeEvent(this.signerContext, make_ChannelPayload_Inception({
468
+ streamId: channelId,
469
+ settings: streamSettings,
470
+ channelSettings: channelSettings,
471
+ }));
472
+ const joinEvent = await makeEvent(this.signerContext, make_MemberPayload_Membership2({
473
+ userId: this.userId,
474
+ op: MembershipOp.SO_JOIN,
475
+ initiatorId: this.userId,
476
+ }));
477
+ return this.createStreamAndSync({
478
+ events: [inceptionEvent, joinEvent],
479
+ streamId: channelId,
480
+ metadata: {},
481
+ });
482
+ }
483
+ async createDMChannel(userId, appAddress, streamSettings) {
484
+ const channelIdStr = makeDMStreamId(this.userId, userId);
485
+ const channelId = streamIdAsBytes(channelIdStr);
486
+ const inceptionEvent = await makeEvent(this.signerContext, make_DMChannelPayload_Inception({
487
+ streamId: channelId,
488
+ firstPartyAddress: this.signerContext.creatorAddress,
489
+ secondPartyAddress: addressFromUserId(userId),
490
+ secondPartyAppAddress: appAddress ? bin_fromHexString(appAddress) : undefined,
491
+ settings: streamSettings,
492
+ }));
493
+ const joinEvent = await makeEvent(this.signerContext, make_MemberPayload_Membership2({
494
+ userId: this.userId,
495
+ op: MembershipOp.SO_JOIN,
496
+ initiatorId: this.userId,
497
+ }));
498
+ const inviteEvent = await makeEvent(this.signerContext, make_MemberPayload_Membership2({
499
+ userId: userId,
500
+ op: MembershipOp.SO_JOIN,
501
+ initiatorId: this.userId,
502
+ appAddress,
503
+ }));
504
+ return this.createStreamAndSync({
505
+ events: [inceptionEvent, joinEvent, inviteEvent],
506
+ streamId: channelId,
507
+ metadata: {},
508
+ });
509
+ }
510
+ async createGDMChannel(users, channelProperties, streamSettings) {
511
+ const channelIdStr = makeUniqueGDMChannelStreamId();
512
+ const channelId = streamIdAsBytes(channelIdStr);
513
+ const events = [];
514
+ const inceptionEvent = await makeEvent(this.signerContext, make_GDMChannelPayload_Inception({
515
+ streamId: channelId,
516
+ channelProperties: channelProperties,
517
+ settings: streamSettings,
518
+ }));
519
+ events.push(inceptionEvent);
520
+ const joinEvent = await makeEvent(this.signerContext, make_MemberPayload_Membership2({
521
+ userId: this.userId,
522
+ op: MembershipOp.SO_JOIN,
523
+ initiatorId: this.userId,
524
+ appAddress: this.appAddress,
525
+ }));
526
+ events.push(joinEvent);
527
+ for (const user of users) {
528
+ const inviteEvent = await makeEvent(this.signerContext, make_MemberPayload_Membership2({
529
+ userId: user.userId,
530
+ op: MembershipOp.SO_JOIN,
531
+ initiatorId: this.userId,
532
+ appAddress: user.appAddress,
533
+ }));
534
+ events.push(inviteEvent);
535
+ }
536
+ return this.createStreamAndSync({
537
+ events: events,
538
+ streamId: channelId,
539
+ metadata: {},
540
+ });
541
+ }
542
+ async createMediaStream(channelId, spaceId, userId, chunkCount, firstChunk, firstChunkIv, streamSettings, perChunkEncryption) {
543
+ assert(this.userStreamId !== undefined, 'userStreamId must be set');
544
+ if (!channelId && !spaceId && !userId) {
545
+ throw Error('channelId, spaceId or userId must be set');
546
+ }
547
+ if (spaceId) {
548
+ assert(isSpaceStreamId(spaceId), 'spaceId must be a valid streamId');
549
+ }
550
+ if (channelId) {
551
+ assert(isChannelStreamId(channelId) ||
552
+ isDMChannelStreamId(channelId) ||
553
+ isGDMChannelStreamId(channelId), 'channelId must be a valid streamId');
554
+ }
555
+ if (userId) {
556
+ assert(isUserId(userId), 'userId must be a valid userId');
557
+ }
558
+ const streamId = makeUniqueMediaStreamId();
559
+ const events = [];
560
+ this.logCall('createMedia', channelId ?? spaceId, userId, streamId);
561
+ // Prepare inception event
562
+ events.push(await makeEvent(this.signerContext, make_MediaPayload_Inception({
563
+ streamId: streamIdAsBytes(streamId),
564
+ channelId: channelId ? streamIdAsBytes(channelId) : undefined,
565
+ spaceId: spaceId ? streamIdAsBytes(spaceId) : undefined,
566
+ userId: userId ? addressFromUserId(userId) : undefined,
567
+ chunkCount,
568
+ settings: streamSettings,
569
+ perChunkEncryption: perChunkEncryption,
570
+ })));
571
+ // Prepare first chunk event
572
+ if (firstChunk && firstChunk.length > 0) {
573
+ events.push(await makeEvent(this.signerContext, make_MediaPayload_Chunk({
574
+ data: firstChunk,
575
+ chunkIndex: 0,
576
+ iv: firstChunkIv,
577
+ })));
578
+ }
579
+ const response = await this.rpcClient.createMediaStream({
580
+ events: events,
581
+ streamId: streamIdAsBytes(streamId),
582
+ });
583
+ check(response?.nextCreationCookie !== undefined, 'nextCreationCookie was expected but was not returned in response');
584
+ return { creationCookie: response.nextCreationCookie };
585
+ }
586
+ async updateChannel(spaceId, channelId, unused1, unused2) {
587
+ this.logCall('updateChannel', channelId, spaceId, unused1, unused2);
588
+ assert(isSpaceStreamId(spaceId), 'spaceId must be a valid streamId');
589
+ assert(isChannelStreamId(channelId), 'channelId must be a valid streamId');
590
+ return this.makeEventAndAddToStream(spaceId, // we send events to the stream of the space where updated channel belongs to
591
+ make_SpacePayload_ChannelUpdate({
592
+ op: ChannelOp.CO_UPDATED,
593
+ channelId: streamIdAsBytes(channelId),
594
+ }), { method: 'updateChannel' });
595
+ }
596
+ async updateChannelAutojoin(spaceId, channelId, autojoin) {
597
+ this.logCall('updateChannelAutojoin', channelId, spaceId, autojoin);
598
+ assert(isSpaceStreamId(spaceId), 'spaceId must be a valid streamId');
599
+ assert(isChannelStreamId(channelId), 'channelId must be a valid streamId');
600
+ return this.makeEventAndAddToStream(spaceId, // we send events to the stream of the space where updated channel belongs to
601
+ make_SpacePayload_UpdateChannelAutojoin({
602
+ channelId: streamIdAsBytes(channelId),
603
+ autojoin: autojoin,
604
+ }), { method: 'updateChannelAutojoin' });
605
+ }
606
+ async updateChannelHideUserJoinLeaveEvents(spaceId, channelId, hideUserJoinLeaveEvents) {
607
+ this.logCall('updateChannelHideUserJoinLeaveEvents', channelId, spaceId, hideUserJoinLeaveEvents);
608
+ assert(isSpaceStreamId(spaceId), 'spaceId must be a valid streamId');
609
+ assert(isChannelStreamId(channelId), 'channelId must be a valid streamId');
610
+ return this.makeEventAndAddToStream(spaceId, // we send events to the stream of the space where updated channel belongs to
611
+ make_SpacePayload_UpdateChannelHideUserJoinLeaveEvents({
612
+ channelId: streamIdAsBytes(channelId),
613
+ hideUserJoinLeaveEvents,
614
+ }), { method: 'updateChannelHideUserJoinLeaveEvents' });
615
+ }
616
+ async updateGDMChannelProperties(streamId, channelName, channelTopic) {
617
+ this.logCall('updateGDMChannelProperties', streamId, channelName, channelTopic);
618
+ assert(isGDMChannelStreamId(streamId), 'streamId must be a valid GDM stream id');
619
+ check(isDefined(this.cryptoBackend));
620
+ const channelProps = create(ChannelPropertiesSchema, {
621
+ name: channelName,
622
+ topic: channelTopic,
623
+ });
624
+ const encryptedData = await this.cryptoBackend.encryptGroupEvent(streamId, toBinary(ChannelPropertiesSchema, channelProps), this.defaultGroupEncryptionAlgorithm);
625
+ const event = make_GDMChannelPayload_ChannelProperties(encryptedData);
626
+ return this.makeEventAndAddToStream(streamId, event, {
627
+ method: 'updateGDMChannelProperties',
628
+ });
629
+ }
630
+ async setStreamEncryptionAlgorithm(streamId, encryptionAlgorithm) {
631
+ assert(isChannelStreamId(streamId) ||
632
+ isSpaceStreamId(streamId) ||
633
+ isDMChannelStreamId(streamId) ||
634
+ isGDMChannelStreamId(streamId), 'channelId must be a valid streamId');
635
+ const stream = this.stream(streamId);
636
+ check(isDefined(stream), 'stream not found');
637
+ check(stream.view.membershipContent.encryptionAlgorithm != encryptionAlgorithm, `encryptionAlgorithm is already set to ${encryptionAlgorithm}`);
638
+ return this.makeEventAndAddToStream(streamId, make_MemberPayload_EncryptionAlgorithm(encryptionAlgorithm), {
639
+ method: 'setStreamEncryptionAlgorithm',
640
+ });
641
+ }
642
+ async sendFullyReadMarkers(channelId, fullyReadMarkers) {
643
+ this.logCall('sendFullyReadMarker', fullyReadMarkers);
644
+ if (!isDefined(this.userSettingsStreamId)) {
645
+ throw Error('userSettingsStreamId is not defined');
646
+ }
647
+ const fullyReadMarkersContent = create(FullyReadMarkersSchema, {
648
+ markers: fullyReadMarkers,
649
+ });
650
+ return this.makeEventAndAddToStream(this.userSettingsStreamId, make_UserSettingsPayload_FullyReadMarkers({
651
+ streamId: streamIdAsBytes(channelId),
652
+ content: { data: toJsonString(FullyReadMarkersSchema, fullyReadMarkersContent) },
653
+ }), { method: 'sendFullyReadMarker' });
654
+ }
655
+ async updateUserBlock(userId, isBlocked) {
656
+ this.logCall('blockUser', userId);
657
+ if (!isDefined(this.userSettingsStreamId)) {
658
+ throw Error('userSettingsStreamId is not defined');
659
+ }
660
+ const dmStreamId = makeDMStreamId(this.userId, userId);
661
+ const lastBlock = this.stream(this.userSettingsStreamId)?.view.userSettingsContent.getLastBlock(userId);
662
+ if (lastBlock?.isBlocked === isBlocked) {
663
+ throw Error(`updateUserBlock isBlocked<${isBlocked}> must be different from existing value`);
664
+ }
665
+ let eventNum = this.stream(dmStreamId)?.view.lastEventNum ?? 0n;
666
+ if (lastBlock && lastBlock.eventNum >= eventNum) {
667
+ eventNum = lastBlock.eventNum + 1n;
668
+ }
669
+ return this.makeEventAndAddToStream(this.userSettingsStreamId, make_UserSettingsPayload_UserBlock({
670
+ userId: addressFromUserId(userId),
671
+ isBlocked: isBlocked,
672
+ eventNum: eventNum,
673
+ }), { method: 'updateUserBlock' });
674
+ }
675
+ async setSpaceImage(spaceStreamId, chunkedMediaInfo) {
676
+ this.logCall('setSpaceImage', spaceStreamId, chunkedMediaInfo.streamId, chunkedMediaInfo.info);
677
+ // create the chunked media to be added
678
+ const spaceAddress = contractAddressFromSpaceId(spaceStreamId);
679
+ const context = spaceAddress.toLowerCase();
680
+ // encrypt the chunked media
681
+ // use the lowercased spaceId as the key phrase
682
+ const { key, iv } = await deriveKeyAndIV(context);
683
+ const { ciphertext } = await encryptAESGCM(toBinary(ChunkedMediaSchema, create(ChunkedMediaSchema, chunkedMediaInfo)), key, iv);
684
+ const encryptedData = create(EncryptedDataSchema, {
685
+ ciphertext: uint8ArrayToBase64(ciphertext),
686
+ algorithm: AES_GCM_DERIVED_ALGORITHM,
687
+ }); // aellis this should probably include `satisfies PlainMessage<EncryptedData>`
688
+ // add the event to the stream
689
+ const event = make_SpacePayload_SpaceImage(encryptedData);
690
+ return this.makeEventAndAddToStream(spaceStreamId, event, { method: 'setSpaceImage' });
691
+ }
692
+ async setUserProfileImage(chunkedMediaInfo, userId) {
693
+ this.logCall('setUserProfileImage', userId, chunkedMediaInfo.streamId, chunkedMediaInfo.info);
694
+ const targetUserId = userId ?? this.userId;
695
+ // create the chunked media to be added
696
+ const context = targetUserId.toLowerCase();
697
+ const userStreamId = makeUserMetadataStreamId(targetUserId);
698
+ // initialize the target user's stream (creates SyncedStream and adds to this.streams)
699
+ // usually only needed in case of bot owner updating their bot profile image
700
+ if (targetUserId !== this.userId) {
701
+ await this.initStream(userStreamId);
702
+ }
703
+ // encrypt the chunked media
704
+ // use the lowercased userId as the key phrase
705
+ const { key, iv } = await deriveKeyAndIV(context);
706
+ const { ciphertext } = await encryptAESGCM(toBinary(ChunkedMediaSchema, create(ChunkedMediaSchema, chunkedMediaInfo)), key, iv);
707
+ const encryptedData = create(EncryptedDataSchema, {
708
+ ciphertext: uint8ArrayToBase64(ciphertext),
709
+ algorithm: AES_GCM_DERIVED_ALGORITHM,
710
+ }); // aellis this should probably include `satisfies PlainMessage<EncryptedData>`
711
+ // add the event to the stream
712
+ const event = make_UserMetadataPayload_ProfileImage(encryptedData);
713
+ return this.makeEventAndAddToStream(userStreamId, event, { method: 'setUserProfileImage' });
714
+ }
715
+ async getUserProfileImage(userId) {
716
+ const streamId = makeUserMetadataStreamId(userId);
717
+ return this.stream(streamId)?.view.userMetadataContent.getProfileImage();
718
+ }
719
+ async setUserBio(bio) {
720
+ this.logCall('setUserBio', bio);
721
+ // create the chunked media to be added
722
+ const context = this.userId.toLowerCase();
723
+ const userStreamId = makeUserMetadataStreamId(this.userId);
724
+ // encrypt the chunked media
725
+ // use the lowercased userId as the key phrase
726
+ const { key, iv } = await deriveKeyAndIV(context);
727
+ bio.updatedAtEpochMs = BigInt(Date.now());
728
+ const bioBinary = toBinary(UserBioSchema, create(UserBioSchema, bio));
729
+ const { ciphertext } = await encryptAESGCM(bioBinary, key, iv);
730
+ const encryptedData = create(EncryptedDataSchema, {
731
+ ciphertext: uint8ArrayToBase64(ciphertext),
732
+ algorithm: AES_GCM_DERIVED_ALGORITHM,
733
+ }); // aellis this should probably include `satisfies PlainMessage<EncryptedData>`
734
+ // add the event to the stream
735
+ const event = make_UserMetadataPayload_Bio(encryptedData);
736
+ return this.makeEventAndAddToStream(userStreamId, event, { method: 'setUserBio' });
737
+ }
738
+ async getUserBio(userId) {
739
+ const streamId = makeUserMetadataStreamId(userId);
740
+ return this.stream(streamId)?.view.userMetadataContent.getBio();
741
+ }
742
+ async setDisplayName(streamId, displayName) {
743
+ check(isDefined(this.cryptoBackend));
744
+ const encryptedData = await this.cryptoBackend.encryptGroupEvent(streamId, new TextEncoder().encode(displayName), this.defaultGroupEncryptionAlgorithm);
745
+ await this.makeEventAndAddToStream(streamId, make_MemberPayload_DisplayName(encryptedData), { method: 'displayName' });
746
+ }
747
+ async setUsername(streamId, username, force = false, options) {
748
+ check(isDefined(this.cryptoBackend));
749
+ check(username.length > 0, 'username cannot be empty');
750
+ const stream = this.stream(streamId);
751
+ check(isDefined(stream), 'stream not found');
752
+ // Clear any existing timeout first
753
+ const existingTimeout = this.pendingUsernameTimeouts.get(streamId);
754
+ if (existingTimeout) {
755
+ clearTimeout(existingTimeout);
756
+ this.pendingUsernameTimeouts.delete(streamId);
757
+ }
758
+ stream.view.getMemberMetadata().usernames.setLocalUsername(this.userId, username, this);
759
+ // be very careful about setting a username for a large group, we don't want to inject
760
+ // more sessions than needed into the group. unless a session has been received in 60 seconds,
761
+ // we will force set the username.
762
+ const memberCount = stream.view.membershipContent.joined.size;
763
+ const hasHybridSession = (await this.cryptoBackend?.hasHybridSession?.(streamId)) ?? false;
764
+ const largeGroupThreshold = options?.largeGroupThreshold ?? 100;
765
+ const delayMs = options?.delayMs ?? 60000;
766
+ if (memberCount > largeGroupThreshold && !hasHybridSession && !force) {
767
+ this.pendingUsernames.set(streamId, username);
768
+ const timeout = setTimeout(() => {
769
+ void this.setUsername(streamId, username, true, options);
770
+ }, delayMs);
771
+ this.pendingUsernameTimeouts.set(streamId, timeout);
772
+ return;
773
+ }
774
+ // Clean up pending state
775
+ this.pendingUsernames.delete(streamId);
776
+ this.pendingUsernameTimeouts.delete(streamId);
777
+ try {
778
+ const encryptedData = await this.cryptoBackend.encryptGroupEvent(streamId, new TextEncoder().encode(username), this.defaultGroupEncryptionAlgorithm);
779
+ encryptedData.checksum = usernameChecksum(username, streamId);
780
+ await this.makeEventAndAddToStream(streamId, make_MemberPayload_Username(encryptedData), { method: 'username' });
781
+ }
782
+ catch (err) {
783
+ stream.view.getMemberMetadata().usernames.resetLocalUsername(this.userId);
784
+ // Clean up pending state on error
785
+ this.pendingUsernames.delete(streamId);
786
+ this.pendingUsernameTimeouts.delete(streamId);
787
+ throw err;
788
+ }
789
+ }
790
+ async setPendingUsernames() {
791
+ await Promise.all(Array.from(this.pendingUsernames.entries()).map(([streamId, pendingUsername]) => {
792
+ this.pendingUsernames.delete(streamId);
793
+ return this.setUsername(streamId, pendingUsername);
794
+ }));
795
+ }
796
+ async setEnsAddress(streamId, walletAddress) {
797
+ check(isDefined(this.cryptoBackend));
798
+ const bytes = typeof walletAddress === 'string' ? addressFromUserId(walletAddress) : walletAddress;
799
+ await this.makeEventAndAddToStream(streamId, make_MemberPayload_EnsAddress(bytes), {
800
+ method: 'ensAddress',
801
+ });
802
+ }
803
+ async setNft(streamId, tokenId, chainId, contractAddress) {
804
+ const payload = tokenId.length > 0
805
+ ? create(MemberPayload_NftSchema, {
806
+ chainId: chainId,
807
+ contractAddress: bin_fromHexString(contractAddress),
808
+ tokenId: bin_fromString(tokenId),
809
+ })
810
+ : create(MemberPayload_NftSchema);
811
+ await this.makeEventAndAddToStream(streamId, make_MemberPayload_Nft(payload), {
812
+ method: 'nft',
813
+ });
814
+ }
815
+ async getPersistedEvent(streamId, eventId) {
816
+ const timelineEvent = this.streamsView.timelinesView.value.timelines[streamId]?.find((e) => e.eventId === eventId);
817
+ if (!timelineEvent) {
818
+ return undefined;
819
+ }
820
+ const blockNumber = timelineEvent.confirmedInBlockNum;
821
+ if (!blockNumber) {
822
+ return undefined;
823
+ }
824
+ const miniblock = await this.persistenceStore.getMiniblock(streamId, blockNumber);
825
+ if (!miniblock) {
826
+ return undefined;
827
+ }
828
+ const event = miniblock.events.find((e) => e.hashStr === eventId);
829
+ if (!event) {
830
+ return undefined;
831
+ }
832
+ return event;
833
+ }
834
+ async pin(streamId, eventId) {
835
+ const timelineEvent = this.streamsView.timelinesView.value.timelines[streamId]?.find((e) => e.eventId === eventId);
836
+ check(isDefined(timelineEvent), 'pin timeline event not found');
837
+ const blockNumber = timelineEvent.confirmedInBlockNum;
838
+ let event;
839
+ if (blockNumber) {
840
+ const miniblock = await this.persistenceStore.getMiniblock(streamId, blockNumber);
841
+ check(isDefined(miniblock), 'miniblock not found');
842
+ event = miniblock.events.find((e) => e.hashStr === eventId);
843
+ }
844
+ else {
845
+ const stream = this.stream(streamId);
846
+ check(isDefined(stream), 'stream not found');
847
+ event = stream.view.minipoolEvents.get(eventId)?.remoteEvent;
848
+ }
849
+ check(isDefined(event), 'pin event not found');
850
+ const streamEvent = event.event;
851
+ check(isDefined(streamEvent), 'pin streamEvent not found');
852
+ const result = await this.makeEventAndAddToStream(streamId, make_MemberPayload_Pin(event.hash, streamEvent), {
853
+ method: 'pin',
854
+ });
855
+ return result;
856
+ }
857
+ async unpin(streamId, eventId) {
858
+ const stream = this.streams.get(streamId);
859
+ check(isDefined(stream), 'stream not found');
860
+ const pin = stream.view.membershipContent.pins.find((x) => x.event.hashStr === eventId);
861
+ check(isDefined(pin), 'pin not found');
862
+ check(isDefined(pin.event.remoteEvent), 'remoteEvent not found');
863
+ const result = await this.makeEventAndAddToStream(streamId, make_MemberPayload_Unpin(pin.event.remoteEvent.hash), {
864
+ method: 'unpin',
865
+ });
866
+ return result;
867
+ }
868
+ isUsernameAvailable(streamId, username) {
869
+ const stream = this.streams.get(streamId);
870
+ check(isDefined(stream), 'stream not found');
871
+ return (stream.view.getMemberMetadata().usernames.cleartextUsernameAvailable(username) ?? false);
872
+ }
873
+ async waitForStream(inStreamId, opts) {
874
+ this.logCall('waitForStream', inStreamId);
875
+ const timeoutMs = opts?.timeoutMs ?? getMaxTimeoutMs(this.rpcClient.opts);
876
+ const streamId = streamIdAsString(inStreamId);
877
+ let stream = this.stream(streamId);
878
+ if (stream !== undefined && stream.view.isInitialized) {
879
+ this.logCall('waitForStream: stream already initialized', streamId);
880
+ return stream;
881
+ }
882
+ const logId = opts?.logId ? opts.logId + ' ' : '';
883
+ const timeoutError = new Error(`waitForStream: timeout waiting for ${logId}${streamId} creating streams: ${Array.from(this.creatingStreamIds).join(',')} rpcUrl: ${this.rpcClient.url}`);
884
+ await new Promise((resolve, reject) => {
885
+ const timeout = setTimeout(() => {
886
+ this.off('streamInitialized', handler);
887
+ reject(timeoutError);
888
+ }, timeoutMs);
889
+ const handler = (newStreamId) => {
890
+ if (newStreamId === streamId) {
891
+ this.logCall('waitForStream: got streamInitialized', newStreamId);
892
+ this.off('streamInitialized', handler);
893
+ clearTimeout(timeout);
894
+ resolve();
895
+ }
896
+ else {
897
+ this.logCall('waitForStream: still waiting for ', streamId, ' got ', newStreamId);
898
+ }
899
+ };
900
+ this.on('streamInitialized', handler);
901
+ });
902
+ stream = this.stream(streamId);
903
+ if (!stream) {
904
+ throw new Error(`Stream ${streamIdAsString(streamId)} not found after waiting`);
905
+ }
906
+ return stream;
907
+ }
908
+ async getStream(streamId) {
909
+ const existingRequest = this.getStreamRequests.get(streamId);
910
+ if (existingRequest) {
911
+ this.logCall(`had existing get request for ${streamId}, returning promise`);
912
+ return await existingRequest;
913
+ }
914
+ const request = this._getStream(streamId);
915
+ this.getStreamRequests.set(streamId, request);
916
+ let streamView;
917
+ try {
918
+ streamView = await request;
919
+ }
920
+ finally {
921
+ this.getStreamRequests.delete(streamId);
922
+ }
923
+ return streamView;
924
+ }
925
+ async _getStream(streamId, streamsView) {
926
+ try {
927
+ this.logCall('getStream', streamId);
928
+ const response = await this.rpcClient.getStream({
929
+ streamId: streamIdAsBytes(streamId),
930
+ });
931
+ const unpackedResponse = await unpackStream(response.stream, this.opts?.unpackEnvelopeOpts);
932
+ return this.streamViewFromUnpackedResponse(streamId, unpackedResponse, streamsView);
933
+ }
934
+ catch (err) {
935
+ this.logCall('getStream', streamId, 'ERROR', err);
936
+ throw err;
937
+ }
938
+ }
939
+ streamViewFromUnpackedResponse(streamId, unpackedResponse, streamsView) {
940
+ const streamView = new StreamStateView(this.userId, streamIdAsString(streamId), streamsView);
941
+ streamView.initialize(unpackedResponse.streamAndCookie.nextSyncCookie, unpackedResponse.streamAndCookie.events, unpackedResponse.snapshot, unpackedResponse.streamAndCookie.miniblocks, [], unpackedResponse.prevSnapshotMiniblockNum, undefined, [], undefined);
942
+ return streamView;
943
+ }
944
+ async getStreamEx(streamId) {
945
+ const existingRequest = this.getStreamExRequests.get(streamId);
946
+ if (existingRequest) {
947
+ this.logCall(`had existing get request for ${streamId}, returning promise`);
948
+ return await existingRequest;
949
+ }
950
+ const request = this._getStreamEx(streamId);
951
+ this.getStreamExRequests.set(streamId, request);
952
+ let streamView;
953
+ try {
954
+ streamView = await request;
955
+ }
956
+ finally {
957
+ this.getStreamExRequests.delete(streamId);
958
+ }
959
+ return streamView;
960
+ }
961
+ async _getStreamEx(streamId, streamsView) {
962
+ try {
963
+ this.logCall('getStreamEx', streamId);
964
+ const response = this.rpcClient.getStreamEx({
965
+ streamId: streamIdAsBytes(streamId),
966
+ });
967
+ const data = await waitForStreamEx(streamId, response);
968
+ const unpackedResponse = await unpackStreamEx(data.miniblocks, data.snapshot, this.opts?.unpackEnvelopeOpts);
969
+ return this.streamViewFromUnpackedResponse(streamId, unpackedResponse, streamsView);
970
+ }
971
+ catch (err) {
972
+ this.logCall('getStreamEx', streamId, 'ERROR', err);
973
+ throw err;
974
+ }
975
+ }
976
+ async initStream(streamId, allowGetStream = true, persistedData) {
977
+ const streamIdStr = streamIdAsString(streamId);
978
+ const existingRequest = this.initStreamRequests.get(streamIdStr);
979
+ if (existingRequest) {
980
+ this.logCall('initStream: had existing request for', streamIdStr, 'returning promise');
981
+ return existingRequest;
982
+ }
983
+ const request = this._initStream(streamIdStr, allowGetStream, persistedData);
984
+ this.initStreamRequests.set(streamIdStr, request);
985
+ let stream;
986
+ try {
987
+ stream = await request;
988
+ }
989
+ finally {
990
+ this.initStreamRequests.delete(streamIdStr);
991
+ }
992
+ return stream;
993
+ }
994
+ async _initStream(streamId, allowGetStream = true, persistedData) {
995
+ try {
996
+ this.logCall('initStream', streamId);
997
+ const stream = this.stream(streamId);
998
+ if (stream) {
999
+ if (stream.view.isInitialized) {
1000
+ this.logCall('initStream', streamId, 'already initialized');
1001
+ return stream;
1002
+ }
1003
+ else {
1004
+ return this.waitForStream(streamId);
1005
+ }
1006
+ }
1007
+ else {
1008
+ this.logCall('initStream creating stream', streamId);
1009
+ const stream = this.createSyncedStream(streamId);
1010
+ // Try initializing from persistence
1011
+ const success = await stream.initializeFromPersistence(persistedData);
1012
+ if (success) {
1013
+ if (stream.view.syncCookie) {
1014
+ this.streams.addStreamToSync(streamId, stream.view.syncCookie);
1015
+ }
1016
+ return stream;
1017
+ }
1018
+ // if we're only allowing initializing from persistence, we've failed.
1019
+ if (!allowGetStream) {
1020
+ this.logCall('initStream deleting stream', streamId);
1021
+ // We need to remove the stream from syncedStreams, since we added it above
1022
+ this.streams.delete(streamId);
1023
+ throw new Error(`Failed to initialize stream from persistence ${streamIdAsString(streamId)}`);
1024
+ }
1025
+ try {
1026
+ const response = await this.rpcClient.getStream({
1027
+ streamId: streamIdAsBytes(streamId),
1028
+ });
1029
+ const unpacked = await unpackStream(response.stream, this.opts?.unpackEnvelopeOpts);
1030
+ this.logCall('initStream calling initializingFromResponse', streamId);
1031
+ await stream.initializeFromResponse(unpacked);
1032
+ if (stream.view.syncCookie) {
1033
+ this.streams.addStreamToSync(streamId, stream.view.syncCookie);
1034
+ }
1035
+ }
1036
+ catch (err) {
1037
+ this.logError('Failed to initialize stream', streamId, err);
1038
+ this.streams.delete(streamId);
1039
+ throw err;
1040
+ }
1041
+ return stream;
1042
+ }
1043
+ }
1044
+ catch (err) {
1045
+ this.logCall('initStream', streamId, 'ERROR', err);
1046
+ throw err;
1047
+ }
1048
+ }
1049
+ onJoinedStream = async (streamId) => {
1050
+ this.logEvent('onJoinedStream', streamId);
1051
+ if (!this.creatingStreamIds.has(streamId)) {
1052
+ await this.initStream(streamId);
1053
+ }
1054
+ };
1055
+ onInvitedToStream = async (streamId) => {
1056
+ this.logEvent('onInvitedToStream', streamId);
1057
+ if (isDMChannelStreamId(streamId) || isGDMChannelStreamId(streamId)) {
1058
+ await this.initStream(streamId);
1059
+ }
1060
+ };
1061
+ onLeftStream = async (streamId) => {
1062
+ this.logEvent('onLeftStream', streamId);
1063
+ return await this.streams.removeStreamFromSync(streamId);
1064
+ };
1065
+ onStreamUpToDate = (streamId) => {
1066
+ // we're migrating away from the old megolm based encryption to the new `grpaes` encryption,
1067
+ // this is to avoid too many active crypto sessions active in the same stream
1068
+ // this function will:
1069
+ // - check if the user's username is encrypted with the old algorithm
1070
+ // - check if the user has a hybrid session ready to go (hasHybridSession)
1071
+ // - re-encrypt the username with the new algorithm
1072
+ const updateUsernameEncryptionIfNeeded = async () => {
1073
+ if (!isSpaceStreamId(streamId)) {
1074
+ return;
1075
+ }
1076
+ const hasHybridSession = (await this.cryptoBackend?.hasHybridSession(streamId)) ?? false;
1077
+ if (!hasHybridSession) {
1078
+ return;
1079
+ }
1080
+ const stream = this.stream(streamId);
1081
+ if (!stream) {
1082
+ return;
1083
+ }
1084
+ const currentUsernameEncryptedData = stream.view.membershipContent.memberMetadata.usernames.currentUsernameEncryptedData;
1085
+ if (!currentUsernameEncryptedData ||
1086
+ currentUsernameEncryptedData.algorithm ===
1087
+ GroupEncryptionAlgorithmId.HybridGroupEncryption) {
1088
+ return;
1089
+ }
1090
+ const currentUsername = stream.view.membershipContent.memberMetadata.usernames.info(this.userId);
1091
+ if (!currentUsername || currentUsername.username.length === 0) {
1092
+ return;
1093
+ }
1094
+ await this.setUsername(streamId, currentUsername.username);
1095
+ };
1096
+ void updateUsernameEncryptionIfNeeded();
1097
+ };
1098
+ startSync() {
1099
+ this.syncedStreamsExtensions.setStartSyncRequested(true);
1100
+ }
1101
+ async stopSync() {
1102
+ this.syncedStreamsExtensions.setStartSyncRequested(false);
1103
+ await this.streams.stopSync();
1104
+ }
1105
+ emit(event, ...args) {
1106
+ this.logEmitFromClient(event, ...args);
1107
+ return super.emit(event, ...args);
1108
+ }
1109
+ async sendMessage(streamId, body, mentions, attachments = []) {
1110
+ return this.sendChannelMessage_Text(streamId, {
1111
+ content: {
1112
+ body,
1113
+ mentions: mentions ?? [],
1114
+ attachments: attachments,
1115
+ },
1116
+ });
1117
+ }
1118
+ async sendChannelMessage(streamId, inPayload, opts) {
1119
+ const stream = this.stream(streamId);
1120
+ check(stream !== undefined, 'stream not found');
1121
+ const payload = create(ChannelMessageSchema, inPayload);
1122
+ const localId = stream.appendLocalEvent(payload, 'sending');
1123
+ opts?.onLocalEventAppended?.(localId);
1124
+ if (opts?.beforeSendEventHook) {
1125
+ await opts?.beforeSendEventHook;
1126
+ }
1127
+ return this.makeAndSendChannelMessageEvent(streamId, payload, localId, {
1128
+ disableTags: opts?.disableTags,
1129
+ appClientAddress: opts?.appClientAddress,
1130
+ });
1131
+ }
1132
+ async makeAndSendChannelMessageEvent(streamId, payload, localId, opts) {
1133
+ const stream = this.stream(streamId);
1134
+ check(isDefined(stream), 'stream not found');
1135
+ const tags = opts?.disableTags === true
1136
+ ? undefined
1137
+ : makeTags(payload, stream.view, opts?.appClientAddress ? MessageInteractionType.SLASH_COMMAND : undefined);
1138
+ if (opts?.appClientAddress && tags) {
1139
+ tags.appClientAddress = bin_fromHexString(opts.appClientAddress);
1140
+ }
1141
+ const cleartext = toBinary(ChannelMessageSchema, payload);
1142
+ let message;
1143
+ const encryptionAlgorithm = stream.view.membershipContent.encryptionAlgorithm;
1144
+ const buffer = toBinary(ChannelMessageSchema, payload);
1145
+ switch (encryptionAlgorithm) {
1146
+ case GroupEncryptionAlgorithmId.HybridGroupEncryption:
1147
+ message = await this.encryptGroupEvent(buffer, streamId, GroupEncryptionAlgorithmId.HybridGroupEncryption);
1148
+ break;
1149
+ case GroupEncryptionAlgorithmId.GroupEncryption:
1150
+ message = await this.encryptGroupEvent(buffer, streamId, GroupEncryptionAlgorithmId.GroupEncryption);
1151
+ break;
1152
+ default: {
1153
+ message = await this.encryptGroupEvent(buffer, streamId, this.defaultGroupEncryptionAlgorithm);
1154
+ }
1155
+ }
1156
+ if (!message) {
1157
+ throw new Error('failed to encrypt message');
1158
+ }
1159
+ message.refEventId = getRefEventIdFromChannelMessage(payload);
1160
+ if (isChannelStreamId(streamId)) {
1161
+ return this.makeEventAndAddToStream(streamId, make_ChannelPayload_Message(message), {
1162
+ method: 'sendMessage',
1163
+ localId,
1164
+ cleartext,
1165
+ tags,
1166
+ });
1167
+ }
1168
+ else if (isDMChannelStreamId(streamId)) {
1169
+ return this.makeEventAndAddToStream(streamId, make_DMChannelPayload_Message(message), {
1170
+ method: 'sendMessageDM',
1171
+ localId,
1172
+ cleartext,
1173
+ tags,
1174
+ });
1175
+ }
1176
+ else if (isGDMChannelStreamId(streamId)) {
1177
+ return this.makeEventAndAddToStream(streamId, make_GDMChannelPayload_Message(message), {
1178
+ method: 'sendMessageGDM',
1179
+ localId,
1180
+ cleartext,
1181
+ tags,
1182
+ });
1183
+ }
1184
+ else {
1185
+ throw new Error(`invalid streamId: ${streamId}`);
1186
+ }
1187
+ }
1188
+ async sendChannelMessage_Text(streamId, payload, opts) {
1189
+ const { content, ...options } = payload;
1190
+ return this.sendChannelMessage(streamId, {
1191
+ payload: {
1192
+ case: 'post',
1193
+ value: {
1194
+ ...options,
1195
+ content: {
1196
+ case: 'text',
1197
+ value: content,
1198
+ },
1199
+ },
1200
+ },
1201
+ }, opts);
1202
+ }
1203
+ async sendChannelMessage_Image(streamId, payload, opts) {
1204
+ const { content, ...options } = payload;
1205
+ return this.sendChannelMessage(streamId, {
1206
+ payload: {
1207
+ case: 'post',
1208
+ value: {
1209
+ ...options,
1210
+ content: {
1211
+ case: 'image',
1212
+ value: content,
1213
+ },
1214
+ },
1215
+ },
1216
+ }, opts);
1217
+ }
1218
+ async sendChannelMessage_GM(streamId, payload, opts) {
1219
+ const { content, ...options } = payload;
1220
+ return this.sendChannelMessage(streamId, {
1221
+ payload: {
1222
+ case: 'post',
1223
+ value: {
1224
+ ...options,
1225
+ content: {
1226
+ case: 'gm',
1227
+ value: content,
1228
+ },
1229
+ },
1230
+ },
1231
+ }, opts);
1232
+ }
1233
+ async sendMediaPayload(creationCookie, last, data, chunkIndex, iv) {
1234
+ const payload = make_MediaPayload_Chunk({
1235
+ data: data,
1236
+ chunkIndex: chunkIndex,
1237
+ iv: iv,
1238
+ });
1239
+ return this.makeMediaEventWithHashAndAddToMediaStream(creationCookie, last, payload);
1240
+ }
1241
+ async getMediaPayload(streamId, secretKey, iv) {
1242
+ const { miniblocks } = await this.getMiniblocks(streamId, 0n, 1000n);
1243
+ let chunkCount;
1244
+ let chunks;
1245
+ for (const miniblock of miniblocks) {
1246
+ for (const parsedEvent of miniblock.events) {
1247
+ const payload = parsedEvent.event.payload;
1248
+ if (payload.case !== 'mediaPayload') {
1249
+ continue;
1250
+ }
1251
+ const mediaPayload = payload.value;
1252
+ if (!mediaPayload) {
1253
+ continue;
1254
+ }
1255
+ switch (mediaPayload.content.case) {
1256
+ case 'inception': {
1257
+ const inception = mediaPayload.content.value;
1258
+ if (!inception?.chunkCount) {
1259
+ break;
1260
+ }
1261
+ chunkCount = inception.chunkCount;
1262
+ chunks = new Array(chunkCount);
1263
+ break;
1264
+ }
1265
+ case 'chunk': {
1266
+ if (!chunks || chunkCount === undefined) {
1267
+ break;
1268
+ }
1269
+ const chunk = mediaPayload.content.value;
1270
+ if (chunk.chunkIndex < 0 || chunk.chunkIndex >= chunkCount) {
1271
+ break;
1272
+ }
1273
+ chunks[chunk.chunkIndex] = chunk.data;
1274
+ break;
1275
+ }
1276
+ case undefined:
1277
+ break;
1278
+ default:
1279
+ logNever(mediaPayload.content);
1280
+ }
1281
+ }
1282
+ }
1283
+ if (!chunks || chunkCount === undefined) {
1284
+ return undefined;
1285
+ }
1286
+ const data = new Uint8Array(chunks.reduce((totalLength, chunk) => totalLength + chunk.length, 0));
1287
+ let offset = 0;
1288
+ chunks.forEach((chunk) => {
1289
+ data.set(chunk, offset);
1290
+ offset += chunk.length;
1291
+ });
1292
+ return decryptAESGCM(data, secretKey, iv);
1293
+ }
1294
+ async sendChannelMessage_Reaction(streamId, payload, opts) {
1295
+ return this.sendChannelMessage(streamId, {
1296
+ payload: {
1297
+ case: 'reaction',
1298
+ value: payload,
1299
+ },
1300
+ }, opts);
1301
+ }
1302
+ async sendChannelMessage_Redaction(streamId, payload) {
1303
+ const stream = this.stream(streamId);
1304
+ if (!stream) {
1305
+ throw new Error(`stream not found: ${streamId}`);
1306
+ }
1307
+ return this.sendChannelMessage(streamId, {
1308
+ payload: {
1309
+ case: 'redaction',
1310
+ value: payload,
1311
+ },
1312
+ });
1313
+ }
1314
+ async sendChannelMessage_Edit(streamId, refEventId, newPost) {
1315
+ return this.sendChannelMessage(streamId, {
1316
+ payload: {
1317
+ case: 'edit',
1318
+ value: {
1319
+ refEventId: refEventId,
1320
+ post: newPost,
1321
+ },
1322
+ },
1323
+ });
1324
+ }
1325
+ async sendChannelMessage_Edit_Text(streamId, refEventId, payload) {
1326
+ const { content, ...options } = payload;
1327
+ return this.sendChannelMessage_Edit(streamId, refEventId, {
1328
+ ...options,
1329
+ content: {
1330
+ case: 'text',
1331
+ value: content,
1332
+ },
1333
+ });
1334
+ }
1335
+ async sendInteractionRequest(streamId, content, recipient, opts) {
1336
+ const stream = this.stream(streamId);
1337
+ check(isDefined(stream), 'stream not found');
1338
+ check(isDefined(this.cryptoBackend), 'crypto backend not initialized');
1339
+ // Create payload with content and encryption device for responses
1340
+ const payload = create(InteractionRequestPayloadSchema, {
1341
+ encryptionDevice: this.userDeviceKey(),
1342
+ content: content,
1343
+ });
1344
+ // Encrypt using group encryption (same as messages)
1345
+ const encryptionAlgorithm = stream.view.membershipContent.encryptionAlgorithm ??
1346
+ this.defaultGroupEncryptionAlgorithm;
1347
+ const encryptedData = await this.cryptoBackend.encryptGroupEvent(streamId, toBinary(InteractionRequestPayloadSchema, payload), encryptionAlgorithm);
1348
+ // Create the request matching InteractionResquest structure
1349
+ const request = {
1350
+ recipient: typeof recipient === 'string'
1351
+ ? bin_fromHexString(recipient)
1352
+ : (recipient ?? undefined),
1353
+ encryptedData: encryptedData,
1354
+ threadId: opts?.tags?.threadId,
1355
+ };
1356
+ return this.makeEventAndAddToStream(streamId, make_payload_InteractionRequest(streamId, request), {
1357
+ method: 'sendInteractionRequest',
1358
+ tags: opts?.tags,
1359
+ ephemeral: opts?.ephemeral,
1360
+ });
1361
+ }
1362
+ async sendInteractionResponse(streamId, recipient, payload, toUserDevice, opts) {
1363
+ const binaryData = toBinary(InteractionResponsePayloadSchema, create(InteractionResponsePayloadSchema, payload));
1364
+ const string = bin_toBase64(binaryData);
1365
+ const ciphertextmap = await this.encryptWithDeviceKeys(string, [toUserDevice]);
1366
+ const ciphertext = ciphertextmap[toUserDevice.deviceKey];
1367
+ check(isDefined(ciphertext), 'ciphertext not found');
1368
+ const response = {
1369
+ recipient: recipient,
1370
+ threadId: opts?.threadId ? bin_fromHexString(opts?.threadId) : undefined,
1371
+ encryptedData: {
1372
+ ciphertext: ciphertext,
1373
+ algorithm: EncryptionAlgorithmId.Olm,
1374
+ senderKey: this.userDeviceKey().deviceKey,
1375
+ sessionId: '',
1376
+ checksum: '',
1377
+ ciphertextBytes: new Uint8Array(),
1378
+ ivBytes: new Uint8Array(),
1379
+ sessionIdBytes: new Uint8Array(),
1380
+ version: EncryptedDataVersion.ENCRYPTED_DATA_VERSION_0,
1381
+ deviceKey: toUserDevice.deviceKey,
1382
+ },
1383
+ };
1384
+ const tags = {
1385
+ groupMentionTypes: [],
1386
+ mentionedUserAddresses: [],
1387
+ ...(opts?.tags ?? {}),
1388
+ messageInteractionType: opts?.tags?.messageInteractionType ?? MessageInteractionType.REPLY,
1389
+ participatingUserAddresses: [
1390
+ ...(opts?.tags?.participatingUserAddresses ?? []),
1391
+ recipient,
1392
+ ],
1393
+ };
1394
+ return this.makeEventAndAddToStream(streamId, make_payload_InteractionResponse(streamId, response), {
1395
+ method: 'sendInteractionResponse',
1396
+ tags,
1397
+ ephemeral: opts?.ephemeral,
1398
+ });
1399
+ }
1400
+ async redactMessage(streamId, eventId) {
1401
+ const stream = this.stream(streamId);
1402
+ check(isDefined(stream), 'stream not found');
1403
+ return this.makeEventAndAddToStream(streamId, make_payload_Redaction(streamId, bin_fromHexString(eventId)), {
1404
+ method: 'redactMessage',
1405
+ tags: {
1406
+ groupMentionTypes: [],
1407
+ messageInteractionType: MessageInteractionType.REDACTION,
1408
+ mentionedUserAddresses: [],
1409
+ participatingUserAddresses: [],
1410
+ },
1411
+ });
1412
+ }
1413
+ async retrySendMessage(streamId, localId) {
1414
+ const stream = this.stream(streamId);
1415
+ check(isDefined(stream), 'stream not found' + streamId);
1416
+ const event = stream.view.minipoolEvents.get(localId) ??
1417
+ Array.from(stream.view.minipoolEvents.values()).find((e) => e.localEvent?.localId === localId);
1418
+ check(isDefined(event), 'retry event not found');
1419
+ check(isDefined(event.localEvent), 'retry local event not found');
1420
+ check(event.localEvent.status === 'failed', 'event not in failed state');
1421
+ await this.makeAndSendChannelMessageEvent(streamId, event.localEvent.channelMessage, event.hashStr);
1422
+ }
1423
+ async inviteUser(streamId, userId) {
1424
+ await this.initStream(streamId);
1425
+ check(isDefined(this.userStreamId));
1426
+ return this.makeEventAndAddToStream(this.userStreamId, make_UserPayload_UserMembershipAction({
1427
+ op: MembershipOp.SO_INVITE,
1428
+ userId: addressFromUserId(userId),
1429
+ streamId: streamIdAsBytes(streamId),
1430
+ }), { method: 'inviteUser' });
1431
+ }
1432
+ async joinUser(streamId, userId) {
1433
+ check(isDefined(this.userStreamId));
1434
+ const { eventId } = await this.makeEventAndAddToStream(this.userStreamId, make_UserPayload_UserMembershipAction({
1435
+ op: MembershipOp.SO_JOIN,
1436
+ userId: bin_fromHexString(userId),
1437
+ streamId: streamIdAsBytes(streamId),
1438
+ }), { method: 'joinUser' });
1439
+ // share the latest group session to the user
1440
+ try {
1441
+ await this.encryptAndShareLatestGroupSessionToUser(streamId, userId);
1442
+ }
1443
+ catch (error) {
1444
+ this.logError('Failed to share group session to user', {
1445
+ streamId,
1446
+ userId,
1447
+ error,
1448
+ });
1449
+ }
1450
+ return { eventId };
1451
+ }
1452
+ async joinStream(streamId, opts) {
1453
+ this.logCall('joinStream', streamId);
1454
+ check(isDefined(this.userStreamId), 'userStreamId not defined');
1455
+ const userStream = this.stream(this.userStreamId);
1456
+ check(isDefined(userStream), 'userStream not defined');
1457
+ const streamIdStr = streamIdAsString(streamId);
1458
+ const stream = await this.initStream(streamId);
1459
+ // check your user stream for membership as that's the final source of truth
1460
+ if (userStream.view.userContent.isJoined(streamIdStr)) {
1461
+ this.logError('joinStream: user already a member', streamId);
1462
+ return stream;
1463
+ }
1464
+ // add event to user stream, this triggers events in the target stream
1465
+ await this.makeEventAndAddToStream(this.userStreamId, make_UserPayload_UserMembership({
1466
+ op: MembershipOp.SO_JOIN,
1467
+ streamId: streamIdAsBytes(streamId),
1468
+ invitePayload: opts?.invitePayload,
1469
+ }), { method: 'joinStream' });
1470
+ if (opts?.skipWaitForMiniblockConfirmation !== true) {
1471
+ await stream.waitForMembership(MembershipOp.SO_JOIN);
1472
+ }
1473
+ if (opts?.skipWaitForUserStreamUpdate !== true) {
1474
+ if (!userStream.view.userContent.isJoined(streamIdStr)) {
1475
+ await userStream.waitFor('userStreamMembershipChanged', () => userStream.view.userContent.isJoined(streamIdStr));
1476
+ }
1477
+ }
1478
+ return stream;
1479
+ }
1480
+ async leaveStream(streamId) {
1481
+ this.logCall('leaveStream', streamId);
1482
+ check(isDefined(this.userStreamId));
1483
+ if (isSpaceStreamId(streamId)) {
1484
+ const channelIds = Object.keys(this.stream(streamId)?.view.spaceContent.spaceChannelsMetadata ?? {});
1485
+ const userStream = this.stream(this.userStreamId);
1486
+ for (const channelId of channelIds) {
1487
+ if (userStream?.view.userContent.streamMemberships[channelId]?.op ===
1488
+ MembershipOp.SO_JOIN) {
1489
+ await this.leaveStream(channelId);
1490
+ }
1491
+ }
1492
+ }
1493
+ return this.makeEventAndAddToStream(this.userStreamId, make_UserPayload_UserMembership({
1494
+ op: MembershipOp.SO_LEAVE,
1495
+ streamId: streamIdAsBytes(streamId),
1496
+ }), { method: 'leaveStream' });
1497
+ }
1498
+ async removeUser(streamId, userId) {
1499
+ check(isDefined(this.userStreamId));
1500
+ this.logCall('removeUser', streamId, userId);
1501
+ if (isSpaceStreamId(streamId)) {
1502
+ const channelIds = Object.keys(this.stream(streamId)?.view.spaceContent.spaceChannelsMetadata ?? {});
1503
+ const userStreamId = makeUserStreamId(userId);
1504
+ const userStream = await this.getStream(userStreamId);
1505
+ for (const channelId of channelIds) {
1506
+ if (userStream.userContent.streamMemberships[channelId]?.op === MembershipOp.SO_JOIN) {
1507
+ try {
1508
+ await this.removeUser(channelId, userId);
1509
+ }
1510
+ catch (error) {
1511
+ this.logError('Failed to remove user from channel', {
1512
+ channelId,
1513
+ userId,
1514
+ error,
1515
+ });
1516
+ }
1517
+ }
1518
+ }
1519
+ }
1520
+ return this.makeEventAndAddToStream(this.userStreamId, make_UserPayload_UserMembershipAction({
1521
+ op: MembershipOp.SO_LEAVE,
1522
+ userId: addressFromUserId(userId),
1523
+ streamId: streamIdAsBytes(streamId),
1524
+ }), { method: 'removeUser' });
1525
+ }
1526
+ // upload transactions made on the base chain
1527
+ async addTransaction(chainId, receipt, content, tags) {
1528
+ check(isDefined(this.userStreamId));
1529
+ const transaction = {
1530
+ receipt: !isSolanaTransactionReceipt(receipt)
1531
+ ? create(BlockchainTransactionReceiptSchema, {
1532
+ chainId: BigInt(chainId),
1533
+ transactionHash: bin_fromHexString(receipt.transactionHash),
1534
+ blockNumber: BigInt(receipt.blockNumber),
1535
+ to: bin_fromHexString(receipt.to),
1536
+ from: bin_fromHexString(receipt.from),
1537
+ logs: receipt.logs.map((log) => create(BlockchainTransactionReceipt_LogSchema, {
1538
+ address: bin_fromHexString(log.address),
1539
+ topics: log.topics.map(bin_fromHexString),
1540
+ data: bin_fromHexString(log.data),
1541
+ })),
1542
+ })
1543
+ : undefined,
1544
+ solanaReceipt: isSolanaTransactionReceipt(receipt)
1545
+ ? create(SolanaBlockchainTransactionReceiptSchema, {
1546
+ ...receipt,
1547
+ })
1548
+ : undefined,
1549
+ content: content ?? { case: undefined },
1550
+ };
1551
+ const event = make_UserPayload_BlockchainTransaction(transaction);
1552
+ return this.makeEventAndAddToStream(this.userStreamId, event, {
1553
+ method: 'addTransaction',
1554
+ tags,
1555
+ });
1556
+ }
1557
+ async addTransaction_Tip(chainId, receipt, event, toUserId, opts) {
1558
+ const stream = this.stream(ensureNoHexPrefix(event.channelId));
1559
+ const tags = opts?.disableTags || !stream?.view
1560
+ ? undefined
1561
+ : makeTipTags(event, toUserId, stream.view);
1562
+ return this.addTransaction(chainId, receipt, {
1563
+ case: 'tip',
1564
+ value: {
1565
+ event: {
1566
+ tokenId: event.tokenId?.toBigInt(),
1567
+ currency: bin_fromHexString(event.currency),
1568
+ sender: addressFromUserId(event.sender),
1569
+ receiver: addressFromUserId(event.receiver),
1570
+ amount: event.amount.toBigInt(),
1571
+ messageId: bin_fromHexString(event.messageId),
1572
+ channelId: streamIdAsBytes(event.channelId),
1573
+ },
1574
+ toUserAddress: addressFromUserId(toUserId),
1575
+ },
1576
+ }, tags);
1577
+ }
1578
+ async addTransaction_Transfer(chainId, receipt, event, opts) {
1579
+ const stream = this.stream(streamIdAsString(event.channelId));
1580
+ const tags = opts?.disableTags || !stream?.view ? undefined : makeTransferTags(event, stream.view);
1581
+ return this.addTransaction(chainId, receipt, {
1582
+ case: 'tokenTransfer',
1583
+ value: event,
1584
+ }, tags);
1585
+ }
1586
+ async addTransaction_SpaceReview(chainId, receipt, event, spaceId) {
1587
+ check(event.action !== SpaceReviewAction.None, 'invalid space review event');
1588
+ return this.addTransaction(chainId, receipt, {
1589
+ case: 'spaceReview',
1590
+ value: {
1591
+ action: event.action.valueOf(),
1592
+ spaceAddress: bin_fromHexString(SpaceAddressFromSpaceId(spaceId)),
1593
+ event: {
1594
+ rating: event.rating,
1595
+ user: addressFromUserId(event.user),
1596
+ },
1597
+ },
1598
+ });
1599
+ }
1600
+ async getMiniblocks(streamId, fromInclusive, toExclusive, exclusionFilter, opts, callOptions) {
1601
+ const cachedMiniblocks = [];
1602
+ if (!opts?.skipPersistence) {
1603
+ try {
1604
+ for (let i = toExclusive - 1n; i >= fromInclusive; i = i - 1n) {
1605
+ const miniblock = await this.persistenceStore.getMiniblock(streamIdAsString(streamId), i);
1606
+ if (miniblock) {
1607
+ cachedMiniblocks.push(miniblock);
1608
+ toExclusive = i;
1609
+ }
1610
+ else {
1611
+ break;
1612
+ }
1613
+ }
1614
+ cachedMiniblocks.reverse();
1615
+ }
1616
+ catch (error) {
1617
+ this.logError('error getting miniblocks', error);
1618
+ }
1619
+ }
1620
+ // Apply exclusion filtering to cached miniblocks if filters are provided
1621
+ const filteredCachedMiniblocks = exclusionFilter && exclusionFilter.length > 0
1622
+ ? applyExclusionFilterToMiniblocks(cachedMiniblocks, exclusionFilter)
1623
+ : cachedMiniblocks;
1624
+ if (toExclusive === fromInclusive) {
1625
+ return {
1626
+ miniblocks: filteredCachedMiniblocks,
1627
+ terminus: toExclusive === 0n,
1628
+ };
1629
+ }
1630
+ const { miniblocks, terminus } = await getMiniblocks(this.rpcClient, streamId, fromInclusive, toExclusive, true, exclusionFilter, this.opts?.unpackEnvelopeOpts, callOptions);
1631
+ if (opts?.skipPersistence !== true) {
1632
+ await this.persistenceStore.saveMiniblocks(streamIdAsString(streamId), miniblocks, 'backward');
1633
+ }
1634
+ return {
1635
+ terminus: terminus,
1636
+ miniblocks: [...miniblocks, ...filteredCachedMiniblocks],
1637
+ };
1638
+ }
1639
+ async scrollback(streamId) {
1640
+ const currentRequest = this.getScrollbackRequests.get(streamId);
1641
+ if (currentRequest) {
1642
+ return currentRequest;
1643
+ }
1644
+ const _scrollback = async () => {
1645
+ const stream = this.stream(streamId);
1646
+ check(isDefined(stream), `stream not found: ${streamId}`);
1647
+ check(isDefined(stream.view.miniblockInfo), `stream not initialized: ${streamId}`);
1648
+ if (stream.view.miniblockInfo.terminusReached) {
1649
+ this.logCall('scrollback', streamId, 'terminus reached');
1650
+ return {
1651
+ terminus: true,
1652
+ fromInclusiveMiniblockNum: stream.view.miniblockInfo.min,
1653
+ };
1654
+ }
1655
+ check(stream.view.miniblockInfo.min >= stream.view.prevSnapshotMiniblockNum);
1656
+ this.logCall('scrollback', {
1657
+ streamId,
1658
+ miniblockInfo: stream.view.miniblockInfo,
1659
+ prevSnapshotMiniblockNum: stream.view.prevSnapshotMiniblockNum,
1660
+ });
1661
+ const toExclusive = stream.view.miniblockInfo.min;
1662
+ const fromInclusive = stream.view.prevSnapshotMiniblockNum;
1663
+ const response = await this.getMiniblocks(streamId, fromInclusive, toExclusive, this.excludeEventsInScrollback);
1664
+ const eventIds = response.miniblocks.flatMap((m) => m.events.map((e) => e.hashStr));
1665
+ const cleartexts = await this.persistenceStore.getCleartexts(eventIds);
1666
+ // a race may occur here: if the state view has been reinitialized during the scrollback
1667
+ // request, we need to discard the new miniblocks.
1668
+ if ((stream.view.miniblockInfo?.min ?? -1n) === toExclusive) {
1669
+ stream.prependEvents(response.miniblocks, cleartexts, response.terminus);
1670
+ return {
1671
+ terminus: response.terminus,
1672
+ fromInclusiveMiniblockNum: fromInclusive,
1673
+ };
1674
+ }
1675
+ return {
1676
+ terminus: false,
1677
+ fromInclusiveMiniblockNum: fromInclusive,
1678
+ };
1679
+ };
1680
+ try {
1681
+ const request = _scrollback();
1682
+ this.getScrollbackRequests.set(streamId, request);
1683
+ return await request;
1684
+ }
1685
+ finally {
1686
+ this.getScrollbackRequests.delete(streamId);
1687
+ }
1688
+ }
1689
+ /**
1690
+ * Get the list of active devices for all users in the room
1691
+ *
1692
+ *
1693
+ * @returns Promise which resolves to `null`, or an array whose
1694
+ * first element is a {@link DeviceInfoMap} indicating
1695
+ * the devices that messages should be encrypted to, and whose second
1696
+ * element is a map from userId to deviceId to data indicating the devices
1697
+ * that are in the room but that have been blocked.
1698
+ */
1699
+ async getDevicesInStream(stream_id) {
1700
+ const members = await this.getUsersEntitledToKeyExchange(stream_id);
1701
+ this.logInfo(`getDevicesInStream: downloading device info for: `, members.length);
1702
+ const info = await this.downloadUserDeviceInfo(members);
1703
+ this.logCall('getDevicesInStream: done, keys.length ', Object.keys(info).length);
1704
+ return info;
1705
+ }
1706
+ async getUsersEntitledToKeyExchange(streamId) {
1707
+ let stream;
1708
+ stream = this.stream(streamId)?.view;
1709
+ if (!stream || !stream.isInitialized) {
1710
+ stream = await this.getStream(streamId);
1711
+ }
1712
+ if (!stream) {
1713
+ this.logError(`stream for room ${streamId} not found`);
1714
+ return [];
1715
+ }
1716
+ const members = Array.from(stream.getUsersEntitledToKeyExchange());
1717
+ return members;
1718
+ }
1719
+ async getMiniblockInfo(streamId) {
1720
+ const streamView = this.stream(streamId)?.view;
1721
+ // if we don't have a local copy, or if it's just not initialized, fetch the latest
1722
+ if (streamView && streamView.isInitialized) {
1723
+ check(isDefined(streamView.miniblockInfo), `stream not initialized: ${streamId}`);
1724
+ check(isDefined(streamView.prevMiniblockHash), `prevMiniblockHash not found: ${streamId}`);
1725
+ return {
1726
+ miniblockNum: streamView.miniblockInfo.max,
1727
+ miniblockHash: streamView.prevMiniblockHash,
1728
+ };
1729
+ }
1730
+ const r = await this.getStreamLastMiniblockHash(streamId);
1731
+ return {
1732
+ miniblockNum: r.miniblockNum,
1733
+ miniblockHash: r.hash,
1734
+ };
1735
+ }
1736
+ async downloadNewInboxMessages() {
1737
+ this.logCall('downloadNewInboxMessages');
1738
+ check(isDefined(this.userInboxStreamId));
1739
+ const stream = this.stream(this.userInboxStreamId);
1740
+ check(isDefined(stream));
1741
+ check(isDefined(stream.view.miniblockInfo));
1742
+ if (stream.view.miniblockInfo.terminusReached) {
1743
+ return;
1744
+ }
1745
+ const deviceSummary = stream.view.userInboxContent.deviceSummary[this.userDeviceKey().deviceKey];
1746
+ if (!deviceSummary) {
1747
+ return;
1748
+ }
1749
+ if (deviceSummary.lowerBound < stream.view.miniblockInfo.min) {
1750
+ const toExclusive = stream.view.miniblockInfo.min;
1751
+ const fromInclusive = deviceSummary.lowerBound;
1752
+ const response = await this.getMiniblocks(this.userInboxStreamId, fromInclusive, toExclusive, undefined, { skipPersistence: true });
1753
+ const eventIds = response.miniblocks.flatMap((m) => m.events.map((e) => e.hashStr));
1754
+ const cleartexts = await this.persistenceStore.getCleartexts(eventIds);
1755
+ stream.prependEvents(response.miniblocks, cleartexts, response.terminus);
1756
+ }
1757
+ }
1758
+ async downloadSingleUserDeviceInfo(userId, forceDownload) {
1759
+ const streamId = makeUserMetadataStreamId(userId);
1760
+ try {
1761
+ // except for small spaces and your own userId, check for the devices in the crypto store cause you might already have them
1762
+ if (!forceDownload && userId !== this.userId) {
1763
+ const devicesFromStore = await this.cryptoStore.getUserDevices(userId);
1764
+ if (devicesFromStore.length > 0) {
1765
+ return { userId, devices: devicesFromStore };
1766
+ }
1767
+ }
1768
+ // return latest 10 device keys
1769
+ const deviceLookback = 10;
1770
+ const stream = await this.getStream(streamId);
1771
+ const userDevices = stream.userMetadataContent.deviceKeys.slice(-deviceLookback);
1772
+ await this.cryptoStore.saveUserDevices(userId, userDevices);
1773
+ return { userId, devices: userDevices };
1774
+ }
1775
+ catch (e) {
1776
+ this.logError('Error downloading user device keys', e);
1777
+ return { userId, devices: [] };
1778
+ }
1779
+ }
1780
+ async downloadUserDeviceInfo(userIds) {
1781
+ // always fetch keys for arbitrarily small channels/dms/gdms. For large channels only
1782
+ // fetch keys if you don't already have keys, extended keysharing should work for those cases
1783
+ const forceDownload = userIds.length <= 10;
1784
+ const promises = userIds.map(async (userId) => {
1785
+ return this.downloadSingleUserDeviceInfo(userId, forceDownload);
1786
+ });
1787
+ return (await Promise.all(promises)).reduce((acc, current) => {
1788
+ acc[current.userId] = current.devices;
1789
+ return acc;
1790
+ }, {});
1791
+ }
1792
+ async knownDevicesForUserId(userId) {
1793
+ return await this.cryptoStore.getUserDevices(userId);
1794
+ }
1795
+ async makeEventAndAddToStream(streamId, payload, options = {}) {
1796
+ // TODO: filter this.logged payload for PII reasons
1797
+ this.logCall('await makeEventAndAddToStream', options.method, streamId, payload, options.localId);
1798
+ assert(this.userStreamId !== undefined, 'userStreamId must be set');
1799
+ const stream = this.streams.get(streamId);
1800
+ assert(stream !== undefined, 'unknown stream ' + streamIdAsString(streamId));
1801
+ const prevHash = stream.view.prevMiniblockHash;
1802
+ assert(isDefined(prevHash), 'no prev miniblock hash for stream ' + streamIdAsString(streamId));
1803
+ const prevMiniblockNum = stream.view.prevMiniblockNum;
1804
+ assert(isDefined(prevMiniblockNum), 'no prev miniblock num for stream ' + streamIdAsString(streamId));
1805
+ const { eventId, newEvents } = await this.makeEventWithHashAndAddToStream(streamId, payload, prevHash, prevMiniblockNum, options.localId, options.cleartext, options.tags, undefined, // retryCount
1806
+ options.ephemeral);
1807
+ return { eventId, newEvents };
1808
+ }
1809
+ async makeEventWithHashAndAddToStream(streamId, payload, prevMiniblockHash, prevMiniblockNum, localId, cleartext, tags, retryCount, ephemeral) {
1810
+ const streamIdStr = streamIdAsString(streamId);
1811
+ check(isDefined(streamIdStr) && streamIdStr !== '', 'streamId must be defined');
1812
+ const event = await makeEvent(this.signerContext, payload, prevMiniblockHash, prevMiniblockNum, tags, ephemeral);
1813
+ const eventId = bin_toHexString(event.hash);
1814
+ if (localId) {
1815
+ // when we have a localId, we need to update the local event with the eventId
1816
+ const stream = this.streams.get(streamId);
1817
+ assert(stream !== undefined, 'unknown stream ' + streamIdStr);
1818
+ stream.updateLocalEvent(localId, eventId, 'sending');
1819
+ }
1820
+ if (cleartext) {
1821
+ // if we have cleartext, save it so we don't have to re-decrypt it later
1822
+ await this.persistenceStore.saveCleartext(eventId, cleartext);
1823
+ }
1824
+ try {
1825
+ const result = await this.rpcClient.addEvent({
1826
+ streamId: streamIdAsBytes(streamId),
1827
+ event,
1828
+ });
1829
+ if (localId) {
1830
+ const stream = this.streams.get(streamId);
1831
+ stream?.updateLocalEvent(localId, eventId, 'sent');
1832
+ }
1833
+ return { prevMiniblockHash, eventId, newEvents: result.newEvents };
1834
+ }
1835
+ catch (err) {
1836
+ // custom retry logic for addEvent
1837
+ // if we send up a stale prevMiniblockHash, the server will return a BAD_PREV_MINIBLOCK_HASH
1838
+ // error and include the expected hash in the error message
1839
+ // if we had a localEventId, pass the last id so the ui can continue to update to the latest hash
1840
+ retryCount = retryCount ?? 0;
1841
+ const makeRetry = async (prevMiniblockHash, prevMiniblockNum) => {
1842
+ return this.makeEventWithHashAndAddToStream(streamId, payload, prevMiniblockHash, prevMiniblockNum, isDefined(localId) ? eventId : undefined, cleartext, tags, (retryCount ?? 0) + 1, ephemeral);
1843
+ };
1844
+ if (errorContains(err, Err.MINIBLOCK_TOO_NEW)) {
1845
+ this.logInfo('RETRYING event after MINIBLOCK_TOO_NEW response', {
1846
+ syncStats: this.streams.stats(),
1847
+ retryCount,
1848
+ prevMiniblockHash,
1849
+ prevMiniblockNum,
1850
+ });
1851
+ await new Promise((resolve) => setTimeout(resolve, 1000));
1852
+ return await makeRetry(prevMiniblockHash, prevMiniblockNum);
1853
+ }
1854
+ else if (errorContains(err, Err.BAD_PREV_MINIBLOCK_HASH) && retryCount < 3) {
1855
+ const expectedHash = getRpcErrorProperty(err, 'expected');
1856
+ this.logInfo('RETRYING event after BAD_PREV_MINIBLOCK_HASH response', {
1857
+ syncStats: this.streams.stats(),
1858
+ retryCount,
1859
+ prevMiniblockHash,
1860
+ expectedHash,
1861
+ });
1862
+ check(isDefined(expectedHash), 'expected hash not found in error');
1863
+ const expectedMiniblockNum = getRpcErrorProperty(err, 'expNum');
1864
+ check(isDefined(expectedMiniblockNum), 'expected miniblock num not found in error');
1865
+ return await makeRetry(bin_fromHexString(expectedHash), BigInt(expectedMiniblockNum));
1866
+ }
1867
+ else if (
1868
+ // for blockchain transactions: if we get a permission denied error, and the error message contains 'Transaction has 0 confirmations',
1869
+ // we need to retry the event, since the node is likely lagging behind, and waiting a few seconds will allow it to catch up
1870
+ errorContains(err, Err.PERMISSION_DENIED) &&
1871
+ (errorContainsMessage(err, 'Transaction has 0 confirmations.') ||
1872
+ errorContainsMessage(err, 'Transaction receipt not found')) &&
1873
+ retryCount < 3) {
1874
+ this.logInfo('RETRYING event after PERMISSION_DENIED (transaction has 0 confirmations) response', {
1875
+ syncStats: this.streams.stats(),
1876
+ retryCount,
1877
+ prevMiniblockHash,
1878
+ prevMiniblockNum,
1879
+ });
1880
+ await new Promise((resolve) => setTimeout(resolve, 2000));
1881
+ return await makeRetry(prevMiniblockHash, prevMiniblockNum);
1882
+ }
1883
+ else {
1884
+ if (localId) {
1885
+ const stream = this.streams.get(streamId);
1886
+ stream?.updateLocalEvent(localId, eventId, 'failed');
1887
+ }
1888
+ throw err;
1889
+ }
1890
+ }
1891
+ }
1892
+ // makeMediaEventWithHashAndAddToMediaStream is used for uploading media chunks to the media stream.
1893
+ // This function uses media stream specific RPC endpoints to upload media chunks.
1894
+ // These endpoints are optimized for media uploads and are not used for general stream events.
1895
+ async makeMediaEventWithHashAndAddToMediaStream(creationCookie, last, payload) {
1896
+ const streamIdStr = streamIdAsString(creationCookie.streamId);
1897
+ check(isDefined(streamIdStr) && streamIdStr !== '', 'streamId must be defined');
1898
+ const event = await makeEvent(this.signerContext, payload, creationCookie.prevMiniblockHash);
1899
+ const resp = await this.rpcClient.addMediaEvent({
1900
+ event,
1901
+ creationCookie,
1902
+ last,
1903
+ });
1904
+ check(isDefined(resp.creationCookie), 'creationCookie not found in response');
1905
+ return { creationCookie: resp.creationCookie };
1906
+ }
1907
+ async getStreamLastMiniblockHash(streamId) {
1908
+ const r = await this.rpcClient.getLastMiniblockHash({ streamId: streamIdAsBytes(streamId) });
1909
+ return r;
1910
+ }
1911
+ async initCrypto(opts) {
1912
+ this.logCall('initCrypto');
1913
+ if (this.cryptoBackend) {
1914
+ this.logCall('Attempt to re-init crypto backend, ignoring');
1915
+ return;
1916
+ }
1917
+ check(this.userId !== undefined, 'userId must be set to init crypto');
1918
+ await this.cryptoStore.initialize();
1919
+ const crypto = new GroupEncryptionCrypto(this, this.cryptoStore);
1920
+ await crypto.init(opts);
1921
+ this.cryptoBackend = crypto;
1922
+ this.decryptionExtensions = new ClientDecryptionExtensions(this, crypto, this.userId, this.userDeviceKey(), this.opts?.unpackEnvelopeOpts, this.logId, this.opts?.decryptionExtensionsOpts ?? { enableEphemeralKeySolicitations: true });
1923
+ }
1924
+ /**
1925
+ * Resets crypto backend and creates a new encryption account, uploading device keys to UserDeviceKey stream.
1926
+ */
1927
+ async resetCrypto() {
1928
+ this.logCall('resetCrypto');
1929
+ if (this.userId == undefined) {
1930
+ throw new Error('userId must be set to reset crypto');
1931
+ }
1932
+ this.cryptoBackend = undefined;
1933
+ await this.decryptionExtensions?.stop();
1934
+ this.decryptionExtensions = undefined;
1935
+ await this.cryptoStore.deleteAccount(this.userId);
1936
+ await this.initCrypto();
1937
+ await this.uploadDeviceKeys();
1938
+ }
1939
+ async uploadDeviceKeys() {
1940
+ check(isDefined(this.cryptoBackend), 'crypto backend not initialized');
1941
+ this.logCall('initCrypto:: uploading device keys...');
1942
+ check(isDefined(this.userMetadataStreamId));
1943
+ const stream = this.stream(this.userMetadataStreamId);
1944
+ check(isDefined(stream), 'device key stream not found');
1945
+ return this.makeEventAndAddToStream(this.userMetadataStreamId, make_UserMetadataPayload_EncryptionDevice({
1946
+ ...this.userDeviceKey(),
1947
+ }), { method: 'userDeviceKey' });
1948
+ }
1949
+ async ackInboxStream() {
1950
+ check(isDefined(this.userInboxStreamId), 'user to device stream not found');
1951
+ check(isDefined(this.cryptoBackend), 'crypto backend not initialized');
1952
+ const inboxStream = this.streams.get(this.userInboxStreamId);
1953
+ check(isDefined(inboxStream), 'user to device stream not found');
1954
+ const miniblockNum = inboxStream?.view.miniblockInfo?.max;
1955
+ check(isDefined(miniblockNum), 'miniblockNum not found');
1956
+ this.logCall('ackInboxStream:: acking received keys...');
1957
+ const previousAck = inboxStream.view.userInboxContent.deviceSummary[this.userDeviceKey().deviceKey];
1958
+ if (previousAck && previousAck.lowerBound >= miniblockNum) {
1959
+ this.logCall('ackInboxStream:: already acked', previousAck, 'miniblockNum:', miniblockNum);
1960
+ return;
1961
+ }
1962
+ await this.makeEventAndAddToStream(this.userInboxStreamId, make_UserInboxPayload_Ack({
1963
+ deviceKey: this.userDeviceKey().deviceKey,
1964
+ miniblockNum,
1965
+ }));
1966
+ }
1967
+ setHighPriorityStreams(streamIds) {
1968
+ this.logCall('setHighPriorityStreams', streamIds);
1969
+ this.decryptionExtensions?.setHighPriorityStreams(streamIds);
1970
+ this.syncedStreamsExtensions.setHighPriorityStreams(streamIds);
1971
+ this.persistenceStore.setHighPriorityStreams(streamIds);
1972
+ this.streams.setHighPriorityStreams(streamIds);
1973
+ this.streamsView.setHighPriorityStreams(streamIds);
1974
+ }
1975
+ async ensureOutboundSession(streamId, opts) {
1976
+ check(isDefined(this.cryptoBackend), 'crypto backend not initialized');
1977
+ return this.cryptoBackend.ensureOutboundSession(streamId, this.defaultGroupEncryptionAlgorithm, opts);
1978
+ }
1979
+ /**
1980
+ * decrypts and updates the decrypted event
1981
+ */
1982
+ async decryptGroupEvent(streamId, eventId, kind, // kind of data
1983
+ encryptedData) {
1984
+ this.logCall('decryptGroupEvent', streamId, eventId, kind, encryptedData);
1985
+ const stream = this.stream(streamId);
1986
+ check(isDefined(stream), 'stream not found');
1987
+ check(isEncryptedContentKind(kind), `invalid kind ${kind}`);
1988
+ const cleartext = await this.cleartextForGroupEvent(streamId, eventId, encryptedData);
1989
+ const decryptedContent = toDecryptedContent(kind, encryptedData.version, cleartext);
1990
+ stream.updateDecryptedContent(eventId, decryptedContent);
1991
+ }
1992
+ async cleartextForGroupEvent(streamId, eventId, encryptedData) {
1993
+ const cached = await this.persistenceStore.getCleartext(eventId);
1994
+ if (cached) {
1995
+ this.logDebug('Cache hit for cleartext', eventId);
1996
+ return cached;
1997
+ }
1998
+ this.logDebug('Cache miss for cleartext', eventId);
1999
+ if (!this.cryptoBackend) {
2000
+ throw new Error('crypto backend not initialized');
2001
+ }
2002
+ const cleartext = await this.cryptoBackend.decryptGroupEvent(streamId, encryptedData);
2003
+ await this.persistenceStore.saveCleartext(eventId, cleartext);
2004
+ return cleartext;
2005
+ }
2006
+ _makeShareGroupSessionsContent(inStreamId, sessions, algorithm) {
2007
+ const streamIdStr = streamIdAsString(inStreamId);
2008
+ const streamIdBytes = streamIdAsBytes(inStreamId);
2009
+ check(isDefined(this.cryptoBackend), "crypto backend isn't initialized");
2010
+ check(sessions.length >= 0, 'no sessions to encrypt');
2011
+ check(new Set(sessions.map((s) => s.streamId)).size === 1, 'sessions should all be from the same stream');
2012
+ check(sessions[0].algorithm === algorithm, 'algorithm mismatch');
2013
+ check(new Set(sessions.map((s) => s.algorithm)).size === 1, 'all sessions should be the same algorithm');
2014
+ check(sessions[0].streamId === streamIdStr, 'streamId mismatch');
2015
+ const sessionIds = sessions.map((session) => session.sessionId);
2016
+ const payload = makeSessionKeys(sessions);
2017
+ const payloadClearText = toJsonString(SessionKeysSchema, payload);
2018
+ return { streamIdBytes, sessionIds, payload, payloadClearText };
2019
+ }
2020
+ async _encryptAndShareGroupSessionsToDevice(inStreamId, content, algorithm, userId, deviceKeys, userDevice, printLog = false) {
2021
+ const { streamIdBytes, sessionIds, payloadClearText } = content;
2022
+ try {
2023
+ if (deviceKeys.length === 0) {
2024
+ // means we failed to download the device keys, we should enqueue a retry
2025
+ this.logCall('encryptAndShareGroupSessions: no device keys to send', inStreamId, userId);
2026
+ return;
2027
+ }
2028
+ const ciphertext = await this.encryptWithDeviceKeys(payloadClearText, deviceKeys);
2029
+ if (Object.keys(ciphertext).length === 0) {
2030
+ // if you only have one device this is a valid state
2031
+ if (userId !== this.userId) {
2032
+ this.logError('encryptAndShareGroupSessions: no ciphertext to send', userId);
2033
+ }
2034
+ return;
2035
+ }
2036
+ const toStreamId = makeUserInboxStreamId(userId);
2037
+ const gslmhResp = await this.getStreamLastMiniblockHash(toStreamId);
2038
+ const { hash: miniblockHash, miniblockNum } = gslmhResp;
2039
+ if (printLog) {
2040
+ this.logCall("encryptAndShareGroupSessions: sent to user's devices", {
2041
+ toStreamId,
2042
+ deviceKeys: deviceKeys.map((d) => d.deviceKey).join(','),
2043
+ });
2044
+ }
2045
+ await this.makeEventWithHashAndAddToStream(toStreamId, make_UserInboxPayload_GroupEncryptionSessions({
2046
+ streamId: streamIdBytes,
2047
+ senderKey: userDevice.deviceKey,
2048
+ sessionIds: sessionIds,
2049
+ ciphertexts: ciphertext,
2050
+ algorithm: algorithm,
2051
+ }), miniblockHash, miniblockNum);
2052
+ }
2053
+ catch (error) {
2054
+ this.logError('encryptAndShareGroupSessions: ERROR', error);
2055
+ return undefined;
2056
+ }
2057
+ }
2058
+ async encryptAndShareGroupSessionsToDevice(inStreamId, sessions, algorithm, userId, deviceKeys) {
2059
+ const content = this._makeShareGroupSessionsContent(inStreamId, sessions, algorithm);
2060
+ return this._encryptAndShareGroupSessionsToDevice(inStreamId, content, algorithm, userId, deviceKeys, this.userDeviceKey(), true);
2061
+ }
2062
+ async encryptAndShareGroupSessionsToStream(inStreamId, sessions, algorithm, priorityUserIds) {
2063
+ this.logCall('share', { from: this.userId, to: priorityUserIds });
2064
+ const streamId = streamIdAsString(inStreamId);
2065
+ const users = await this.getUsersEntitledToKeyExchange(streamId);
2066
+ users.sort((a, b) => priorityUserIds.indexOf(a) - priorityUserIds.indexOf(b));
2067
+ const userDevice = this.userDeviceKey();
2068
+ const content = this._makeShareGroupSessionsContent(inStreamId, sessions, algorithm);
2069
+ const promises = users.map(async (userId) => {
2070
+ const forceDownload = users.length <= 10 || userId === this.userId;
2071
+ const deviceKeys = await this.downloadSingleUserDeviceInfo(userId, forceDownload);
2072
+ return this._encryptAndShareGroupSessionsToDevice(inStreamId, content, algorithm, userId, deviceKeys.devices, userDevice, users.length < 10 || Math.random() < 0.1);
2073
+ });
2074
+ this.logCall('encryptAndShareGroupSessions: send to devices', promises.length);
2075
+ await Promise.all(promises);
2076
+ this.logCall('encryptAndShareGroupSessions: done');
2077
+ }
2078
+ // only works with hybrid group encryption
2079
+ async encryptAndShareLatestGroupSessionToUser(inStreamId, toUserId) {
2080
+ const streamId = streamIdAsString(inStreamId);
2081
+ if (!this.cryptoBackend?.hasOutboundSession(streamId, GroupEncryptionAlgorithmId.HybridGroupEncryption)) {
2082
+ throw new Error('No outbound session found');
2083
+ }
2084
+ const sessionId = await this.cryptoBackend.ensureOutboundSession(streamId, GroupEncryptionAlgorithmId.HybridGroupEncryption);
2085
+ const session = await this.cryptoBackend.exportGroupSession(streamId, sessionId);
2086
+ if (!session) {
2087
+ throw new Error('Session not exported');
2088
+ }
2089
+ const deviceInfo = await this.downloadSingleUserDeviceInfo(toUserId, true);
2090
+ if (deviceInfo.devices.length === 0) {
2091
+ throw new Error('No device keys found');
2092
+ }
2093
+ await this.encryptAndShareGroupSessionsToDevice(streamId, [session], GroupEncryptionAlgorithmId.HybridGroupEncryption, toUserId, deviceInfo.devices);
2094
+ }
2095
+ // Encrypt event using GroupEncryption.
2096
+ encryptGroupEvent(event, streamId, algorithm) {
2097
+ if (!this.cryptoBackend) {
2098
+ throw new Error('crypto backend not initialized');
2099
+ }
2100
+ return this.cryptoBackend.encryptGroupEvent(streamId, event, algorithm);
2101
+ }
2102
+ async encryptWithDeviceKeys(payloadClearText, deviceKeys) {
2103
+ check(isDefined(this.cryptoBackend), 'crypto backend not initialized');
2104
+ // Don't encrypt to our own device
2105
+ return this.cryptoBackend.encryptWithDeviceKeys(payloadClearText, deviceKeys.filter((key) => key.deviceKey !== this.userDeviceKey().deviceKey));
2106
+ }
2107
+ // Used during testing
2108
+ userDeviceKey() {
2109
+ if (!this.cryptoBackend) {
2110
+ throw new Error('cryptoBackend not initialized');
2111
+ }
2112
+ return this.cryptoBackend.getUserDevice();
2113
+ }
2114
+ async debugForceMakeMiniblock(streamId, opts) {
2115
+ return this.rpcClient.info({
2116
+ debug: [
2117
+ 'make_miniblock',
2118
+ streamId,
2119
+ opts.forceSnapshot === true ? 'true' : 'false',
2120
+ `${opts.lastKnownMiniblockNum ?? -1n}`,
2121
+ ],
2122
+ });
2123
+ }
2124
+ async debugForceAddEvent(streamId, event) {
2125
+ const jsonStr = toJsonString(EnvelopeSchema, event);
2126
+ await this.rpcClient.info({ debug: ['add_event', streamId, jsonStr] });
2127
+ }
2128
+ async debugDropStream(syncId, streamId) {
2129
+ await this.rpcClient.info({ debug: ['drop_stream', syncId, streamId] });
2130
+ }
2131
+ }
2132
+ function ensureNoHexPrefix(value) {
2133
+ return value.startsWith('0x') ? value.slice(2) : value;
2134
+ }
2135
+ //# sourceMappingURL=client.js.map