@textrp/briij-js-sdk 41.0.1 → 43.0.0

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 (380) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/LICENSE +177 -177
  3. package/README.md +85 -3
  4. package/lib/@types/AESEncryptedSecretStoragePayload.js.map +1 -1
  5. package/lib/@types/IIdentityServerProvider.js.map +1 -1
  6. package/lib/@types/PushRules.js +14 -14
  7. package/lib/@types/PushRules.js.map +1 -1
  8. package/lib/@types/another-json.d.js.map +1 -1
  9. package/lib/@types/auth.d.ts +72 -1
  10. package/lib/@types/auth.d.ts.map +1 -1
  11. package/lib/@types/auth.js +57 -54
  12. package/lib/@types/auth.js.map +1 -1
  13. package/lib/@types/beacon.js +100 -100
  14. package/lib/@types/beacon.js.map +1 -1
  15. package/lib/@types/common.js.map +1 -1
  16. package/lib/@types/crypto.js.map +1 -1
  17. package/lib/@types/event.d.ts +59 -0
  18. package/lib/@types/event.d.ts.map +1 -1
  19. package/lib/@types/event.js +105 -102
  20. package/lib/@types/event.js.map +1 -1
  21. package/lib/@types/events.js.map +1 -1
  22. package/lib/@types/extensible_events.js +53 -53
  23. package/lib/@types/extensible_events.js.map +1 -1
  24. package/lib/@types/local_notifications.js.map +1 -1
  25. package/lib/@types/location.js +41 -41
  26. package/lib/@types/location.js.map +1 -1
  27. package/lib/@types/matrix-sdk-crypto-wasm.d.js.map +1 -1
  28. package/lib/@types/media.js.map +1 -1
  29. package/lib/@types/membership.js +39 -39
  30. package/lib/@types/membership.js.map +1 -1
  31. package/lib/@types/partials.js +25 -25
  32. package/lib/@types/partials.js.map +1 -1
  33. package/lib/@types/polls.js +46 -46
  34. package/lib/@types/polls.js.map +1 -1
  35. package/lib/@types/read_receipts.js +14 -14
  36. package/lib/@types/read_receipts.js.map +1 -1
  37. package/lib/@types/registration.js.map +1 -1
  38. package/lib/@types/search.js +14 -14
  39. package/lib/@types/search.js.map +1 -1
  40. package/lib/@types/signed.js.map +1 -1
  41. package/lib/@types/spaces.js.map +1 -1
  42. package/lib/@types/state_events.js.map +1 -1
  43. package/lib/@types/synapse.js.map +1 -1
  44. package/lib/@types/sync.js +18 -18
  45. package/lib/@types/sync.js.map +1 -1
  46. package/lib/@types/threepids.js +14 -14
  47. package/lib/@types/threepids.js.map +1 -1
  48. package/lib/@types/topic.js +47 -47
  49. package/lib/@types/topic.js.map +1 -1
  50. package/lib/@types/uia.js.map +1 -1
  51. package/lib/NamespacedValue.js +20 -20
  52. package/lib/NamespacedValue.js.map +1 -1
  53. package/lib/ReEmitter.js +16 -16
  54. package/lib/ReEmitter.js.map +1 -1
  55. package/lib/base64.js +32 -32
  56. package/lib/base64.js.map +1 -1
  57. package/lib/briij.d.ts +4 -0
  58. package/lib/briij.d.ts.map +1 -1
  59. package/lib/briij.js +4 -0
  60. package/lib/briij.js.map +1 -1
  61. package/lib/client.d.ts +48 -1
  62. package/lib/client.d.ts.map +1 -1
  63. package/lib/client.js +262 -108
  64. package/lib/client.js.map +1 -1
  65. package/lib/common-crypto/key-passphrase.js +19 -19
  66. package/lib/common-crypto/key-passphrase.js.map +1 -1
  67. package/lib/content-helpers.js +57 -57
  68. package/lib/content-helpers.js.map +1 -1
  69. package/lib/content-repo.js +36 -36
  70. package/lib/content-repo.js.map +1 -1
  71. package/lib/crypto/store/base.js +69 -69
  72. package/lib/crypto/store/base.js.map +1 -1
  73. package/lib/crypto/store/indexeddb-crypto-store-backend.js +58 -58
  74. package/lib/crypto/store/indexeddb-crypto-store-backend.js.map +1 -1
  75. package/lib/crypto/store/indexeddb-crypto-store.js +193 -193
  76. package/lib/crypto/store/indexeddb-crypto-store.js.map +1 -1
  77. package/lib/crypto/store/localStorage-crypto-store.js +72 -72
  78. package/lib/crypto/store/localStorage-crypto-store.js.map +1 -1
  79. package/lib/crypto/store/memory-crypto-store.js +74 -74
  80. package/lib/crypto/store/memory-crypto-store.js.map +1 -1
  81. package/lib/crypto-api/CryptoEventHandlerMap.js.map +1 -1
  82. package/lib/crypto-api/key-passphrase.js +22 -22
  83. package/lib/crypto-api/key-passphrase.js.map +1 -1
  84. package/lib/crypto-api/keybackup.js.map +1 -1
  85. package/lib/crypto-api/recovery-key.js +20 -20
  86. package/lib/crypto-api/recovery-key.js.map +1 -1
  87. package/lib/digest.js +21 -21
  88. package/lib/digest.js.map +1 -1
  89. package/lib/extensible_events_v1/ExtensibleEvent.js +39 -39
  90. package/lib/extensible_events_v1/ExtensibleEvent.js.map +1 -1
  91. package/lib/extensible_events_v1/InvalidEventError.js +16 -16
  92. package/lib/extensible_events_v1/InvalidEventError.js.map +1 -1
  93. package/lib/extensible_events_v1/MessageEvent.js +39 -39
  94. package/lib/extensible_events_v1/MessageEvent.js.map +1 -1
  95. package/lib/extensible_events_v1/PollEndEvent.js +29 -29
  96. package/lib/extensible_events_v1/PollEndEvent.js.map +1 -1
  97. package/lib/extensible_events_v1/PollResponseEvent.js +39 -39
  98. package/lib/extensible_events_v1/PollResponseEvent.js.map +1 -1
  99. package/lib/extensible_events_v1/PollStartEvent.js +52 -52
  100. package/lib/extensible_events_v1/PollStartEvent.js.map +1 -1
  101. package/lib/extensible_events_v1/utilities.js +22 -22
  102. package/lib/extensible_events_v1/utilities.js.map +1 -1
  103. package/lib/feature.js +16 -16
  104. package/lib/feature.js.map +1 -1
  105. package/lib/http-api/method.js +14 -14
  106. package/lib/http-api/method.js.map +1 -1
  107. package/lib/http-api/prefix.js +26 -26
  108. package/lib/http-api/prefix.js.map +1 -1
  109. package/lib/indexeddb-helpers.js +21 -21
  110. package/lib/indexeddb-helpers.js.map +1 -1
  111. package/lib/indexeddb-worker.js +18 -18
  112. package/lib/indexeddb-worker.js.map +1 -1
  113. package/lib/matrixrtc/IKeyTransport.js +17 -17
  114. package/lib/matrixrtc/IKeyTransport.js.map +1 -1
  115. package/lib/matrixrtc/IMembershipManager.js +27 -27
  116. package/lib/matrixrtc/IMembershipManager.js.map +1 -1
  117. package/lib/matrixrtc/LivekitTransport.js +19 -19
  118. package/lib/matrixrtc/LivekitTransport.js.map +1 -1
  119. package/lib/matrixrtc/index.js +14 -14
  120. package/lib/matrixrtc/index.js.map +1 -1
  121. package/lib/matrixrtc/utils.js +27 -27
  122. package/lib/matrixrtc/utils.js.map +1 -1
  123. package/lib/models/ToDeviceMessage.js.map +1 -1
  124. package/lib/models/device.js +24 -24
  125. package/lib/models/device.js.map +1 -1
  126. package/lib/models/event-status.js +17 -17
  127. package/lib/models/event-status.js.map +1 -1
  128. package/lib/models/invites-ignorer-types.js +25 -25
  129. package/lib/models/invites-ignorer-types.js.map +1 -1
  130. package/lib/models/profile-keys.js +26 -26
  131. package/lib/models/profile-keys.js.map +1 -1
  132. package/lib/models/room-summary.js +26 -26
  133. package/lib/models/room-summary.js.map +1 -1
  134. package/lib/models/search-result.js +22 -22
  135. package/lib/models/search-result.js.map +1 -1
  136. package/lib/models/typed-event-emitter.js +122 -122
  137. package/lib/models/typed-event-emitter.js.map +1 -1
  138. package/lib/oidc/authorize.js +76 -76
  139. package/lib/oidc/authorize.js.map +1 -1
  140. package/lib/oidc/error.js +17 -17
  141. package/lib/oidc/error.js.map +1 -1
  142. package/lib/oidc/index.js +17 -17
  143. package/lib/oidc/index.js.map +1 -1
  144. package/lib/oidc/register.js +41 -41
  145. package/lib/oidc/register.js.map +1 -1
  146. package/lib/oidc/tokenRefresher.js +51 -51
  147. package/lib/oidc/tokenRefresher.js.map +1 -1
  148. package/lib/oidc/validate.js +59 -59
  149. package/lib/oidc/validate.js.map +1 -1
  150. package/lib/randomstring.js +35 -35
  151. package/lib/randomstring.js.map +1 -1
  152. package/lib/realtime-callbacks.js +39 -39
  153. package/lib/realtime-callbacks.js.map +1 -1
  154. package/lib/receipt-accumulator.js +44 -44
  155. package/lib/receipt-accumulator.js.map +1 -1
  156. package/lib/rendezvous/RendezvousChannel.js.map +1 -1
  157. package/lib/rendezvous/RendezvousCode.js.map +1 -1
  158. package/lib/rendezvous/RendezvousError.js +14 -14
  159. package/lib/rendezvous/RendezvousError.js.map +1 -1
  160. package/lib/rendezvous/RendezvousFailureReason.js +14 -14
  161. package/lib/rendezvous/RendezvousFailureReason.js.map +1 -1
  162. package/lib/rendezvous/RendezvousIntent.js +14 -14
  163. package/lib/rendezvous/RendezvousIntent.js.map +1 -1
  164. package/lib/rendezvous/RendezvousTransport.js.map +1 -1
  165. package/lib/rendezvous/channels/MSC4108SecureChannel.js +63 -63
  166. package/lib/rendezvous/channels/MSC4108SecureChannel.js.map +1 -1
  167. package/lib/rendezvous/channels/index.js +14 -14
  168. package/lib/rendezvous/channels/index.js.map +1 -1
  169. package/lib/rendezvous/index.js +14 -14
  170. package/lib/rendezvous/index.js.map +1 -1
  171. package/lib/rendezvous/transports/index.js +14 -14
  172. package/lib/rendezvous/transports/index.js.map +1 -1
  173. package/lib/rust-crypto/CrossSigningIdentity.js +29 -29
  174. package/lib/rust-crypto/CrossSigningIdentity.js.map +1 -1
  175. package/lib/rust-crypto/OutgoingRequestsManager.js +37 -37
  176. package/lib/rust-crypto/OutgoingRequestsManager.js.map +1 -1
  177. package/lib/rust-crypto/device-converter.js +30 -30
  178. package/lib/rust-crypto/device-converter.js.map +1 -1
  179. package/lib/rust-crypto/secret-storage.js +30 -30
  180. package/lib/rust-crypto/secret-storage.js.map +1 -1
  181. package/lib/service-types.js +14 -14
  182. package/lib/service-types.js.map +1 -1
  183. package/lib/store/local-storage-events-emitter.js +21 -21
  184. package/lib/store/local-storage-events-emitter.js.map +1 -1
  185. package/lib/sync-accumulator.js +50 -50
  186. package/lib/sync-accumulator.js.map +1 -1
  187. package/lib/thread-utils.js +20 -20
  188. package/lib/thread-utils.js.map +1 -1
  189. package/lib/types.js +34 -34
  190. package/lib/types.js.map +1 -1
  191. package/lib/utils/decryptAESSecretStorageItem.js +22 -22
  192. package/lib/utils/decryptAESSecretStorageItem.js.map +1 -1
  193. package/lib/utils/encryptAESSecretStorageItem.js +26 -26
  194. package/lib/utils/encryptAESSecretStorageItem.js.map +1 -1
  195. package/lib/utils/internal/deriveKeys.js +21 -21
  196. package/lib/utils/internal/deriveKeys.js.map +1 -1
  197. package/lib/utils/roomVersion.js +26 -26
  198. package/lib/utils/roomVersion.js.map +1 -1
  199. package/lib/version-support.js +26 -26
  200. package/lib/version-support.js.map +1 -1
  201. package/lib/wallet-recovery.d.ts +24 -0
  202. package/lib/wallet-recovery.d.ts.map +1 -0
  203. package/lib/wallet-recovery.js +232 -0
  204. package/lib/wallet-recovery.js.map +1 -0
  205. package/lib/webrtc/audioContext.js +24 -24
  206. package/lib/webrtc/audioContext.js.map +1 -1
  207. package/lib/webrtc/callEventTypes.js.map +1 -1
  208. package/lib/webrtc/stats/callFeedStatsReporter.js +14 -14
  209. package/lib/webrtc/stats/callFeedStatsReporter.js.map +1 -1
  210. package/lib/webrtc/stats/callStatsReportGatherer.js +14 -14
  211. package/lib/webrtc/stats/callStatsReportGatherer.js.map +1 -1
  212. package/lib/webrtc/stats/callStatsReportSummary.js.map +1 -1
  213. package/lib/webrtc/stats/connectionStats.js +14 -14
  214. package/lib/webrtc/stats/connectionStats.js.map +1 -1
  215. package/lib/webrtc/stats/connectionStatsBuilder.js +14 -14
  216. package/lib/webrtc/stats/connectionStatsBuilder.js.map +1 -1
  217. package/lib/webrtc/stats/connectionStatsReportBuilder.js +14 -14
  218. package/lib/webrtc/stats/connectionStatsReportBuilder.js.map +1 -1
  219. package/lib/webrtc/stats/groupCallStats.js +14 -14
  220. package/lib/webrtc/stats/groupCallStats.js.map +1 -1
  221. package/lib/webrtc/stats/media/mediaSsrcHandler.js +14 -14
  222. package/lib/webrtc/stats/media/mediaSsrcHandler.js.map +1 -1
  223. package/lib/webrtc/stats/media/mediaTrackHandler.js +14 -14
  224. package/lib/webrtc/stats/media/mediaTrackHandler.js.map +1 -1
  225. package/lib/webrtc/stats/media/mediaTrackStats.js +27 -27
  226. package/lib/webrtc/stats/media/mediaTrackStats.js.map +1 -1
  227. package/lib/webrtc/stats/media/mediaTrackStatsHandler.js +20 -20
  228. package/lib/webrtc/stats/media/mediaTrackStatsHandler.js.map +1 -1
  229. package/lib/webrtc/stats/statsReport.js +14 -14
  230. package/lib/webrtc/stats/statsReport.js.map +1 -1
  231. package/lib/webrtc/stats/statsReportEmitter.js +14 -14
  232. package/lib/webrtc/stats/statsReportEmitter.js.map +1 -1
  233. package/lib/webrtc/stats/trackStatsBuilder.js +4 -4
  234. package/lib/webrtc/stats/trackStatsBuilder.js.map +1 -1
  235. package/lib/webrtc/stats/transportStats.js.map +1 -1
  236. package/lib/webrtc/stats/transportStatsBuilder.js.map +1 -1
  237. package/lib/webrtc/stats/valueFormatter.js +11 -11
  238. package/lib/webrtc/stats/valueFormatter.js.map +1 -1
  239. package/lib/xrpl/identity.d.ts +28 -0
  240. package/lib/xrpl/identity.d.ts.map +1 -0
  241. package/lib/xrpl/identity.js +213 -0
  242. package/lib/xrpl/identity.js.map +1 -0
  243. package/lib/xrpl/trust.d.ts +8 -0
  244. package/lib/xrpl/trust.d.ts.map +1 -0
  245. package/lib/xrpl/trust.js +61 -0
  246. package/lib/xrpl/trust.js.map +1 -0
  247. package/lib/xrpl/verification.d.ts +26 -0
  248. package/lib/xrpl/verification.d.ts.map +1 -0
  249. package/lib/xrpl/verification.js +295 -0
  250. package/lib/xrpl/verification.js.map +1 -0
  251. package/package.json +130 -129
  252. package/src/@types/AESEncryptedSecretStoragePayload.ts +29 -29
  253. package/src/@types/IIdentityServerProvider.ts +24 -24
  254. package/src/@types/PushRules.ts +208 -208
  255. package/src/@types/another-json.d.ts +19 -19
  256. package/src/@types/auth.ts +340 -258
  257. package/src/@types/beacon.ts +140 -140
  258. package/src/@types/common.ts +24 -24
  259. package/src/@types/crypto.ts +71 -71
  260. package/src/@types/event.ts +508 -449
  261. package/src/@types/events.ts +119 -119
  262. package/src/@types/extensible_events.ts +147 -147
  263. package/src/@types/local_notifications.ts +19 -19
  264. package/src/@types/location.ts +92 -92
  265. package/src/@types/matrix-sdk-crypto-wasm.d.ts +39 -39
  266. package/src/@types/media.ts +245 -245
  267. package/src/@types/membership.ts +57 -57
  268. package/src/@types/partials.ts +103 -103
  269. package/src/@types/polls.ts +120 -120
  270. package/src/@types/read_receipts.ts +61 -61
  271. package/src/@types/registration.ts +102 -102
  272. package/src/@types/search.ts +119 -119
  273. package/src/@types/signed.ts +25 -25
  274. package/src/@types/spaces.ts +37 -37
  275. package/src/@types/state_events.ts +153 -153
  276. package/src/@types/synapse.ts +40 -40
  277. package/src/@types/sync.ts +27 -27
  278. package/src/@types/threepids.ts +29 -29
  279. package/src/@types/topic.ts +69 -69
  280. package/src/@types/uia.ts +24 -24
  281. package/src/NamespacedValue.ts +121 -121
  282. package/src/ReEmitter.ts +93 -93
  283. package/src/base64.ts +86 -86
  284. package/src/briij.ts +4 -0
  285. package/src/client.ts +183 -10
  286. package/src/common-crypto/README.md +4 -4
  287. package/src/common-crypto/key-passphrase.ts +43 -43
  288. package/src/content-helpers.ts +298 -298
  289. package/src/content-repo.ts +122 -122
  290. package/src/crypto/store/base.ts +388 -388
  291. package/src/crypto/store/indexeddb-crypto-store-backend.ts +655 -655
  292. package/src/crypto/store/indexeddb-crypto-store.ts +555 -555
  293. package/src/crypto/store/localStorage-crypto-store.ts +409 -409
  294. package/src/crypto/store/memory-crypto-store.ts +326 -326
  295. package/src/crypto-api/CryptoEventHandlerMap.ts +42 -42
  296. package/src/crypto-api/key-passphrase.ts +58 -58
  297. package/src/crypto-api/keybackup.ts +114 -114
  298. package/src/crypto-api/recovery-key.ts +69 -69
  299. package/src/digest.ts +34 -34
  300. package/src/extensible_events_v1/ExtensibleEvent.ts +58 -58
  301. package/src/extensible_events_v1/InvalidEventError.ts +24 -24
  302. package/src/extensible_events_v1/MessageEvent.ts +143 -143
  303. package/src/extensible_events_v1/PollEndEvent.ts +97 -97
  304. package/src/extensible_events_v1/PollResponseEvent.ts +148 -148
  305. package/src/extensible_events_v1/PollStartEvent.ts +207 -207
  306. package/src/extensible_events_v1/utilities.ts +35 -35
  307. package/src/feature.ts +88 -88
  308. package/src/http-api/method.ts +25 -25
  309. package/src/http-api/prefix.ts +48 -48
  310. package/src/indexeddb-helpers.ts +50 -50
  311. package/src/indexeddb-worker.ts +24 -24
  312. package/src/matrixrtc/IKeyTransport.ts +63 -63
  313. package/src/matrixrtc/IMembershipManager.ts +120 -120
  314. package/src/matrixrtc/LivekitTransport.ts +46 -46
  315. package/src/matrixrtc/index.ts +24 -24
  316. package/src/matrixrtc/utils.ts +71 -71
  317. package/src/models/ToDeviceMessage.ts +38 -38
  318. package/src/models/device.ts +85 -85
  319. package/src/models/event-status.ts +39 -39
  320. package/src/models/invites-ignorer-types.ts +58 -58
  321. package/src/models/profile-keys.ts +33 -33
  322. package/src/models/room-summary.ts +78 -78
  323. package/src/models/search-result.ts +57 -57
  324. package/src/models/typed-event-emitter.ts +246 -246
  325. package/src/oidc/authorize.ts +279 -279
  326. package/src/oidc/error.ts +33 -33
  327. package/src/oidc/index.ts +33 -33
  328. package/src/oidc/register.ts +163 -163
  329. package/src/oidc/tokenRefresher.ts +184 -184
  330. package/src/oidc/validate.ts +265 -265
  331. package/src/randomstring.ts +103 -103
  332. package/src/realtime-callbacks.ts +191 -191
  333. package/src/receipt-accumulator.ts +189 -189
  334. package/src/rendezvous/RendezvousChannel.ts +48 -48
  335. package/src/rendezvous/RendezvousCode.ts +25 -25
  336. package/src/rendezvous/RendezvousError.ts +26 -26
  337. package/src/rendezvous/RendezvousFailureReason.ts +49 -49
  338. package/src/rendezvous/RendezvousIntent.ts +20 -20
  339. package/src/rendezvous/RendezvousTransport.ts +58 -58
  340. package/src/rendezvous/channels/MSC4108SecureChannel.ts +270 -270
  341. package/src/rendezvous/channels/index.ts +17 -17
  342. package/src/rendezvous/index.ts +25 -25
  343. package/src/rendezvous/transports/index.ts +17 -17
  344. package/src/rust-crypto/CrossSigningIdentity.ts +195 -195
  345. package/src/rust-crypto/OutgoingRequestsManager.ts +170 -170
  346. package/src/rust-crypto/device-converter.ts +128 -128
  347. package/src/rust-crypto/secret-storage.ts +60 -60
  348. package/src/service-types.ts +20 -20
  349. package/src/store/local-storage-events-emitter.ts +46 -46
  350. package/src/sync-accumulator.ts +779 -779
  351. package/src/thread-utils.ts +31 -31
  352. package/src/types.ts +59 -59
  353. package/src/utils/decryptAESSecretStorageItem.ts +54 -54
  354. package/src/utils/encryptAESSecretStorageItem.ts +73 -73
  355. package/src/utils/internal/deriveKeys.ts +63 -63
  356. package/src/utils/roomVersion.ts +35 -35
  357. package/src/version-support.ts +50 -50
  358. package/src/wallet-recovery.ts +252 -0
  359. package/src/webrtc/audioContext.ts +44 -44
  360. package/src/webrtc/callEventTypes.ts +101 -101
  361. package/src/webrtc/stats/callFeedStatsReporter.ts +91 -91
  362. package/src/webrtc/stats/callStatsReportGatherer.ts +219 -219
  363. package/src/webrtc/stats/callStatsReportSummary.ts +30 -30
  364. package/src/webrtc/stats/connectionStats.ts +47 -47
  365. package/src/webrtc/stats/connectionStatsBuilder.ts +28 -28
  366. package/src/webrtc/stats/connectionStatsReportBuilder.ts +140 -140
  367. package/src/webrtc/stats/groupCallStats.ts +93 -93
  368. package/src/webrtc/stats/media/mediaSsrcHandler.ts +57 -57
  369. package/src/webrtc/stats/media/mediaTrackHandler.ts +70 -70
  370. package/src/webrtc/stats/media/mediaTrackStats.ts +176 -176
  371. package/src/webrtc/stats/media/mediaTrackStatsHandler.ts +90 -90
  372. package/src/webrtc/stats/statsReport.ts +133 -133
  373. package/src/webrtc/stats/statsReportEmitter.ts +49 -49
  374. package/src/webrtc/stats/trackStatsBuilder.ts +207 -207
  375. package/src/webrtc/stats/transportStats.ts +26 -26
  376. package/src/webrtc/stats/transportStatsBuilder.ts +48 -48
  377. package/src/webrtc/stats/valueFormatter.ts +27 -27
  378. package/src/xrpl/identity.ts +245 -0
  379. package/src/xrpl/trust.ts +64 -0
  380. package/src/xrpl/verification.ts +284 -0
