@cef-ebsi/cli 1.3.2 → 1.4.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 (187) hide show
  1. package/bin/cli.js +1 -1
  2. package/dist/abi/pilot/DidRegistry.js +568 -0
  3. package/dist/abi/pilot/DidRegistry.js.map +1 -0
  4. package/dist/abi/pilot/SchemaSCRegistry.js +264 -0
  5. package/dist/abi/pilot/SchemaSCRegistry.js.map +1 -0
  6. package/dist/abi/pilot/Timestamp.js +658 -0
  7. package/dist/abi/pilot/Timestamp.js.map +1 -0
  8. package/dist/abi/pilot/Tir.js +428 -0
  9. package/dist/abi/pilot/Tir.js.map +1 -0
  10. package/dist/abi/pilot/TnT.js +842 -0
  11. package/dist/abi/pilot/TnT.js.map +1 -0
  12. package/dist/abi/pilot/Tpr.js +492 -0
  13. package/dist/abi/pilot/Tpr.js.map +1 -0
  14. package/dist/abi/test/DidRegistry.js +144 -658
  15. package/dist/abi/test/DidRegistry.js.map +1 -1
  16. package/dist/abi/test/SchemaSCRegistry.js +101 -810
  17. package/dist/abi/test/SchemaSCRegistry.js.map +1 -1
  18. package/dist/abi/test/Timestamp.js +239 -673
  19. package/dist/abi/test/Timestamp.js.map +1 -1
  20. package/dist/abi/test/Tir.js +167 -636
  21. package/dist/abi/test/Tir.js.map +1 -1
  22. package/dist/abi/test/TnT.js +842 -0
  23. package/dist/abi/test/TnT.js.map +1 -0
  24. package/dist/abi/test/Tpr.js +166 -942
  25. package/dist/abi/test/Tpr.js.map +1 -1
  26. package/dist/app.js +444 -443
  27. package/dist/app.js.map +1 -1
  28. package/dist/buildParam/{didV3.js → didr.js} +182 -204
  29. package/dist/buildParam/didr.js.map +1 -0
  30. package/dist/buildParam/index.js +32 -48
  31. package/dist/buildParam/index.js.map +1 -1
  32. package/dist/buildParam/{timestampV2.js → timestamp.js} +137 -136
  33. package/dist/buildParam/timestamp.js.map +1 -0
  34. package/dist/buildParam/{tirV3.js → tir.js} +57 -59
  35. package/dist/buildParam/tir.js.map +1 -0
  36. package/dist/buildParam/{tntV2.js → tnt.js} +62 -61
  37. package/dist/buildParam/tnt.js.map +1 -0
  38. package/dist/buildParam/{tprV2.js → tpr.js} +34 -33
  39. package/dist/buildParam/tpr.js.map +1 -0
  40. package/dist/buildParam/{tsrV2.js → tsr.js} +39 -38
  41. package/dist/buildParam/tsr.js.map +1 -0
  42. package/dist/cli.js +1 -0
  43. package/dist/cli.js.map +1 -1
  44. package/dist/commands/{authorisation-v4.js → authorisation.js} +78 -71
  45. package/dist/commands/authorisation.js.map +1 -0
  46. package/dist/commands/compute.js +389 -389
  47. package/dist/commands/compute.js.map +1 -1
  48. package/dist/commands/{conformance-v3.js → conformance.js} +236 -248
  49. package/dist/commands/conformance.js.map +1 -0
  50. package/dist/commands/hardwarewallet.js +5 -5
  51. package/dist/commands/hardwarewallet.js.map +1 -1
  52. package/dist/commands/index.js +4 -4
  53. package/dist/commands/index.js.map +1 -1
  54. package/dist/commands/{ledger-v4.js → ledger.js} +141 -128
  55. package/dist/commands/ledger.js.map +1 -0
  56. package/dist/commands/tnl.js +10 -9
  57. package/dist/commands/tnl.js.map +1 -1
  58. package/dist/commands/tsr.js +46 -0
  59. package/dist/commands/tsr.js.map +1 -0
  60. package/dist/commands/view.js +8 -8
  61. package/dist/commands/view.js.map +1 -1
  62. package/dist/config.js +280 -279
  63. package/dist/config.js.map +1 -1
  64. package/dist/index.js +3 -3
  65. package/dist/index.js.map +1 -1
  66. package/dist/interfaces/index.js +1 -1
  67. package/dist/interfaces/index.js.map +1 -1
  68. package/dist/programs/migrateDid.js +33 -33
  69. package/dist/programs/migrateDid.js.map +1 -1
  70. package/dist/programs/migrateDids.js +39 -42
  71. package/dist/programs/migrateDids.js.map +1 -1
  72. package/dist/programs/migrateTsr.js +109 -113
  73. package/dist/programs/migrateTsr.js.map +1 -1
  74. package/dist/scripts/accreditAndAuthorize/conformance/step1 +1 -1
  75. package/dist/scripts/accreditAndAuthorize/test/step1 +1 -1
  76. package/dist/scripts/accreditTI +1 -1
  77. package/dist/scripts/assets/CTRevocableCredential.json +1 -1
  78. package/dist/scripts/assets/CredentialToAttestVerifiableAuthorisationForTrustChain.json +2 -2
  79. package/dist/scripts/assets/TrustedNodesList.json +1 -1
  80. package/dist/scripts/assets/VerifiableAccreditationToAccredit.json +2 -2
  81. package/dist/scripts/assets/VerifiableAccreditationToAttest.json +2 -2
  82. package/dist/scripts/assets/VerifiableAuthorisationForTrustChain.json +1 -1
  83. package/dist/scripts/assets/VerifiableAuthorisationToOnboard.json +1 -1
  84. package/dist/scripts/bootstrap/6-setupConformanceIssuer +1 -1
  85. package/dist/scripts/issueVcOnboard +1 -1
  86. package/dist/scripts/issueVcRootTAO +1 -1
  87. package/dist/scripts/issueVcTAO +2 -2
  88. package/dist/scripts/issueVcTI +2 -2
  89. package/dist/scripts/issueVcTnl +1 -1
  90. package/dist/scripts/issue_CTRevocableCredential +1 -1
  91. package/dist/scripts/issue_SelfAttestationSupportOffice +2 -2
  92. package/dist/scripts/issue_VerifiableAccreditationToAccredit +2 -2
  93. package/dist/scripts/issue_VerifiableAccreditationToAttest +2 -2
  94. package/dist/scripts/issue_VerifiableAuthorisationForTrustChain +1 -1
  95. package/dist/scripts/issue_VerifiableAuthorisationToOnboard +1 -1
  96. package/dist/scripts/updateVcRootTAO +1 -1
  97. package/dist/scripts/updateVcTAO +2 -2
  98. package/dist/scripts/updateVcTI +2 -2
  99. package/dist/scripts/{wctv3 → wct}/accreditAndAuthorize +1 -1
  100. package/dist/tsconfig.build.tsbuildinfo +1 -0
  101. package/dist/utils/Client.js +81 -68
  102. package/dist/utils/Client.js.map +1 -1
  103. package/dist/utils/HardwareWallet.js +169 -165
  104. package/dist/utils/HardwareWallet.js.map +1 -1
  105. package/dist/utils/http.js +24 -27
  106. package/dist/utils/http.js.map +1 -1
  107. package/dist/utils/index.js +3 -3
  108. package/dist/utils/index.js.map +1 -1
  109. package/dist/utils/jsonrpc.js +14 -14
  110. package/dist/utils/jsonrpc.js.map +1 -1
  111. package/dist/utils/print.js +19 -19
  112. package/dist/utils/print.js.map +1 -1
  113. package/dist/utils/utils.js +180 -173
  114. package/dist/utils/utils.js.map +1 -1
  115. package/package.json +70 -46
  116. package/dist/abi/pilot/DidRegistryV3.js +0 -1082
  117. package/dist/abi/pilot/DidRegistryV3.js.map +0 -1
  118. package/dist/abi/pilot/DidRegistryV4.js +0 -942
  119. package/dist/abi/pilot/DidRegistryV4.js.map +0 -1
  120. package/dist/abi/pilot/SchemaSCRegistryV2.js +0 -474
  121. package/dist/abi/pilot/SchemaSCRegistryV2.js.map +0 -1
  122. package/dist/abi/pilot/TimestampV2.js +0 -1128
  123. package/dist/abi/pilot/TimestampV2.js.map +0 -1
  124. package/dist/abi/pilot/TimestampV3.js +0 -995
  125. package/dist/abi/pilot/TimestampV3.js.map +0 -1
  126. package/dist/abi/pilot/TirV3.js +0 -496
  127. package/dist/abi/pilot/TirV3.js.map +0 -1
  128. package/dist/abi/pilot/TirV4.js +0 -710
  129. package/dist/abi/pilot/TirV4.js.map +0 -1
  130. package/dist/abi/pilot/TnTV1.js +0 -1375
  131. package/dist/abi/pilot/TnTV1.js.map +0 -1
  132. package/dist/abi/pilot/TprV2.js +0 -889
  133. package/dist/abi/pilot/TprV2.js.map +0 -1
  134. package/dist/abi/pilot/TprV3.js +0 -707
  135. package/dist/abi/pilot/TprV3.js.map +0 -1
  136. package/dist/abi/pilot/TsrV3.js +0 -571
  137. package/dist/abi/pilot/TsrV3.js.map +0 -1
  138. package/dist/abi/test/DidRegistryV3.js +0 -1089
  139. package/dist/abi/test/DidRegistryV3.js.map +0 -1
  140. package/dist/abi/test/DidRegistryV4.js +0 -960
  141. package/dist/abi/test/DidRegistryV4.js.map +0 -1
  142. package/dist/abi/test/SchemaSCRegistryV2.js +0 -474
  143. package/dist/abi/test/SchemaSCRegistryV2.js.map +0 -1
  144. package/dist/abi/test/TimestampV2.js +0 -1128
  145. package/dist/abi/test/TimestampV2.js.map +0 -1
  146. package/dist/abi/test/TimestampV3.js +0 -995
  147. package/dist/abi/test/TimestampV3.js.map +0 -1
  148. package/dist/abi/test/TirV3.js +0 -496
  149. package/dist/abi/test/TirV3.js.map +0 -1
  150. package/dist/abi/test/TirV4.js +0 -710
  151. package/dist/abi/test/TirV4.js.map +0 -1
  152. package/dist/abi/test/TnTV1.js +0 -1375
  153. package/dist/abi/test/TnTV1.js.map +0 -1
  154. package/dist/abi/test/TprV2.js +0 -889
  155. package/dist/abi/test/TprV2.js.map +0 -1
  156. package/dist/abi/test/TprV3.js +0 -707
  157. package/dist/abi/test/TprV3.js.map +0 -1
  158. package/dist/abi/test/TsrV3.js +0 -571
  159. package/dist/abi/test/TsrV3.js.map +0 -1
  160. package/dist/buildParam/didV3.js.map +0 -1
  161. package/dist/buildParam/didV4.js +0 -326
  162. package/dist/buildParam/didV4.js.map +0 -1
  163. package/dist/buildParam/timestampV2.js.map +0 -1
  164. package/dist/buildParam/timestampV3.js +0 -317
  165. package/dist/buildParam/timestampV3.js.map +0 -1
  166. package/dist/buildParam/tirV3.js.map +0 -1
  167. package/dist/buildParam/tirV4.js +0 -119
  168. package/dist/buildParam/tirV4.js.map +0 -1
  169. package/dist/buildParam/tntV1.js +0 -185
  170. package/dist/buildParam/tntV1.js.map +0 -1
  171. package/dist/buildParam/tntV2.js.map +0 -1
  172. package/dist/buildParam/tprV2.js.map +0 -1
  173. package/dist/buildParam/tprV3.js +0 -82
  174. package/dist/buildParam/tprV3.js.map +0 -1
  175. package/dist/buildParam/tsrV2.js.map +0 -1
  176. package/dist/buildParam/tsrV3.js +0 -110
  177. package/dist/buildParam/tsrV3.js.map +0 -1
  178. package/dist/commands/authorisation-v4.js.map +0 -1
  179. package/dist/commands/authorisation-v5.js +0 -119
  180. package/dist/commands/authorisation-v5.js.map +0 -1
  181. package/dist/commands/conformance-v3.js.map +0 -1
  182. package/dist/commands/ledger-v4.js.map +0 -1
  183. package/dist/tsconfig.tsbuildinfo +0 -1
  184. /package/dist/scripts/{wctv3 → wct}/holderWallet +0 -0
  185. /package/dist/scripts/{wctv3 → wct}/issueToHolder +0 -0
  186. /package/dist/scripts/{wctv3 → wct}/pda1 +0 -0
  187. /package/dist/scripts/{wctv3 → wct}/verifier +0 -0
