@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
package/README.md CHANGED
@@ -1,98 +1,1140 @@
1
- ![EBSI Logo](https://ec.europa.eu/cefdigital/wiki/images/logo/default-space-logo.svg)
2
-
3
- # EBSI Command Line Interface
4
-
5
- The EBSI CLI is a Command Line Interface to connect and test some of the EBSI Core Services provided on the European Blockchain Service Infrastructure (EBSI).
6
-
7
- **IMPORTANT REMARKS:**
8
-
9
- - EBSI CLI is a sample code to help Early Adopters (EA), this is not perfect code (nor audited code) but we share it in beta version to help EA better understanding through real User Code, how to consume EBSI Core Services.
10
-
11
- - For optimal stability, we highly recommend to use the [**Node.js version 24.14.1**](https://nodejs.org/en/download).
12
-
13
- ## Start the tool
14
-
15
- You can start the tool by running:
16
-
17
- ```sh
18
- npx @europeum-ebsi/cli
19
- ```
20
-
21
- When the CLI prompts `==>` it will be ready to receive commands. There is no need to install the package. It needs Node.js v24 or superior version as a prerequisite.
22
-
23
- ## Documentation
24
-
25
- For more details about the use of this tool see the full documentation in https://hub.ebsi.eu/tools/cli
26
-
27
- For instructions on bootstrapping a new EBSI network, see [Bootstrap Guide](src/scripts/bootstrap/README.md).
28
-
29
- ## Publishing
30
-
31
- ### From main branch
32
-
33
- Create `chore/release` branch off `main` and run the following command to bump version and update change log:
34
-
35
- ```
36
- pnpm run prepare:release
37
- ```
38
-
39
- In the case of a major release run:
40
-
41
- ```
42
- pnpm run prepare:release major
43
- ```
44
-
45
- Push the changes including the tag:
46
-
47
- ```
48
- git push
49
- git push --tags
50
- ```
51
-
52
- Create a PR on Bitbucket and merge it **without squashing it!**
53
-
54
- Then, from the updated `main` run:
55
-
56
- ```
57
- npm publish
58
- ```
59
-
60
- ### From upcoming branch
61
-
62
- Create `chore/release` branch off `upcoming` and run the following command to bump version and update change log:
63
-
64
- ```
65
- pnpm run prepare:release --preRelease=alpha
66
- ```
67
-
68
- In the case of a major release run:
69
-
70
- ```
71
- pnpm run prepare:release major --preRelease=alpha
72
- ```
73
-
74
- Push the changes including the tag:
75
-
76
- ```
77
- git push
78
- git push --tags
79
- ```
80
-
81
- Create a PR on Bitbucket and merge it **without squashing it!**
82
-
83
- Then, from the updated `upcoming` run:
84
-
85
- ```
86
- npm publish --tag upcoming
87
- ```
88
-
89
- ## License
90
-
91
- Copyright (C) 2026 European Union
92
-
93
- This program is free software: you can redistribute it and/or modify it under the terms of the EUROPEAN UNION PUBLIC LICENCE v. 1.2 as published by the European Union.
94
-
95
- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
96
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the EUROPEAN UNION PUBLIC LICENCE v. 1.2 for further details.
97
-
98
- You should have received a copy of the EUROPEAN UNION PUBLIC LICENCE v. 1.2. along with this program. If not, see <https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12>.
1
+ # EBSI CLI
2
+
3
+ A command-line interface for interacting with the [EBSI Core API](https://api-pilot.ebsi.eu/docs).
4
+
5
+ Supports two modes:
6
+
7
+ - **Interactive TUI** — launch without arguments for a fuzzy-search command palette with inline tips
8
+ - **Non-interactive** — `ebsi <group> <command> [args] [flags]` for scripting and piping
9
+
10
+ ## Installation
11
+
12
+ The CLI is part of the `core` monorepo. Build and link it locally:
13
+
14
+ ```sh
15
+ pnpm --filter @europeum-ebsi/cli build
16
+ node cli/dist/index.js --help
17
+ ```
18
+
19
+ Or, if the package is linked globally via `npm link` / `pnpm link`:
20
+
21
+ ```sh
22
+ ebsi --help
23
+ ```
24
+
25
+ ## Quick start
26
+
27
+ ```sh
28
+ # Check API health (defaults to the test environment)
29
+ ebsi health
30
+
31
+ # List DIDs
32
+ ebsi did-registry identifiers list
33
+
34
+ # Get a specific DID document
35
+ ebsi did-registry identifiers get did:ebsi:ziDnioxYYLW1a3FDD
36
+
37
+ # Run against the pilot environment
38
+ ebsi --env pilot did-registry identifiers list
39
+
40
+ # Output as compact JSON (useful for piping to jq)
41
+ ebsi --output json did-registry identifiers list | jq '.items[].did'
42
+ ```
43
+
44
+ ### Local dev onboarding quickstart
45
+
46
+ Against a local stack
47
+
48
+ ```
49
+ rm -rf deployments/31337 && make deploy-all NETWORK=localhost && make finish-setup NETWORK=localhost && make bootstrap NETWORK=localhost && make create-deployer-did NETWORK=localhost && make grant-factory-deploy-policy NETWORK=localhost && make create-root-tao NETWORK=localhost
50
+ ```
51
+
52
+ (see`contracts/deploy-toolkit`'s README), go from nothing to a usable
53
+ `did-registry:write` token in four commands:
54
+
55
+ to get the attributes of the RTAO did
56
+
57
+ ```sh
58
+ export EBSI_RTAO_DID=$(node -p 'require("./contracts/deploy-toolkit/deployments/31337/deployment.json").soDid')
59
+ export EBSI_RTAO_ATTRIBUTE_ID=0x$(curl -s "http://localhost:3000/v1/issuers-registry/issuers/$EBSI_RTAO_DID/attributes" | jq -r '.items[].id')
60
+
61
+ ```
62
+
63
+ then you can export the env as follow
64
+
65
+ ```sh
66
+ export EBSI_RTAO_ES256K_PRIVATE_KEY=$(grep '^SUPPORT_OFFICE_ES256K_PRIVATE_KEY=' .env | cut -d= -f2-)
67
+ export EBSI_RTAO_ES256_PRIVATE_KEY=$(grep '^SUPPORT_OFFICE_ES256_PRIVATE_KEY=' .env | cut -d= -f2-)
68
+ export DID_REGISTRY_ADDRESS=0x23dB4a08f2272df049a4932a4Cc3A6Dc1002B33E
69
+ ```
70
+
71
+ ```sh
72
+ ebsi wallet create --save
73
+ ebis wallet info # will display you adress and did
74
+ ebsi faucet 0xMYWALLET
75
+ ebsi onboarding onboard --env local --to $DID_REGISTRY_ADDRESS
76
+ ebsi --env local did-registry identifiers get did:ebsi:z... # confirm it resolves
77
+
78
+ ```
79
+
80
+ `--rtao-es256-key` signs the credential ES256; swap it for `--rtao-es256k-key` to sign
81
+ ES256K where the deployment accepts that. See [`onboarding`](#onboarding) below
82
+ for what each flag does, and
83
+ [the end-to-end walkthrough](#end-to-end-es256-signed-onboarding-against-a-local-stack)
84
+ for the whole sequence including the chain and API.
85
+
86
+ ## Interactive TUI
87
+
88
+ Run `ebsi` with no arguments (or with `--interactive`) to open the command palette:
89
+
90
+ ```
91
+ ebsi
92
+ ```
93
+
94
+ - **Type** to fuzzy-filter commands by name or description tip
95
+ - **↑ / ↓** (or `j` / `k`) to navigate the list
96
+ - **Enter** to run the selected command
97
+ - **Esc** to clear the search filter
98
+ - **Ctrl-C** to quit
99
+
100
+ The palette shows command summaries alongside each result so you can discover what each command does without leaving the terminal.
101
+
102
+ ## Global options
103
+
104
+ These options are available on every command:
105
+
106
+ | Flag | Description | Default |
107
+ | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
108
+ | `--env <env>` | Target environment: `local`, `test`, `pilot`, `preprod`, `prod` | `test` |
109
+ | `--base-url <url>` | Override the API base URL (must include the `/v1` prefix). Required for `preprod` and `prod`, whose API host is node-specific (`api-preprod.ebsi.<domain>` / `api.ebsi.<domain>`). | — |
110
+ | `--token <jwt>` | Bearer token for write operations. Overrides config/env. | — |
111
+ | `--es256k-key <hex>` | secp256k1 private key (0x-prefixed), mandatory for signing. Overrides config/env. | — |
112
+ | `--es256-key <hex>` | P-256 private key (hex), optional — for signing VCs/VPs only. Overrides config/env. | — |
113
+ | `--sign-alg <alg>` | Which key signs VCs/VPs when both are configured: `ES256` or `ES256K`. Overrides config/env. | — |
114
+ | `--did <did>` | EBSI DID to use as the subject/holder. Overrides config/env. | — |
115
+ | `--output <format>` | Output format: `pretty`, `json`, `table` | `pretty` |
116
+ | `--version` | Print the CLI version | — |
117
+ | `--help` | Print help for any command | — |
118
+
119
+ ## Which key signs what
120
+
121
+ The CLI can hold two keys:
122
+
123
+ - A **secp256k1** key (`--es256k-key` / `EBSI_ES256K_PRIVATE_KEY`) — **mandatory** for any command that signs anything. It always signs Ethereum transactions (a P-256 key cannot), and it signs VCs/VPs (e.g. the VP in `auth token`) whenever no P-256 key is configured.
124
+ - An optional **P-256** key (`--es256-key` / `EBSI_ES256_PRIVATE_KEY`) — used only for signing VCs/VPs, never Ethereum transactions. Useful against deployments whose Authorisation service restricts a scope's accepted credential format to ES256.
125
+
126
+ When **both** keys are configured, you must say which one signs VCs/VPs with `--sign-alg <ES256|ES256K>` (or `EBSI_SIGN_ALG` / `ebsi config set signAlg <alg>`) — the CLI refuses to guess. Commands that don't sign anything (`wallet info`, a plain read, …) work fine with both keys configured and no `--sign-alg`.
127
+
128
+ `onboarding onboard` always signs with the secp256k1 key regardless of `--sign-alg`, since it's the key `insertDidDocument` registers in the DID document; pass `--register-es256-key` to additionally register a configured P-256 key right after, so it can be used to sign afterwards.
129
+
130
+ > **Migrating from `EBSI_PRIVATE_KEY`:** that variable (and the old `--key` flag) has been replaced. Run `ebsi config set es256kPrivateKey <hex>` (or export `EBSI_ES256K_PRIVATE_KEY`) instead — the CLI errors out with this instruction if it still finds `EBSI_PRIVATE_KEY` set or a persisted `privateKey` entry. `ebsi config get`/`ebsi config set` stay reachable even while that error would otherwise fire on every other command, and running `config set` once clears a stale persisted `privateKey` entry for good — unsetting the environment variable, if that's the source, is on you.
131
+
132
+ ## Configuration
133
+
134
+ Settings resolve in this priority order (highest wins):
135
+
136
+ 1. Command-line flag (`--base-url`, `--env`, `--token`, `--es256k-key`, `--es256-key`, `--sign-alg`, `--did`, …)
137
+ 2. Environment variable (see table below)
138
+ 3. Persisted config file (`config.json`, see below)
139
+ 4. Default: `test` environment
140
+
141
+ ### Environment variables
142
+
143
+ | Variable | Description |
144
+ | ------------------------- | ------------------------------------------------------------------- |
145
+ | `EBSI_API_BASE_URL` | Override the API base URL (must include `/v1` prefix) |
146
+ | `EBSI_ENV` | Default environment (`local`, `test`, `pilot`, …) |
147
+ | `EBSI_OUTPUT` | Default output format (`pretty`, `json`, `table`) |
148
+ | `EBSI_ACCESS_TOKEN` | Bearer token for authenticated write operations |
149
+ | `EBSI_ES256K_PRIVATE_KEY` | secp256k1 private key, mandatory for signing (0x-prefixed hex) |
150
+ | `EBSI_ES256_PRIVATE_KEY` | P-256 private key, optional — for signing VCs/VPs only (hex) |
151
+ | `EBSI_SIGN_ALG` | Which key signs VCs/VPs when both are configured (`ES256`/`ES256K`) |
152
+ | `EBSI_DID` | EBSI DID to use as the subject/holder |
153
+
154
+ ### Environment URLs
155
+
156
+ | Environment | Base URL |
157
+ | ----------- | ------------------------------------------------------------------------- |
158
+ | `local` | `http://localhost:3000/v1` |
159
+ | `test` | `https://api-test.testnode02.ebsi.eu/v1` |
160
+ | `pilot` | `https://api-pilot.ebsi.eu/v1` |
161
+ | `preprod` | No default — `https://api-preprod.ebsi.<domain>/v1`, set via `--base-url` |
162
+ | `prod` | No default — `https://api.ebsi.<domain>/v1`, set via `--base-url` |
163
+
164
+ `preprod` and `prod` are served by each node operator under their own domain
165
+ (e.g. `https://api-preprod.ebsi.node1.example.org/v1`), so the CLI cannot pick
166
+ one for you. Pair `--env` with `--base-url` (or `EBSI_ENV` with
167
+ `EBSI_API_BASE_URL`); the `--env` value still determines the EBSI network the
168
+ CLI signs credentials and mints `ebsi:` URIs for.
169
+
170
+ ```sh
171
+ ebsi --env preprod --base-url https://api-preprod.ebsi.node1.example.org/v1 did-registry identifiers list
172
+ ```
173
+
174
+ ### Persisted config file
175
+
176
+ Use `ebsi config set` to persist settings across sessions so you don't have to pass flags every time:
177
+
178
+ ```sh
179
+ # Always use the pilot environment by default
180
+ ebsi config set env pilot
181
+
182
+ # Always output JSON
183
+ ebsi config set output json
184
+
185
+ # Persist the mandatory secp256k1 key (stored in plaintext — use with caution)
186
+ ebsi config set es256kPrivateKey 0xdeadbeef...
187
+
188
+ # Persist an optional P-256 key, for signing VCs/VPs
189
+ ebsi config set es256PrivateKey 0xdeadbeef...
190
+
191
+ # Persist which key signs VCs/VPs when both are configured
192
+ ebsi config set signAlg ES256
193
+
194
+ # Persist an access token
195
+ ebsi config set token eyJ...
196
+
197
+ # Check the current persisted value
198
+ ebsi config get env
199
+
200
+ # See where the config file lives
201
+ ebsi config path
202
+ ```
203
+
204
+ Valid keys: `did`, `env`, `es256PrivateKey`, `es256kPrivateKey`, `output`, `signAlg`, `token`.
205
+
206
+ > **Security note:** `es256PrivateKey`/`es256kPrivateKey` are stored in plaintext in the config file. Use environment variables or pass `--es256-key`/`--es256k-key` per-command in production environments.
207
+
208
+ ## Output formats
209
+
210
+ | Format | Description |
211
+ | -------- | ---------------------------------------------------------------------------- |
212
+ | `pretty` | Indented, colourised JSON (default on a TTY; plain indented JSON when piped) |
213
+ | `json` | Compact single-line JSON — ideal for piping to `jq` |
214
+ | `table` | Key/value table for objects; column table for arrays |
215
+
216
+ ```sh
217
+ ebsi --output table did-registry identifiers list
218
+ ebsi --output json timestamp timestamps list | jq '.items | length'
219
+ ```
220
+
221
+ ## Command reference
222
+
223
+ ### `health`
224
+
225
+ ```
226
+ ebsi health
227
+ ```
228
+
229
+ Check the health of the EBSI API and its blockchain node.
230
+
231
+ ---
232
+
233
+ ### `openapi`
234
+
235
+ ```
236
+ ebsi openapi json
237
+ ebsi openapi yaml
238
+ ```
239
+
240
+ Fetch the OpenAPI 3.1 specification in JSON or YAML format.
241
+
242
+ ---
243
+
244
+ ### `config`
245
+
246
+ ```
247
+ ebsi config get <key>
248
+ ebsi config set <key> <value>
249
+ ```
250
+
251
+ Read or write a persisted config value.
252
+
253
+ Valid keys: `did`, `env`, `es256PrivateKey`, `es256kPrivateKey`, `output`, `signAlg`, `token`.
254
+
255
+ ---
256
+
257
+ ### `wallet`
258
+
259
+ ```
260
+ ebsi wallet create [--es256k-key <hex>] [--es256-key <hex>] [--sign-alg <alg>] [--did <did>] [--save]
261
+ ebsi wallet info [--es256k-key <hex>] [--es256-key <hex>] [--sign-alg <alg>] [--did <did>]
262
+ ```
263
+
264
+ Manage your EBSI signing key(s) and identity.
265
+
266
+ | Command | Description |
267
+ | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
268
+ | `wallet create` | Generate (or derive from `--es256k-key`) a secp256k1 key pair, optionally alongside a P-256 key, with its DID, JWK(s), and Ethereum address. |
269
+ | `wallet info` | Show the DID, address, and per-curve kid/thumbprint for the currently configured key(s). |
270
+
271
+ **Key and DID generation semantics:**
272
+
273
+ - The **secp256k1 key** is randomly generated only when none is already configured. Resolution order: `--es256k-key` flag → `EBSI_ES256K_PRIVATE_KEY`/persisted `es256kPrivateKey` → randomly generated. If a key is already configured (e.g. from a prior `--save`, or `EBSI_ES256K_PRIVATE_KEY` in the environment), `wallet create` reuses it rather than generating a new one.
274
+ - The **P-256 key** (`--es256-key`) is entirely optional and never auto-generated — pass it explicitly (or set `EBSI_ES256_PRIVATE_KEY`) to have it derived and, with `--save`, persisted alongside the secp256k1 key.
275
+ - The **DID** is randomly generated on every `wallet create` invocation, independent of whether the key is new or reused, unless `--did` (or `EBSI_DID`/a persisted `did`) is provided. Invoking `wallet create` with an already-configured key therefore still produces a new DID each time, paired with the same key.
276
+
277
+ To obtain a deterministic, repeatable identity across invocations, specify both `--es256k-key` and `--did` explicitly.
278
+
279
+ **Options:**
280
+
281
+ | Flag | Description |
282
+ | -------------------- | -------------------------------------------------------------------------------------------------- |
283
+ | `--es256k-key <hex>` | Use this secp256k1 private key instead of generating a random one (0x-prefixed hex). |
284
+ | `--es256-key <hex>` | Also derive a P-256 key from this private key (hex), for signing VCs/VPs. |
285
+ | `--sign-alg <alg>` | Which key signs VCs/VPs when both are configured: `ES256` or `ES256K`. |
286
+ | `--did <did>` | Pin a specific EBSI DID (overrides the randomly generated one). |
287
+ | `--save` | Persist the private key(s) and DID to the config file (stored in plaintext; a warning is printed). |
288
+
289
+ **Examples:**
290
+
291
+ ```sh
292
+ # Generate a fresh secp256k1 key pair
293
+ ebsi wallet create
294
+
295
+ # Derive from an existing key without saving
296
+ ebsi wallet create --es256k-key 0xdeadbeef...
297
+
298
+ # Derive and persist to config
299
+ ebsi wallet create --es256k-key 0xdeadbeef... --save
300
+
301
+ # Also derive and persist a P-256 key for signing VCs/VPs
302
+ ebsi wallet create --es256k-key 0xdeadbeef... --es256-key 0xc0ffee... --save
303
+
304
+ # Show the identity tied to the currently configured key(s)
305
+ ebsi wallet info
306
+ ```
307
+
308
+ ---
309
+
310
+ ### `faucet`
311
+
312
+ ```
313
+ ebsi faucet <to> [--private-key <hex>] [--amount-in-eth <eth>] [--rpc-url <url>]
314
+ ```
315
+
316
+ Funds an address with ETH on a local development chain.
317
+
318
+ Unlike every other command, the faucet talks to the JSON-RPC node **directly**
319
+ rather than through the API's `/ledger` proxy — that proxy needs a Bearer token,
320
+ and funding an account is usually the step that comes before it can get one.
321
+ So `--rpc-url` is a node URL, not an API base URL, and `--env` / `--base-url`
322
+ have no effect here.
323
+
324
+ | Option | Default | Description |
325
+ | ----------------------- | ---------------------------------- | ------------------------------------------- |
326
+ | `--private-key <hex>` | Hardhat account #0 (`0xac0974be…`) | Key funding the transfer (0x-prefixed hex). |
327
+ | `--amount-in-eth <eth>` | `1` | Amount of ETH to send, e.g. `0.5`. |
328
+ | `--rpc-url <url>` | `http://127.0.0.1:8545` | JSON-RPC endpoint to send the transfer to. |
329
+
330
+ **Examples:**
331
+
332
+ ```sh
333
+ # Send 1 ETH from Hardhat account #0 to an address
334
+ ebsi faucet 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC
335
+
336
+ # Send a smaller amount
337
+ ebsi faucet 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC --amount-in-eth 0.25
338
+
339
+ # Fund from a different account, against a non-default node
340
+ ebsi faucet 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC \
341
+ --private-key 0x… --rpc-url http://127.0.0.1:9545
342
+ ```
343
+
344
+ ---
345
+
346
+ ### `onboarding`
347
+
348
+ ```
349
+ ebsi onboarding issue-vc [--holder-did <did>] [--holder-thumbprint <thumbprint>]
350
+ --rtao-did <did> --rtao-attribute-id <hex>
351
+ (--rtao-es256-key <hex> | --rtao-es256k-key <hex>)
352
+ [--es256k-key <hex>] [--es256-key <hex>] [--sign-alg <alg>] [--out <file>]
353
+ ebsi onboarding onboard [--vc <file>] [--rtao-did <did> --rtao-attribute-id <hex>
354
+ (--rtao-es256-key <hex> | --rtao-es256k-key <hex>)]
355
+ [--es256k-key <hex>] [--es256-key <hex>] [--register-es256-key]
356
+ [--to <address>] [--spec <draft14|1.0>] [--not-before <epoch>] [--not-after <epoch>]
357
+ ```
358
+
359
+ Mints and consumes the `VerifiableAuthorisationToOnboard` VC needed to
360
+ onboard a _new_ DID via the `did-registry:invite` scope. There is no HTTP endpoint
361
+ for minting this VC — it's a local signing operation performed by an RTAO
362
+ already registered as `RootTAO` on chain (run
363
+ `pnpm exec hardhat bootstrap --network <network>` in
364
+ `contracts/deploy-toolkit`, or `scripts/tests/setup-rtao.ts` for your own
365
+ DID/keys, to get one).
366
+
367
+ #### Which key signs the VC
368
+
369
+ The credential is signed with **ES256** when `--rtao-es256-key` is given, and
370
+ with **ES256K** otherwise. Which one you need depends on the deployment:
371
+
372
+ - The Authorisation service constrains the `did-registry:invite` **credential** format
373
+ per scope. Where that constraint is `["ES256"]`, an ES256K-signed VC is
374
+ rejected outright and you must pass `--rtao-es256-key`.
375
+ - Deployments whose scopes share `SUPPORTED_ALGS` (`["ES256", "ES256K"]`)
376
+ accept either.
377
+
378
+ ES256 is therefore the safer choice: every deployment that accepts ES256K for
379
+ this credential also accepts ES256, but not the reverse. It stays opt-in only
380
+ so existing ES256K setups keep working unchanged.
381
+
382
+ The RTAO's DID Document must carry the matching verification method with an
383
+ `assertionMethod` relationship. Both `hardhat bootstrap` and
384
+ `scripts/tests/setup-rtao.ts` register the ES256K **and** ES256 methods, so an
385
+ RTAO created by either is ready for both.
386
+
387
+ `--rtao-es256k-key` is optional once `--rtao-es256-key` is set — the secp256k1 key
388
+ signs nothing in that case. At least one of the two is required.
389
+
390
+ | Command | Description |
391
+ | --------------------- | ------------------------------------------------------------------------------------------------------------ |
392
+ | `onboarding issue-vc` | Sign a `VerifiableAuthorisationToOnboard` VC for a holder DID/key. |
393
+ | `onboarding onboard` | One-shot: mint (or load) the VC, exchange it for a `did-registry:invite` token, and insert the DID document. |
394
+
395
+ **Options:**
396
+
397
+ | Flag | Description |
398
+ | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
399
+ | `--rtao-did <did>` | The RTAO's DID. Also read from `EBSI_RTAO_DID`. |
400
+ | `--rtao-es256k-key <hex>` | The RTAO's secp256k1 private key, signing the VC ES256K. Optional when `--rtao-es256-key` is given. Also read from `EBSI_RTAO_ES256K_PRIVATE_KEY`. |
401
+ | `--rtao-es256-key <hex>` | The RTAO's P-256 private key, signing the VC ES256 instead of ES256K. Also read from `EBSI_RTAO_ES256_PRIVATE_KEY`. |
402
+ | `--rtao-attribute-id <hex>` | The RTAO's Issuers Registry attribute id (from `ebsi issuers-registry issuers attributes list <rtaoDid>`). Also read from `EBSI_RTAO_ATTRIBUTE_ID`. |
403
+ | `--holder-did <did>` | (`issue-vc` only) DID to embed as `credentialSubject.id`. Defaults to the configured wallet's DID. |
404
+ | `--holder-thumbprint <tp>` | (`issue-vc` only) JWK thumbprint to embed. Defaults to the configured wallet's signing key thumbprint (see `--sign-alg`). |
405
+ | `--es256k-key <hex>` | The **holder's** secp256k1 key — overrides config/env. Not the RTAO's key (see `--rtao-*` above). |
406
+ | `--es256-key <hex>` | The **holder's** optional P-256 key — overrides config/env. `onboard` always signs with the secp256k1 key regardless of `--sign-alg` (see below). |
407
+ | `--sign-alg <alg>` | (`issue-vc` only) Which of the holder's keys the default `--holder-thumbprint` binds to, when both are configured. |
408
+ | `--out <file>` | (`issue-vc` only) Also write the signed VC JWT to this file. |
409
+ | `--vc <file>` | (`onboard` only) Use a pre-obtained VC instead of minting one inline. |
410
+ | `--to <address>` | (`onboard` only) DID Registry contract address. Defaults to `DID_REGISTRY_CONTRACT_ADDRESS`. |
411
+ | `--spec <draft14\|1.0>` | (`onboard` only) Which OpenID4VP grant to speak for the `did-registry:invite` token. Default `draft14`. |
412
+ | `--not-before` / `--not-after` | (`onboard` only) Validity window for the inserted DID document. Default `0` / `9999999999`. |
413
+ | `--register-es256-key` | (`onboard` only) After registering the DID document, also register the configured `--es256-key` as an additional verification method (`authentication` + `assertionMethod`), so it can sign VCs/VPs afterwards. Requires a P-256 key; mints its own `did-registry:write` token, always ES256K-signed. |
414
+
415
+ **Examples:**
416
+
417
+ ```sh
418
+ # Mint an ES256-signed onboarding VC for the currently configured wallet
419
+ ebsi onboarding issue-vc \
420
+ --rtao-did did:ebsi:zRtao... --rtao-es256-key <p256-hex> --rtao-attribute-id 0x... \
421
+ --out ./onboarding-vc.jwt
422
+
423
+ # The same VC, signed ES256K instead (only where the deployment accepts it)
424
+ ebsi onboarding issue-vc \
425
+ --rtao-did did:ebsi:zRtao... --rtao-es256k-key 0x... --rtao-attribute-id 0x... \
426
+ --out ./onboarding-vc.jwt
427
+
428
+ # One-shot: mint the VC inline, get a did-registry:invite token, and write the DID document
429
+ ebsi wallet create --save
430
+ ebsi onboarding onboard \
431
+ --rtao-did did:ebsi:zRtao... --rtao-es256-key <p256-hex> --rtao-attribute-id 0x...
432
+
433
+ # Same, but with a pre-obtained VC
434
+ ebsi onboarding onboard --vc ./onboarding-vc.jwt
435
+
436
+ # Now get a plain write token for further did-registry/issuers-registry/... writes
437
+ ebsi auth token --scope did-registry:write --save
438
+ ```
439
+
440
+ #### End-to-end: ES256-signed onboarding against a local stack
441
+
442
+ The full sequence, from an empty chain to a resolvable DID registered through
443
+ an ES256-signed credential. Four shells; every value the later steps need is
444
+ printed by step 3.
445
+
446
+ **Shell 1 — chain**
447
+
448
+ ```sh
449
+ cd contracts/deploy-toolkit
450
+ pnpm exec hardhat node --network default
451
+ ```
452
+
453
+ **Shell 2 — contracts and RTAO**
454
+
455
+ ```sh
456
+ cd contracts/deploy-toolkit
457
+ make deploy-all NETWORK=localhost
458
+
459
+ # Creates the Support Office DID, registers its ES256K *and* ES256
460
+ # verification methods, and self-attests it as RootTAO.
461
+ EBSI_DOMAIN=http://localhost:3000 pnpm exec hardhat bootstrap --network localhost
462
+ ```
463
+
464
+ `bootstrap` prints the three values the CLI needs — keep them:
465
+
466
+ ```
467
+ Support Office ES256 Private Key: <p256-hex> -> --rtao-es256-key
468
+ SO DID: did:ebsi:z... -> --rtao-did
469
+ SO Root TAO attribute id: 0x... -> --rtao-attribute-id
470
+ ```
471
+
472
+ (To use your own RTAO keys instead, run `scripts/tests/setup-rtao.ts` with
473
+ `RTAO_DID` / `RTAO_ES256_PRIVATE_KEY` / `RTAO_ES256K_PRIVATE_KEY` set; it
474
+ prints the same DID and attribute id and registers both methods too.)
475
+
476
+ **Shell 3 — API**
477
+
478
+ ```sh
479
+ pnpm --filter @europeum-ebsi/api start # serves http://localhost:3000/v1
480
+ ```
481
+
482
+ **Shell 4 — the flow**
483
+
484
+ ```sh
485
+ pnpm --filter @europeum-ebsi/cli build
486
+ alias ebsi="node cli/dist/index.js"
487
+
488
+ export EBSI_ENV=local
489
+ export EBSI_OUTPUT=json
490
+ export DID_REGISTRY_CONTRACT_ADDRESS=$(
491
+ jq -r '.system.DidRegistry' contracts/deploy-toolkit/deployments/31337/deployment.json
492
+ )
493
+
494
+ # From step 3's output:
495
+ export EBSI_RTAO_DID=did:ebsi:z...
496
+ export EBSI_RTAO_ES256_PRIVATE_KEY=<p256-hex>
497
+ export EBSI_RTAO_ATTRIBUTE_ID=0x...
498
+
499
+ # 1. A fresh holder wallet (its secp256k1 key signs the VP and the tx)
500
+ HOLDER_DID=$(ebsi wallet create --save | jq -r .did)
501
+ echo "holder: $HOLDER_DID"
502
+
503
+ # 2. Issue the VC on its own first — confirms it really is ES256-signed
504
+ ebsi onboarding issue-vc --out ./onboarding-vc.jwt | jq '{alg, rtaoKid, holderDid}'
505
+
506
+ # ...and read the JWT header back, independently of what the CLI reported
507
+ node -p "JSON.stringify(JSON.parse(Buffer.from(require('fs').readFileSync('./onboarding-vc.jwt','utf8').trim().split('.')[0],'base64url')))"
508
+
509
+ # 3. Onboard: trade the VC for a did-registry:invite token, insert the DID document
510
+ ebsi onboarding onboard --vc ./onboarding-vc.jwt
511
+
512
+ # 4. Confirm the DID resolves, and that a plain write token now works
513
+ ebsi did-registry identifiers get "$HOLDER_DID"
514
+ ebsi auth token --scope did-registry:write --save
515
+ ```
516
+
517
+ Step 2 should report `"alg": "ES256"` and a `kid` whose fragment is the RTAO's
518
+ P-256 thumbprint. Drop `EBSI_RTAO_ES256_PRIVATE_KEY` and set
519
+ `EBSI_RTAO_ES256K_PRIVATE_KEY` instead to run the same flow ES256K-signed.
520
+
521
+ Steps 2 and 3 can be collapsed into one — `onboarding onboard` mints the VC
522
+ inline when `--vc` is omitted — but issuing it separately lets you check the
523
+ signature before spending it.
524
+
525
+ ---
526
+
527
+ ### `auth`
528
+
529
+ ```
530
+ ebsi auth token --scope <scope> [--vc <file>] [--es256k-key <hex>] [--es256-key <hex>] [--sign-alg <alg>] [--did <did>] [--save] [--spec <draft14|1.0>]
531
+ ```
532
+
533
+ Obtain an EBSI access token via the OIDC4VP `vp_token` grant flow.
534
+
535
+ A secp256k1 private key is required (resolved from `--es256k-key`, `EBSI_ES256K_PRIVATE_KEY`, or persisted config). When a P-256 key is also configured, `--sign-alg` picks which one signs the VP.
536
+
537
+ **Options:**
538
+
539
+ | Flag | Description |
540
+ | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
541
+ | `--scope <scope>` | **Required.** EBSI scope string — a single scope (e.g. `did-registry:write`) or several space-separated write scopes for a multi-scope token (e.g. `"did-registry:write issuers-registry:write"`). |
542
+ | `--vc <file>` | Path to a VC JWT file. Required for VC-scopes: `did-registry:invite`, `ledger:invoke`, `issuers-registry:invite`, `track-and-trace:authorise`. |
543
+ | `--es256k-key <hex>` | secp256k1 private key override (0x-prefixed hex). |
544
+ | `--es256-key <hex>` | P-256 private key override (hex), optional. |
545
+ | `--sign-alg <alg>` | Which key signs the VP when both are configured: `ES256` or `ES256K`. |
546
+ | `--did <did>` | DID override. |
547
+ | `--save` | Persist the obtained token to config (equivalent to `ebsi config set token <jwt>`). |
548
+ | `--spec <draft14\|1.0>` | Which OpenID4VP grant to speak: `draft14` (Presentation Exchange, the default) or `1.0` (final, DCQL). See below. |
549
+
550
+ **`--spec 1.0` (DCQL grant):** speaks the OpenID4VP 1.0 (final)/DCQL `vp_token`
551
+ shape instead of the legacy Presentation Exchange one; both are accepted by the
552
+ server side by side. For scopes that need no explicit credential on the legacy
553
+ grant (the seven "Combinable" scopes below), the CLI automatically mints and
554
+ presents a self-issued `SelfAttestation` credential — `--vc` still
555
+ takes precedence and is required as usual for the VC-bearing scopes.
556
+
557
+ ```sh
558
+ ebsi auth token --scope did-registry:write --spec 1.0
559
+ ```
560
+
561
+ **Scopes and VC requirements:**
562
+
563
+ | Scope | VC required? | Combinable? | Description |
564
+ | --------------------------- | ------------ | ----------- | ---------------------------------- |
565
+ | `did-registry:write` | No | Yes | Write to the DID Registry |
566
+ | `issuers-registry:write` | No | Yes | Write to the Issuers Registry |
567
+ | `policies-registry:write` | No | Yes | Write to the Policies Registry |
568
+ | `schemas-registry:write` | No | Yes | Write to the Schemas Registry |
569
+ | `timestamp:write` | No | Yes | Write timestamps |
570
+ | `track-and-trace:create` | No | Yes | Create Track and Trace documents |
571
+ | `track-and-trace:write` | No | Yes | Write to Track and Trace |
572
+ | `did-registry:invite` | Yes | No | Onboard a new DID via invitation |
573
+ | `ledger:invoke` | Yes | No | Invoke the Ledger service directly |
574
+ | `issuers-registry:invite` | Yes | No | Invite an issuer to the registry |
575
+ | `track-and-trace:authorise` | Yes | No | Grant Track and Trace access |
576
+
577
+ **Multi-scope tokens:** the seven "Combinable" scopes above can be requested together
578
+ in a single space-separated `--scope` value, e.g. `"did-registry:write issuers-registry:write"`. The
579
+ resulting token authorises writes to every combined registry — the holder must
580
+ independently qualify for each one (it's a pure AND of the individual checks, so a
581
+ combined token never grants more than the same scopes requested separately would).
582
+ Invite/invoke scopes (VC required) can only ever be requested alone.
583
+
584
+ **Instance targeting:** any scope may be suffixed with `:<0x-address>` (e.g.
585
+ `"track-and-trace:write:0x61c36a8d610163660E21a8b7359e1Cac0C9133e1"`) to target a specific deployed
586
+ beacon-proxy instance of that scope's registry instead of the environment-configured
587
+ default. `ledger write`/`ledger write-batch` do this automatically with `--auto-token`
588
+ — the minted token is always instance-targeted at the resolved `--to` address(es), not
589
+ just the bare family scope shown in the table above — so a token minted for one
590
+ instance can't be reused to write to a different instance of the same registry.
591
+
592
+ **`did-registry:invite` key binding:** the `VerifiableAuthorisationToOnboard` VC issued by the RTAO must carry the
593
+ target key's RFC 7638 thumbprint in `credentialSubject.jwkThumbprint` — the Authorisation service rejects the
594
+ token request otherwise, and the CLI checks it locally first so a mismatch fails fast with a clear message.
595
+ Run `ebsi wallet info` to read the configured wallet's thumbprint and hand it to the RTAO before it issues the
596
+ VC.
597
+
598
+ **Examples:**
599
+
600
+ ```sh
601
+ # Get a token for a write scope (no VC required)
602
+ ebsi auth token --scope did-registry:write
603
+
604
+ # Get a token and persist it
605
+ ebsi auth token --scope did-registry:write --save
606
+
607
+ # Get a single token covering two registries
608
+ ebsi auth token --scope "did-registry:write issuers-registry:write" --save
609
+
610
+ # Target a specific contract instance instead of the environment default
611
+ ebsi auth token --scope track-and-trace:write:0x61c36a8d610163660E21a8b7359e1Cac0C9133e1
612
+
613
+ # Check the wallet's key thumbprint before asking the RTAO to issue an onboard VC for it
614
+ ebsi wallet info
615
+
616
+ # Get a token for an invite scope (VC required; the VC's credentialSubject.jwkThumbprint
617
+ # must match this wallet's thumbprint)
618
+ ebsi auth token --scope did-registry:invite --vc ./my-credential.jwt
619
+
620
+ # One-liner: set key + get + persist token
621
+ ebsi --es256k-key 0xdeadbeef... auth token --scope did-registry:write --save
622
+ ```
623
+
624
+ ---
625
+
626
+ ### `ledger`
627
+
628
+ ```
629
+ ebsi ledger call <method> [params]
630
+ ebsi ledger block <blockNumberOrTag>
631
+ ebsi ledger tx <hash>
632
+ ebsi ledger read <registry> <function> <args>
633
+ ebsi ledger write <registry> <function> <args>
634
+ ebsi ledger batch <source>
635
+ ebsi ledger write-batch <file>
636
+ ```
637
+
638
+ Interact with the EBSI Besu node via the Ledger service JSON-RPC proxy.
639
+
640
+ #### `ledger call`
641
+
642
+ Send an arbitrary JSON-RPC request to the node.
643
+
644
+ ```sh
645
+ ebsi ledger call eth_blockNumber
646
+ ebsi ledger call eth_getBlockByNumber '["latest", false]'
647
+ ebsi ledger call eth_getBalance '["0xabc...", "latest"]'
648
+ ```
649
+
650
+ Options: `--id <n>` (JSON-RPC request id, default `1`).
651
+
652
+ #### `ledger block`
653
+
654
+ Get a block by number or tag. Shorthand for `eth_getBlockByNumber`.
655
+
656
+ ```sh
657
+ ebsi ledger block latest
658
+ ebsi ledger block 0x1e240
659
+ ```
660
+
661
+ #### `ledger tx`
662
+
663
+ Get a transaction by hash. Shorthand for `eth_getTransactionByHash`.
664
+
665
+ ```sh
666
+ ebsi ledger tx 0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b
667
+ ```
668
+
669
+ #### `ledger read`
670
+
671
+ ABI-encode a registry **view/pure** function call and resolve it via `eth_call` — the
672
+ read-only counterpart to `ledger write`. No wallet or token needed, since `eth_call` is
673
+ served anonymously. Returns the function's outputs as an array, in declaration order.
674
+
675
+ ```
676
+ ebsi ledger read <registry> <function> <args-json> [--to <address>]
677
+ ```
678
+
679
+ | Argument | Description |
680
+ | ----------- | ----------------------------------------------------------------- |
681
+ | `registry` | Target registry (see table under [`ledger write`](#ledger-write)) |
682
+ | `function` | Smart contract view/pure function name (e.g. `getTimestamp`) |
683
+ | `args-json` | Function arguments as a JSON array string |
684
+
685
+ `--to <address>` behaves exactly as it does for `ledger write` — if omitted, it falls
686
+ back to the registry's address env var.
687
+
688
+ ```sh
689
+ ebsi ledger read timestamp getTimestamp '["0xtimestampId"]' --to 0xContractAddress
690
+ ```
691
+
692
+ #### `ledger write`
693
+
694
+ ABI-encode a registry function call, sign an Ethereum transaction, and submit it via the Ledger service.
695
+
696
+ ```
697
+ ebsi ledger write <registry> <function> <args-json> [options]
698
+ ```
699
+
700
+ | Argument | Description |
701
+ | ----------- | -------------------------------------------------------------------- |
702
+ | `registry` | Target registry (see table below) |
703
+ | `function` | Smart contract function name (e.g. `insertDidDocument`, `addIssuer`) |
704
+ | `args-json` | Function arguments as a JSON array string |
705
+
706
+ **Options:**
707
+
708
+ | Flag | Description |
709
+ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
710
+ | `--to <address>` | Contract address (0x-prefixed). If omitted, read from the registry's env var (see table below). |
711
+ | `--token <jwt>` | Bearer access token. Resolved from `--token`, `EBSI_ACCESS_TOKEN`, or persisted config. |
712
+ | `--auto-token` | Mint a fresh access token inline via the VP flow instead of using a pre-obtained one. |
713
+ | `--scope <scope>` | EBSI scope for `--auto-token`. Defaults to the registry/function's default scope, instance-targeted at the resolved `--to` address (see below). |
714
+ | `--vc <file>` | VC JWT file for VC-required scopes when using `--auto-token`. |
715
+ | `--es256k-key <hex>` | secp256k1 private key override (0x-prefixed hex). |
716
+ | `--did <did>` | DID override. |
717
+ | `--gas-limit <value>` | Advanced: manual gas limit (decimal or `0x`-prefixed hex). By default estimated from the node via `eth_estimateGas`. |
718
+ | `--gas-price <value>` | Advanced: manual gas price (decimal or `0x`-prefixed hex), forcing a legacy transaction. By default fees are derived from the node (EIP-1559 when supported). |
719
+
720
+ Gas is estimated dynamically from the node by default (with 20% headroom over the raw
721
+ `eth_estimateGas` figure, to absorb state shifting between estimation and inclusion) —
722
+ `--gas-limit`/`--gas-price` are escape hatches for when you need to override that (e.g.
723
+ a known gas-hungry call, or matching a specific fee for testing). If gas estimation
724
+ fails (e.g. the call would revert), `ledger write` fails immediately with a descriptive
725
+ error instead of signing and submitting a transaction that's likely doomed on-chain.
726
+
727
+ **Known registries:**
728
+
729
+ | Registry name | Default scope | Address env var |
730
+ | ------------------- | ------------------------- | ------------------------------------ |
731
+ | `did-registry` | `did-registry:write` | `DID_REGISTRY_CONTRACT_ADDRESS` |
732
+ | `issuers-registry` | `issuers-registry:write` | `ISSUERS_REGISTRY_CONTRACT_ADDRESS` |
733
+ | `policies-registry` | `policies-registry:write` | `POLICIES_REGISTRY_CONTRACT_ADDRESS` |
734
+ | `schemas-registry` | `schemas-registry:write` | `SCHEMAS_REGISTRY_CONTRACT_ADDRESS` |
735
+ | `timestamp` | `timestamp:write` | `TIMESTAMP_CONTRACT_ADDRESS` |
736
+ | `track-and-trace` | `track-and-trace:write` | `TRACK_AND_TRACE_CONTRACT_ADDRESS` |
737
+
738
+ > **Exceptions:**
739
+ >
740
+ > - `did-registry`'s `insertDidDocument` onboards a _new_ DID and requires `did-registry:invite`
741
+ > (a VC-bearing scope, see [`auth`](#auth)), not `did-registry:write` — every other
742
+ > `did-registry` write function uses the default scope shown above.
743
+ > - `track-and-trace`'s `authoriseDid` requires `track-and-trace:authorise` (VC-bearing), and
744
+ > `createDocument`/`commitCreateDocument` require `track-and-trace:create` — every other
745
+ > `track-and-trace` write function (`grantAccess`, `removeDocument`, `revokeAccess`,
746
+ > `writeEvent`) uses the default `track-and-trace:write` shown above.
747
+ >
748
+ > With `--auto-token` and no `--scope`, the CLI picks the right one automatically.
749
+
750
+ With `--auto-token` and no explicit `--scope`, the minted token is always
751
+ **instance-targeted** at the resolved `--to` address (e.g. `did-registry:invite:0xContractAddress`),
752
+ not just the bare family scope shown above — see "Instance targeting" under
753
+ [`auth`](#auth).
754
+
755
+ **Examples:**
756
+
757
+ ```sh
758
+ # Insert a DID document using a pre-obtained token (needs a did-registry:invite-scoped token,
759
+ # with a VerifiableAuthorisationToOnboard VC bound to this wallet's key — see `auth`)
760
+ ebsi ledger write did-registry insertDidDocument \
761
+ '["did:ebsi:z123", "{}", "thumbprint", "0xpubkey", true, 0, 9999999999]' \
762
+ --to 0xContractAddress \
763
+ --token eyJ...
764
+
765
+ # Same, but mint the token automatically (requires a configured key and a VC file;
766
+ # --auto-token derives the required did-registry:invite:<address> scope automatically)
767
+ ebsi ledger write did-registry insertDidDocument \
768
+ '["did:ebsi:z123", "{}", "thumbprint", "0xpubkey", true, 0, 9999999999]' \
769
+ --to 0xContractAddress \
770
+ --vc ./my-credential.jwt \
771
+ --auto-token
772
+
773
+ # Full one-liner: key + auto-token + contract address from env
774
+ export DID_REGISTRY_CONTRACT_ADDRESS=0xContractAddress
775
+ export EBSI_ES256K_PRIVATE_KEY=0xdeadbeef...
776
+ ebsi ledger write did-registry insertDidDocument \
777
+ '["did:ebsi:z123", "{}", "thumbprint", "0xpubkey", true, 0, 9999999999]' \
778
+ --vc ./my-credential.jwt \
779
+ --auto-token
780
+
781
+ # A did-registry write that's NOT insertDidDocument only needs the plain
782
+ # did-registry:write default scope (no VC required)
783
+ ebsi ledger write did-registry addController \
784
+ '["did:ebsi:z123", "0xNewControllerAddress"]' \
785
+ --to 0xContractAddress \
786
+ --auto-token
787
+ ```
788
+
789
+ #### `ledger batch`
790
+
791
+ Send a raw JSON-RPC **batch** request to the Besu node: an array of independent
792
+ requests submitted under a single `Authorization` header and processed in order.
793
+ Besu accepts at most **1024** requests per batch. An entry without an `id` is a
794
+ JSON-RPC _notification_ — it's still processed, but gets no response entry.
795
+
796
+ ```
797
+ ebsi ledger batch <source>
798
+ ```
799
+
800
+ `<source>` is a path to a JSON file containing a JSON array of requests, or `-` to
801
+ read the array from stdin. Each entry: `{"method": "...", "params": [...], "id": ...}`
802
+ (`params` defaults to `[]`, `id` may be omitted).
803
+
804
+ The Bearer token, if any is needed (e.g. the batch includes `eth_sendRawTransaction`
805
+ entries), comes from `--token` / `EBSI_ACCESS_TOKEN` / `ebsi config set token`, same as
806
+ `ledger call`.
807
+
808
+ **Examples:**
809
+
810
+ ```sh
811
+ # batch.json:
812
+ # [
813
+ # {"id": 1, "method": "eth_blockNumber"},
814
+ # {"id": 2, "method": "eth_getBalance", "params": ["0xabc...", "latest"]}
815
+ # ]
816
+ ebsi ledger batch ./batch.json
817
+
818
+ # Pipe a batch in from stdin
819
+ echo '[{"id": 1, "method": "eth_blockNumber"}]' | ebsi ledger batch -
820
+ ```
821
+
822
+ #### `ledger write-batch`
823
+
824
+ Sign several registry writes from one wallet, under one access token, and submit them
825
+ as a **single** JSON-RPC batch request — one round-trip instead of one per write. Each
826
+ write is assigned a sequential nonce so they don't collide. Returns transaction
827
+ hashes, not receipts — use `ledger tx <hash>` afterwards to check status.
828
+
829
+ ```
830
+ ebsi ledger write-batch <file> [options]
831
+ ```
832
+
833
+ `<file>` is a JSON array of write entries, one per transaction — the same shape as
834
+ `ledger write`'s positional args:
835
+
836
+ ```json
837
+ [
838
+ { "registry": "did-registry", "function": "insertDidDocument", "args": [...], "to": "0x..." },
839
+ { "registry": "issuers-registry", "function": "addIssuerProxy", "args": [...], "to": "0x..." }
840
+ ]
841
+ ```
842
+
843
+ `to` is optional per entry and falls back to the registry's address env var, same as
844
+ `ledger write`.
845
+
846
+ **Options:** same as `ledger write` (`--auto-token`, `--scope`, `--vc`, `--key`,
847
+ `--did`, `--gas-limit`, `--gas-price`) — `--gas-limit`/`--gas-price`, when given, apply
848
+ to **every** entry in the batch; by default each entry's gas limit is estimated
849
+ independently and fees are resolved once for the whole batch. Unlike `ledger write`,
850
+ an entry whose gas estimation fails doesn't fail the whole batch — a batch entry can
851
+ legitimately only become valid once an earlier entry in the same batch has been
852
+ mined, so a warning is printed and a generous default gas limit is used for that
853
+ entry instead. With `--auto-token` and no `--scope`, the CLI derives the **minimal
854
+ multi-scope token** covering every distinct registry referenced in the batch, each
855
+ instance-targeted at its entry's resolved contract address (e.g. a batch writing to
856
+ `did-registry` at `0xDidContractAddress` and `issuers-registry` at
857
+ `0xIssuersContractAddress` mints `"did-registry:write:0xDidContractAddress
858
+ issuers-registry:write:0xIssuersContractAddress"`) — one token, one round-trip, instead of minting
859
+ one per registry. This only works when every entry's default scope is combinable (see
860
+ [`auth`](#auth)) — a batch containing `insertDidDocument` (which needs the
861
+ non-combinable `did-registry:invite`) can't use `--auto-token` without an explicit
862
+ `--scope`/`--token` covering just that one write.
863
+
864
+ **Examples:**
865
+
866
+ ```sh
867
+ # writes.json:
868
+ # [
869
+ # { "registry": "did-registry", "function": "addController",
870
+ # "args": ["did:ebsi:z123", "0xNewControllerAddress"],
871
+ # "to": "0xDidContractAddress" },
872
+ # { "registry": "issuers-registry", "function": "addIssuerProxy",
873
+ # "args": ["did:ebsi:z123", "0xhash"], "to": "0xIssuersContractAddress" }
874
+ # ]
875
+
876
+ # Mint one multi-scope token covering both registries and submit both writes together
877
+ ebsi --es256k-key 0xdeadbeef... ledger write-batch ./writes.json --auto-token
878
+ ```
879
+
880
+ ---
881
+
882
+ ## Read commands
883
+
884
+ Every read command below (`did-registry`, `schemas-registry`, `issuers-registry`,
885
+ `policies-registry`, `timestamp`, `track-and-trace`, `contracts-registry`) accepts a
886
+ `--contract-address <address>` option. If omitted, it defaults to the **same
887
+ address env var used by `ledger write`** for that registry (see the table under
888
+ [`ledger write`](#ledger-write)) — e.g. `did-registry identifiers list` defaults to
889
+ `DID_REGISTRY_CONTRACT_ADDRESS` if set. This keeps reads and writes pointed at the
890
+ same contract instance within one environment, but it also means an env var set
891
+ only to pick a signing target for `ledger write` will silently redirect reads too;
892
+ pass `--contract-address` explicitly on a read command to override it for that call
893
+ only. `contracts-registry` has no write path, so its `contracts`/`templates`
894
+ sub-resources instead default from `PROXY_FACTORY_CONTRACT_ADDRESS` and
895
+ `PROXY_TEMPLATES_REGISTRY_CONTRACT_ADDRESS` respectively (the API's own config keys for that
896
+ domain). If none of the flag, env var, or persisted config apply, the API's own
897
+ configured default address is used.
898
+
899
+ ### `did-registry`
900
+
901
+ ```
902
+ ebsi did-registry identifiers list [--page-after <cursor>] [--page-size <n>] [--controller <did>]
903
+ [--verification-method-id <id>] [--verification-relationship <rel>]
904
+ ebsi did-registry identifiers get <did> [--valid-at <date>]
905
+ ebsi did-registry abi
906
+ ```
907
+
908
+ | Command | Description |
909
+ | ----------------------- | -------------------------------------------------------------------------------------------------------------------------- |
910
+ | `identifiers list` | List all EBSI DIDs. Supports pagination and filtering by controller, verification method id, or verification relationship. |
911
+ | `identifiers get <did>` | Resolve a DID document. Use `--valid-at <ISO-8601>` to retrieve a historical version. |
912
+ | `abi` | Get the ABI of the DID Registry smart contract. |
913
+
914
+ **`identifiers list` filter options:**
915
+
916
+ | Flag | Description |
917
+ | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
918
+ | `--controller <did>` | Filter by controller DID. |
919
+ | `--verification-method-id <id>` | Filter by verification method id (e.g. `did:ebsi:z...#key-1`). |
920
+ | `--verification-relationship <rel>` | Filter by verification relationship: `authentication`, `assertionMethod`, `keyAgreement`, `capabilityInvocation`, or `capabilityDelegation`. |
921
+
922
+ ---
923
+
924
+ ### `schemas-registry`
925
+
926
+ ```
927
+ ebsi schemas-registry schemas list [--page-after <cursor>] [--page-size <n>]
928
+ ebsi schemas-registry schemas get <schemaId>
929
+ ebsi schemas-registry schemas revisions <schemaId> [--page-after <cursor>] [--page-size <n>]
930
+ ebsi schemas-registry schemas revision <schemaId> <schemaRevisionId>
931
+ ebsi schemas-registry schemas metadata list <schemaId> <schemaRevisionId> [--page-after <cursor>] [--page-size <n>]
932
+ ebsi schemas-registry schemas metadata get <schemaId> <schemaRevisionId> <metadataId>
933
+ ebsi schemas-registry abi
934
+ ```
935
+
936
+ | Command | Description |
937
+ | ----------------------------------------------------------------- | --------------------------------------------------- |
938
+ | `schemas list` | List all trusted schemas on the EBSI ledger. |
939
+ | `schemas get <schemaId>` | Get a schema by its ID. |
940
+ | `schemas revisions <schemaId>` | List all revisions of a schema. |
941
+ | `schemas revision <schemaId> <schemaRevisionId>` | Get a specific revision of a schema. |
942
+ | `schemas metadata list <schemaId> <schemaRevisionId>` | List metadata for a schema revision. |
943
+ | `schemas metadata get <schemaId> <schemaRevisionId> <metadataId>` | Get metadata for a schema revision. |
944
+ | `abi` | Get the ABI of the Schemas Registry smart contract. |
945
+
946
+ ---
947
+
948
+ ### `issuers-registry`
949
+
950
+ ```
951
+ ebsi issuers-registry issuers list [--page-after <cursor>] [--page-size <n>]
952
+ ebsi issuers-registry issuers get <did>
953
+ ebsi issuers-registry issuers attributes list <did> [--page-after <cursor>] [--page-size <n>]
954
+ ebsi issuers-registry issuers attributes get <did> <attributeId>
955
+ ebsi issuers-registry issuers attributes revisions <did> <attributeId> [--page-after <cursor>] [--page-size <n>]
956
+ ebsi issuers-registry issuers attributes revision <did> <attributeId> <revisionId>
957
+ ebsi issuers-registry issuers proxies list <did> [--page-after <cursor>] [--page-size <n>]
958
+ ebsi issuers-registry issuers proxies get <did> <proxyId>
959
+ ebsi issuers-registry issuers proxies content <did> <proxyId> <path>
960
+ ebsi issuers-registry abi
961
+ ```
962
+
963
+ | Command | Description |
964
+ | -------------------------------------------------------------- | ------------------------------------------------------- |
965
+ | `issuers list` | List trusted issuers on the EBSI ledger. |
966
+ | `issuers get <did>` | Get an issuer by DID. |
967
+ | `issuers attributes list <did>` | List attributes for an issuer. |
968
+ | `issuers attributes get <did> <attributeId>` | Get an attribute for an issuer. |
969
+ | `issuers attributes revisions <did> <attributeId>` | List revisions of an issuer attribute. |
970
+ | `issuers attributes revision <did> <attributeId> <revisionId>` | Get a specific revision of an issuer attribute. |
971
+ | `issuers proxies list <did>` | List proxy data for an issuer. |
972
+ | `issuers proxies get <did> <proxyId>` | Get a proxy for an issuer. |
973
+ | `issuers proxies content <did> <proxyId> <path>` | Get a status list credential through an issuer's proxy. |
974
+ | `abi` | Get the ABI of the Issuers Registry smart contract. |
975
+
976
+ ---
977
+
978
+ ### `policies-registry`
979
+
980
+ ```
981
+ ebsi policies-registry policies list [--page-after <cursor>] [--page-size <n>]
982
+ ebsi policies-registry policies get <policyName>
983
+ ebsi policies-registry subjects list [--page-after <cursor>] [--page-size <n>]
984
+ ebsi policies-registry subjects get <subject>
985
+ ebsi policies-registry subjects policies <subject> [--page-after <cursor>] [--page-size <n>]
986
+ ebsi policies-registry subjects policy <subject> <policyName>
987
+ ebsi policies-registry abi
988
+ ```
989
+
990
+ | Command | Description |
991
+ | ---------------------------------------- | ------------------------------------------------------ |
992
+ | `policies list` | List all policies on the EBSI ledger. |
993
+ | `policies get <policyName>` | Get a policy by name (e.g. `VerifiableAuthorisation`). |
994
+ | `subjects list` | List all subjects with assigned policies. |
995
+ | `subjects get <subject>` | Get a subject by DID. |
996
+ | `subjects policies <subject>` | List all policies assigned to a subject DID. |
997
+ | `subjects policy <subject> <policyName>` | Get a specific policy assigned to a subject. |
998
+ | `abi` | Get the ABI of the Policies Registry smart contract. |
999
+
1000
+ ---
1001
+
1002
+ ### `timestamp`
1003
+
1004
+ ```
1005
+ ebsi timestamp timestamps list [--page-after <cursor>] [--page-size <n>]
1006
+ ebsi timestamp timestamps get <timestampId>
1007
+ ebsi timestamp records list [--page-after <cursor>] [--page-size <n>]
1008
+ ebsi timestamp records get <recordId>
1009
+ ebsi timestamp records versions <recordId> [--page-after <cursor>] [--page-size <n>]
1010
+ ebsi timestamp records version <recordId> <versionId>
1011
+ ebsi timestamp hash-algorithms list [--page-after <cursor>] [--page-size <n>]
1012
+ ebsi timestamp hash-algorithms get <hashAlgorithmId>
1013
+ ebsi timestamp abi
1014
+ ```
1015
+
1016
+ | Command | Description |
1017
+ | ---------------------------------------- | ------------------------------------------------ |
1018
+ | `timestamps list` | List timestamps on the EBSI ledger. |
1019
+ | `timestamps get <timestampId>` | Get a timestamp by its ID. |
1020
+ | `records list` | List timestamp records. |
1021
+ | `records get <recordId>` | Get a timestamp record by ID. |
1022
+ | `records versions <recordId>` | List all versions of a timestamp record. |
1023
+ | `records version <recordId> <versionId>` | Get a specific version of a timestamp record. |
1024
+ | `hash-algorithms list` | List supported hash algorithms for timestamping. |
1025
+ | `hash-algorithms get <hashAlgorithmId>` | Get a hash algorithm by its ID. |
1026
+ | `abi` | Get the ABI of the Timestamp smart contract. |
1027
+
1028
+ ---
1029
+
1030
+ ### `track-and-trace`
1031
+
1032
+ ```
1033
+ ebsi track-and-trace documents list [--page-after <cursor>] [--page-size <n>]
1034
+ ebsi track-and-trace documents get <documentId>
1035
+ ebsi track-and-trace documents events <documentId> [--page-after <cursor>] [--page-size <n>]
1036
+ ebsi track-and-trace documents event <documentId> <eventId>
1037
+ ebsi track-and-trace documents accesses <documentId> [--page-after <cursor>] [--page-size <n>]
1038
+ ebsi track-and-trace accesses get <subject>
1039
+ ebsi track-and-trace accesses check <creator>
1040
+ ebsi track-and-trace abi
1041
+ ```
1042
+
1043
+ | Command | Description |
1044
+ | ---------------------------------------- | --------------------------------------------------------- |
1045
+ | `documents list` | List all Track and Trace documents. |
1046
+ | `documents get <documentId>` | Get a document by ID. |
1047
+ | `documents events <documentId>` | List events for a document. |
1048
+ | `documents event <documentId> <eventId>` | Get an event for a document. |
1049
+ | `documents accesses <documentId>` | List accesses for a document. |
1050
+ | `accesses get <subject>` | Get access control entries for a subject DID. |
1051
+ | `accesses check <creator>` | Check whether a DID is allowlisted as a document creator. |
1052
+ | `abi` | Get the ABI of the Track and Trace smart contract. |
1053
+
1054
+ ---
1055
+
1056
+ ### `contracts-registry`
1057
+
1058
+ ```
1059
+ ebsi contracts-registry contracts list [--page-after <cursor>] [--page-size <n>]
1060
+ ebsi contracts-registry contracts get <address>
1061
+ ebsi contracts-registry templates list [--page-after <cursor>] [--page-size <n>]
1062
+ ebsi contracts-registry templates get <id>
1063
+ ebsi contracts-registry abi
1064
+ ```
1065
+
1066
+ | Command | Description |
1067
+ | ------------------------- | ----------------------------------------------------- |
1068
+ | `contracts list` | List smart contracts in the EBSI Contracts Registry. |
1069
+ | `contracts get <address>` | Get a contract by its hex address. |
1070
+ | `templates list` | List contract templates. |
1071
+ | `templates get <id>` | Get a contract template by ID. |
1072
+ | `abi` | Get the ABI of the Contracts Registry smart contract. |
1073
+
1074
+ ---
1075
+
1076
+ ## Pagination
1077
+
1078
+ List commands that return paginated results accept these options:
1079
+
1080
+ | Option | Description |
1081
+ | ----------------------- | ------------------------------------------------------------------------- |
1082
+ | `--page-after <cursor>` | Cursor for the next page (value of `links.next` from a previous response) |
1083
+ | `--page-size <n>` | Maximum items per page |
1084
+
1085
+ ```sh
1086
+ # First page
1087
+ ebsi did-registry identifiers list --page-size 10
1088
+
1089
+ # Next page (use the cursor from the previous response's `links.next`)
1090
+ ebsi did-registry identifiers list --page-size 10 --page-after eyJhbGciOi...
1091
+ ```
1092
+
1093
+ ## Scripting examples
1094
+
1095
+ ```sh
1096
+ # Count DIDs on the pilot network
1097
+ ebsi --env pilot --output json did-registry identifiers list | jq '.total'
1098
+
1099
+ # Extract all trusted issuer DIDs
1100
+ ebsi --output json issuers-registry issuers list | jq -r '.items[].did'
1101
+
1102
+ # Check health, exit 1 on failure (useful in CI)
1103
+ ebsi --output json health | jq -e '.status == "ok"'
1104
+
1105
+ # Persist pilot as default, then query without flags
1106
+ ebsi config set env pilot
1107
+ ebsi did-registry identifiers list
1108
+
1109
+ # End-to-end DID write: generate key, get token, add a controller to an existing DID
1110
+ ebsi wallet create --save
1111
+ ebsi auth token --scope did-registry:write --save
1112
+ ebsi ledger write did-registry addController \
1113
+ '["did:ebsi:z123", "0xNewControllerAddress"]' \
1114
+ --to 0xContractAddress
1115
+
1116
+ # Same, in a single command using --auto-token
1117
+ ebsi --es256k-key 0xdeadbeef... ledger write did-registry addController \
1118
+ '["did:ebsi:z123", "0xNewControllerAddress"]' \
1119
+ --to 0xContractAddress \
1120
+ --auto-token
1121
+ ```
1122
+
1123
+ ## Development
1124
+
1125
+ ```sh
1126
+ # Install dependencies
1127
+ pnpm install
1128
+
1129
+ # Regenerate API types from openapi.yaml
1130
+ pnpm --filter @europeum-ebsi/cli gen:api-types
1131
+
1132
+ # Build
1133
+ pnpm --filter @europeum-ebsi/cli build
1134
+
1135
+ # Run tests
1136
+ pnpm --filter @europeum-ebsi/cli test:ci
1137
+
1138
+ # Lint
1139
+ pnpm --filter @europeum-ebsi/cli lint
1140
+ ```