@@ -0,0 +1,245 @@
1
+ /*
2
+ Copyright 2026 The Matrix.org Foundation C.I.C.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+ import { Client as XrplClient, NFTokenMintFlags, type NFTokenMint } from "xrpl";
18
+
19
+ import { sha256 } from "../digest.ts";
20
+ import { logger } from "../logger.ts";
21
+
22
+ const XRPL_IDENTITY_ACCOUNT_DATA_TYPE = "io.textrp.xrpl.identity_nft";
23
+ const DEFAULT_XRPL_NETWORK = "testnet";
24
+ const DEFAULT_XRPL_TESTNET_WS = "wss://s.altnet.rippletest.net:51233";
25
+ const DEFAULT_XRPL_MAINNET_WS = "wss://s1.ripple.com";
26
+
27
+ export interface XrplIdentityAccountData {
28
+ nftTokenId: string;
29
+ xrplAddress: string;
30
+ ipfsUri: string;
31
+ txHash: string;
32
+ mintedAt: string;
33
+ }
34
+
35
+ export interface XamanWalletAdapter {
36
+ getAddress(): Promise<string>;
37
+ signAndSubmit(tx: Record<string, unknown>): Promise<{ hash: string }>;
38
+ }
39
+
40
+ export interface XrplIdentityMintingConfig {
41
+ homeserverBaseUrl: string;
42
+ accessToken: string;
43
+ websocketUrl?: string;
44
+ network?: "mainnet" | "testnet";
45
+ xamanWallet: XamanWalletAdapter;
46
+ ipfsUriFactory?: (matrixUserId: string, xrplAddress: string) => Promise<string> | string;
47
+ }
48
+
49
+ export interface XrplIdentityMintResult extends XrplIdentityAccountData {
50
+ minted: boolean;
51
+ }
52
+
53
+ let mintingConfig: Partial<XrplIdentityMintingConfig> = {};
54
+
55
+ export function configureXrplIdentityMinting(config: Partial<XrplIdentityMintingConfig>): void {
56
+ mintingConfig = {
57
+ ...mintingConfig,
58
+ ...config,
59
+ };
60
+ }
61
+
62
+ export function setXamanWalletForXrplIdentity(xamanWallet: XamanWalletAdapter): void {
63
+ mintingConfig = {
64
+ ...mintingConfig,
65
+ xamanWallet,
66
+ };
67
+ }
68
+
69
+ export async function mintSoulboundIdentityNFT(matrixUserId: string): Promise<XrplIdentityMintResult | null> {
70
+ const { homeserverBaseUrl, accessToken, xamanWallet } = mintingConfig;
71
+ if (!homeserverBaseUrl || !accessToken || !xamanWallet) {
72
+ logger.warn(
73
+ "Skipping XRPL identity mint for %s: missing homeserver auth and/or Xaman wallet adapter",
74
+ matrixUserId,
75
+ );
76
+ return null;
77
+ }
78
+
79
+ const existing = await getIdentityAccountData(homeserverBaseUrl, accessToken, matrixUserId);
80
+ if (existing?.nftTokenId && existing.xrplAddress) {
81
+ return {
82
+ ...existing,
83
+ minted: false,
84
+ };
85
+ }
86
+
87
+ const xrplAddress = await xamanWallet.getAddress();
88
+ const ipfsUri = await buildIpfsUri(matrixUserId, xrplAddress);
89
+ const encodedUri = toHex(ipfsUri);
90
+
91
+ const xrplClient = new XrplClient(resolveXrplWebSocketUrl());
92
+ await xrplClient.connect();
93
+
94
+ try {
95
+ const mintTransaction: NFTokenMint = {
96
+ TransactionType: "NFTokenMint",
97
+ Account: xrplAddress,
98
+ NFTokenTaxon: 0,
99
+ URI: encodedUri,
100
+ Flags: NFTokenMintFlags.tfMutable | NFTokenMintFlags.tfBurnable,
101
+ };
102
+
103
+ const autofilled = await xrplClient.autofill(mintTransaction);
104
+ const { hash: txHash } = await xamanWallet.signAndSubmit(autofilled as unknown as Record<string, unknown>);
105
+ const txResult = await xrplClient.request({
106
+ command: "tx",
107
+ transaction: txHash,
108
+ });
109
+
110
+ const nftTokenId =
111
+ extractNftTokenId(txResult.result?.meta) ??
112
+ (await findAccountNftByUri(xrplClient, xrplAddress, encodedUri));
113
+ if (!nftTokenId) {
114
+ throw new Error(`Unable to resolve NFTokenID for transaction ${txHash}`);
115
+ }
116
+
117
+ const accountData: XrplIdentityAccountData = {
118
+ nftTokenId,
119
+ xrplAddress,
120
+ ipfsUri,
121
+ txHash,
122
+ mintedAt: new Date().toISOString(),
123
+ };
124
+
125
+ await setIdentityAccountData(homeserverBaseUrl, accessToken, matrixUserId, accountData);
126
+
127
+ return {
128
+ ...accountData,
129
+ minted: true,
130
+ };
131
+ } finally {
132
+ await xrplClient.disconnect().catch(() => undefined);
133
+ }
134
+ }
135
+
136
+ async function buildIpfsUri(matrixUserId: string, xrplAddress: string): Promise<string> {
137
+ if (mintingConfig.ipfsUriFactory) {
138
+ return await mintingConfig.ipfsUriFactory(matrixUserId, xrplAddress);
139
+ }
140
+
141
+ const payload = JSON.stringify({ matrixUserId, xrplAddress });
142
+ const digest = await sha256(payload);
143
+ return `ipfs://textrp-briij/${toHex(digest).slice(0, 46)}`;
144
+ }
145
+
146
+ function resolveXrplWebSocketUrl(): string {
147
+ if (mintingConfig.websocketUrl) return mintingConfig.websocketUrl;
148
+ const network = mintingConfig.network ?? DEFAULT_XRPL_NETWORK;
149
+ return network === "mainnet" ? DEFAULT_XRPL_MAINNET_WS : DEFAULT_XRPL_TESTNET_WS;
150
+ }
151
+
152
+ function accountDataUrl(baseUrl: string, matrixUserId: string): string {
153
+ const trimmedBaseUrl = baseUrl.replace(/\/+$/, "");
154
+ return `${trimmedBaseUrl}/_matrix/client/v3/user/${encodeURIComponent(matrixUserId)}/account_data/${encodeURIComponent(XRPL_IDENTITY_ACCOUNT_DATA_TYPE)}`;
155
+ }
156
+
157
+ async function getIdentityAccountData(
158
+ homeserverBaseUrl: string,
159
+ accessToken: string,
160
+ matrixUserId: string,
161
+ ): Promise<XrplIdentityAccountData | null> {
162
+ const response = await fetch(accountDataUrl(homeserverBaseUrl, matrixUserId), {
163
+ method: "GET",
164
+ headers: {
165
+ Authorization: `Bearer ${accessToken}`,
166
+ "Content-Type": "application/json",
167
+ },
168
+ });
169
+
170
+ if (response.status === 404) return null;
171
+ if (!response.ok) {
172
+ throw new Error(`Failed to read XRPL identity account_data: HTTP ${response.status}`);
173
+ }
174
+
175
+ return (await response.json()) as XrplIdentityAccountData;
176
+ }
177
+
178
+ async function setIdentityAccountData(
179
+ homeserverBaseUrl: string,
180
+ accessToken: string,
181
+ matrixUserId: string,
182
+ payload: XrplIdentityAccountData,
183
+ ): Promise<void> {
184
+ const response = await fetch(accountDataUrl(homeserverBaseUrl, matrixUserId), {
185
+ method: "PUT",
186
+ headers: {
187
+ Authorization: `Bearer ${accessToken}`,
188
+ "Content-Type": "application/json",
189
+ },
190
+ body: JSON.stringify(payload),
191
+ });
192
+
193
+ if (!response.ok) {
194
+ throw new Error(`Failed to persist XRPL identity account_data: HTTP ${response.status}`);
195
+ }
196
+ }
197
+
198
+ async function findAccountNftByUri(xrplClient: XrplClient, xrplAddress: string, encodedUri: string): Promise<string | null> {
199
+ const response = await xrplClient.request({
200
+ command: "account_nfts",
201
+ account: xrplAddress,
202
+ });
203
+
204
+ const targetUri = encodedUri.toUpperCase();
205
+ const nft = response.result?.account_nfts?.find((candidate: { URI?: string }) => {
206
+ return candidate.URI?.toUpperCase() === targetUri;
207
+ }) as { NFTokenID?: string } | undefined;
208
+
209
+ return nft?.NFTokenID ?? null;
210
+ }
211
+
212
+ function extractNftTokenId(meta: unknown): string | null {
213
+ if (!meta || typeof meta !== "object") return null;
214
+ const affectedNodes = (meta as { AffectedNodes?: unknown[] }).AffectedNodes ?? [];
215
+
216
+ for (const nodeWrapper of affectedNodes) {
217
+ if (!nodeWrapper || typeof nodeWrapper !== "object") continue;
218
+ const [nodeValue] = Object.values(nodeWrapper as Record<string, unknown>);
219
+ if (!nodeValue || typeof nodeValue !== "object") continue;
220
+
221
+ const newFields = (nodeValue as { NewFields?: unknown }).NewFields;
222
+ const finalFields = (nodeValue as { FinalFields?: unknown }).FinalFields;
223
+ const tokensContainer = [newFields, finalFields].find((container) => {
224
+ if (!container || typeof container !== "object") return false;
225
+ return Array.isArray((container as { NFTokens?: unknown[] }).NFTokens);
226
+ }) as { NFTokens?: unknown[] } | undefined;
227
+
228
+ const nftokens = tokensContainer?.NFTokens ?? [];
229
+ for (const tokenEntry of nftokens) {
230
+ if (!tokenEntry || typeof tokenEntry !== "object") continue;
231
+ const token = (tokenEntry as { NFToken?: { NFTokenID?: string } }).NFToken;
232
+ if (token?.NFTokenID) return token.NFTokenID;
233
+ }
234
+ }
235
+
236
+ return null;
237
+ }
238
+
239
+ function toHex(input: string | Uint8Array): string {
240
+ const bytes = typeof input === "string" ? new TextEncoder().encode(input) : input;
241
+ return Array.from(bytes)
242
+ .map((value) => value.toString(16).padStart(2, "0"))
243
+ .join("")
244
+ .toUpperCase();
245
+ }
@@ -0,0 +1,64 @@
1
+ /*
2
+ Copyright 2026 The Matrix.org Foundation C.I.C.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+ const DEFAULT_TRUST_PATH = "/_matrix/client/v3/org.textrp.xrpl/trust";
18
+
19
+ export interface XrplTrustConfig {
20
+ homeserverBaseUrl: string;
21
+ accessToken: string;
22
+ trustPath?: string;
23
+ }
24
+
25
+ let xrplTrustConfig: Partial<XrplTrustConfig> = {};
26
+
27
+ export function configureXrplTrust(config: Partial<XrplTrustConfig>): void {
28
+ xrplTrustConfig = {
29
+ ...xrplTrustConfig,
30
+ ...config,
31
+ };
32
+ }
33
+
34
+ export async function getTrustScore(payer: string, payee: string): Promise<number> {
35
+ const homeserverBaseUrl = xrplTrustConfig.homeserverBaseUrl;
36
+ const accessToken = xrplTrustConfig.accessToken;
37
+ if (!homeserverBaseUrl || !accessToken) {
38
+ throw new Error("XRPL trust config is incomplete");
39
+ }
40
+
41
+ const trimmedBaseUrl = homeserverBaseUrl.replace(/\/+$/, "");
42
+ const trustPath = xrplTrustConfig.trustPath ?? DEFAULT_TRUST_PATH;
43
+ const query = new URLSearchParams({
44
+ payer,
45
+ payee,
46
+ });
47
+ const response = await fetch(`${trimmedBaseUrl}${trustPath}?${query.toString()}`, {
48
+ method: "GET",
49
+ headers: {
50
+ Authorization: `Bearer ${accessToken}`,
51
+ "Content-Type": "application/json",
52
+ },
53
+ });
54
+
55
+ if (!response.ok) {
56
+ throw new Error(`Failed to fetch trust score: HTTP ${response.status}`);
57
+ }
58
+
59
+ const payload = (await response.json()) as { score?: number; trusted?: boolean };
60
+ if (typeof payload.score === "number") {
61
+ return payload.score;
62
+ }
63
+ return payload.trusted ? 1 : 0;
64
+ }
@@ -0,0 +1,284 @@
1
+ /*
2
+ Copyright 2026 The Matrix.org Foundation C.I.C.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+ import { Client as XrplClient, type SubmittableTransaction } from "xrpl";
18
+
19
+ import { EventType } from "../@types/event.ts";
20
+ import type { BriijClient } from "../client.ts";
21
+ import { type XamanWalletAdapter, type XrplIdentityAccountData } from "./identity.ts";
22
+
23
+ export const XRPL_VERIFY_REQUEST_EVENT: EventType.UserVerifyRequest = EventType.UserVerifyRequest;
24
+ export const XRPL_VERIFY_ACCEPT_EVENT: EventType.UserVerifyAccept = EventType.UserVerifyAccept;
25
+ export const XRPL_VERIFIED_EVENT: EventType.UserVerified = EventType.UserVerified;
26
+
27
+ const NFT_TRUST_TAG = "nft_metadata";
28
+ const XRPL_IDENTITY_ACCOUNT_DATA_TYPE = "io.textrp.xrpl.identity_nft";
29
+
30
+ const DEFAULT_XRPL_NETWORK = "testnet";
31
+ const DEFAULT_XRPL_TESTNET_WS = "wss://s.altnet.rippletest.net:51233";
32
+ const DEFAULT_XRPL_MAINNET_WS = "wss://s1.ripple.com";
33
+
34
+ export interface XrplVerificationConfig {
35
+ matrixClient: Pick<BriijClient, "sendEvent" | "getUserId" | "getAccessToken"> & { baseUrl: string };
36
+ xamanWallet: XamanWalletAdapter;
37
+ verificationRoomId?: string;
38
+ resolveVerificationRoomId?: (counterpartyXrplAddress: string) => Promise<string> | string;
39
+ pinJsonToIpfs?: (payload: Record<string, unknown>) => Promise<string>;
40
+ pinataJwt?: string;
41
+ websocketUrl?: string;
42
+ network?: "mainnet" | "testnet";
43
+ }
44
+
45
+ export interface XrplVerificationTxResult {
46
+ txHash: string;
47
+ credentialTypeHex: string;
48
+ }
49
+
50
+ let verificationConfig: Partial<XrplVerificationConfig> = {};
51
+
52
+ export function configureXrplVerification(config: Partial<XrplVerificationConfig>): void {
53
+ verificationConfig = {
54
+ ...verificationConfig,
55
+ ...config,
56
+ };
57
+ }
58
+
59
+ export async function requestVerification(targetXrplAddress: string): Promise<XrplVerificationTxResult> {
60
+ const { matrixClient, xamanWallet } = verificationConfig;
61
+ if (!matrixClient || !xamanWallet) {
62
+ throw new Error("XRPL verification is not configured with matrixClient and xamanWallet");
63
+ }
64
+
65
+ const issuerXrplAddress = await xamanWallet.getAddress();
66
+ const roomId = await getVerificationRoomId(targetXrplAddress);
67
+ await matrixClient.sendEvent(roomId, XRPL_VERIFY_REQUEST_EVENT, {
68
+ tx_hash: "",
69
+ issuer_xrpl_address: issuerXrplAddress,
70
+ target_xrpl_address: targetXrplAddress,
71
+ trust_model: NFT_TRUST_TAG,
72
+ });
73
+
74
+ return {
75
+ txHash: "",
76
+ credentialTypeHex: NFT_TRUST_TAG,
77
+ };
78
+ }
79
+
80
+ export async function acceptVerification(issuerXrplAddress: string): Promise<XrplVerificationTxResult> {
81
+ const { matrixClient, xamanWallet } = verificationConfig;
82
+ if (!matrixClient || !xamanWallet) {
83
+ throw new Error("XRPL verification is not configured with matrixClient and xamanWallet");
84
+ }
85
+
86
+ const signerAddress = await xamanWallet.getAddress();
87
+ const identity = await getIdentityAccountData(matrixClient);
88
+ const metadata = await loadTrustMetadata(identity.ipfsUri);
89
+ const currentVerifiers = new Set(
90
+ Array.isArray(metadata.verifiers)
91
+ ? metadata.verifiers
92
+ .filter((value): value is string => typeof value === "string" && Boolean(value.trim()))
93
+ .map((value) => value.trim())
94
+ : [],
95
+ );
96
+ currentVerifiers.add(issuerXrplAddress);
97
+ const updatedUri = await pinTrustMetadata({
98
+ ...metadata,
99
+ verifiers: Array.from(currentVerifiers),
100
+ });
101
+
102
+ const roomId = await getVerificationRoomId(issuerXrplAddress);
103
+ const txHash = await signAndValidateOnXrpl(
104
+ {
105
+ TransactionType: "NFTokenModify",
106
+ Account: signerAddress,
107
+ NFTokenID: identity.nftTokenId,
108
+ URI: toHex(updatedUri),
109
+ },
110
+ async (xrplClient) => {
111
+ await assertAccountOwnsToken(xrplClient, signerAddress, identity.nftTokenId);
112
+ },
113
+ );
114
+
115
+ await matrixClient.sendEvent(roomId, XRPL_VERIFY_ACCEPT_EVENT, {
116
+ tx_hash: txHash,
117
+ issuer_xrpl_address: signerAddress,
118
+ accepter_xrpl_address: issuerXrplAddress,
119
+ nft_token_id: identity.nftTokenId,
120
+ ipfs_uri: updatedUri,
121
+ trust_model: NFT_TRUST_TAG,
122
+ });
123
+
124
+ return {
125
+ txHash,
126
+ credentialTypeHex: NFT_TRUST_TAG,
127
+ };
128
+ }
129
+
130
+ async function signAndValidateOnXrpl(
131
+ transaction: Record<string, unknown>,
132
+ preflight?: (xrplClient: XrplClient) => Promise<void>,
133
+ ): Promise<string> {
134
+ const { xamanWallet } = verificationConfig;
135
+ if (!xamanWallet) {
136
+ throw new Error("Missing Xaman wallet adapter");
137
+ }
138
+
139
+ const xrplClient = new XrplClient(resolveXrplWebSocketUrl());
140
+ await xrplClient.connect();
141
+
142
+ try {
143
+ if (preflight) {
144
+ await preflight(xrplClient);
145
+ }
146
+ const autofilled = await xrplClient.autofill(transaction as unknown as SubmittableTransaction);
147
+ const { hash: txHash } = await xamanWallet.signAndSubmit(autofilled as Record<string, unknown>);
148
+ await waitForValidation(xrplClient, txHash);
149
+ return txHash;
150
+ } finally {
151
+ await xrplClient.disconnect().catch(() => undefined);
152
+ }
153
+ }
154
+
155
+ async function waitForValidation(xrplClient: XrplClient, txHash: string): Promise<void> {
156
+ for (let attempt = 0; attempt < 15; attempt += 1) {
157
+ const response = await xrplClient.request({
158
+ command: "tx",
159
+ transaction: txHash,
160
+ });
161
+
162
+ if (response.result?.validated === true) return;
163
+ await sleep(1000);
164
+ }
165
+
166
+ throw new Error(`Timed out waiting for XRPL tx validation: ${txHash}`);
167
+ }
168
+
169
+ async function getVerificationRoomId(counterpartyXrplAddress: string): Promise<string> {
170
+ if (verificationConfig.verificationRoomId) {
171
+ return verificationConfig.verificationRoomId;
172
+ }
173
+ if (verificationConfig.resolveVerificationRoomId) {
174
+ return await verificationConfig.resolveVerificationRoomId(counterpartyXrplAddress);
175
+ }
176
+ throw new Error("No verification room configured");
177
+ }
178
+
179
+ function resolveXrplWebSocketUrl(): string {
180
+ if (verificationConfig.websocketUrl) return verificationConfig.websocketUrl;
181
+ const network = verificationConfig.network ?? DEFAULT_XRPL_NETWORK;
182
+ return network === "mainnet" ? DEFAULT_XRPL_MAINNET_WS : DEFAULT_XRPL_TESTNET_WS;
183
+ }
184
+
185
+ function toHex(input: string | Uint8Array): string {
186
+ const bytes = typeof input === "string" ? new TextEncoder().encode(input) : input;
187
+ return Array.from(bytes)
188
+ .map((value) => value.toString(16).padStart(2, "0"))
189
+ .join("")
190
+ .toUpperCase();
191
+ }
192
+
193
+ async function getIdentityAccountData(
194
+ matrixClient: Pick<BriijClient, "getUserId" | "getAccessToken"> & { baseUrl: string },
195
+ ): Promise<XrplIdentityAccountData> {
196
+ const userId = matrixClient.getUserId();
197
+ const accessToken = matrixClient.getAccessToken();
198
+ if (!userId || !accessToken) {
199
+ throw new Error("Missing Matrix session for XRPL verification");
200
+ }
201
+
202
+ const accountDataUrl =
203
+ `${matrixClient.baseUrl.replace(/\/+$/, "")}` +
204
+ `/_matrix/client/v3/user/${encodeURIComponent(userId)}/account_data/${encodeURIComponent(XRPL_IDENTITY_ACCOUNT_DATA_TYPE)}`;
205
+ const response = await fetch(accountDataUrl, {
206
+ method: "GET",
207
+ headers: {
208
+ "Authorization": `Bearer ${accessToken}`,
209
+ "Content-Type": "application/json",
210
+ },
211
+ });
212
+ if (!response.ok) {
213
+ throw new Error(`Unable to fetch identity NFT account_data: HTTP ${response.status}`);
214
+ }
215
+ return (await response.json()) as XrplIdentityAccountData;
216
+ }
217
+
218
+ async function assertAccountOwnsToken(xrplClient: XrplClient, account: string, tokenId: string): Promise<void> {
219
+ const response = await xrplClient.request({
220
+ command: "account_nfts",
221
+ account,
222
+ });
223
+ const found = response.result?.account_nfts?.some((entry: { NFTokenID?: string }) => entry.NFTokenID === tokenId);
224
+ if (!found) {
225
+ throw new Error(`Identity NFT ${tokenId} not found on account ${account}`);
226
+ }
227
+ }
228
+
229
+ async function loadTrustMetadata(uri: string): Promise<Record<string, unknown>> {
230
+ if (!uri) return {};
231
+ if (uri.startsWith("{")) {
232
+ return JSON.parse(uri) as Record<string, unknown>;
233
+ }
234
+
235
+ if (uri.startsWith("data:application/json,")) {
236
+ const payload = decodeURIComponent(uri.split(",", 2)[1] ?? "{}");
237
+ return JSON.parse(payload) as Record<string, unknown>;
238
+ }
239
+
240
+ if (uri.startsWith("ipfs://")) {
241
+ const cidPath = uri.replace("ipfs://", "");
242
+ const response = await fetch(`https://ipfs.io/ipfs/${cidPath}`);
243
+ if (!response.ok) {
244
+ throw new Error(`Failed to fetch IPFS metadata: HTTP ${response.status}`);
245
+ }
246
+ return (await response.json()) as Record<string, unknown>;
247
+ }
248
+
249
+ return {};
250
+ }
251
+
252
+ async function pinTrustMetadata(payload: Record<string, unknown>): Promise<string> {
253
+ if (verificationConfig.pinJsonToIpfs) {
254
+ return await verificationConfig.pinJsonToIpfs(payload);
255
+ }
256
+
257
+ const jwt = verificationConfig.pinataJwt;
258
+ if (!jwt) {
259
+ throw new Error("Set pinJsonToIpfs or pinataJwt before acceptVerification()");
260
+ }
261
+
262
+ const response = await fetch("https://api.pinata.cloud/pinning/pinJSONToIPFS", {
263
+ method: "POST",
264
+ headers: {
265
+ "Authorization": `Bearer ${jwt}`,
266
+ "Content-Type": "application/json",
267
+ },
268
+ body: JSON.stringify({ pinataContent: payload }),
269
+ });
270
+ if (!response.ok) {
271
+ throw new Error(`Pinata pin failed: HTTP ${response.status}`);
272
+ }
273
+ const body = (await response.json()) as { IpfsHash?: string };
274
+ if (!body.IpfsHash) {
275
+ throw new Error("Pinata response missing IpfsHash");
276
+ }
277
+ return `ipfs://${body.IpfsHash}`;
278
+ }
279
+
280
+ async function sleep(ms: number): Promise<void> {
281
+ await new Promise((resolve) => {
282
+ setTimeout(resolve, ms);
283
+ });
284
+ }