@europeum-ebsi/cli 0.0.0 → 1.0.0-rc.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 (384) hide show
  1. package/LICENSE.txt +289 -289
  2. package/LICENSES.txt +538 -0
  3. package/README.md +1140 -98
  4. package/dist/api/client.d.ts +4 -0
  5. package/dist/api/client.d.ts.map +1 -0
  6. package/dist/api/client.js +14 -0
  7. package/dist/api/client.js.map +1 -0
  8. package/dist/api/fetch.d.ts +13 -0
  9. package/dist/api/fetch.d.ts.map +1 -0
  10. package/dist/api/fetch.js +30 -0
  11. package/dist/api/fetch.js.map +1 -0
  12. package/dist/api/params.d.ts +4 -0
  13. package/dist/api/params.d.ts.map +1 -0
  14. package/dist/api/params.js +9 -0
  15. package/dist/api/params.js.map +1 -0
  16. package/dist/auth/dcql.d.ts +5 -0
  17. package/dist/auth/dcql.d.ts.map +1 -0
  18. package/dist/auth/dcql.js +41 -0
  19. package/dist/auth/dcql.js.map +1 -0
  20. package/dist/auth/presentation.d.ts +30 -0
  21. package/dist/auth/presentation.d.ts.map +1 -0
  22. package/dist/auth/presentation.js +99 -0
  23. package/dist/auth/presentation.js.map +1 -0
  24. package/dist/auth/token.d.ts +11 -0
  25. package/dist/auth/token.d.ts.map +1 -0
  26. package/dist/auth/token.js +116 -0
  27. package/dist/auth/token.js.map +1 -0
  28. package/dist/cli.d.ts +3 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +96 -10
  31. package/dist/cli.js.map +1 -1
  32. package/dist/commands/auth.d.ts +3 -0
  33. package/dist/commands/auth.d.ts.map +1 -0
  34. package/dist/commands/auth.js +99 -0
  35. package/dist/commands/auth.js.map +1 -0
  36. package/dist/commands/config-cmd.d.ts +3 -0
  37. package/dist/commands/config-cmd.d.ts.map +1 -0
  38. package/dist/commands/config-cmd.js +86 -0
  39. package/dist/commands/config-cmd.js.map +1 -0
  40. package/dist/commands/contracts-registry.d.ts +3 -0
  41. package/dist/commands/contracts-registry.d.ts.map +1 -0
  42. package/dist/commands/contracts-registry.js +132 -0
  43. package/dist/commands/contracts-registry.js.map +1 -0
  44. package/dist/commands/did-registry.d.ts +3 -0
  45. package/dist/commands/did-registry.d.ts.map +1 -0
  46. package/dist/commands/did-registry.js +110 -0
  47. package/dist/commands/did-registry.js.map +1 -0
  48. package/dist/commands/faucet.d.ts +3 -0
  49. package/dist/commands/faucet.d.ts.map +1 -0
  50. package/dist/commands/faucet.js +78 -0
  51. package/dist/commands/faucet.js.map +1 -0
  52. package/dist/commands/health.d.ts +3 -0
  53. package/dist/commands/health.d.ts.map +1 -0
  54. package/dist/commands/health.js +20 -0
  55. package/dist/commands/health.js.map +1 -0
  56. package/dist/commands/issuers-registry.d.ts +3 -0
  57. package/dist/commands/issuers-registry.d.ts.map +1 -0
  58. package/dist/commands/issuers-registry.js +340 -0
  59. package/dist/commands/issuers-registry.js.map +1 -0
  60. package/dist/commands/ledger.d.ts +3 -0
  61. package/dist/commands/ledger.d.ts.map +1 -0
  62. package/dist/commands/ledger.js +549 -372
  63. package/dist/commands/ledger.js.map +1 -1
  64. package/dist/commands/onboarding.d.ts +3 -0
  65. package/dist/commands/onboarding.d.ts.map +1 -0
  66. package/dist/commands/onboarding.js +301 -0
  67. package/dist/commands/onboarding.js.map +1 -0
  68. package/dist/commands/openapi.d.ts +3 -0
  69. package/dist/commands/openapi.d.ts.map +1 -0
  70. package/dist/commands/openapi.js +37 -0
  71. package/dist/commands/openapi.js.map +1 -0
  72. package/dist/commands/policies-registry.d.ts +3 -0
  73. package/dist/commands/policies-registry.d.ts.map +1 -0
  74. package/dist/commands/policies-registry.js +198 -0
  75. package/dist/commands/policies-registry.js.map +1 -0
  76. package/dist/commands/registry.d.ts +27 -0
  77. package/dist/commands/registry.d.ts.map +1 -0
  78. package/dist/commands/registry.js +62 -0
  79. package/dist/commands/registry.js.map +1 -0
  80. package/dist/commands/schemas-registry.d.ts +3 -0
  81. package/dist/commands/schemas-registry.d.ts.map +1 -0
  82. package/dist/commands/schemas-registry.js +231 -0
  83. package/dist/commands/schemas-registry.js.map +1 -0
  84. package/dist/commands/shared/args.d.ts +2 -0
  85. package/dist/commands/shared/args.d.ts.map +1 -0
  86. package/dist/commands/shared/args.js +4 -0
  87. package/dist/commands/shared/args.js.map +1 -0
  88. package/dist/commands/shared/wallet-opts.d.ts +9 -0
  89. package/dist/commands/shared/wallet-opts.d.ts.map +1 -0
  90. package/dist/commands/shared/wallet-opts.js +44 -0
  91. package/dist/commands/shared/wallet-opts.js.map +1 -0
  92. package/dist/commands/timestamp.d.ts +3 -0
  93. package/dist/commands/timestamp.d.ts.map +1 -0
  94. package/dist/commands/timestamp.js +250 -0
  95. package/dist/commands/timestamp.js.map +1 -0
  96. package/dist/commands/track-and-trace.d.ts +3 -0
  97. package/dist/commands/track-and-trace.d.ts.map +1 -0
  98. package/dist/commands/track-and-trace.js +235 -0
  99. package/dist/commands/track-and-trace.js.map +1 -0
  100. package/dist/commands/wallet.d.ts +3 -0
  101. package/dist/commands/wallet.d.ts.map +1 -0
  102. package/dist/commands/wallet.js +123 -0
  103. package/dist/commands/wallet.js.map +1 -0
  104. package/dist/config/config.d.ts +45 -0
  105. package/dist/config/config.d.ts.map +1 -0
  106. package/dist/config/config.js +111 -0
  107. package/dist/config/config.js.map +1 -0
  108. package/dist/config/ebsi-env.d.ts +4 -0
  109. package/dist/config/ebsi-env.d.ts.map +1 -0
  110. package/dist/config/ebsi-env.js +37 -0
  111. package/dist/config/ebsi-env.js.map +1 -0
  112. package/dist/crypto/wallet.d.ts +34 -0
  113. package/dist/crypto/wallet.d.ts.map +1 -0
  114. package/dist/crypto/wallet.js +100 -0
  115. package/dist/crypto/wallet.js.map +1 -0
  116. package/dist/index.d.ts +3 -0
  117. package/dist/index.d.ts.map +1 -0
  118. package/dist/index.js +15 -6
  119. package/dist/index.js.map +1 -1
  120. package/dist/ledger/read.d.ts +11 -0
  121. package/dist/ledger/read.d.ts.map +1 -0
  122. package/dist/ledger/read.js +24 -0
  123. package/dist/ledger/read.js.map +1 -0
  124. package/dist/ledger/registries.d.ts +25 -0
  125. package/dist/ledger/registries.d.ts.map +1 -0
  126. package/dist/ledger/registries.js +111 -0
  127. package/dist/ledger/registries.js.map +1 -0
  128. package/dist/ledger/write.d.ts +43 -0
  129. package/dist/ledger/write.d.ts.map +1 -0
  130. package/dist/ledger/write.js +119 -0
  131. package/dist/ledger/write.js.map +1 -0
  132. package/dist/onboarding/vc.d.ts +18 -0
  133. package/dist/onboarding/vc.d.ts.map +1 -0
  134. package/dist/onboarding/vc.js +72 -0
  135. package/dist/onboarding/vc.js.map +1 -0
  136. package/dist/output/format.d.ts +7 -0
  137. package/dist/output/format.d.ts.map +1 -0
  138. package/dist/output/format.js +94 -0
  139. package/dist/output/format.js.map +1 -0
  140. package/dist/tui/App.d.ts +3 -0
  141. package/dist/tui/App.d.ts.map +1 -0
  142. package/dist/tui/App.js +99 -0
  143. package/dist/tui/App.js.map +1 -0
  144. package/dist/tui/CommandPalette.d.ts +8 -0
  145. package/dist/tui/CommandPalette.d.ts.map +1 -0
  146. package/dist/tui/CommandPalette.js +105 -0
  147. package/dist/tui/CommandPalette.js.map +1 -0
  148. package/package.json +66 -108
  149. package/src/api/client.ts +26 -0
  150. package/src/api/fetch.ts +53 -0
  151. package/src/api/params.ts +17 -0
  152. package/src/auth/dcql.ts +84 -0
  153. package/src/auth/presentation.ts +255 -0
  154. package/src/auth/token.ts +244 -0
  155. package/src/cli.ts +164 -0
  156. package/src/commands/auth.ts +119 -0
  157. package/src/commands/config-cmd.ts +122 -0
  158. package/src/commands/contracts-registry.ts +156 -0
  159. package/src/commands/did-registry.ts +126 -0
  160. package/src/commands/faucet.ts +112 -0
  161. package/src/commands/health.ts +21 -0
  162. package/src/commands/issuers-registry.ts +385 -0
  163. package/src/commands/ledger.ts +777 -0
  164. package/src/commands/onboarding.ts +411 -0
  165. package/src/commands/openapi.ts +42 -0
  166. package/src/commands/policies-registry.ts +218 -0
  167. package/src/commands/registry.ts +152 -0
  168. package/src/commands/schemas-registry.ts +255 -0
  169. package/src/commands/shared/args.ts +14 -0
  170. package/src/commands/shared/wallet-opts.ts +85 -0
  171. package/src/commands/timestamp.ts +272 -0
  172. package/src/commands/track-and-trace.ts +263 -0
  173. package/src/commands/wallet.ts +175 -0
  174. package/src/config/config.ts +275 -0
  175. package/src/config/ebsi-env.ts +67 -0
  176. package/src/crypto/wallet.ts +291 -0
  177. package/src/index.ts +24 -0
  178. package/src/ledger/read.ts +70 -0
  179. package/src/ledger/registries.ts +285 -0
  180. package/src/ledger/write.ts +381 -0
  181. package/src/onboarding/vc.ts +205 -0
  182. package/src/output/format.ts +157 -0
  183. package/src/tui/App.tsx +282 -0
  184. package/src/tui/CommandPalette.tsx +223 -0
  185. package/bin/cli.js +0 -13
  186. package/dist/abi/pilot/DidRegistry.js +0 -568
  187. package/dist/abi/pilot/DidRegistry.js.map +0 -1
  188. package/dist/abi/pilot/Ptr.js +0 -666
  189. package/dist/abi/pilot/Ptr.js.map +0 -1
  190. package/dist/abi/pilot/SchemaSCRegistry.js +0 -264
  191. package/dist/abi/pilot/SchemaSCRegistry.js.map +0 -1
  192. package/dist/abi/pilot/Tcr.js +0 -715
  193. package/dist/abi/pilot/Tcr.js.map +0 -1
  194. package/dist/abi/pilot/Timestamp.js +0 -658
  195. package/dist/abi/pilot/Timestamp.js.map +0 -1
  196. package/dist/abi/pilot/Tir.js +0 -428
  197. package/dist/abi/pilot/Tir.js.map +0 -1
  198. package/dist/abi/pilot/TnT.js +0 -842
  199. package/dist/abi/pilot/TnT.js.map +0 -1
  200. package/dist/abi/pilot/Tpr.js +0 -492
  201. package/dist/abi/pilot/Tpr.js.map +0 -1
  202. package/dist/abi/test/DidRegistry.js +0 -568
  203. package/dist/abi/test/DidRegistry.js.map +0 -1
  204. package/dist/abi/test/Ptr.js +0 -666
  205. package/dist/abi/test/Ptr.js.map +0 -1
  206. package/dist/abi/test/SchemaSCRegistry.js +0 -300
  207. package/dist/abi/test/SchemaSCRegistry.js.map +0 -1
  208. package/dist/abi/test/Tcr.js +0 -715
  209. package/dist/abi/test/Tcr.js.map +0 -1
  210. package/dist/abi/test/Timestamp.js +0 -658
  211. package/dist/abi/test/Timestamp.js.map +0 -1
  212. package/dist/abi/test/Tir.js +0 -428
  213. package/dist/abi/test/Tir.js.map +0 -1
  214. package/dist/abi/test/TnT.js +0 -842
  215. package/dist/abi/test/TnT.js.map +0 -1
  216. package/dist/abi/test/Tpr.js +0 -492
  217. package/dist/abi/test/Tpr.js.map +0 -1
  218. package/dist/app.js +0 -659
  219. package/dist/app.js.map +0 -1
  220. package/dist/buildParam/didr.js +0 -374
  221. package/dist/buildParam/didr.js.map +0 -1
  222. package/dist/buildParam/index.js +0 -53
  223. package/dist/buildParam/index.js.map +0 -1
  224. package/dist/buildParam/ptr.js +0 -80
  225. package/dist/buildParam/ptr.js.map +0 -1
  226. package/dist/buildParam/tcr.js +0 -36
  227. package/dist/buildParam/tcr.js.map +0 -1
  228. package/dist/buildParam/timestamp.js +0 -350
  229. package/dist/buildParam/timestamp.js.map +0 -1
  230. package/dist/buildParam/tir.js +0 -110
  231. package/dist/buildParam/tir.js.map +0 -1
  232. package/dist/buildParam/tnt.js +0 -214
  233. package/dist/buildParam/tnt.js.map +0 -1
  234. package/dist/buildParam/tpr.js +0 -91
  235. package/dist/buildParam/tpr.js.map +0 -1
  236. package/dist/buildParam/tsr.js +0 -115
  237. package/dist/buildParam/tsr.js.map +0 -1
  238. package/dist/commands/authorisation.js +0 -144
  239. package/dist/commands/authorisation.js.map +0 -1
  240. package/dist/commands/compute.js +0 -680
  241. package/dist/commands/compute.js.map +0 -1
  242. package/dist/commands/conformance.js +0 -813
  243. package/dist/commands/conformance.js.map +0 -1
  244. package/dist/commands/hardwarewallet.js +0 -41
  245. package/dist/commands/hardwarewallet.js.map +0 -1
  246. package/dist/commands/index.js +0 -8
  247. package/dist/commands/index.js.map +0 -1
  248. package/dist/commands/ptr.js +0 -54
  249. package/dist/commands/ptr.js.map +0 -1
  250. package/dist/commands/tcr.js +0 -50
  251. package/dist/commands/tcr.js.map +0 -1
  252. package/dist/commands/tir.js +0 -64
  253. package/dist/commands/tir.js.map +0 -1
  254. package/dist/commands/tnl.js +0 -81
  255. package/dist/commands/tnl.js.map +0 -1
  256. package/dist/commands/tsr.js +0 -45
  257. package/dist/commands/tsr.js.map +0 -1
  258. package/dist/commands/view.js +0 -53
  259. package/dist/commands/view.js.map +0 -1
  260. package/dist/config.js +0 -497
  261. package/dist/config.js.map +0 -1
  262. package/dist/interfaces/context.js +0 -2
  263. package/dist/interfaces/context.js.map +0 -1
  264. package/dist/interfaces/contracts/ProxyFactory.js +0 -2
  265. package/dist/interfaces/contracts/ProxyFactory.js.map +0 -1
  266. package/dist/interfaces/contracts/ProxyTemplateRegistry.js +0 -2
  267. package/dist/interfaces/contracts/ProxyTemplateRegistry.js.map +0 -1
  268. package/dist/interfaces/contracts/SchemaSCRegistry.js +0 -2
  269. package/dist/interfaces/contracts/SchemaSCRegistry.js.map +0 -1
  270. package/dist/interfaces/contracts/common.js +0 -2
  271. package/dist/interfaces/contracts/common.js.map +0 -1
  272. package/dist/interfaces/index.js +0 -5
  273. package/dist/interfaces/index.js.map +0 -1
  274. package/dist/interfaces/jsonrpc.interface.js +0 -2
  275. package/dist/interfaces/jsonrpc.interface.js.map +0 -1
  276. package/dist/interfaces/paginated-list.interface.js +0 -2
  277. package/dist/interfaces/paginated-list.interface.js.map +0 -1
  278. package/dist/interfaces/unsigned-transaction.interface.js +0 -2
  279. package/dist/interfaces/unsigned-transaction.interface.js.map +0 -1
  280. package/dist/interfaces/utils.interface.js +0 -2
  281. package/dist/interfaces/utils.interface.js.map +0 -1
  282. package/dist/programs/migrateDid.js +0 -159
  283. package/dist/programs/migrateDid.js.map +0 -1
  284. package/dist/programs/migrateDids.js +0 -232
  285. package/dist/programs/migrateDids.js.map +0 -1
  286. package/dist/programs/migrateTsr.js +0 -201
  287. package/dist/programs/migrateTsr.js.map +0 -1
  288. package/dist/scripts/accreditAndAuthorize/conformance/step1 +0 -34
  289. package/dist/scripts/accreditAndAuthorize/conformance/step2 +0 -18
  290. package/dist/scripts/accreditAndAuthorize/conformance/step3 +0 -9
  291. package/dist/scripts/accreditAndAuthorize/conformance/step4 +0 -27
  292. package/dist/scripts/accreditAndAuthorize/conformance/step5 +0 -13
  293. package/dist/scripts/accreditAndAuthorize/conformance/step6 +0 -14
  294. package/dist/scripts/accreditAndAuthorize/conformance/step7 +0 -7
  295. package/dist/scripts/accreditAndAuthorize/test/step1 +0 -34
  296. package/dist/scripts/accreditAndAuthorize/test/step2 +0 -18
  297. package/dist/scripts/accreditAndAuthorize/test/step3 +0 -9
  298. package/dist/scripts/accreditAndAuthorize/test/step4 +0 -27
  299. package/dist/scripts/accreditAndAuthorize/test/step5 +0 -13
  300. package/dist/scripts/accreditAndAuthorize/test/step6 +0 -14
  301. package/dist/scripts/accreditAndAuthorize/test/step7 +0 -7
  302. package/dist/scripts/accreditTI +0 -21
  303. package/dist/scripts/assets/Nodes.json +0 -27
  304. package/dist/scripts/assets/vcdm1.1/CTRevocableCredential.json +0 -30
  305. package/dist/scripts/assets/vcdm1.1/CredentialToAttestVerifiableAuthorisationForTrustChain.json +0 -29
  306. package/dist/scripts/assets/vcdm1.1/Nodes.json +0 -27
  307. package/dist/scripts/assets/vcdm1.1/TrustedNodesList.json +0 -35
  308. package/dist/scripts/assets/vcdm1.1/VerifiableAccreditationToAccredit.json +0 -35
  309. package/dist/scripts/assets/vcdm1.1/VerifiableAccreditationToAttest.json +0 -33
  310. package/dist/scripts/assets/vcdm1.1/VerifiableAuthorisationForTrustChain.json +0 -22
  311. package/dist/scripts/assets/vcdm1.1/VerifiableAuthorisationToInvoke.json +0 -24
  312. package/dist/scripts/assets/vcdm1.1/VerifiableAuthorisationToOnboard.json +0 -24
  313. package/dist/scripts/assets/vcdm2.0/CredentialToAttestVerifiableAuthorisationForTrustChain.json +0 -29
  314. package/dist/scripts/assets/vcdm2.0/TrustedNodesList.json +0 -36
  315. package/dist/scripts/assets/vcdm2.0/VerifiableAccreditationToAccredit.json +0 -40
  316. package/dist/scripts/assets/vcdm2.0/VerifiableAccreditationToAttest.json +0 -38
  317. package/dist/scripts/assets/vcdm2.0/VerifiableAuthorisationForTrustChain.json +0 -30
  318. package/dist/scripts/assets/vcdm2.0/VerifiableAuthorisationToInvoke.json +0 -24
  319. package/dist/scripts/assets/vcdm2.0/VerifiableAuthorisationToOnboard.json +0 -23
  320. package/dist/scripts/bootstrap/0a-loadTPROperator +0 -5
  321. package/dist/scripts/bootstrap/0b-loadAdmin +0 -8
  322. package/dist/scripts/bootstrap/1-populateTPR +0 -92
  323. package/dist/scripts/bootstrap/2-populateDID +0 -6
  324. package/dist/scripts/bootstrap/3-populateTimestamp +0 -9
  325. package/dist/scripts/bootstrap/4-populateTIR +0 -8
  326. package/dist/scripts/bootstrap/5-populateTSR +0 -85
  327. package/dist/scripts/bootstrap/6-setupConformanceIssuer +0 -35
  328. package/dist/scripts/bootstrap/README.md +0 -218
  329. package/dist/scripts/issueVcInvoke +0 -10
  330. package/dist/scripts/issueVcOnboard +0 -9
  331. package/dist/scripts/issueVcRootTAO +0 -11
  332. package/dist/scripts/issueVcTAO +0 -12
  333. package/dist/scripts/issueVcTI +0 -12
  334. package/dist/scripts/issueVcTnl +0 -32
  335. package/dist/scripts/issue_CTRevocableCredential +0 -12
  336. package/dist/scripts/issue_SelfAttestationSupportOffice +0 -10
  337. package/dist/scripts/issue_VerifiableAccreditationToAccredit +0 -11
  338. package/dist/scripts/issue_VerifiableAccreditationToAttest +0 -11
  339. package/dist/scripts/issue_VerifiableAuthorisationForTrustChain +0 -10
  340. package/dist/scripts/issue_VerifiableAuthorisationToOnboard +0 -9
  341. package/dist/scripts/preregisterIssuer +0 -6
  342. package/dist/scripts/registerDidDocument +0 -15
  343. package/dist/scripts/registerIssuer +0 -6
  344. package/dist/scripts/updateVcRootTAO +0 -10
  345. package/dist/scripts/updateVcTAO +0 -11
  346. package/dist/scripts/updateVcTI +0 -11
  347. package/dist/scripts/vcdm2.0/issueSelfAttestationSupportOffice +0 -10
  348. package/dist/scripts/vcdm2.0/issueVcInvoke +0 -12
  349. package/dist/scripts/vcdm2.0/issueVcOnboard +0 -11
  350. package/dist/scripts/vcdm2.0/issueVcRootTAO +0 -14
  351. package/dist/scripts/vcdm2.0/issueVcTAO +0 -15
  352. package/dist/scripts/vcdm2.0/issueVcTI +0 -15
  353. package/dist/scripts/vcdm2.0/issueVcTnl +0 -34
  354. package/dist/scripts/vcdm2.0/registerDidDocument +0 -15
  355. package/dist/scripts/vcdm2.0/updateVcRootTAO +0 -13
  356. package/dist/scripts/vcdm2.0/updateVcTAO +0 -14
  357. package/dist/scripts/vcdm2.0/updateVcTI +0 -14
  358. package/dist/scripts/vcdm2.0/verifyVcTnl +0 -10
  359. package/dist/scripts/verifyVcTnl +0 -10
  360. package/dist/scripts/wct/accreditAndAuthorize +0 -133
  361. package/dist/scripts/wct/accreditAndAuthorize2 +0 -89
  362. package/dist/scripts/wct/holderWallet +0 -39
  363. package/dist/scripts/wct/holderWallet2 +0 -39
  364. package/dist/scripts/wct/issueToHolder +0 -38
  365. package/dist/scripts/wct/issueToHolder2 +0 -38
  366. package/dist/scripts/wct/pda1 +0 -3
  367. package/dist/scripts/wct/verifier +0 -8
  368. package/dist/scripts/wct/verifier2 +0 -7
  369. package/dist/utils/Client.js +0 -155
  370. package/dist/utils/Client.js.map +0 -1
  371. package/dist/utils/HardwareWallet.js +0 -326
  372. package/dist/utils/HardwareWallet.js.map +0 -1
  373. package/dist/utils/http.js +0 -132
  374. package/dist/utils/http.js.map +0 -1
  375. package/dist/utils/index.js +0 -8
  376. package/dist/utils/index.js.map +0 -1
  377. package/dist/utils/jsonrpc.js +0 -38
  378. package/dist/utils/jsonrpc.js.map +0 -1
  379. package/dist/utils/print.js +0 -56
  380. package/dist/utils/print.js.map +0 -1
  381. package/dist/utils/utils.js +0 -427
  382. package/dist/utils/utils.js.map +0 -1
  383. package/dist/utils/vcdm.js +0 -47
  384. package/dist/utils/vcdm.js.map +0 -1
