11import {
22 AccessTokenResponse ,
3+ CredentialIssuerMetadata ,
34 CredentialIssuerMetadataV1_0_13 ,
4- CredentialOfferPayloadV1_0_13 ,
55 CredentialOfferRequestWithBaseUrl ,
66 determineSpecVersionFromOffer ,
77 EndpointMetadata ,
88 ExperimentalSubjectIssuance ,
9- getIssuerFromCredentialOfferPayload ,
109 OID4VCICredentialFormat ,
1110 OpenId4VCIVersion ,
1211 UniformCredentialOfferRequest ,
1312} from '@sphereon/oid4vci-common' ;
1413import { CredentialFormat } from '@sphereon/ssi-types' ;
1514
1615import { CredentialOfferClient } from './CredentialOfferClient' ;
17- import { CredentialRequestClient } from './CredentialRequestClient' ;
16+ import { CredentialRequestClientBuilderV1_0_11 } from './CredentialRequestClientBuilderV1_0_11' ;
17+ import { CredentialRequestClientBuilderV1_0_13 } from './CredentialRequestClientBuilderV1_0_13' ;
18+
19+ type CredentialRequestClientBuilderVersionSpecific = CredentialRequestClientBuilderV1_0_11 | CredentialRequestClientBuilderV1_0_13 ;
20+
21+ function isV1_0_13 ( builder : CredentialRequestClientBuilderVersionSpecific ) : builder is CredentialRequestClientBuilderV1_0_13 {
22+ return ( builder as CredentialRequestClientBuilderV1_0_13 ) . withCredentialIdentifier !== undefined ;
23+ }
1824
1925export class CredentialRequestClientBuilder {
20- credentialEndpoint ?: string ;
21- deferredCredentialEndpoint ?: string ;
22- deferredCredentialAwait = false ;
23- deferredCredentialIntervalInMS = 5000 ;
24- credentialIdentifier ?: string ;
25- credentialTypes ?: string [ ] = [ ] ;
26- format ?: CredentialFormat | OID4VCICredentialFormat ;
27- token ?: string ;
28- version ?: OpenId4VCIVersion ;
29- subjectIssuance ?: ExperimentalSubjectIssuance ;
26+ private _builder : CredentialRequestClientBuilderVersionSpecific ;
27+
28+ private constructor ( builder : CredentialRequestClientBuilderVersionSpecific ) {
29+ this . _builder = builder ;
30+ }
3031
3132 public static fromCredentialIssuer ( {
3233 credentialIssuer,
@@ -41,25 +42,40 @@ export class CredentialRequestClientBuilder {
4142 credentialIdentifier ?: string ;
4243 credentialTypes ?: string | string [ ] ;
4344 } ) : CredentialRequestClientBuilder {
44- const issuer = credentialIssuer ;
45- const builder = new CredentialRequestClientBuilder ( ) ;
46- builder . withVersion ( version ?? OpenId4VCIVersion . VER_1_0_11 ) ;
47- builder . withCredentialEndpoint ( metadata ?. credential_endpoint ?? ( issuer . endsWith ( '/' ) ? `${ issuer } credential` : `${ issuer } /credential` ) ) ;
48- if ( metadata ?. deferred_credential_endpoint ) {
49- builder . withDeferredCredentialEndpoint ( metadata . deferred_credential_endpoint ) ;
50- }
51- if ( credentialIdentifier ) {
52- builder . withCredentialIdentifier ( credentialIdentifier ) ;
53- }
54- if ( credentialTypes ) {
55- builder . withCredentialType ( credentialTypes ) ;
45+ const specVersion = version ?? OpenId4VCIVersion . VER_1_0_13 ;
46+ let builder ;
47+
48+ if ( specVersion >= OpenId4VCIVersion . VER_1_0_13 ) {
49+ builder = CredentialRequestClientBuilderV1_0_13 . fromCredentialIssuer ( {
50+ credentialIssuer,
51+ metadata,
52+ version,
53+ credentialIdentifier,
54+ credentialTypes,
55+ } ) ;
56+ } else {
57+ if ( ! credentialTypes || credentialTypes . length === 0 ) {
58+ throw new Error ( 'CredentialTypes must be provided for v1_0_11' ) ;
59+ }
60+ builder = CredentialRequestClientBuilderV1_0_11 . fromCredentialIssuer ( {
61+ credentialIssuer,
62+ metadata,
63+ version,
64+ credentialTypes,
65+ } ) ;
5666 }
57- return builder ;
67+
68+ return new CredentialRequestClientBuilder ( builder ) ;
5869 }
5970
6071 public static async fromURI ( { uri, metadata } : { uri : string ; metadata ?: EndpointMetadata } ) : Promise < CredentialRequestClientBuilder > {
6172 const offer = await CredentialOfferClient . fromURI ( uri ) ;
62- return CredentialRequestClientBuilder . fromCredentialOfferRequest ( { request : offer , ...offer , metadata, version : offer . version } ) ;
73+ return CredentialRequestClientBuilder . fromCredentialOfferRequest ( {
74+ request : offer ,
75+ ...offer ,
76+ metadata,
77+ version : offer . version ,
78+ } ) ;
6379 }
6480
6581 public static fromCredentialOfferRequest ( opts : {
@@ -69,24 +85,17 @@ export class CredentialRequestClientBuilder {
6985 version ?: OpenId4VCIVersion ;
7086 metadata ?: EndpointMetadata ;
7187 } ) : CredentialRequestClientBuilder {
72- const { request, metadata } = opts ;
88+ const { request } = opts ;
7389 const version = opts . version ?? request . version ?? determineSpecVersionFromOffer ( request . original_credential_offer ) ;
90+ let builder ;
91+
7492 if ( version < OpenId4VCIVersion . VER_1_0_13 ) {
75- throw new Error ( 'Versions below v1.0.13 (draft 13) are not supported.' ) ;
76- }
77- const builder = new CredentialRequestClientBuilder ( ) ;
78- const issuer = getIssuerFromCredentialOfferPayload ( request . credential_offer ) ?? ( metadata ?. issuer as string ) ;
79- builder . withVersion ( version ) ;
80- builder . withCredentialEndpoint ( metadata ?. credential_endpoint ?? ( issuer . endsWith ( '/' ) ? `${ issuer } credential` : `${ issuer } /credential` ) ) ;
81- if ( metadata ?. deferred_credential_endpoint ) {
82- builder . withDeferredCredentialEndpoint ( metadata . deferred_credential_endpoint ) ;
83- }
84- const ids : string [ ] = ( request . credential_offer as CredentialOfferPayloadV1_0_13 ) . credential_configuration_ids ;
85- // if there's only one in the offer, we pre-select it. if not, you should provide the credentialType
86- if ( ids . length && ids . length === 1 ) {
87- builder . withCredentialIdentifier ( ids [ 0 ] ) ;
93+ builder = CredentialRequestClientBuilderV1_0_11 . fromCredentialOfferRequest ( opts ) ;
94+ } else {
95+ builder = CredentialRequestClientBuilderV1_0_13 . fromCredentialOfferRequest ( opts ) ;
8896 }
89- return builder ;
97+
98+ return new CredentialRequestClientBuilder ( builder ) ;
9099 }
91100
92101 public static fromCredentialOffer ( {
@@ -96,78 +105,100 @@ export class CredentialRequestClientBuilder {
96105 credentialOffer : CredentialOfferRequestWithBaseUrl ;
97106 metadata ?: EndpointMetadata ;
98107 } ) : CredentialRequestClientBuilder {
99- return CredentialRequestClientBuilder . fromCredentialOfferRequest ( {
100- request : credentialOffer ,
101- metadata,
102- version : credentialOffer . version ,
103- } ) ;
108+ const version = determineSpecVersionFromOffer ( credentialOffer . credential_offer ) ;
109+ let builder ;
110+
111+ if ( version < OpenId4VCIVersion . VER_1_0_13 ) {
112+ builder = CredentialRequestClientBuilderV1_0_11 . fromCredentialOffer ( {
113+ credentialOffer,
114+ metadata,
115+ } ) ;
116+ } else {
117+ builder = CredentialRequestClientBuilderV1_0_13 . fromCredentialOffer ( {
118+ credentialOffer,
119+ metadata,
120+ } ) ;
121+ }
122+
123+ return new CredentialRequestClientBuilder ( builder ) ;
124+ }
125+
126+ public getVersion ( ) : OpenId4VCIVersion | undefined {
127+ return this . _builder . version ;
104128 }
105129
106- public withCredentialEndpointFromMetadata ( metadata : CredentialIssuerMetadataV1_0_13 ) : this {
107- this . credentialEndpoint = metadata . credential_endpoint ;
130+ public withCredentialEndpointFromMetadata ( metadata : CredentialIssuerMetadata | CredentialIssuerMetadataV1_0_13 ) : this {
131+ if ( isV1_0_13 ( this . _builder ) ) {
132+ this . _builder . withCredentialEndpointFromMetadata ( metadata as CredentialIssuerMetadataV1_0_13 ) ;
133+ } else {
134+ this . _builder . withCredentialEndpointFromMetadata ( metadata as CredentialIssuerMetadata ) ;
135+ }
108136 return this ;
109137 }
110138
111139 public withCredentialEndpoint ( credentialEndpoint : string ) : this {
112- this . credentialEndpoint = credentialEndpoint ;
140+ this . _builder . withCredentialEndpoint ( credentialEndpoint ) ;
113141 return this ;
114142 }
115143
116- public withDeferredCredentialEndpointFromMetadata ( metadata : CredentialIssuerMetadataV1_0_13 ) : this {
117- this . deferredCredentialEndpoint = metadata . deferred_credential_endpoint ;
144+ public withDeferredCredentialEndpointFromMetadata ( metadata : CredentialIssuerMetadata | CredentialIssuerMetadataV1_0_13 ) : this {
145+ if ( isV1_0_13 ( this . _builder ) ) {
146+ this . _builder . withDeferredCredentialEndpointFromMetadata ( metadata as CredentialIssuerMetadataV1_0_13 ) ;
147+ } else {
148+ this . _builder . withDeferredCredentialEndpointFromMetadata ( metadata as CredentialIssuerMetadata ) ;
149+ }
118150 return this ;
119151 }
120152
121153 public withDeferredCredentialEndpoint ( deferredCredentialEndpoint : string ) : this {
122- this . deferredCredentialEndpoint = deferredCredentialEndpoint ;
154+ this . _builder . withDeferredCredentialEndpoint ( deferredCredentialEndpoint ) ;
123155 return this ;
124156 }
125157
126158 public withDeferredCredentialAwait ( deferredCredentialAwait : boolean , deferredCredentialIntervalInMS ?: number ) : this {
127- this . deferredCredentialAwait = deferredCredentialAwait ;
128- this . deferredCredentialIntervalInMS = deferredCredentialIntervalInMS ?? 5000 ;
159+ this . _builder . withDeferredCredentialAwait ( deferredCredentialAwait , deferredCredentialIntervalInMS ) ;
129160 return this ;
130161 }
131162
132163 public withCredentialIdentifier ( credentialIdentifier : string ) : this {
133- this . credentialIdentifier = credentialIdentifier ;
164+ if ( this . _builder . version === undefined || this . _builder . version < OpenId4VCIVersion . VER_1_0_13 ) {
165+ throw new Error ( 'Version of spec should be equal or higher than v1_0_13' ) ;
166+ }
167+ ( this . _builder as CredentialRequestClientBuilderV1_0_13 ) . withCredentialIdentifier ( credentialIdentifier ) ;
134168 return this ;
135169 }
136170
137171 public withCredentialType ( credentialTypes : string | string [ ] ) : this {
138- this . credentialTypes = Array . isArray ( credentialTypes ) ? credentialTypes : [ credentialTypes ] ;
172+ this . _builder . withCredentialType ( credentialTypes ) ;
139173 return this ;
140174 }
141175
142176 public withFormat ( format : CredentialFormat | OID4VCICredentialFormat ) : this {
143- this . format = format ;
177+ this . _builder . withFormat ( format ) ;
144178 return this ;
145179 }
146180
147181 public withSubjectIssuance ( subjectIssuance : ExperimentalSubjectIssuance ) : this {
148- this . subjectIssuance = subjectIssuance ;
182+ this . _builder . withSubjectIssuance ( subjectIssuance ) ;
149183 return this ;
150184 }
151185
152186 public withToken ( accessToken : string ) : this {
153- this . token = accessToken ;
187+ this . _builder . withToken ( accessToken ) ;
154188 return this ;
155189 }
156190
157191 public withTokenFromResponse ( response : AccessTokenResponse ) : this {
158- this . token = response . access_token ;
192+ this . _builder . withTokenFromResponse ( response ) ;
159193 return this ;
160194 }
161195
162196 public withVersion ( version : OpenId4VCIVersion ) : this {
163- this . version = version ;
197+ this . _builder . withVersion ( version ) ;
164198 return this ;
165199 }
166200
167- public build ( ) : CredentialRequestClient {
168- if ( ! this . version ) {
169- this . withVersion ( OpenId4VCIVersion . VER_1_0_11 ) ;
170- }
171- return new CredentialRequestClient ( this ) ;
201+ public build ( ) {
202+ return this . _builder . build ( ) ;
172203 }
173204}
0 commit comments