@@ -1,271 +1,29 @@
1
- import { randomUUID, randomBytes, createHash, } from "node:crypto";
2
- import Multihash from "multihashes";
3
- import { ethers } from "ethers";
4
- import { base64url, calculateJwkThumbprint } from "jose";
5
1
  import { util } from "@cef-ebsi/ebsi-did-resolver";
6
- import Joi from "joi";
7
- import { decodeJWT } from "did-jwt";
8
2
  import { ValidationError, verifyCredentialJwt, } from "@cef-ebsi/verifiable-credential";
9
3
  import { verifyPresentationJwt, } from "@cef-ebsi/verifiable-presentation";
10
4
  import { EbsiWallet } from "@cef-ebsi/wallet-lib";
11
- import { formatEthersUnsignedTransaction, removePrefix0x, yellow, red, computeSchemaId, multibaseEncode, encodePublicKey, encodePrivateKey, } from "../utils/index.js";
12
- import { ledgerGetTransaction, ledgerGetTransactionReceipt, } from "./ledger-v4.js";
13
- export function getUserPin(did) {
14
- return createHash("sha256")
15
- .update(did)
16
- .digest()
17
- .slice(-4)
18
- .map((byte) => byte % 10)
19
- .reduce((acc, digit) => `${acc}${digit}`, "");
20
- }
21
- export async function computeVerifyVcJwt(inputs, context) {
22
- const [vcJwt, options, expectedResult] = inputs;
23
- const ebsiEnvConfig = {
24
- hosts: [context.config.domain.replace(/^https?:\/\//, "")],
25
- scheme: "ebsi",
26
- network: {
27
- name: context.config.env,
28
- isOptional: false,
29
- },
30
- services: {
31
- "did-registry": context.config.api.did.version,
32
- "trusted-issuers-registry": context.config.api.tir.version,
33
- "trusted-policies-registry": context.config.api.tpr.version,
34
- "trusted-schemas-registry": context.config.api.tsr.version,
35
- },
36
- };
37
- try {
38
- await verifyCredentialJwt(vcJwt, ebsiEnvConfig, options);
39
- switch (expectedResult) {
40
- case "expectRevoked": {
41
- throw new Error("Credential is not revoked");
42
- }
43
- default:
44
- return "Verifiable Credential is valid";
45
- }
46
- }
47
- catch (error) {
48
- if (expectedResult === "expectRevoked") {
49
- if (error.message === "Credential is not revoked")
50
- throw error;
51
- if (error.message.includes("revoked")) {
52
- return "Verifiable Credential is revoked";
53
- }
54
- }
55
- throw error;
56
- }
57
- }
58
- export async function computeVerifyVpJwt(inputs, context) {
59
- const [vpJwt, audience, options] = inputs;
60
- const ebsiEnvConfig = {
61
- hosts: [context.config.domain.replace(/^https?:\/\//, "")],
62
- scheme: "ebsi",
63
- network: {
64
- name: context.config.env,
65
- isOptional: false,
66
- },
67
- services: {
68
- "did-registry": context.config.api.did.version,
69
- "trusted-issuers-registry": context.config.api.tir.version,
70
- "trusted-policies-registry": context.config.api.tpr.version,
71
- "trusted-schemas-registry": context.config.api.tsr.version,
72
- },
73
- };
74
- await verifyPresentationJwt(vpJwt, audience, ebsiEnvConfig, options);
75
- return "Verifiable Presentation is valid";
76
- }
77
- export function sha256(data) {
78
- let hash = createHash("sha256");
79
- if (data.startsWith("0x")) {
80
- hash = hash.update(removePrefix0x(data), "hex");
81
- }
82
- else {
83
- hash = hash.update(data, "utf8");
84
- }
85
- return hash.digest().toString("hex");
86
- }
87
- export function getProperties(input) {
88
- return Object.keys(input)
89
- .filter((key) => Number.isNaN(Number(key)))
90
- .reduce((obj, key) => {
91
- /* eslint-disable-next-line no-param-reassign */
92
- obj[key] = input[key];
93
- return obj;
94
- }, {});
95
- }
96
- export function getApiByContractId(contractId, context) {
97
- const apiName = Object.keys(context.config.api).find((a) => {
98
- const api = context.config.api[a];
99
- return (api.contract &&
100
- contractId.toLowerCase() === api.contract.address.toLowerCase());
101
- });
102
- if (!apiName)
103
- throw new Error(`cannot get API with address ${contractId}`);
104
- return context.config.api[apiName];
105
- }
106
- export function decodeLog(log, context) {
107
- const api = getApiByContractId(log.address, context);
108
- const logDecoded = api.contract.interface.parseLog(log);
109
- const { name, signature, topic, args: argsWithArray } = logDecoded;
110
- const args = getProperties(argsWithArray);
111
- return { name, signature, topic, args };
112
- }
113
- export async function decodeLogs(input, context) {
114
- if (!input)
115
- throw new Error("Invalid logs: no input provided");
116
- let receipt;
117
- let logs;
118
- if (typeof input === "string") {
119
- receipt = await ledgerGetTransactionReceipt([input], false, context);
120
- }
121
- if (input.receipt) {
122
- receipt = input.receipt;
123
- }
124
- if (input.logs) {
125
- receipt = input;
126
- }
127
- if (receipt) {
128
- if (!Array.isArray(receipt.logs)) {
129
- throw new Error("Invalid logs: The input must be a transaction hash, a transaction receipt, or an array of logs");
130
- }
131
- logs = receipt.logs;
132
- }
133
- else {
134
- if (!Array.isArray(input)) {
135
- throw new Error("Invalid logs: The input must be a transaction hash, a transaction receipt, or an array of logs");
136
- }
137
- logs = input;
138
- }
139
- return logs.map((log) => decodeLog(log, context));
140
- }
141
- export async function decodeTransaction(tx, context) {
142
- let txData;
143
- if (typeof tx === "string") {
144
- txData = (await ledgerGetTransaction([tx], false, context));
145
- }
146
- else {
147
- txData = tx;
148
- }
149
- if (!txData.data && !txData.input) {
150
- throw new Error("Invalid transaction: There is no input or data");
151
- }
152
- const api = getApiByContractId(txData.to, context);
153
- const { args, functionFragment } = api.contract.interface.parseTransaction({
154
- data: (txData.data || txData.input),
155
- });
156
- return { name: functionFragment.name, args: getProperties(args) };
157
- }
5
+ import { decodeJWT } from "did-jwt";
6
+ import { ethers } from "ethers";
7
+ import Joi from "joi";
8
+ import { base64url, calculateJwkThumbprint } from "jose";
9
+ import Multihash from "multihashes";
10
+ import { createHash, randomBytes, randomUUID, } from "node:crypto";
11
+ import { computeSchemaId, encodePrivateKey, encodePublicKey, formatEthersUnsignedTransaction, multibaseEncode, red, removePrefix0x, yellow, } from "../utils/index.js";
12
+ import { ledgerGetTransaction, ledgerGetTransactionReceipt } from "./ledger.js";
158
13
  export async function compute(method, inputs, context) {
159
14
  const { client } = context;
160
15
  switch (method) {
161
- case "signTransaction": {
162
- const unsignedTransaction = inputs[0];
163
- const uTx = formatEthersUnsignedTransaction(JSON.parse(JSON.stringify(unsignedTransaction)));
164
- const sgnTx = await client.ethWallet.signTransaction(uTx);
165
- yellow(sgnTx);
166
- return sgnTx;
167
- }
168
- case "createVpJwt": {
169
- const inputVerifiableCredential = inputs[0];
170
- const payloadVp = inputs[1];
171
- const payloadJwt = inputs[2];
172
- const alg = inputs[3] || "ES256K";
173
- const verifiableCredential = typeof inputVerifiableCredential === "string"
174
- ? [inputVerifiableCredential]
175
- : inputVerifiableCredential;
176
- // NOTE: We cannot use @cef-ebsi/verifiable-presentation library
177
- // because it requires the private key and the CLI tool
178
- // now supports Hardware Wallets, which do not expose private keys.
179
- const now = Math.floor(Date.now() / 1000);
180
- const jti = `urn:did:${randomUUID()}`;
181
- const payload = {
182
- iat: now,
183
- jti,
184
- nbf: now - 60, // 1 minute in the past
185
- exp: now + 120, // 2 minutes in the future
186
- sub: client.did,
187
- iss: client.did,
188
- vp: {
189
- "@context": ["https://www.w3.org/2018/credentials/v1"],
190
- id: jti,
191
- type: ["VerifiablePresentation"],
192
- holder: client.did,
193
- verifiableCredential,
194
- ...payloadVp,
195
- },
196
- aud: "any",
197
- nonce: randomUUID(),
198
- ...payloadJwt,
199
- };
200
- const vp = await client.signJWT(payload, {}, alg);
201
- yellow(vp);
202
- return vp;
203
- }
204
- case "createVcJwt": {
205
- const payloadVc = inputs[0];
206
- const payloadJwt = inputs[1];
207
- const alg = (inputs[2] || "ES256K");
208
- Joi.assert(alg, Joi.string().valid("ES256K", "ES256", "RS256", "EdDSA").required());
209
- const iat = Math.floor(Date.now() / 1000) - 10;
210
- const exp = iat + 5 * 365 * 24 * 3600;
211
- const issuanceDate = `${new Date(iat * 1000)
212
- .toISOString()
213
- .slice(0, -5)}Z`;
214
- const expirationDate = `${new Date(exp * 1000)
215
- .toISOString()
216
- .slice(0, -5)}Z`;
217
- const jti = payloadVc.id || `urn:uuid:${randomUUID()}`;
218
- const sub = payloadVc.credentialSubject?.id;
219
- const payload = {
220
- iat,
221
- jti,
222
- nbf: iat,
223
- exp,
224
- sub,
225
- iss: client.did,
226
- vc: {
227
- "@context": ["https://www.w3.org/2018/credentials/v1"],
228
- id: jti,
229
- type: ["VerifiableCredential"],
230
- issuer: client.did,
231
- issuanceDate,
232
- issued: issuanceDate,
233
- validFrom: issuanceDate,
234
- expirationDate,
235
- ...payloadVc,
236
- },
237
- ...payloadJwt,
238
- };
239
- const vc = await client.signJWT(payload, {}, alg);
240
- yellow(vc);
241
- return vc;
242
- }
243
- case "signJwt": {
244
- const [payload, alg, headers] = inputs;
245
- const jwt = await client.signJWT(payload, headers, alg);
246
- yellow(jwt);
247
- return jwt;
248
- }
249
- case "wait": {
250
- const [seconds] = inputs;
251
- const milliseconds = Math.round(Number(seconds) * 1000);
252
- console.log(`waiting ${milliseconds / 1000} seconds`);
253
- await new Promise((r) => {
254
- setTimeout(r, milliseconds);
255
- });
256
- return 0;
257
- }
258
- case "userPin": {
259
- const [did] = inputs;
260
- const userPin = getUserPin(did);
261
- yellow(userPin);
262
- return userPin;
263
- }
264
- case "schemaId": {
265
- const [schema, base] = inputs;
266
- const schemaId = await computeSchemaId(schema, base);
267
- yellow(schemaId);
268
- return schemaId;
16
+ case "address": {
17
+ const [hexOrJwk] = inputs;
18
+ const publicKeyHex = typeof hexOrJwk === "string"
19
+ ? hexOrJwk
20
+ : encodePublicKey({
21
+ format: "hex",
22
+ key: hexOrJwk,
23
+ });
24
+ const address = ethers.utils.computeAddress(publicKeyHex);
25
+ yellow(address);
26
+ return address;
269
27
  }
270
28
  case "checkStatusList2021CredentialSchema": {
271
29
  const [credential] = inputs;
@@ -279,24 +37,24 @@ export async function compute(method, inputs, context) {
279
37
  .required())
280
38
  .items(Joi.string().uri())
281
39
  .required(),
282
- type: Joi.array()
283
- .ordered(
284
- // First item must be "VerifiableCredential"
285
- Joi.string().valid("VerifiableCredential").required())
286
- .items(
287
- // "StatusList2021Credential" must be present
288
- Joi.string().valid("StatusList2021Credential").required(), Joi.string())
289
- .required(),
290
40
  credentialSubject: Joi.object({
41
+ encodedList: Joi.string().required(),
291
42
  id: Joi.string().uri().required(),
292
- type: Joi.string().valid("StatusList2021").required(),
293
43
  statusPurpose: Joi.string()
294
44
  .valid("revocation", "suspension")
295
45
  .required(),
296
- encodedList: Joi.string().required(),
46
+ type: Joi.string().valid("StatusList2021").required(),
297
47
  })
298
48
  .unknown(true)
299
49
  .required(),
50
+ type: Joi.array()
51
+ .ordered(
52
+ // First item must be "VerifiableCredential"
53
+ Joi.string().valid("VerifiableCredential").required())
54
+ .items(
55
+ // "StatusList2021Credential" must be present
56
+ Joi.string().valid("StatusList2021Credential").required(), Joi.string())
57
+ .required(),
300
58
  })
301
59
  // Allow additional properties
302
60
  .unknown(true));
@@ -346,58 +104,80 @@ export async function compute(method, inputs, context) {
346
104
  yellow(did);
347
105
  return did;
348
106
  }
349
- case "sha256": {
350
- const [data] = inputs;
351
- if (typeof data === "object") {
352
- return sha256(JSON.stringify(data));
353
- }
354
- return sha256(data);
355
- }
356
- case "decodeJWT": {
357
- const jwt = inputs[0];
358
- Joi.assert(jwt, Joi.string());
359
- const decoded = decodeJWT(jwt);
360
- yellow(decoded);
361
- return decoded;
362
- }
363
- case "encodePublicKey": {
364
- const [key, options] = inputs;
365
- Joi.assert(options, Joi.object({
366
- format: Joi.string().valid("jwk", "hex", "pem"),
367
- alg: Joi.string()
368
- .valid("ES256K", "ES256", "RS256", "EdDSA")
369
- .optional(),
370
- }));
371
- const result = encodePublicKey({ key, ...options });
372
- yellow(result);
373
- return result;
374
- }
375
- case "encodePrivateKey": {
376
- const [key, options] = inputs;
377
- Joi.assert(options, Joi.object({
378
- format: Joi.string().valid("jwk", "hex", "pem"),
379
- alg: Joi.string()
380
- .valid("ES256K", "ES256", "RS256", "EdDSA")
381
- .optional(),
382
- type: Joi.string().valid("pkcs1", "pkcs8", "sec1", "spki").optional(),
383
- }));
384
- const result = encodePrivateKey({ key, ...options });
385
- yellow(result);
386
- return result;
387
- }
388
- case "encodeBase64": {
389
- const dec = inputs[0];
390
- Joi.assert(dec, Joi.string());
391
- const encoded = Buffer.from(removePrefix0x(dec), "hex").toString("base64");
392
- yellow(encoded);
393
- return encoded;
107
+ case "createVcJwt": {
108
+ const payloadVc = inputs[0];
109
+ const payloadJwt = inputs[1];
110
+ const alg = (inputs[2] || "ES256K");
111
+ Joi.assert(alg, Joi.string().valid("ES256K", "ES256", "RS256", "EdDSA").required());
112
+ const iat = Math.floor(Date.now() / 1000) - 10;
113
+ const exp = iat + 5 * 365 * 24 * 3600;
114
+ const issuanceDate = `${new Date(iat * 1000)
115
+ .toISOString()
116
+ .slice(0, -5)}Z`;
117
+ const expirationDate = `${new Date(exp * 1000)
118
+ .toISOString()
119
+ .slice(0, -5)}Z`;
120
+ const jti = payloadVc.id || `urn:uuid:${randomUUID()}`;
121
+ const sub = payloadVc.credentialSubject?.id;
122
+ const payload = {
123
+ exp,
124
+ iat,
125
+ iss: client.did,
126
+ jti,
127
+ nbf: iat,
128
+ sub,
129
+ vc: {
130
+ "@context": ["https://www.w3.org/2018/credentials/v1"],
131
+ expirationDate,
132
+ id: jti,
133
+ issuanceDate,
134
+ issued: issuanceDate,
135
+ issuer: client.did,
136
+ type: ["VerifiableCredential"],
137
+ validFrom: issuanceDate,
138
+ ...payloadVc,
139
+ },
140
+ ...payloadJwt,
141
+ };
142
+ const vc = await client.signJWT(payload, {}, alg);
143
+ yellow(vc);
144
+ return vc;
394
145
  }
395
- case "encodeBase64url": {
396
- const dec = inputs[0];
397
- Joi.assert(dec, Joi.string());
398
- const encoded = base64url.encode(Buffer.from(removePrefix0x(dec), "hex"));
399
- yellow(encoded);
400
- return encoded;
146
+ case "createVpJwt": {
147
+ const inputVerifiableCredential = inputs[0];
148
+ const payloadVp = inputs[1];
149
+ const payloadJwt = inputs[2];
150
+ const alg = inputs[3] || "ES256K";
151
+ const verifiableCredential = typeof inputVerifiableCredential === "string"
152
+ ? [inputVerifiableCredential]
153
+ : inputVerifiableCredential;
154
+ // NOTE: We cannot use @cef-ebsi/verifiable-presentation library
155
+ // because it requires the private key and the CLI tool
156
+ // now supports Hardware Wallets, which do not expose private keys.
157
+ const now = Math.floor(Date.now() / 1000);
158
+ const jti = `urn:did:${randomUUID()}`;
159
+ const payload = {
160
+ aud: "any",
161
+ exp: now + 120, // 2 minutes in the future
162
+ iat: now,
163
+ iss: client.did,
164
+ jti,
165
+ nbf: now - 60, // 1 minute in the past
166
+ nonce: randomUUID(),
167
+ sub: client.did,
168
+ vp: {
169
+ "@context": ["https://www.w3.org/2018/credentials/v1"],
170
+ holder: client.did,
171
+ id: jti,
172
+ type: ["VerifiablePresentation"],
173
+ verifiableCredential,
174
+ ...payloadVp,
175
+ },
176
+ ...payloadJwt,
177
+ };
178
+ const vp = await client.signJWT(payload, {}, alg);
179
+ yellow(vp);
180
+ return vp;
401
181
  }
402
182
  case "decodeBase64": {
403
183
  const enc = inputs[0];
@@ -431,26 +211,84 @@ export async function compute(method, inputs, context) {
431
211
  yellow(decoded);
432
212
  return decoded;
433
213
  }
214
+ case "decodeJWT": {
215
+ const jwt = inputs[0];
216
+ Joi.assert(jwt, Joi.string());
217
+ const decoded = decodeJWT(jwt);
218
+ yellow(decoded);
219
+ return decoded;
220
+ }
434
221
  case "decodeLogs": {
435
222
  const logs = inputs[0];
436
223
  const logsDecoded = await decodeLogs(logs, context);
437
224
  yellow(logsDecoded);
438
225
  return logsDecoded;
439
226
  }
440
- case "decodeTransaction": {
441
- const tx = inputs[0];
442
- const txDecoded = await decodeTransaction(tx, context);
443
- yellow(txDecoded);
444
- return txDecoded;
227
+ case "decodeTransaction": {
228
+ const tx = inputs[0];
229
+ const txDecoded = await decodeTransaction(tx, context);
230
+ yellow(txDecoded);
231
+ return txDecoded;
232
+ }
233
+ case "encodeBase64": {
234
+ const dec = inputs[0];
235
+ Joi.assert(dec, Joi.string());
236
+ const encoded = Buffer.from(removePrefix0x(dec), "hex").toString("base64");
237
+ yellow(encoded);
238
+ return encoded;
239
+ }
240
+ case "encodeBase64url": {
241
+ const dec = inputs[0];
242
+ Joi.assert(dec, Joi.string());
243
+ const encoded = base64url.encode(Buffer.from(removePrefix0x(dec), "hex"));
244
+ yellow(encoded);
245
+ return encoded;
246
+ }
247
+ case "encodePrivateKey": {
248
+ const [key, options] = inputs;
249
+ Joi.assert(options, Joi.object({
250
+ alg: Joi.string()
251
+ .valid("ES256K", "ES256", "RS256", "EdDSA")
252
+ .optional(),
253
+ format: Joi.string().valid("jwk", "hex", "pem"),
254
+ type: Joi.string().valid("pkcs1", "pkcs8", "sec1", "spki").optional(),
255
+ }));
256
+ const result = encodePrivateKey({ key, ...options });
257
+ yellow(result);
258
+ return result;
259
+ }
260
+ case "encodePublicKey": {
261
+ const [key, options] = inputs;
262
+ Joi.assert(options, Joi.object({
263
+ alg: Joi.string()
264
+ .valid("ES256K", "ES256", "RS256", "EdDSA")
265
+ .optional(),
266
+ format: Joi.string().valid("jwk", "hex", "pem"),
267
+ }));
268
+ const result = encodePublicKey({ key, ...options });
269
+ yellow(result);
270
+ return result;
271
+ }
272
+ case "epochtime": {
273
+ let result;
274
+ if (!inputs[0])
275
+ result = Math.round(Date.now() / 1000);
276
+ else if (typeof inputs[0] === "string")
277
+ result = Math.round(new Date(inputs[0]).getTime() / 1000);
278
+ else
279
+ result = new Date(inputs[0] * 1000).toISOString();
280
+ yellow(result);
281
+ return result;
282
+ }
283
+ case "length": {
284
+ const [array] = inputs;
285
+ Joi.assert(array, Joi.array());
286
+ const len = array.length;
287
+ yellow(len);
288
+ return len;
445
289
  }
446
- case "timestampId": {
447
- const hash = inputs[0];
448
- Joi.assert(hash, Joi.string());
449
- const bufferSha256 = Buffer.from(sha256(hash), "hex");
450
- const multihash = Multihash.encode(bufferSha256, "sha2-256", 32);
451
- const timestampId = `u${base64url.encode(multihash)}`;
452
- yellow(timestampId);
453
- return timestampId;
290
+ case "randomID": {
291
+ return randomBytes(32).toString("hex");
454
292
  }
455
293
  case "recordId": {
456
294
  const [address, blockNumber, hashValue] = inputs;
@@ -461,37 +299,33 @@ export async function compute(method, inputs, context) {
461
299
  yellow(recordId);
462
300
  return recordId;
463
301
  }
464
- case "randomID": {
465
- return randomBytes(32).toString("hex");
302
+ case "schemaId": {
303
+ const [schema, base] = inputs;
304
+ const schemaId = await computeSchemaId(schema, base);
305
+ yellow(schemaId);
306
+ return schemaId;
466
307
  }
467
- case "length": {
468
- const [array] = inputs;
469
- Joi.assert(array, Joi.array());
470
- const len = array.length;
471
- yellow(len);
472
- return len;
308
+ case "sha256": {
309
+ const [data] = inputs;
310
+ if (typeof data === "object") {
311
+ return sha256(JSON.stringify(data));
312
+ }
313
+ return sha256(data);
473
314
  }
474
- case "epochtime": {
475
- let result;
476
- if (!inputs[0])
477
- result = Math.round(Date.now() / 1000);
478
- else if (typeof inputs[0] === "string")
479
- result = Math.round(new Date(inputs[0]).getTime() / 1000);
480
- else
481
- result = new Date(inputs[0] * 1000).toISOString();
482
- yellow(result);
483
- return result;
315
+ case "signJwt": {
316
+ const [payload, alg, headers] = inputs;
317
+ const jwt = await client.signJWT(payload, headers, alg);
318
+ yellow(jwt);
319
+ return jwt;
484
320
  }
485
- case "subaccountDid": {
486
- const [did] = inputs;
487
- Joi.assert(did, Joi.string());
488
- const subaccountMsiBytes = createHash("sha256")
489
- .update(did, "utf8")
490
- .digest()
491
- .slice(0, 16);
492
- const subaccount = util.createDid(subaccountMsiBytes);
493
- yellow(subaccount);
494
- return subaccount;
321
+ case "signTransaction": {
322
+ const unsignedTransaction = inputs[0];
323
+ const uTx = formatEthersUnsignedTransaction(
324
+ // eslint-disable-next-line unicorn/prefer-structured-clone
325
+ JSON.parse(JSON.stringify(unsignedTransaction)));
326
+ const sgnTx = await client.ethWallet.signTransaction(uTx);
327
+ yellow(sgnTx);
328
+ return sgnTx;
495
329
  }
496
330
  case "statusListIndex": {
497
331
  const [did] = inputs;
@@ -500,46 +334,212 @@ export async function compute(method, inputs, context) {
500
334
  .update(did, "utf8")
501
335
  .digest()
502
336
  .slice(0, 6)
503
- .readUInt32BE() % 131072).toString();
337
+ .readUInt32BE() % 131_072).toString();
504
338
  yellow(statusListIndex);
505
339
  return statusListIndex;
506
340
  }
341
+ case "subaccountDid": {
342
+ const [did] = inputs;
343
+ Joi.assert(did, Joi.string());
344
+ const subaccountMsiBytes = createHash("sha256")
345
+ .update(did, "utf8")
346
+ .digest()
347
+ .slice(0, 16);
348
+ const subaccount = util.createDid(subaccountMsiBytes);
349
+ yellow(subaccount);
350
+ return subaccount;
351
+ }
507
352
  case "thumbprint": {
508
353
  const [hexOrJwk, alg] = inputs;
509
- let publicKeyJwk;
510
- if (typeof hexOrJwk === "string") {
511
- publicKeyJwk = encodePublicKey({
512
- key: hexOrJwk,
513
- format: "jwk",
354
+ const publicKeyJwk = typeof hexOrJwk === "string"
355
+ ? encodePublicKey({
514
356
  alg,
515
- });
516
- }
517
- else {
518
- publicKeyJwk = hexOrJwk;
519
- }
357
+ format: "jwk",
358
+ key: hexOrJwk,
359
+ })
360
+ : hexOrJwk;
520
361
  const thumbprint = await calculateJwkThumbprint(publicKeyJwk, "sha256");
521
362
  yellow(thumbprint);
522
363
  return thumbprint;
523
364
  }
524
- case "address": {
525
- const [hexOrJwk] = inputs;
526
- let publicKeyHex;
527
- if (typeof hexOrJwk === "string") {
528
- publicKeyHex = hexOrJwk;
365
+ case "timestampId": {
366
+ const hash = inputs[0];
367
+ Joi.assert(hash, Joi.string());
368
+ const bufferSha256 = Buffer.from(sha256(hash), "hex");
369
+ const multihash = Multihash.encode(bufferSha256, "sha2-256", 32);
370
+ const timestampId = `u${base64url.encode(multihash)}`;
371
+ yellow(timestampId);
372
+ return timestampId;
373
+ }
374
+ case "userPin": {
375
+ const [did] = inputs;
376
+ const userPin = getUserPin(did);
377
+ yellow(userPin);
378
+ return userPin;
379
+ }
380
+ case "wait": {
381
+ const [seconds] = inputs;
382
+ const milliseconds = Math.round(Number(seconds) * 1000);
383
+ console.log(`waiting ${milliseconds / 1000} seconds`);
384
+ await new Promise((r) => {
385
+ setTimeout(r, milliseconds);
386
+ });
387
+ return 0;
388
+ }
389
+ default: {
390
+ throw new Error(`Invalid method '${method}'`);
391
+ }
392
+ }
393
+ }
394
+ export async function computeVerifyVcJwt(inputs, context) {
395
+ const [vcJwt, options, expectedResult] = inputs;
396
+ const ebsiEnvConfig = {
397
+ hosts: [context.config.domain.replace(/^https?:\/\//, "")],
398
+ network: {
399
+ isOptional: false,
400
+ name: context.config.env,
401
+ },
402
+ scheme: "ebsi",
403
+ services: {
404
+ "did-registry": context.config.api.did.version,
405
+ "trusted-issuers-registry": context.config.api.tir.version,
406
+ "trusted-policies-registry": context.config.api.tpr.version,
407
+ "trusted-schemas-registry": context.config.api.tsr.version,
408
+ },
409
+ };
410
+ try {
411
+ await verifyCredentialJwt(vcJwt, ebsiEnvConfig, options);
412
+ switch (expectedResult) {
413
+ case "expectRevoked": {
414
+ throw new Error("Credential is not revoked");
529
415
  }
530
- else {
531
- publicKeyHex = encodePublicKey({
532
- key: hexOrJwk,
533
- format: "hex",
534
- });
416
+ default: {
417
+ return "Verifiable Credential is valid";
535
418
  }
536
- const address = ethers.utils.computeAddress(publicKeyHex);
537
- yellow(address);
538
- return address;
539
419
  }
540
- default:
541
- throw new Error(`Invalid method '${method}'`);
542
420
  }
421
+ catch (error) {
422
+ if (expectedResult === "expectRevoked") {
423
+ if (error.message === "Credential is not revoked")
424
+ throw error;
425
+ if (error.message.includes("revoked")) {
426
+ return "Verifiable Credential is revoked";
427
+ }
428
+ }
429
+ throw error;
430
+ }
431
+ }
432
+ export async function computeVerifyVpJwt(inputs, context) {
433
+ const [vpJwt, audience, options] = inputs;
434
+ const ebsiEnvConfig = {
435
+ hosts: [context.config.domain.replace(/^https?:\/\//, "")],
436
+ network: {
437
+ isOptional: false,
438
+ name: context.config.env,
439
+ },
440
+ scheme: "ebsi",
441
+ services: {
442
+ "did-registry": context.config.api.did.version,
443
+ "trusted-issuers-registry": context.config.api.tir.version,
444
+ "trusted-policies-registry": context.config.api.tpr.version,
445
+ "trusted-schemas-registry": context.config.api.tsr.version,
446
+ },
447
+ };
448
+ await verifyPresentationJwt(vpJwt, audience, ebsiEnvConfig, options);
449
+ return "Verifiable Presentation is valid";
450
+ }
451
+ export function decodeLog(log, context) {
452
+ const api = getApiByContractId(log.address, context);
453
+ const logDecoded = api.contract.interface.parseLog(log);
454
+ const { args: argsWithArray, name, signature, topic } = logDecoded;
455
+ const args = getProperties(argsWithArray);
456
+ return { args, name, signature, topic };
457
+ }
458
+ export async function decodeLogs(input, context) {
459
+ if (!input)
460
+ throw new Error("Invalid logs: no input provided");
461
+ let receipt;
462
+ let logs;
463
+ if (typeof input === "string") {
464
+ receipt = await ledgerGetTransactionReceipt([input], false, context);
465
+ }
466
+ if (input.receipt) {
467
+ receipt = input.receipt;
468
+ }
469
+ if (input.logs) {
470
+ receipt = input;
471
+ }
472
+ if (receipt) {
473
+ if (!Array.isArray(receipt.logs)) {
474
+ throw new TypeError("Invalid logs: The input must be a transaction hash, a transaction receipt, or an array of logs");
475
+ }
476
+ logs = receipt.logs;
477
+ }
478
+ else {
479
+ if (!Array.isArray(input)) {
480
+ throw new TypeError("Invalid logs: The input must be a transaction hash, a transaction receipt, or an array of logs");
481
+ }
482
+ logs = input;
483
+ }
484
+ return logs.map((log) => decodeLog(log, context));
485
+ }
486
+ export async function decodeTransaction(tx, context) {
487
+ let txData;
488
+ if (typeof tx === "string") {
489
+ txData =
490
+ tx.length <= 66
491
+ ? // it is a tx hash
492
+ (await ledgerGetTransaction([tx], false, context))
493
+ : // it is a signed transaction
494
+ ethers.utils.parseTransaction(tx);
495
+ }
496
+ else {
497
+ txData = tx;
498
+ }
499
+ if (!txData.data && !txData.input) {
500
+ throw new Error("Invalid transaction: There is no input or data");
501
+ }
502
+ const api = getApiByContractId(txData.to, context);
503
+ const { args, functionFragment } = api.contract.interface.parseTransaction({
504
+ data: (txData.data || txData.input),
505
+ });
506
+ return {
507
+ dataDecoded: { args: getProperties(args), name: functionFragment.name },
508
+ tx: txData,
509
+ };
510
+ }
511
+ export function getApiByContractId(contractId, context) {
512
+ const apiName = Object.keys(context.config.api).find((a) => {
513
+ const api = context.config.api[a];
514
+ return (api.contract &&
515
+ contractId.toLowerCase() === api.contract.address.toLowerCase());
516
+ });
517
+ if (!apiName)
518
+ throw new Error(`cannot get API with address ${contractId}`);
519
+ return context.config.api[apiName];
520
+ }
521
+ export function getProperties(input) {
522
+ return Object.keys(input)
523
+ .filter((key) => Number.isNaN(Number(key)))
524
+ .reduce((obj, key) => {
525
+ obj[key] = input[key];
526
+ return obj;
527
+ }, {});
528
+ }
529
+ export function getUserPin(did) {
530
+ return createHash("sha256")
531
+ .update(did)
532
+ .digest()
533
+ .slice(-4)
534
+ .map((byte) => byte % 10)
535
+ .reduce((acc, digit) => `${acc}${digit}`, "");
536
+ }
537
+ export function sha256(data) {
538
+ let hash = createHash("sha256");
539
+ hash = data.startsWith("0x")
540
+ ? hash.update(removePrefix0x(data), "hex")
541
+ : hash.update(data, "utf8");
542
+ return hash.digest().toString("hex");
543
543
  }
544
544
  export default compute;
545
545
  //# sourceMappingURL=compute.js.map