@sphereon/ssi-sdk.vc-status-list 0.34.0 → 0.34.1-feature.SSISDK.17.bitstring.sl.7

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.
@@ -0,0 +1,301 @@
1
+ import type { IAgentContext, ICredentialPlugin, ProofFormat as VeramoProofFormat } from '@veramo/core'
2
+ import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
3
+ import {
4
+ CredentialMapper,
5
+ type CredentialProofFormat,
6
+ DocumentFormat,
7
+ type IIssuer,
8
+ type StatusListCredential,
9
+ StatusListType,
10
+ } from '@sphereon/ssi-types'
11
+
12
+ import type { IStatusList } from './IStatusList'
13
+ import {
14
+ BitstringStatus,
15
+ CheckStatusIndexArgs,
16
+ CreateStatusListArgs,
17
+ StatusListResult,
18
+ ToStatusListDetailsArgs,
19
+ UpdateStatusListFromEncodedListArgs,
20
+ UpdateStatusListIndexArgs,
21
+ } from '../types'
22
+
23
+ import { assertValidProofType, getAssertedProperty, getAssertedValue, getAssertedValues } from '../utils'
24
+ import { BitstringStatusListCredential } from '../types/BitstringStatusList'
25
+ import { BitstreamStatusList, BitstringStatusPurpose, createStatusListCredential } from '@4sure-tech/vc-bitstring-status-lists'
26
+
27
+ export const DEFAULT_LIST_LENGTH = 131072 // W3C spec minimum
28
+ export const DEFAULT_PROOF_FORMAT = 'lds' as CredentialProofFormat
29
+ export const DEFAULT_STATUS_PURPOSE: BitstringStatusPurpose = 'revocation'
30
+
31
+ export class BitstringStatusListImplementation implements IStatusList {
32
+ async createNewStatusList(
33
+ args: CreateStatusListArgs,
34
+ context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
35
+ ): Promise<StatusListResult> {
36
+ if (!args.bitstringStatusList) {
37
+ throw new Error('BitstringStatusList options are required for type BitstringStatusList')
38
+ }
39
+
40
+ const length = args?.length ?? DEFAULT_LIST_LENGTH
41
+ const proofFormat: CredentialProofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT
42
+ assertValidProofType(StatusListType.BitstringStatusList, proofFormat)
43
+ const veramoProofFormat: VeramoProofFormat = proofFormat as VeramoProofFormat
44
+
45
+ const { issuer, id } = args
46
+ const correlationId = getAssertedValue('correlationId', args.correlationId)
47
+ const { statusPurpose, bitsPerStatus, validFrom, validUntil, ttl } = args.bitstringStatusList
48
+ const statusListCredential = await this.createVerifiableCredential(
49
+ {
50
+ ...args,
51
+ proofFormat: veramoProofFormat,
52
+ statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
53
+ validFrom,
54
+ validUntil,
55
+ ttl,
56
+ },
57
+ context,
58
+ )
59
+
60
+ return {
61
+ encodedList: statusListCredential.credentialSubject.encodedList,
62
+ statusListCredential: statusListCredential,
63
+ bitstringStatusList: {
64
+ statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
65
+ ...(statusListCredential.validFrom && { validFrom: new Date(statusListCredential.validFrom) }),
66
+ ...(statusListCredential.validUntil && { validUntil: new Date(statusListCredential.validUntil) }),
67
+ ttl,
68
+ bitsPerStatus,
69
+ },
70
+ length,
71
+ type: StatusListType.BitstringStatusList,
72
+ proofFormat,
73
+ id,
74
+ correlationId,
75
+ issuer,
76
+ statuslistContentType: this.buildContentType(proofFormat),
77
+ }
78
+ }
79
+
80
+ async updateStatusListIndex(
81
+ args: UpdateStatusListIndexArgs,
82
+ context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
83
+ ): Promise<StatusListResult> {
84
+ if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
85
+ return Promise.reject('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListIndex)')
86
+ }
87
+
88
+ const credential = args.statusListCredential
89
+ const uniform = CredentialMapper.toUniformCredential(credential)
90
+ const { issuer, credentialSubject } = uniform
91
+ const id = getAssertedValue('id', uniform.id)
92
+ const origEncodedList = getAssertedProperty('encodedList', credentialSubject)
93
+
94
+ const index = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
95
+ const statusList: BitstreamStatusList = await BitstreamStatusList.decode({ encodedList: origEncodedList, statusSize: args.bitsPerStatus })
96
+ statusList.setStatus(index, args.value)
97
+
98
+ const proofFormat = CredentialMapper.detectDocumentType(credential) === DocumentFormat.JWT ? 'jwt' : 'lds'
99
+
100
+ const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject
101
+
102
+ const statusPurpose = getAssertedProperty('statusPurpose', credSubject)
103
+
104
+ const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : undefined
105
+ const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : undefined
106
+ const ttl = credSubject.ttl
107
+
108
+ const updatedCredential = await this.createVerifiableCredential(
109
+ {
110
+ ...args,
111
+ id,
112
+ issuer,
113
+ statusList,
114
+ proofFormat: proofFormat,
115
+ statusPurpose,
116
+ ttl,
117
+ validFrom,
118
+ validUntil,
119
+ },
120
+ context,
121
+ )
122
+
123
+ return {
124
+ statusListCredential: updatedCredential,
125
+ encodedList: updatedCredential.credentialSubject.encodedList,
126
+ bitstringStatusList: {
127
+ statusPurpose,
128
+ ...(updatedCredential.validFrom && { validFrom: new Date(updatedCredential.validFrom) }),
129
+ ...(updatedCredential.validUntil && { validUntil: new Date(updatedCredential.validUntil) }),
130
+ bitsPerStatus: args.bitsPerStatus,
131
+ ttl,
132
+ },
133
+ length: statusList.getLength(),
134
+ type: StatusListType.BitstringStatusList,
135
+ proofFormat: proofFormat,
136
+ id,
137
+ issuer,
138
+ statuslistContentType: this.buildContentType(proofFormat),
139
+ }
140
+ }
141
+
142
+ async updateStatusListFromEncodedList(
143
+ args: UpdateStatusListFromEncodedListArgs,
144
+ context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
145
+ ): Promise<StatusListResult> {
146
+ if (!args.bitstringStatusList) {
147
+ throw new Error('bitstringStatusList options required for type BitstringStatusList')
148
+ }
149
+
150
+ if (args.bitstringStatusList.bitsPerStatus < 1) {
151
+ return Promise.reject('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListFromEncodedList)')
152
+ }
153
+
154
+ const { statusPurpose, bitsPerStatus, ttl, validFrom, validUntil } = args.bitstringStatusList
155
+
156
+ const proofFormat: CredentialProofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT
157
+ assertValidProofType(StatusListType.BitstringStatusList, proofFormat)
158
+ const veramoProofFormat: VeramoProofFormat = proofFormat as VeramoProofFormat
159
+
160
+ const { issuer, id } = getAssertedValues(args)
161
+ const statusList: BitstreamStatusList = await BitstreamStatusList.decode({ encodedList: args.encodedList, statusSize: bitsPerStatus })
162
+ const index = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
163
+ statusList.setStatus(index, args.value)
164
+
165
+ const credential = await this.createVerifiableCredential(
166
+ {
167
+ id,
168
+ issuer,
169
+ statusList,
170
+ proofFormat: veramoProofFormat,
171
+ keyRef: args.keyRef,
172
+ statusPurpose,
173
+ validFrom,
174
+ validUntil,
175
+ ttl,
176
+ },
177
+ context,
178
+ )
179
+
180
+ return {
181
+ type: StatusListType.BitstringStatusList,
182
+ statusListCredential: credential,
183
+ encodedList: credential.credentialSubject.encodedList,
184
+ bitstringStatusList: {
185
+ statusPurpose,
186
+ bitsPerStatus,
187
+ ...(credential.validFrom && { validFrom: new Date(credential.validFrom) }),
188
+ ...(credential.validUntil && { validUntil: new Date(credential.validUntil) }),
189
+ ttl,
190
+ },
191
+ length: statusList.getLength(),
192
+ proofFormat: args.proofFormat ?? 'lds',
193
+ id: id,
194
+ issuer: issuer,
195
+ statuslistContentType: this.buildContentType(proofFormat),
196
+ }
197
+ }
198
+
199
+ async checkStatusIndex(args: CheckStatusIndexArgs): Promise<BitstringStatus> {
200
+ if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
201
+ return Promise.reject('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (checkStatusIndex)')
202
+ }
203
+
204
+ const uniform = CredentialMapper.toUniformCredential(args.statusListCredential)
205
+ const { credentialSubject } = uniform
206
+ const encodedList = getAssertedProperty('encodedList', credentialSubject)
207
+
208
+ const statusSize = args.bitsPerStatus
209
+ const statusList = await BitstreamStatusList.decode({ encodedList, statusSize })
210
+
211
+ const numIndex = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
212
+ if (statusList.getLength() <= numIndex) {
213
+ throw new Error(`Status list index out of bounds, has ${statusList.getLength()} entries, requested ${numIndex}`)
214
+ }
215
+ return statusList.getStatus(numIndex)
216
+ }
217
+
218
+ async toStatusListDetails(args: ToStatusListDetailsArgs): Promise<StatusListResult> {
219
+ const { statusListPayload, bitsPerStatus } = args
220
+ if (!bitsPerStatus || bitsPerStatus < 1) {
221
+ return Promise.reject('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (toStatusListDetails)')
222
+ }
223
+
224
+ const uniform = CredentialMapper.toUniformCredential(statusListPayload)
225
+ const { issuer, credentialSubject } = uniform
226
+ const id = getAssertedValue('id', uniform.id)
227
+ const encodedList = getAssertedProperty('encodedList', credentialSubject)
228
+ const proofFormat: CredentialProofFormat = CredentialMapper.detectDocumentType(statusListPayload) === DocumentFormat.JWT ? 'jwt' : 'lds'
229
+ const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject
230
+ const statusPurpose = getAssertedProperty('statusPurpose', credSubject)
231
+ const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : undefined
232
+ const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : undefined
233
+ const ttl = credSubject.ttl
234
+ const statuslistLength: number = BitstreamStatusList.getStatusListLength(encodedList, bitsPerStatus)
235
+
236
+ return {
237
+ id,
238
+ encodedList,
239
+ issuer,
240
+ type: StatusListType.BitstringStatusList,
241
+ proofFormat,
242
+ length: statuslistLength,
243
+ statusListCredential: statusListPayload,
244
+ statuslistContentType: this.buildContentType(proofFormat),
245
+ bitstringStatusList: {
246
+ statusPurpose,
247
+ bitsPerStatus,
248
+ validFrom,
249
+ validUntil,
250
+ ttl,
251
+ },
252
+ ...(args.correlationId && { correlationId: args.correlationId }),
253
+ ...(args.driverType && { driverType: args.driverType }),
254
+ }
255
+ }
256
+
257
+ private async createVerifiableCredential(
258
+ args: {
259
+ id: string
260
+ issuer: string | IIssuer
261
+ statusList?: BitstreamStatusList
262
+ proofFormat: VeramoProofFormat
263
+ statusPurpose: BitstringStatusPurpose
264
+ validFrom?: Date
265
+ validUntil?: Date
266
+ ttl?: number
267
+ keyRef?: string
268
+ },
269
+ context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
270
+ ): Promise<BitstringStatusListCredential> {
271
+ const identifier = await context.agent.identifierManagedGet({
272
+ identifier: typeof args.issuer === 'string' ? args.issuer : args.issuer.id,
273
+ vmRelationship: 'assertionMethod',
274
+ offlineWhenNoDIDRegistered: true,
275
+ })
276
+
277
+ const unsignedCredential = await createStatusListCredential(args)
278
+
279
+ const verifiableCredential = await context.agent.createVerifiableCredential({
280
+ credential: unsignedCredential,
281
+ keyRef: args.keyRef ?? identifier.kmsKeyRef,
282
+ proofFormat: args.proofFormat,
283
+ fetchRemoteContexts: true,
284
+ })
285
+
286
+ return CredentialMapper.toWrappedVerifiableCredential(verifiableCredential as StatusListCredential).original as BitstringStatusListCredential
287
+ }
288
+
289
+ private buildContentType(proofFormat: CredentialProofFormat | undefined) {
290
+ switch (proofFormat) {
291
+ case 'jwt':
292
+ return `application/statuslist+jwt`
293
+ case 'cbor':
294
+ return `application/statuslist+cwt`
295
+ case 'lds':
296
+ return 'application/statuslist+ld+json'
297
+ default:
298
+ throw Error(`Unsupported content type '${proofFormat}' for status lists`)
299
+ }
300
+ }
301
+ }
@@ -1,6 +1,7 @@
1
1
  import type { IAgentContext, ICredentialPlugin } from '@veramo/core'