@@ -0,0 +1,381 @@
1
+ import { ethers, FetchRequest } from "ethers";
2
+
3
+ import type { CliConfig } from "../config/config.ts";
4
+ import type { WalletDetails } from "../crypto/wallet.ts";
5
+ import type { RegistryEntry } from "./registries.ts";
6
+
7
+ import { printWarning } from "../output/format.ts";
8
+
9
+ /**
10
+ * Manual gas overrides for `ledger write` / `ledger write-batch` (`--gas-limit`
11
+ * / `--gas-price`). When omitted, both are derived from the node:
12
+ * `gasLimit` via `eth_estimateGas`, fees via `eth_getFeeData` (EIP-1559 when
13
+ * the node supports it, legacy `gasPrice` otherwise). Setting `gasPrice`
14
+ * explicitly forces a legacy (type 0) transaction.
15
+ */
16
+ export interface GasOverrides {
17
+ gasLimit?: bigint;
18
+ gasPrice?: bigint;
19
+ }
20
+
21
+ /**
22
+ * Gas limit used by `signWriteBatch` only, when an entry's `eth_estimateGas`
23
+ * fails and no `--gas-limit` override was given for the batch — e.g. an
24
+ * entry that only becomes valid once a prior entry in the same batch has
25
+ * been mined, so estimating it against current (pre-submission) chain state
26
+ * legitimately reverts. `writeToRegistry` (a single write, with no such
27
+ * batch-ordering ambiguity) surfaces an estimation failure as a real error
28
+ * instead of silently substituting this and submitting a transaction that
29
+ * may be doomed to revert on-chain.
30
+ */
31
+ const FALLBACK_GAS_LIMIT = 0x1_00_00_00n;
32
+
33
+ /**
34
+ * Percentage headroom added on top of a node-estimated (not overridden) gas
35
+ * limit. `eth_estimateGas` reflects chain state at call time; by the time
36
+ * the signed transaction actually lands, state may have shifted enough to
37
+ * need more gas than that moment-in-time estimate — e.g. `write-batch`
38
+ * submitting several writes together where an earlier entry changes storage
39
+ * a later entry also touches, or simply other transactions landing first.
40
+ * A call that would genuinely revert is still a real error either way; this
41
+ * buffer only protects an estimate that succeeds but comes in slightly low.
42
+ */
43
+ const GAS_LIMIT_BUFFER_PERCENT = 120n;
44
+
45
+ export interface SignWriteBatchOptions {
46
+ /**
47
+ * Resolved CLI configuration (used for baseUrl)
48
+ */
49
+ config: CliConfig;
50
+ /**
51
+ * The writes to sign, in submission order
52
+ */
53
+ entries: BatchWriteEntry[];
54
+ /**
55
+ * Manual gas overrides shared by every entry in the batch. By default gas
56
+ * is estimated dynamically (see `GasOverrides`).
57
+ */
58
+ gas?: GasOverrides;
59
+ /**
60
+ * Access token (Bearer) shared by every write in the batch
61
+ */
62
+ token: string;
63
+ /**
64
+ * Resolved wallet — `wallet.wallet` (the ethers Wallet, always the
65
+ * secp256k1 key) signs the transaction
66
+ */
67
+ wallet: WalletDetails;
68
+ }
69
+
70
+ export interface WriteOptions {
71
+ /**
72
+ * Resolved CLI configuration (used for baseUrl)
73
+ */
74
+ config: CliConfig;
75
+ /**
76
+ * Contract address (0x-prefixed)
77
+ */
78
+ contractAddress: string;
79
+ /**
80
+ * Parsed function arguments (from the JSON array on the CLI)
81
+ */
82
+ functionArgs: unknown[];
83
+ /**
84
+ * Smart contract function name (e.g. "insertDidDocument")
85
+ */
86
+ functionName: string;
87
+ /**
88
+ * Manual gas overrides. By default gas is estimated dynamically (see
89
+ * `GasOverrides`).
90
+ */
91
+ gas?: GasOverrides;
92
+ /**
93
+ * Registry entry providing the ABI interface
94
+ */
95
+ registry: RegistryEntry;
96
+ /**
97
+ * Access token (Bearer) to attach to /ledger requests
98
+ */
99
+ token: string;
100
+ /**
101
+ * Resolved wallet — `wallet.wallet` (the ethers Wallet, always the
102
+ * secp256k1 key) signs the transaction
103
+ */
104
+ wallet: WalletDetails;
105
+ }
106
+
107
+ export interface WriteReceipt {
108
+ blockHash: string | undefined;
109
+ blockNumber: number | undefined;
110
+ contractAddress: string;
111
+ from: string;
112
+ hash: string;
113
+ status: number | undefined;
114
+ to: string;
115
+ }
116
+
117
+ interface BatchWriteEntry {
118
+ /**
119
+ * Parsed function arguments (from the JSON array in the batch file)
120
+ */
121
+ functionArgs: unknown[];
122
+ /**
123
+ * Smart contract function name (e.g. "insertDidDocument")
124
+ */
125
+ functionName: string;
126
+ /**
127
+ * Registry entry providing the ABI interface
128
+ */
129
+ registry: RegistryEntry;
130
+ /**
131
+ * Contract address (0x-prefixed)
132
+ */
133
+ to: string;
134
+ }
135
+
136
+ /**
137
+ * Encodes and signs a batch of registry write transactions from the same
138
+ * wallet, assigning each one a sequential nonce (starting from the wallet's
139
+ * current pending nonce) so they can be submitted together as a single
140
+ * JSON-RPC batch request without nonce collisions.
141
+ *
142
+ * Returns the raw signed transactions in the same order as `entries`, ready
143
+ * to be wrapped in `eth_sendRawTransaction` JSON-RPC requests. Does not
144
+ * submit anything — the caller is responsible for building and sending the
145
+ * batch (see `ledger write-batch`).
146
+ */
147
+ export async function signWriteBatch(
148
+ opts: SignWriteBatchOptions,
149
+ ): Promise<string[]> {
150
+ const { config, entries, gas, token, wallet: walletDetails } = opts;
151
+
152
+ const provider = makeLedgerProvider(config, token);
153
+ const connectedWallet = walletDetails.wallet.connect(provider);
154
+
155
+ // The base nonce and the fee fields are shared by every entry in the
156
+ // batch, so resolve each with a single RPC round-trip up front (rather
157
+ // than once per entry) and fan out from there.
158
+ const [baseNonce, feeFields] = await Promise.all([
159
+ connectedWallet.getNonce("pending"),
160
+ resolveFeeFields(provider, gas),
161
+ ]);
162
+
163
+ // Each entry gets a precomputed, distinct nonce (baseNonce + index), so
164
+ // encoding + estimating + populating + signing has no cross-entry
165
+ // dependency and can run concurrently — only the final array order (==
166
+ // submission order) matters, which Promise.all preserves regardless of
167
+ // completion timing.
168
+ return Promise.all(
169
+ entries.map(async ({ functionArgs, functionName, registry, to }, index) => {
170
+ const position = `Entry #${(index + 1).toString()}`;
171
+ let data: string;
172
+ try {
173
+ data = registry
174
+ .getInterface()
175
+ .encodeFunctionData(functionName, functionArgs);
176
+ } catch (error) {
177
+ const message = error instanceof Error ? error.message : String(error);
178
+ throw new Error(
179
+ `${position}: failed to encode function data for "${functionName}": ${message}. ` +
180
+ "Check the function name and argument types.",
181
+ { cause: error },
182
+ );
183
+ }
184
+
185
+ let gasLimit: bigint;
186
+ try {
187
+ gasLimit = await resolveGasLimit(
188
+ provider,
189
+ { data, from: walletDetails.address, to },
190
+ gas,
191
+ position,
192
+ );
193
+ } catch (error) {
194
+ // Unlike `writeToRegistry`, a batch entry can legitimately fail
195
+ // estimation against pre-submission chain state — e.g. it only
196
+ // becomes valid once an earlier entry in this same batch has been
197
+ // mined — so fall back to a generous default instead of failing the
198
+ // whole batch over it.
199
+ const message = error instanceof Error ? error.message : String(error);
200
+ printWarning(
201
+ `${message}; falling back to the default gas limit ${FALLBACK_GAS_LIMIT.toString()}.`,
202
+ );
203
+ gasLimit = FALLBACK_GAS_LIMIT;
204
+ }
205
+
206
+ const populated = await connectedWallet.populateTransaction({
207
+ ...feeFields,
208
+ data,
209
+ gasLimit,
210
+ nonce: baseNonce + index,
211
+ to,
212
+ });
213
+ return connectedWallet.signTransaction(populated);
214
+ }),
215
+ );
216
+ }
217
+
218
+ /**
219
+ * Encodes a contract function call, signs it with the wallet, and submits it
220
+ * through the Ledger service (`POST /ledger`) using Pattern A (see
221
+ * `makeLedgerProvider`).
222
+ *
223
+ * ethers automatically fills nonce and chainId. Gas is resolved dynamically
224
+ * against the node (fees via `getFeeData`, limit via `estimateGas`) unless
225
+ * overridden — see `GasOverrides`.
226
+ */
227
+ export async function writeToRegistry(
228
+ opts: WriteOptions,
229
+ ): Promise<WriteReceipt> {
230
+ const {
231
+ config,
232
+ contractAddress,
233
+ functionArgs,
234
+ functionName,
235
+ gas,
236
+ registry,
237
+ token,
238
+ wallet: walletDetails,
239
+ } = opts;
240
+
241
+ // Encode calldata
242
+ const iface = registry.getInterface();
243
+ let data: string;
244
+ try {
245
+ data = iface.encodeFunctionData(functionName, functionArgs);
246
+ } catch (error) {
247
+ const message = error instanceof Error ? error.message : String(error);
248
+ throw new Error(
249
+ `Failed to encode function data for "${functionName}": ${message}. ` +
250
+ "Check the function name and argument types.",
251
+ { cause: error },
252
+ );
253
+ }
254
+
255
+ const provider = makeLedgerProvider(config, token);
256
+
257
+ const [feeFields, gasLimit] = await Promise.all([
258
+ resolveFeeFields(provider, gas),
259
+ resolveGasLimit(
260
+ provider,
261
+ { data, from: walletDetails.address, to: contractAddress },
262
+ gas,
263
+ "ledger write",
264
+ ),
265
+ ]);
266
+
267
+ // Connect wallet to the provider and send the transaction
268
+ const connectedWallet = walletDetails.wallet.connect(provider);
269
+ const tx = await connectedWallet.sendTransaction({
270
+ ...feeFields,
271
+ data,
272
+ gasLimit,
273
+ to: contractAddress,
274
+ });
275
+
276
+ const receipt = await tx.wait();
277
+
278
+ // receipt?.status is typed `number | null` in ethers; coerce null to undefined
279
+ // so the WriteReceipt interface stays null-free (unicorn/no-null)
280
+ const status = receipt?.status;
281
+ return {
282
+ blockHash: receipt?.blockHash,
283
+ blockNumber: receipt?.blockNumber,
284
+ contractAddress,
285
+ from: walletDetails.address,
286
+ hash: tx.hash,
287
+ status: status === null ? undefined : status,
288
+ to: contractAddress,
289
+ };
290
+ }
291
+
292
+ /**
293
+ * Builds a JSON-RPC provider pointed at the Ledger service (`POST /ledger`)
294
+ * using Pattern A:
295
+ *
296
+ * FetchRequest → preflightFunc injects Bearer token → JsonRpcProvider
297
+ *
298
+ * Shared by `writeToRegistry` (single write) and `signWriteBatch` (several
299
+ * writes signed against one nonce sequence and submitted as a single
300
+ * JSON-RPC batch).
301
+ */
302
+ function makeLedgerProvider(
303
+ config: CliConfig,
304
+ token: string,
305
+ ): ethers.JsonRpcProvider {
306
+ const ledgerUrl = `${config.baseUrl}/ledger`;
307
+ const fetchReq = new FetchRequest(ledgerUrl);
308
+ // @ts-expect-error preflightFunc expects Promise<FetchRequest> in ethers types but sync return is accepted at runtime
309
+ fetchReq.preflightFunc = (req: FetchRequest) => {
310
+ req.setHeader("Authorization", `Bearer ${token}`);
311
+ return req;
312
+ };
313
+ return new ethers.JsonRpcProvider(fetchReq);
314
+ }
315
+
316
+ /**
317
+ * Resolves the fee fields for a transaction: an explicit `gas.gasPrice`
318
+ * override always wins, and stamps `type: 0` alongside it — otherwise, on a
319
+ * network that also supports EIP-1559 (like this one), ethers silently
320
+ * reinterprets a bare `gasPrice` as identical `maxFeePerGas`/
321
+ * `maxPriorityFeePerGas` values and signs a type-2 transaction instead (see
322
+ * `ethers`' `Signer.populateTransaction`), defeating the override. Without an
323
+ * override, this asks the node for its current fee data and forwards
324
+ * EIP-1559 fields (`maxFeePerGas`/`maxPriorityFeePerGas`) when the node
325
+ * supports them, falling back to a legacy `gasPrice` otherwise. Never
326
+ * returns both shapes — `ethers.Transaction` rejects a mix of the two.
327
+ */
328
+ async function resolveFeeFields(
329
+ provider: ethers.JsonRpcProvider,
330
+ overrides: GasOverrides | undefined,
331
+ ): Promise<Record<string, bigint | number>> {
332
+ if (overrides?.gasPrice !== undefined) {
333
+ return { gasPrice: overrides.gasPrice, type: 0 };
334
+ }
335
+
336
+ const feeData = await provider.getFeeData();
337
+ if (feeData.maxFeePerGas !== null && feeData.maxPriorityFeePerGas !== null) {
338
+ return {
339
+ maxFeePerGas: feeData.maxFeePerGas,
340
+ maxPriorityFeePerGas: feeData.maxPriorityFeePerGas,
341
+ };
342
+ }
343
+ if (feeData.gasPrice !== null) {
344
+ return { gasPrice: feeData.gasPrice };
345
+ }
346
+ /* v8 ignore next -- defensive: every network ethers supports returns at
347
+ least one of the two fee shapes from getFeeData() */
348
+ return {};
349
+ }
350
+
351
+ /**
352
+ * Resolves the gas limit for a transaction: an explicit `gas.gasLimit`
353
+ * override always wins and is used exactly as given (no buffer). Otherwise
354
+ * asks the node to estimate it via `eth_estimateGas` and adds
355
+ * `GAS_LIMIT_BUFFER_PERCENT` headroom. A genuine estimation failure (e.g. a
356
+ * call that would revert) propagates as a descriptive error — this function
357
+ * never silently substitutes a fallback limit; `signWriteBatch`, which has a
358
+ * legitimate reason an entry's estimation can fail transiently, decides for
359
+ * itself whether to fall back (see `FALLBACK_GAS_LIMIT`).
360
+ */
361
+ async function resolveGasLimit(
362
+ provider: ethers.JsonRpcProvider,
363
+ tx: { data: string; from: string; to: string },
364
+ overrides: GasOverrides | undefined,
365
+ label: string,
366
+ ): Promise<bigint> {
367
+ if (overrides?.gasLimit !== undefined) {
368
+ return overrides.gasLimit;
369
+ }
370
+
371
+ try {
372
+ const estimated = await provider.estimateGas(tx);
373
+ return (estimated * GAS_LIMIT_BUFFER_PERCENT) / 100n;
374
+ } catch (error) {
375
+ const message = error instanceof Error ? error.message : String(error);
376
+ throw new Error(
377
+ `${label}: gas estimation failed (${message}). Provide --gas-limit to override.`,
378
+ { cause: error },
379
+ );
380
+ }
381
+ }
@@ -0,0 +1,205 @@
1
+ import type { EbsiIssuer } from "@europeum-ebsi/verifiable-credential";
2
+ import type { Schemas } from "@europeum-ebsi/verifiable-credential/vcdm11.js";
3
+
4
+ import { fromUrl } from "@europeum-ebsi/ebsi-uri";
5
+ import { metadata as attestationSchema } from "@europeum-ebsi/vcdm1.1-attestation-schema";
6
+ import { createVerifiableCredentialJwt } from "@europeum-ebsi/verifiable-credential/vcdm11.js";
7
+ import { randomUUID } from "node:crypto";
8
+
9
+ import type { CliConfig } from "../config/config.ts";
10
+
11
+ import { buildEbsiEnvConfig } from "../config/ebsi-env.ts";
12
+ import { deriveEs256Issuer, deriveWallet } from "../crypto/wallet.ts";
13
+
14
+ /**
15
+ * The services whose resources this credential's ids can name. Narrower than
16
+ * `buildEbsiEnvConfig`'s list on purpose -- `credentialSchema.id` and
17
+ * `termsOfUse.id` only ever point at a schema or an issuer's accreditation.
18
+ */
19
+ const EBSI_URI_SERVICES = [
20
+ "did-registry",
21
+ "issuers-registry",
22
+ "schemas-registry",
23
+ ];
24
+
25
+ export interface BuildOnboardingVcOptions {
26
+ /**
27
+ * Resolved CLI config. Supplies the API base URL the VC's resource
28
+ * references are derived from (`credentialSchema`, `termsOfUse` -- already
29
+ * including the `/v1` prefix) and, via `buildEbsiEnvConfig`, the EBSI
30
+ * network they are named against. Neither reference keeps the host: both
31
+ * are rewritten to EBSI URIs by `toEbsiUri`.
32
+ */
33
+ config: CliConfig;
34
+ holderDid: string;
35
+ holderThumbprint: string;
36
+ /**
37
+ * The RTAO's Issuers Registry attribute id carrying its RootTAO
38
+ * self-attestation — see `ebsi issuers-registry issuers attributes list
39
+ * <rtaoDid>`. Accepted with or without a `0x`/`0h` prefix; the credential
40
+ * always names it in the registry's canonical unprefixed form.
41
+ */
42
+ rtaoAttributeId: string;
43
+ rtaoDid: string;
44
+ /**
45
+ * The RTAO's secp256k1 private key, used to sign the VC ES256K when no
46
+ * ES256 key is given.
47
+ */
48
+ rtaoEs256kPrivateKey?: string;
49
+ /**
50
+ * The RTAO's P-256 private key. When provided the VC is signed ES256 and
51
+ * `rtaoEs256kPrivateKey` is not used for signing at all. Required against a
52
+ * deployment whose Authorisation service restricts the `did-registry:invite`
53
+ * credential format to ES256 -- ES256K is accepted only where every scope
54
+ * shares `SUPPORTED_ALGS` (`["ES256", "ES256K"]`).
55
+ */
56
+ rtaoEs256PrivateKey?: string;
57
+ }
58
+
59
+ export interface BuildOnboardingVcResult {
60
+ // Algorithm the VC was signed with, so callers can report the key used.
61
+ alg: EbsiIssuer["alg"];
62
+ rtaoKid: string;
63
+ vcJwt: string;
64
+ }
65
+
66
+ /**
67
+ * Signs a "VerifiableAuthorisationToOnboard" VC for `holderDid`/`holderThumbprint`,
68
+ * issued by the given RTAO. Mirrors `buildVerifiableAuthorisationToOnboard` in
69
+ * `api/tests/utils/access-tokens.ts` (the only other place in the repo that
70
+ * builds this VC type), but as a reusable, non-test-only function.
71
+ *
72
+ * The RTAO must already be registered on chain as `RootTAO` (e.g. via
73
+ * `hardhat bootstrap` or `contracts/deploy-toolkit/scripts/tests/setup-rtao.ts`)
74
+ * for the resulting VC to pass the Authorisation service's trust-chain check.
75
+ *
76
+ * @throws If neither `rtaoEs256PrivateKey` nor `rtaoEs256kPrivateKey` is set.
77
+ */
78
+ export async function buildOnboardingVc(
79
+ opts: BuildOnboardingVcOptions,
80
+ ): Promise<BuildOnboardingVcResult> {
81
+ const {
82
+ config,
83
+ holderDid,
84
+ holderThumbprint,
85
+ rtaoAttributeId,
86
+ rtaoDid,
87
+ rtaoEs256kPrivateKey,
88
+ rtaoEs256PrivateKey,
89
+ } = opts;
90
+ const issuer = await resolveIssuer(
91
+ rtaoDid,
92
+ rtaoEs256PrivateKey,
93
+ rtaoEs256kPrivateKey,
94
+ );
95
+
96
+ // `config.baseUrl` already carries the API version prefix (e.g.
97
+ // "https://api-pilot.ebsi.eu/v1"), so resource references are built from it
98
+ // directly rather than from the bare origin plus a hardcoded "/v1".
99
+ const apiBaseUrl = config.baseUrl.replace(/\/+$/, "");
100
+ const ebsiEnvConfig = buildEbsiEnvConfig(config);
101
+ const { name: network } = ebsiEnvConfig.network;
102
+
103
+ // The Issuers Registry returns attribute ids unprefixed, and that's their
104
+ // canonical form in a resource path, so strip any "0x"/"0h" the caller
105
+ // passed -- the URI must name the attribute identically however the id was
106
+ // supplied, or two credentials naming the same attribute won't compare equal.
107
+ const attributeId = rtaoAttributeId.replace(/^0[hx]/, "");
108
+
109
+ const issuanceDate = new Date(Date.now() - 5000);
110
+ const expirationDate = new Date(issuanceDate.getTime() + 2 * 60 * 60 * 1000);
111
+ const iso = (date: Date) => `${date.toISOString().slice(0, -5)}Z`;
112
+
113
+ const vcPayload: Schemas["Attestation"] = {
114
+ "@context": ["https://www.w3.org/2018/credentials/v1"],
115
+ credentialSchema: {
116
+ id: toEbsiUri(
117
+ `${apiBaseUrl}/schemas-registry/schemas/${attestationSchema.id.base16}`,
118
+ network,
119
+ ),
120
+ type: "FullJsonSchemaValidator2021",
121
+ },
122
+ credentialSubject: {
123
+ id: holderDid,
124
+ jwkThumbprint: holderThumbprint,
125
+ type: "same-device",
126
+ },
127
+ expirationDate: iso(expirationDate),
128
+ id: `urn:uuid:${randomUUID()}`,
129
+ issuanceDate: iso(issuanceDate),
130
+ issued: iso(issuanceDate),
131
+ issuer: rtaoDid,
132
+ termsOfUse: {
133
+ id: toEbsiUri(
134
+ `${apiBaseUrl}/issuers-registry/issuers/${rtaoDid}/attributes/${attributeId}`,
135
+ network,
136
+ ),
137
+ type: "IssuanceCertificate",
138
+ },
139
+ type: [
140
+ "VerifiableCredential",
141
+ "VerifiableAttestation",
142
+ "VerifiableAuthorisationToOnboard",
143
+ ],
144
+ validFrom: iso(issuanceDate),
145
+ };
146
+
147
+ const vcJwt = await createVerifiableCredentialJwt(
148
+ vcPayload,
149
+ issuer,
150
+ ebsiEnvConfig,
151
+ { skipValidation: true },
152
+ );
153
+
154
+ return { alg: issuer.alg, rtaoKid: issuer.kid, vcJwt };
155
+ }
156
+
157
+ /**
158
+ * Picks the signing identity: the RTAO's ES256 key when it has one, otherwise
159
+ * the ES256K ledger key `deriveWallet` doubles up as a JWT signer. Preferring
160
+ * ES256 is deliberate -- every deployment that accepts ES256K for this
161
+ * credential also accepts ES256, but not the reverse.
162
+ */
163
+ async function resolveIssuer(
164
+ rtaoDid: string,
165
+ rtaoEs256PrivateKey: string | undefined,
166
+ rtaoES256kPrivateKey: string | undefined,
167
+ ): Promise<EbsiIssuer> {
168
+ if (rtaoEs256PrivateKey) {
169
+ return deriveEs256Issuer(rtaoEs256PrivateKey, rtaoDid);
170
+ }
171
+ if (!rtaoES256kPrivateKey) {
172
+ throw new Error(
173
+ "No RTAO signing key. Provide --rtao-es256-key <hex> (P-256, signs " +
174
+ "ES256) or --rtao-es256k-key <hex> (secp256k1, signs ES256K), or set " +
175
+ "EBSI_RTAO_ES256_PRIVATE_KEY / EBSI_RTAO_ES256K_PRIVATE_KEY.",
176
+ );
177
+ }
178
+ const wallet = await deriveWallet(
179
+ { es256kPrivateKey: rtaoES256kPrivateKey },
180
+ rtaoDid,
181
+ );
182
+ return wallet.es256k.issuer;
183
+ }
184
+
185
+ /**
186
+ * Turns a core-services URL into the EBSI URI it names
187
+ * (`ebsi:<network>:<service>:<resource>`), so ids embedded in a VC
188
+ * (`credentialSchema.id`, `termsOfUse.id`, ...) name a resource on the EBSI
189
+ * network rather than binding to whichever node happened to serve this
190
+ * command's requests -- a node that may later be dropped from the trust
191
+ * chain, invalidating every credential that pointed at it directly.
192
+ *
193
+ * `hosts` is taken from the URL itself rather than from `buildEbsiEnvConfig`:
194
+ * `parseUrl` matches `config.hosts` against the URL's `host`, which carries
195
+ * the port, while the shared env config holds the bare `hostname` -- so a
196
+ * local `localhost:3000` base URL would otherwise be rejected outright.
197
+ */
198
+ function toEbsiUri(url: string, network: string): string {
199
+ return fromUrl(url, {
200
+ hosts: [new URL(url).host],
201
+ network: { name: network },
202
+ scheme: "ebsi",
203
+ services: EBSI_URI_SERVICES,
204
+ });
205
+ }