2
2
  import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
3
- import type {
3
+ import {
4
+ BitstringStatus,
4
5
  CheckStatusIndexArgs,
5
6
  CreateStatusListArgs,
6
7
  Status2021,
@@ -33,7 +34,7 @@ export interface IStatusList {
33
34
  /**
34
35
  * Checks the status at a given index in the status list
35
36
  */
36
- checkStatusIndex(args: CheckStatusIndexArgs): Promise<number | Status2021 | StatusOAuth>
37
+ checkStatusIndex(args: CheckStatusIndexArgs): Promise<number | Status2021 | StatusOAuth | BitstringStatus>
37
38
 
38
39
  /**
39
40
  * Collects the status list details
@@ -20,7 +20,7 @@ import { createSignedCbor, decodeStatusListCWT } from './encoding/cbor'
20
20
 
21
21
  type IRequiredContext = IAgentContext<ICredentialPlugin & IJwtService & IIdentifierResolution & IKeyManager>
22
22
 
23
- export const DEFAULT_BITS_PER_STATUS = 1 // 1 bit is sufficient for 0x00 - "VALID" 0x01 - "INVALID" saving space in the process
23
+ export const DEFAULT_BITS_PER_STATUS = 1 // 1 bit is sufficient for 0x00 - "VALID" 0x01 - "INVALID" saving space in the process
24
24
  export const DEFAULT_LIST_LENGTH = 250000
25
25
  export const DEFAULT_PROOF_FORMAT = 'jwt' as CredentialProofFormat
26
26
 
@@ -70,6 +70,10 @@ export class OAuthStatusListImplementation implements IStatusList {
70
70
  throw new Error('Status list index out of bounds')
71
71
  }
72
72
 
73
+ if (typeof value !== 'number') {
74
+ throw new Error('Status list values should be of type number')
75
+ }
76
+
73
77
  statusList.setStatus(index, value)
74
78
  const { statusListCredential: signedCredential, encodedList } = await this.createSignedStatusList(
75
79
  proofFormat,
@@ -109,8 +113,7 @@ export class OAuthStatusListImplementation implements IStatusList {
109
113
 
110
114
  const listToUpdate = StatusList.decompressStatusList(args.encodedList, bitsPerStatus ?? DEFAULT_BITS_PER_STATUS)
111
115
  const index = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
112
- // FIXME: See above.
113
- listToUpdate.setStatus(index, args.value ? 1 : 0)
116
+ listToUpdate.setStatus(index, args.value)
114
117
 
115
118
  const { statusListCredential, encodedList } = await this.createSignedStatusList(
116
119
  proofFormat ?? DEFAULT_PROOF_FORMAT,
@@ -138,7 +141,7 @@ export class OAuthStatusListImplementation implements IStatusList {
138
141
  }
139
142
  }
140
143
 
141
- private buildContentType(proofFormat: 'jwt' | 'lds' | 'EthereumEip712Signature2021' | 'cbor' | undefined) {
144
+ private buildContentType(proofFormat: CredentialProofFormat | undefined) {
142
145
  return `application/statuslist+${proofFormat === 'cbor' ? 'cwt' : 'jwt'}`
143
146
  }
144
147
 
@@ -153,7 +156,7 @@ export class OAuthStatusListImplementation implements IStatusList {
153
156
 
154
157
  const index = typeof statusListIndex === 'number' ? statusListIndex : parseInt(statusListIndex)
155
158
  if (index < 0 || index >= statusList.statusList.length) {
156
- throw new Error('Status list index out of bounds')
159
+ throw new Error(`Status list index out of bounds, has ${statusList.statusList.length} items, requested ${index}`)
157
160
  }
158
161
 
159
162
  return statusList.getStatus(index)
@@ -184,7 +187,7 @@ export class OAuthStatusListImplementation implements IStatusList {
184
187
  }
185
188
 
186
189
  private async createSignedStatusList(
187
- proofFormat: 'jwt' | 'lds' | 'EthereumEip712Signature2021' | 'cbor',
190
+ proofFormat: CredentialProofFormat,
188
191
  context: IAgentContext<ICredentialPlugin & IJwtService & IIdentifierResolution & IKeyManager>,
189
192
  statusList: StatusList,
190
193
  issuerString: string,
@@ -24,7 +24,7 @@ import { Status2021 } from '../types'
24
24
  import { assertValidProofType, getAssertedProperty, getAssertedValue, getAssertedValues } from '../utils'
25
25
 
26
26
  export const DEFAULT_LIST_LENGTH = 250000
27
- export const DEFAULT_PROOF_FORMAT = 'lds' as VeramoProofFormat
27
+ export const DEFAULT_PROOF_FORMAT = 'lds' as CredentialProofFormat
28
28
 
29
29
  export class StatusList2021Implementation implements IStatusList {
30
30
  async createNewStatusList(
@@ -126,7 +126,7 @@ export class StatusList2021Implementation implements IStatusList {
126
126
  const { issuer, id } = getAssertedValues(args)
127
127
  const statusList = await StatusList.decode({ encodedList: args.encodedList })
128
128
  const index = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
129
- statusList.setStatus(index, args.value)
129
+ statusList.setStatus(index, args.value !== 0)
130
130
 
131
131
  const newEncodedList = await statusList.encode()
132
132
  const credential = await this.createVerifiableCredential(
@@ -234,7 +234,7 @@ export class StatusList2021Implementation implements IStatusList {
234
234
  return CredentialMapper.toWrappedVerifiableCredential(verifiableCredential as StatusListCredential).original as StatusListCredential
235
235
  }
236
236
 
237
- private buildContentType(proofFormat: 'jwt' | 'lds' | 'EthereumEip712Signature2021' | 'cbor' | undefined) {
237
+ private buildContentType(proofFormat: CredentialProofFormat | undefined) {
238
238
  switch (proofFormat) {
239
239
  case 'jwt':
240
240
  return `application/statuslist+jwt`
@@ -2,6 +2,7 @@ import type { IStatusList } from './IStatusList'
2
2
  import { StatusList2021Implementation } from './StatusList2021'
3
3
  import { OAuthStatusListImplementation } from './OAuthStatusList'
4
4
  import { StatusListType } from '@sphereon/ssi-types'
5
+ import { BitstringStatusListImplementation } from './BitstringStatusListImplementation'
5
6
 
6
7
  export class StatusListFactory {
7
8
  private static instance: StatusListFactory
@@ -11,6 +12,7 @@ export class StatusListFactory {
11
12
  this.implementations = new Map()
12
13
  this.implementations.set(StatusListType.StatusList2021, new StatusList2021Implementation())
13
14
  this.implementations.set(StatusListType.OAuthStatusList, new OAuthStatusListImplementation())
15
+ this.implementations.set(StatusListType.BitstringStatusList, new BitstringStatusListImplementation())
14
16
  }
15
17
 
16
18
  public static getInstance(): StatusListFactory {
@@ -0,0 +1,4 @@
1
+ import { StatusListCredential } from '@sphereon/ssi-types'
2
+ import { BitstringStatusListCredentialUnsigned } from '../../../../../vc-bitstring-status-lists'
3
+
4
+ export type BitstringStatusListCredential = BitstringStatusListCredentialUnsigned & StatusListCredential
@@ -1,11 +1,11 @@
1
1
  import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
2
2
  import {
3
+ type CredentialProofFormat,
3
4
  type ICredential,
4
5
  type ICredentialStatus,
5
6
  type IIssuer,
6
7
  type IVerifiableCredential,
7
8
  type OrPromise,
8
- type CredentialProofFormat,
9
9
  type StatusListCredential,
10
10
  StatusListCredentialIdMode,
11
11
  StatusListDriverType,
@@ -26,6 +26,7 @@ import { DataSource } from 'typeorm'
26
26
  import type { BitsPerStatus } from '@sd-jwt/jwt-status-list'
27
27
  import type { SdJwtVcPayload } from '@sd-jwt/sd-jwt-vc'
28
28
  import type { StatusListOpts } from '@sphereon/oid4vci-common'
29
+ import { BitstringStatusPurpose } from '@4sure-tech/vc-bitstring-status-lists'
29
30
 
30
31
  export enum StatusOAuth {
31
32
  Valid = 0,
@@ -38,6 +39,8 @@ export enum Status2021 {
38
39
  Invalid = 1,
39
40
  }
40
41
 
42
+ export type BitstringStatus = number
43
+
41
44
  export type StatusList2021Args = {
42
45
  indexingDirection: StatusListIndexingDirection
43
46
  statusPurpose?: StatusPurpose2021
@@ -49,6 +52,14 @@ export type OAuthStatusListArgs = {
49
52
  expiresAt?: Date
50
53
  }
51
54
 
55
+ export type BitstringStatusListArgs = {
56
+ statusPurpose: BitstringStatusPurpose
57
+ bitsPerStatus: number
58
+ ttl?: number
59
+ validFrom?: Date
60
+ validUntil?: Date
61
+ }
62
+
52
63
  export type BaseCreateNewStatusListArgs = {
53
64
  type: StatusListType
54
65
  id: string
@@ -59,6 +70,7 @@ export type BaseCreateNewStatusListArgs = {
59
70
  keyRef?: string
60
71
  statusList2021?: StatusList2021Args
61
72
  oauthStatusList?: OAuthStatusListArgs
73
+ bitstringStatusList?: BitstringStatusListArgs
62
74
  driverType?: StatusListDriverType
63
75
  }
64
76
 
@@ -71,10 +83,18 @@ export type UpdateOAuthStatusListArgs = {
71
83
  expiresAt?: Date
72
84
  }
73
85
 
86
+ export type UpdateBitstringStatusListArgs = {
87
+ statusPurpose: BitstringStatusPurpose
88
+ bitsPerStatus: number
89
+ validFrom?: Date
90
+ validUntil?: Date
91
+ ttl?: number
92
+ }
93
+
74
94
  export interface UpdateStatusListFromEncodedListArgs {
75
95
  type?: StatusListType
76
96
  statusListIndex: number | string
77
- value: boolean
97
+ value: number
78
98
  proofFormat?: CredentialProofFormat
79
99
  keyRef?: string
80
100
  correlationId?: string
@@ -83,13 +103,14 @@ export interface UpdateStatusListFromEncodedListArgs {
83
103
  id: string
84
104
  statusList2021?: UpdateStatusList2021Args
85
105
  oauthStatusList?: UpdateOAuthStatusListArgs
106
+ bitstringStatusList?: UpdateBitstringStatusListArgs
86
107
  }
87
108
 
88
109
  export interface UpdateStatusListFromStatusListCredentialArgs {
89
110
  statusListCredential: StatusListCredential // | CompactJWT
90
111
  keyRef?: string
91
112
  statusListIndex: number | string
92
- value: number | Status2021 | StatusOAuth
113
+ value: number | Status2021 | StatusOAuth | BitstringStatus
93
114
  }
94
115
 
95
116
  export interface StatusListResult {
@@ -103,6 +124,7 @@ export interface StatusListResult {
103
124
  issuer: string | IIssuer
104
125
  statusList2021?: StatusList2021Details
105
126
  oauthStatusList?: OAuthStatusDetails
127
+ bitstringStatusList?: BitstringStatusDetails
106
128
 
107
129
  // These cannot be deduced from the VC, so they are present when callers pass in these values as params
108
130
  correlationId?: string
@@ -120,6 +142,14 @@ interface OAuthStatusDetails {
120
142
  expiresAt?: Date
121
143
  }
122
144
 
145
+ interface BitstringStatusDetails {
146
+ statusPurpose: BitstringStatusPurpose
147
+ bitsPerStatus: number
148
+ validFrom?: Date
149
+ validUntil?: Date
150
+ ttl?: number
151
+ }
152
+
123
153
  export interface StatusList2021EntryCredentialStatus extends ICredentialStatus {
124
154
  type: 'StatusList2021Entry'
125
155
  statusPurpose: StatusPurpose2021
@@ -135,6 +165,16 @@ export interface StatusListOAuthEntryCredentialStatus extends ICredentialStatus
135
165
  expiresAt?: Date
136
166
  }
137
167
 
168
+ export interface BitstringStatusListEntryCredentialStatus extends ICredentialStatus {
169
+ type: 'BitstringStatusListEntry'
170
+ statusPurpose: BitstringStatusPurpose | BitstringStatusPurpose[]
171
+ statusListIndex: string
172
+ statusListCredential: string
173
+ bitsPerStatus?: number
174
+ statusMessage?: Array<BitstringStatus>
175
+ statusReference?: string | string[]
176
+ }
177
+
138
178
  export interface StatusList2021ToVerifiableCredentialArgs {
139
179
  issuer: string | IIssuer
140
180
  id: string
@@ -154,12 +194,14 @@ export interface CreateStatusListArgs {
154
194
  length?: number
155
195
  statusList2021?: StatusList2021Args
156
196
  oauthStatusList?: OAuthStatusListArgs
197
+ bitstringStatusList?: BitstringStatusListArgs
157
198
  }
158
199
 
159
200
  export interface UpdateStatusListIndexArgs {
160
201
  statusListCredential: StatusListCredential // | CompactJWT
161
202
  statusListIndex: number | string
162
- value: number | Status2021 | StatusOAuth
203
+ value: number | Status2021 | StatusOAuth | BitstringStatus
204
+ bitsPerStatus?: number
163
205
  keyRef?: string
164
206
  expiresAt?: Date
165
207
  }
@@ -167,12 +209,14 @@ export interface UpdateStatusListIndexArgs {
167
209
  export interface CheckStatusIndexArgs {
168
210
  statusListCredential: StatusListCredential // | CompactJWT
169
211
  statusListIndex: string | number
212
+ bitsPerStatus?: number
170
213
  }
171
214
 
172
215
  export interface ToStatusListDetailsArgs {
173
216
  statusListPayload: StatusListCredential
174
217
  correlationId?: string
175
218
  driverType?: StatusListDriverType
219
+ bitsPerStatus?: number
176
220
  }
177
221
 
178
222
  /**
package/src/utils.ts CHANGED
@@ -11,7 +11,7 @@ import { jwtDecode } from 'jwt-decode'
11
11
 
12
12
  export function getAssertedStatusListType(type?: StatusListType) {
13
13
  const assertedType = type ?? StatusListType.StatusList2021
14
- if (![StatusListType.StatusList2021, StatusListType.OAuthStatusList].includes(assertedType)) {
14
+ if (![StatusListType.StatusList2021, StatusListType.OAuthStatusList, StatusListType.BitstringStatusList].includes(assertedType)) {
15
15
  throw Error(`StatusList type ${assertedType} is not supported (yet)`)
16
16
  }
17
17
  return assertedType
@@ -39,8 +39,9 @@ export function getAssertedProperty<T extends object>(propertyName: string, obj:
39
39
  }
40
40
 
41
41
  const ValidProofTypeMap = new Map<StatusListType, CredentialProofFormat[]>([
42
- [StatusListType.StatusList2021, ['jwt', 'lds', 'EthereumEip712Signature2021']],
42
+ [StatusListType.StatusList2021, ['jwt', 'lds']],
43
43
  [StatusListType.OAuthStatusList, ['jwt', 'cbor']],
44
+ [StatusListType.BitstringStatusList, ['lds']],
44
45
  ])
45
46
 
46
47
  export function assertValidProofType(type: StatusListType, proofFormat: CredentialProofFormat) {