PageSourceSearch

https://1keep.com/_app/immutable/entry/(app)-credentials-new-oid4vci-page.svelte.361bac6f.js

js 1keep.com collected 2026-09-28 06:37:05 UTC 36,410 bytes, 1,284 lines download raw bytes

1import { S as SvelteComponent, i as init, s as safe_not_equal, e as empty, b as insert_hydration, d as transition_out, f as check_outros, g as transition_in, h as detach, L as component_subscribe, o as onMount, v as group_outros, Z as get_store_value, y as create_component, z as claim_component, A as mount_component, C as noop, B as destroy_component, k as element, l as claim_element, m as children, n as attr, P as destroy_each, q as text, a as space, r as claim_text, c as claim_space, K as append_hydration, N as listen, E as run_all } from '../chunks/index.ce768326.js';
2import { p as page } from '../chunks/stores.d4b0c126.js';
3import '../chunks/pbkdf2.2a33b8e7.js';
4import { f as findTheMagic, w as wallet, h as getVerificationKeyForDID } from '../chunks/wallet.f9c29244.js';
5import '../chunks/sha256.4d501cbe.js';
6import { e as encode } from '../chunks/MiniCollectible.svelte_svelte_type_style_lang.6e7fac41.js';
7import { L as Large } from '../chunks/Large.2444f5ca.js';
8import { g as goto } from '../chunks/navigation.3e146b75.js';
9import { L as Loading } from '../chunks/Loading.f65422fb.js';
10import { V as VerifiablePresentationRequest } from '../chunks/VerifiablePresentationRequest.5706074b.js';
11import { _ as __vitePreload } from '../chunks/preload-helper.6910039e.js';
12import { c as chapiEvent } from '../chunks/chapi.de903e50.js';
13
14/*!
15 * Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved.
16 */
17// no-op for browsers
18function convertAgent(options) {
19  return options;
20}
21
22function deferred(f) {
23  let promise;
24
25  return {
26    then(
27      onfulfilled,
28      onrejected
29    ) {
30      // Use logical OR assignment when Node.js 14.x support is dropped
31      //promise ||= new Promise(resolve => resolve(f()));
32      promise || (promise = new Promise(resolve => resolve(f())));
33      return promise.then(
34        onfulfilled,
35        onrejected
36      );
37    },
38  };
39}
40
41const kyOriginalPromise = deferred(() => __vitePreload(() => import('../chunks/browser.0113dac2.js'),true?[]:void 0,import.meta.url)
42  .then(({default: ky}) => ky));
43
44const DEFAULT_HEADERS = {
45  Accept: 'application/ld+json, application/json'
46};
47
48// methods to proxy from ky
49const PROXY_METHODS = new Set([
50  'get', 'post', 'put', 'push', 'patch', 'head', 'delete'
51]);
52
53/**
54 * Returns a custom httpClient instance. Used to specify default headers and
55 * other default overrides.
56 *
57 * @param {object} [options={}] - Options hashmap.
58 * @param {object} [options.parent] - The ky promise to inherit from.
59 * @param {object} [options.headers={}] - Default header overrides.
60 * @param {object} [options.params] - Other default overrides.
61 *
62 * @returns {Function} Custom httpClient instance.
63 */
64function createInstance({
65  parent = kyOriginalPromise, headers = {}, ...params
66} = {}) {
67  // convert legacy agent options
68  params = convertAgent(params);
69
70  // create new ky instance that will asynchronously resolve
71  const kyPromise = deferred(() => parent.then(kyBase => {
72    let ky;
73    if(parent === kyOriginalPromise) {
74      // ensure default headers, allow overrides
75      ky = kyBase.create({
76        headers: {...DEFAULT_HEADERS, ...headers},
77        ...params
78      });
79    } else {
80      // extend parent
81      ky = kyBase.extend({headers, ...params});
82    }
83    return ky;
84  }));
85
86  return _createHttpClient(kyPromise);
87}
88
89function _createHttpClient(kyPromise) {
90  async function httpClient(...args) {
91    const ky = await kyPromise;
92    const method = ((args[1] && args[1].method) || 'get').toLowerCase();
93    if(PROXY_METHODS.has(method)) {
94      return httpClient[method].apply(ky[method], args);
95    }
96
97    // convert legacy agent options
98    args[1] = convertAgent(args[1]);
99    return ky.apply(ky, args);
100  }
101
102  for(const method of PROXY_METHODS) {
103    httpClient[method] = async function(...args) {
104      const ky = await kyPromise;
105      return _handleResponse(ky[method], ky, args);
106    };
107  }
108
109  httpClient.create = function({headers = {}, ...params}) {
110    return createInstance({headers, ...params});
111  };
112
113  httpClient.extend = function({headers = {}, ...params}) {
114    return createInstance({parent: kyPromise, headers, ...params});
115  };
116
117  // default async `stop` signal getter
118  Object.defineProperty(httpClient, 'stop', {
119    async get() {
120      const ky = await kyPromise;
121      return ky.stop;
122    }
123  });
124
125  return httpClient;
126}
127
128async function _handleResponse(target, thisArg, args) {
129  // convert legacy agent options
130  args[1] = convertAgent(args[1]);
131
132  let response;
133  const [url] = args;
134  try {
135    response = await target.apply(thisArg, args);
136  } catch(error) {
137    return _handleError({error, url});
138  }
139  const {parseBody = true} = args[1] || {};
140  // always set 'data', default to undefined
141  let data;
142  if(parseBody) {
143    // a 204 will not include a content-type header
144    const contentType = response.headers.get('content-type');
145    if(contentType && contentType.includes('json')) {
146      data = await response.json();
147    }
148  }
149  Object.defineProperty(response, 'data', {value: data});
150  return response;
151}
152
153/**
154 * @param {object} options - Options hashmap.
155 * @param {Error} options.error - Error thrown during http operation.
156 * @param {string} options.url - Target URL of the request.
157 *
158 * @returns {Promise} Rejects with a thrown error.
159 */
160async function _handleError({error, url}) {
161  error.requestUrl = url;
162
163  // handle network errors and system errors that do not have a response
164  if(!error.response) {
165    if(error.message === 'Failed to fetch') {
166      error.message = `Failed to fetch "${url}". Possible CORS error.`;
167    }
168    // ky's TimeoutError class
169    if(error.name === 'TimeoutError') {
170      error.message = `Request to "${url}" timed out.`;
171    }
172
173    throw error;
174  }
175
176  // always move status up to the root of error
177  error.status = error.response.status;
178
179  const contentType = error.response.headers.get('content-type');
180  if(contentType && contentType.includes('json')) {
181    const errorBody = await error.response.json();
182    // the HTTPError received from ky has a generic message based on status
183    // use that if the JSON body does not include a message
184    error.message = errorBody.message || error.message;
185    error.data = errorBody;
186  }
187  throw error;
188}
189
190/*!
191 * Copyright (c) 2020-2022 Digital Bazaar, Inc. All rights reserved.
192 */
193
194const httpClient = createInstance();
195
196/*!
197 * Copyright (c) 2022-2023 Digital Bazaar, Inc. All rights reserved.
198 */
199
200const TEXT_ENCODER = new TextEncoder();
201const ENCODED_PERIOD = TEXT_ENCODER.encode('.');
202const WELL_KNOWN_REGEX = /\/\.well-known\/([^\/]+)/;
203
204async function discoverIssuer({issuerConfigUrl, agent} = {}) {
205  try {
206    if(!(issuerConfigUrl && typeof issuerConfigUrl === 'string')) {
207      throw new TypeError('"issuerConfigUrl" must be a string.');
208    }
209
210    const response = await _fetchJSON({url: issuerConfigUrl, agent});
211    if(!response.data) {
212      const error = new Error('Issuer configuration format is not JSON.');
213      error.name = 'DataError';
214      throw error;
215    }
216
217    const {data: issuerMetaData} = response;
218    const {issuer, authorization_server} = issuerMetaData;
219
220    if(authorization_server && authorization_server !== issuer) {
221      // not yet implemented
222      throw new Error('Separate authorization server not yet implemented.');
223    }
224
225    // validate `issuer`
226    if(!(typeof issuer === 'string' && issuer.startsWith('https://'))) {
227      const error = new Error('"issuer" is not an HTTPS URL.');
228      error.name = 'DataError';
229      throw error;
230    }
231
232    /* Validate `issuer` value against `issuerConfigUrl` (per RFC 8414):
233
234    The `origin` and `path` element must be parsed from `issuer` and checked
235    against `issuerConfigUrl` like so:
236
237    For issuer `<origin>` (no path), `issuerConfigUrl` must match:
238    `<origin>/.well-known/<any-path-segment>`
239
240    For issuer `<origin><path>`, `issuerConfigUrl` must be:
241    `<origin>/.well-known/<any-path-segment><path>` */
242    const {pathname: wellKnownPath} = new URL(issuerConfigUrl);
243    const anyPathSegment = wellKnownPath.match(WELL_KNOWN_REGEX)[1];
244    const {origin, pathname} = new URL(issuer);
245    let expectedConfigUrl = `${origin}/.well-known/${anyPathSegment}`;
246    if(pathname !== '/') {
247      expectedConfigUrl += pathname;
248    }
249    if(issuerConfigUrl !== expectedConfigUrl) {
250      const error = new Error('"issuer" does not match configuration URL.');
251      error.name = 'DataError';
252      throw error;
253    }
254
255    // fetch AS meta data
256    const asMetaDataUrl =
257      `${origin}/.well-known/oauth-authorization-server${pathname}`;
258    const asMetaDataResponse = await _fetchJSON({url: asMetaDataUrl, agent});
259    if(!asMetaDataResponse.data) {
260      const error = new Error('Authorization server meta data is not JSON.');
261      error.name = 'DataError';
262      throw error;
263    }
264
265    const {data: asMetaData} = response;
266    // merge AS meta data into total issuer config
267    const issuerConfig = {...issuerMetaData, ...asMetaData};
268
269    // ensure `token_endpoint` is valid
270    const {token_endpoint} = asMetaData;
271    if(!(token_endpoint && typeof token_endpoint === 'string')) {
272      const error = new TypeError('"token_endpoint" must be a string.');
273      error.name = 'DataError';
274      throw error;
275    }
276
277    // return merged config and separate issuer and AS configs
278    const metadata = {issuer: issuerMetaData, authorizationServer: asMetaData};
279    return {issuerConfig, metadata};
280  } catch(cause) {
281    const error = new Error('Could not get OpenID issuer configuration.');
282    error.name = 'OperationError';
283    error.cause = cause;
284    throw error;
285  }
286}
287
288async function generateDIDProofJWT({
289  signer, nonce, iss, aud, exp, nbf
290} = {}) {
291  /* Example:
292  {
293    "alg": "ES256",
294    "kid":"did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1"
295  }.
296  {
297    "iss": "s6BhdRkqt3",
298    "aud": "https://server.example.com",
299    "iat": 1659145924,
300    "nonce": "tZignsnFbp"
301  }
302  */
303
304  if(exp === undefined) {
305    // default to 5 minute expiration time
306    exp = Math.floor(Date.now() / 1000) + 60 * 5;
307  }
308  if(nbf === undefined) {
309    // default to now
310    nbf = Math.floor(Date.now() / 1000);
311  }
312
313  const {id: kid} = signer;
314  const alg = _curveToAlg(signer.algorithm);
315  const payload = {nonce, iss, aud, exp, nbf};
316  const protectedHeader = {alg, kid};
317
318  return signJWT({payload, protectedHeader, signer});
319}
320
321async function signJWT({payload, protectedHeader, signer} = {}) {
322  // encode payload and protected header
323  const b64Payload = encode(JSON.stringify(payload));
324  const b64ProtectedHeader = encode(JSON.stringify(protectedHeader));
325  payload = TEXT_ENCODER.encode(b64Payload);
326  protectedHeader = TEXT_ENCODER.encode(b64ProtectedHeader);
327
328  // concatenate
329  const data = new Uint8Array(
330    protectedHeader.length + ENCODED_PERIOD.length + payload.length);
331  data.set(protectedHeader);
332  data.set(ENCODED_PERIOD, protectedHeader.length);
333  data.set(payload, protectedHeader.length + ENCODED_PERIOD.length);
334
335  // sign
336  const signature = await signer.sign({data});
337
338  // create JWS
339  const jws = {
340    signature: encode(signature),
341    payload: b64Payload,
342    protected: b64ProtectedHeader
343  };
344
345  // create compact JWT
346  return `${jws.protected}.${jws.payload}.${jws.signature}`;
347}
348
349function _curveToAlg(crv) {
350  if(crv === 'Ed25519' || crv === 'Ed448') {
351    return 'EdDSA';
352  }
353  if(crv?.startsWith('P-')) {
354    return `ES${crv.slice(2)}`;
355  }
356  if(crv === 'secp256k1') {
357    return 'ES256K';
358  }
359  return crv;
360}
361
362function _fetchJSON({url, agent}) {
363  // allow these params to be passed / configured
364  const fetchOptions = {
365    // max size for issuer config related responses (in bytes, ~4 KiB)
366    size: 4096,
367    // timeout in ms for fetching an issuer config
368    timeout: 5000,
369    agent
370  };
371
372  return httpClient.get(url, fetchOptions);
373}
374
375/*!
376 * Copyright (c) 2022-2023 Digital Bazaar, Inc. All rights reserved.
377 */
378
379const GRANT_TYPES = new Map([
380  ['preAuthorizedCode', 'urn:ietf:params:oauth:grant-type:pre-authorized_code']
381]);
382const HEADERS = {accept: 'application/json'};
383
384class OID4Client {
385  constructor({accessToken = null, agent, issuerConfig, metadata, offer} = {}) {
386    this.accessToken = accessToken;
387    this.agent = agent;
388    this.metadata = metadata;
389    this.issuerConfig = issuerConfig;
390    this.offer = offer;
391  }
392
393  async requestCredential({
394    credentialDefinition, did, didProofSigner, agent
395  } = {}) {
396    const {issuerConfig, offer} = this;
397    let requests;
398    if(credentialDefinition === undefined) {
399      if(!offer) {
400        throw new TypeError('"credentialDefinition" must be an object.');
401      }
402      requests = _createCredentialRequestsFromOffer({issuerConfig, offer});
403      if(requests.length > 1) {
404        throw new Error(
405          'More than one credential is offered; ' +
406          'use "requestCredentials()" instead.');
407      }
408    } else {
409      requests = [{
410        format: 'ldp_vc',
411        credential_definition: credentialDefinition
412      }];
413    }
414    return this.requestCredentials({requests, did, didProofSigner, agent});
415  }
416
417  async requestCredentials({
418    requests, did, didProofSigner, agent, alwaysUseBatchEndpoint = false
419  }
419 = {}) {
420    const {issuerConfig, offer} = this;
421    if(requests === undefined && offer) {
422      requests = _createCredentialRequestsFromOffer({issuerConfig, offer});
423    } else if(!(Array.isArray(requests) && requests.length > 0)) {
424      throw new TypeError('"requests" must be an array of length >= 1.');
425    }
426    requests.forEach(_assertRequest);
427    // set default `format`
428    requests = requests.map(r => ({format: 'ldp_vc', ...r}));
429
430    try {
431      /* First send credential request(s) to DS without DID proof JWT, e.g.:
432
433      POST /credential HTTP/1.1
434      Host: server.example.com
435      Content-Type: application/json
436      Authorization: BEARER czZCaGRSa3F0MzpnWDFmQmF0M2JW
437
438      {
439        "format": "ldp_vc",
440        "credential_definition": {...},
441        // only present on retry after server requests it
442        "proof": {
443          "proof_type": "jwt",
444          "jwt": "eyJraW..."
445        }
446      }
447
448      OR (if multiple `requests` were given)
449
450      POST /batch_credential HTTP/1.1
451      Host: server.example.com
452      Content-Type: application/json
453      Authorization: BEARER czZCaGRSa3F0MzpnWDFmQmF0M2JW
454
455      {
456        "credential_requests": [{
457          "format": "ldp_vc",
458          "credential_definition": {...},
459          // only present on retry after server requests it
460          "proof": {
461            "proof_type": "jwt",
462            "jwt": "eyJraW..."
463          }
464        }, {
465          ...
466        }]
467      }
468      */
469      let url;
470      let json;
471      if(requests.length > 1 || alwaysUseBatchEndpoint) {
472        ({batch_credential_endpoint: url} = this.issuerConfig);
473        json = {credential_requests: requests};
474      } else {
475        ({credential_endpoint: url} = this.issuerConfig);
476        json = {...requests[0]};
477      }
478
479      let result;
480      const headers = {
481        ...HEADERS,
482        authorization: `Bearer ${this.accessToken}`
483      };
484      for(let retries = 0; retries <= 1; ++retries) {
485        try {
486          const response = await httpClient.post(url, {agent, headers, json});
487          result = response.data;
488          if(!result) {
489            const error = new Error('Credential response format is not JSON.');
490            error.name = 'DataError';
491            throw error;
492          }
493          break;
494        } catch(cause) {
495          if(!_isMissingProofError(cause)) {
496            // non-specific error case
497            throw cause;
498          }
499
500          // if `didProofSigner` is not provided, throw error
501          if(!(did && didProofSigner)) {
502            const {data: details} = cause;
503            const error = new Error('DID authentication is required.');
504            error.name = 'NotAllowedError';
505            error.cause = cause;
506            error.details = details;
507            throw error;
508          }
509
510          // validate that `result` has
511          const {data: {c_nonce: nonce}} = cause;
512          if(!(nonce && typeof nonce === 'string')) {
513            const error = new Error('No DID proof challenge specified.');
514            error.name = 'DataError';
515            throw error;
516          }
517
518          // generate a DID proof JWT
519          const {issuer: aud} = this.issuerConfig;
520          const jwt = await generateDIDProofJWT({
521            signer: didProofSigner,
522            nonce,
523            // the entity identified by the DID is issuing this JWT
524            iss: did,
525            // audience MUST be the target issuer per the OID4VC spec
526            aud
527          });
528
529          // add proof to body to be posted and loop to retry
530          const proof = {proof_type: 'jwt', jwt};
531          if(json.credential_requests) {
532            json.credential_requests = json.credential_requests.map(
533              cr => ({...cr, proof}));
534          } else {
535            json.proof = proof;
536          }
537        }
538      }
539
540      // wallet / client receives credential:
541      /* Note: The credential is not wrapped here in a VP in the current spec:
542
543      HTTP/1.1 200 OK
544        Content-Type: application/json
545        Cache-Control: no-store
546
547      {
548        "format": "ldp_vc"
549        "credential" : {...}
550      }
551
552      OR (if multiple `requests` were given)
553
554      {
555        "credential_responses": [{
556          "format": "ldp_vc",
557          "credential": {...}
558        }]
559      }
560      */
561      return result;
562    } catch(cause) {
563      const error = new Error('Could not receive credentials.');
564      error.name = 'OperationError';
565      error.cause = cause;
566      throw error;
567    }
568  }
569
570  // create a client from a credential offer
571  static async fromCredentialOffer({offer, agent} = {}) {
572    // validate offer
573    const {credential_issuer, credentials, grants = {}} = offer;
574    let parsedIssuer;
575    try {
576      parsedIssuer = new URL(credential_issuer);
577      if(parsedIssuer.protocol !== 'https:') {
578        throw new Error('Only "https" credential issuer URLs are supported.');
579      }
580    } catch(e) {
581      const err = new Error('"offer.credential_issuer" is not valid.');
582      err.cause = e;
583      throw err;
584    }
585    if(!(Array.isArray(credentials) && credentials.length > 0 &&
586      credentials.every(c => c && typeof c === 'object'))) {
587      throw new Error('"offer.credentials" is not valid.');
588    }
589    const grant = grants[GRANT_TYPES.get('preAuthorizedCode')];
590    if(!grant) {
591      // FIXME: implement `authorization_code` grant type as well
592      throw new Error('Only "pre-authorized_code" grant type is implemented.');
593    }
594    const {
595      'pre-authorized_code': preAuthorizedCode,
596      user_pin_required: userPinRequired
597    } = grant;
598    if(!preAuthorizedCode) {
599      throw new Error('"offer.grant" is missing "pre-authorized_code".');
600    }
601    if(userPinRequired) {
602      throw new Error('User pin is not implemented.');
603    }
604
605    try {
606      // discover issuer info
607      const issuerConfigUrl =
608        `${parsedIssuer.origin}/.well-known/openid-credential-issuer` +
609        parsedIssuer.pathname;
610      const {issuerConfig, metadata} = await discoverIssuer(
611        {issuerConfigUrl, agent});
612
613      /* First get access token from AS (Authorization Server), e.g.:
614
615      POST /token HTTP/1.1
616        Host: server.example.com
617        Content-Type: application/x-www-form-urlencoded
618        grant_type=urn:ietf:params:oauth:grant-type:pre-authorized_code
619        &pre-authorized_code=SplxlOBeZQQYbYS6WxSbIA
620        &user_pin=493536
621
622      Note a bad response would look like:
623
624      /*
625      HTTP/1.1 400 Bad Request
626      Content-Type: application/json
627      Cache-Control: no-store
628      {
629        "error": "invalid_request"
630      }
631      */
632      const body = new URLSearchParams();
633      body.set('grant_type', GRANT_TYPES.get('preAuthorizedCode'));
634      body.set('pre-authorized_code', preAuthorizedCode);
635      const {token_endpoint} = issuerConfig;
636      const response = await httpClient.post(token_endpoint, {
637        agent, body, headers: HEADERS
638      });
639      const {data: result} = response;
640      if(!result) {
641        const error = new Error(
642          'Could not get access token; response is not JSON.');
643        error.name = 'DataError';
644        throw error;
645      }
646
647      /* Validate response body (Note: Do not check or use `c_nonce*` here
648      because it conflates AS with DS (Delivery Server)), e.g.:
649
650      HTTP/1.1 200 OK
651        Content-Type: application/json
652        Cache-Control: no-store
653
654        {
655          "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6Ikp..sHQ",
656          "token_type": "bearer",
657          "expires_in": 86400
658        }
659      */
660      const {access_token: accessToken, token_type} = result;
661      if(!(accessToken && typeof accessToken === 'string')) {
662        const error = new Error(
663          'Invalid access token response; "access_token" must be a string.');
664        error.name = 'DataError';
665        throw error;
666      }
667      if(token_type !== 'bearer') {
668        const error = new Error(
669          'Invalid access token response; "token_type" must be a "bearer".');
670        error.name = 'DataError';
671        throw error;
672      }
673
674      // create client w/access token
675      return new OID4Client(
676        {accessToken, agent, issuerConfig, metadata, offer});
677    } catch(cause) {
678      const error = new Error('Could not create OID4 client.');
679      error.name = 'OperationError';
680      error.cause = cause;
681      throw error;
682    }
683  }
684}
685
686function _assertRequest(request) {
687  if(!(request && typeof request === 'object')) {
688    throw new TypeError('"request" must be an object.');
689  }
690  const {credential_definition, format} = request;
691  if(format !== undefined && format !== 'ldp_vc') {
692    throw new TypeError('Credential request "format" must be "ldp_vc".');
693  }
694  if(!(credential_definition && typeof credential_definition === 'object')) {
695    throw new TypeError(
696      'Credential request "credential_definition" must be an object.');
697  }
698  const {'@context': context, type: type} = credential_definition;
699  if(!(Array.isArray(context) && context.length > 0)) {
700    throw new TypeError(
701      'Credential definition "@context" must be an array of length >= 1.');
702  }
703  if(!(Array.isArray(type) && type.length > 0)) {
704    throw new TypeError(
705      'Credential definition "type" must be an array of length >= 2.');
706  }
707}
708
709function _isMissingProofError(error) {
710  /* If DID authn is required, delivery server sends, e.g.:
711
712  HTTP/1.1 400 Bad Request
713    Content-Type: application/json
714    Cache-Control: no-store
715
716  {
717    "error": "invalid_or_missing_proof"
718    "error_description":
719        "Credential issuer requires proof element in Credential Request"
720    "c_nonce": "8YE9hCnyV2",
721    "c_nonce_expires_in": 86400
722  }
723  */
724  return error.status === 400 &&
725    error?.data?.error === 'invalid_or_missing_proof';
726}
727
728function _createCredentialRequestFromId({id, issuerConfig}) {
729  const {credentials_supported: supported = []} = issuerConfig;
730  const meta = supported.find(d => d.id === id);
731  if(!meta) {
732    throw new Error(`No supported credential "${id}" found.`);
733  }
734  const {format, credential_definition} = meta;
735  if(typeof format !== 'string') {
736    throw new Error(
737      `Invalid supported credential "${id}"; "format" not specified.`);
738  }
739  if(format !== 'ldp_vc') {
740    throw new Error(`Unsupported "format" "${format}".`);
741  }
742  if(!(Array.isArray(credential_definition?.['@context']) &&
743    Array.isArray(credential_definition?.types))) {
744    throw new Error(
745      `Invalid supported credential "${id}"; "credential_definition" not ` +
746      'fully specified.');
747  }
748  return {format, credential_definition};
749}
750
751function _createCredentialRequestsFromOffer({issuerConfig, offer}) {
752  // build requests from `offer`
753  return offer.credentials.map(c => {
754    if(typeof c === 'string') {
755      // use issuer config metadata to dereference string
756      return _createCredentialRequestFromId({id: c, issuerConfig});
757    }
758    return c;
759  });
760}
761
762/* src/routes/(app)/credentials/new/oid4vci/+page.svelte generated by Svelte v3.58.0 */
763
764function get_each_context(ctx, list, i) {
765	const child_ctx = ctx.slice();
766	child_ctx[13] = list[i];
767	child_ctx[15] = i;
768	return child_ctx;
769}
770
771// (109:0) {:else}
772function create_else_block(ctx) {
773	let loading;
774	let current;
775	loading = new Loading({});
776
777	return {
778		c() {
779			create_component(loading.$$.fragment);
780		},
781		l(nodes) {
782			claim_component(loading.$$.fragment, nodes);
783		},
784		m(target, anchor) {
785			mount_component(loading, target, anchor);
786			current = true;
787		},
788		p: noop,
789		i(local) {
790			if (current) return;
791			transition_in(loading.$$.fragment, local);
792			current = true;
793		},
794		o(local) {
795			transition_out(loading.$$.fragment, local);
796			current = false;
797		},
798		d(detaching) {
799			destroy_component(loading, detaching);
800		}
801	};
802}
803
804// (107:14) 
805function create_if_block_2(ctx) {
806	let verifiablepresentationrequest;
807	let current;
808
809	verifiablepresentationrequest = new VerifiablePresentationRequest({
810			props: {
811				vpr: /*vpr*/ ctx[0],
812				created: /*respondToVPR*/ ctx[5]
813			}
814		});
815
816	return {
817		c() {
818			create_component(verifiablepresentationrequest.$$.fragment);
819		},
820		l(nodes) {
821			claim_component(verifiablepresentationrequest.$$.fragment, nodes);
822		},
823		m(target, anchor) {
824			mount_component(verifiablepresentationrequest, target, anchor);
825			current = true;
826		},
827		p(ctx, dirty) {
828			const verifiablepresentationrequest_changes = {};
829			if (dirty & /*vpr*/ 1) verifiablepresentationrequest_changes.vpr = /*vpr*/ ctx[0];
830			verifiablepresentationrequest.$set(verifiablepresentationrequest_changes);
831		},
832		i(local) {
833			if (current) return;
834			transition_in(verifiablepresentationrequest.$$.fragment, local);
835			current = true;
836		},
837		o(local) {
838			transition_out(verifiablepresentationrequest.$$.fragment, local);
839			current = false;
840		},
841		d(detaching) {
842			destroy_component(verifiablepresentationrequest, detaching);
843		}
844	};
845}
846
847// (91:0) {#if vcs.length > 0}
848function create_if_block(ctx) {
849	let div;
850	let current;
851	let each_value = /*vcs*/ ctx[1];
852	let each_blocks = [];
853
854	for (let i = 0; i < each_value.length; i += 1) {
855		each_blocks[i] = create_each_block(get_each_context(ctx, each_value, i));
856	}
857
858	const out = i => transition_out(each_blocks[i], 1, 1, () => {
859		each_blocks[i] = null;
860	});
861
862	return {
863		c() {
864			div = element("div");
865
866			for (let i = 0; i < each_blocks.length; i += 1) {
867				each_blocks[i].c();
868			}
869
870			this.h();
871		},
872		l(nodes) {
873			div = claim_element(nodes, "DIV", { class: true });
874			var div_nodes = children(div);
875
876			for (let i = 0; i < each_blocks.length; i += 1) {
877				each_blocks[i].l(div_nodes);
878			}
879
880			div_nodes.forEach(detach);
881			this.h();
882		},
883		h() {
884			attr(div, "class", "p-3");
885		},
886		m(target, anchor) {
887			insert_hydration(target, div, anchor);
888
889			for (let i = 0; i < each_blocks.length; i += 1) {
890				if (each_blocks[i]) {
891					each_blocks[i].m(div, null);
892				}
893			}
894
895			current = true;
896		},
897		p(ctx, dirty) {
898			if (dirty & /*vcs, skipVC, addVC, handled*/ 30) {
899				each_value = /*vcs*/ ctx[1];
900				let i;
901
902				for (i = 0; i < each_value.length; i += 1) {
903					const child_ctx = get_each_context(ctx, each_value, i);
904
905					if (each_blocks[i]) {
906						each_blocks[i].p(child_ctx, dirty);
907						transition_in(each_blocks[i], 1);
908					} else {
909						each_blocks[i] = create_each_block(child_ctx);
910						each_blocks[i].c();
911						transition_in(each_blocks[i], 1);
912						each_blocks[i].m(div, null);
913					}
914				}
915
916				group_outros();
917
918				for (i = each_value.length; i < each_blocks.length; i += 1) {
919					out(i);
920				}
921
922				check_outros();
923			}
924		},
925		i(local) {
926			if (current) return;
927
928			for (let i = 0; i < each_value.length; i += 1) {
929				transition_in(each_blocks[i]);
930			}
931
932			current = true;
933		},
934		o(local) {
935			each_blocks = each_blocks.filter(Boolean);
936
937			for (let i = 0; i < each_blocks.length; i += 1) {
938				transition_out(each_blocks[i]);
939			}
940
941			current = false;
942		},
943		d(detaching) {
944			if (detaching) detach(div);
945			destroy_each(each_blocks, detaching);
946		}
947	};
948}
949
950// (94:3) {#if !handled[index]}
951function create_if_block_1(ctx) {
952	let div;
953	let button0;
954	let t0;
955	let t1;
956	let button1;
957	let t2;
958	let t3;
959	let largecredential;
960	let current;
961	let mounted;
962	let dispose;
963
964	function click_handler() {
965		return /*click_handler*/ ctx[6](/*index*/ ctx[15], /*vc*/ ctx[13]);
966	}
967
968	function click_handler_1() {
969		return /*click_handler_1*/ ctx[7](/*index*/ ctx[15]);
970	}
971
972	largecredential = new Large({
973			props: {
974				entry: /*vc*/ ctx[13],
975				rotation: 'a51000000000'
976			}
977		});
978
979	return {
980		c() {
981			div = element("div");
982			button0 = element("button");
983			t0 = text("Accept");
984			t1 = space();
985			button1 = element("button");
986			t2 = text("Reject");
987			t3 = space();
988			create_component(largecredential.$$.fragment);
989			this.h();
990		},
991		l(nodes) {
992			div = claim_element(nodes, "DIV", { class: true });
993			var div_nodes = children(div);
994			button0 = claim_element(div_nodes, "BUTTON", { class: true });
995			var button0_nodes = children(button0);
996			t0 = claim_text(button0_nodes, "Accept");
997			button0_nodes.forEach(detach);
998			t1 = claim_space(div_nodes);
999			button1 = claim_element(div_nodes, "BUTTON", { class: true });
1000			var button1_nodes = children(button1);
1001			t2 = claim_text(button1_nodes, "Reject");
1002			button1_nodes.forEach(detach);
1003			div_nodes.forEach(detach);
1004			t3 = claim_space(nodes);
1005			claim_component(largecredential.$$.fragment, nodes);
1006			this.h();
1007		},
1008		h() {
1009			attr(button0, "class", "bg-amber-300 text-stone-800 w-full");
1010			attr(button1, "class", "border-amber-300 border-4 text-stone-800");
1011			attr(div, "class", "grid grid-cols-2 relative bg-white/50 backdrop-blur-md w-full");
1012		},
1013		m(target, anchor) {
1014			insert_hydration(target, div, anchor);
1015			append_hydration(div, button0);
1016			append_hydration(button0, t0);
1017			append_hydration(div, t1);
1018			append_hydration(div, button1);
1019			append_hydration(button1, t2);
1020			insert_hydration(target, t3, anchor);
1021			mount_component(largecredential, target, anchor);
1022			current = true;
1023
1024			if (!mounted) {
1025				dispose = [
1026					listen(button0, "click", click_handler),
1027					listen(button1, "click", click_handler_1)
1028				];
1029
1030				mounted = true;
1031			}
1032		},
1033		p(new_ctx, dirty) {
1034			ctx = new_ctx;
1035			const largecredential_changes = {};
1036			if (dirty & /*vcs*/ 2) largecredential_changes.entry = /*vc*/ ctx[13];
1037			largecredential.$set(largecredential_changes);
1038		},
1039		i(local) {
1040			if (current) return;
1041			transition_in(largecredential.$$.fragment, local);
1042			current = true;
1043		},
1044		o(local) {
1045			transition_out(largecredential.$$.fragment, local);
1046			current = false;
1047		},
1048		d(detaching) {
1049			if (detaching) detach(div);
1050			if (detaching) detach(t3);
1051			destroy_component(largecredential, detaching);
1052			mounted = false;
1053			run_all(dispose);
1054		}
1055	};
1056}
1057
1058// (93:2) {#each vcs as vc, index}
1059function create_each_block(ctx) {
1060	let if_block_anchor;
1061	let current;
1062	let if_block = !/*handled*/ ctx[2][/*index*/ ctx[15]] && create_if_block_1(ctx);
1063
1064	return {
1065		c() {
1066			if (if_block) if_block.c();
1067			if_block_anchor = empty();
1068		},
1069		l(nodes) {
1070			if (if_block) if_block.l(nodes);
1071			if_block_anchor = empty();
1072		},
1073		m(target, anchor) {
1074			if (if_block) if_block.m(target, anchor);
1075			insert_hydration(target, if_block_anchor, anchor);
1076			current = true;
1077		},
1078		p(ctx, dirty) {
1079			if (!/*handled*/ ctx[2][/*index*/ ctx[15]]) {
1080				if (if_block) {
1081					if_block.p(ctx, dirty);
1082
1083					if (dirty & /*handled*/ 4) {
1084						transition_in(if_block, 1);
1085					}
1086				} else {
1087					if_block = create_if_block_1(ctx);
1088					if_block.c();
1089					transition_in(if_block, 1);
1090					if_block.m(if_block_anchor.parentNode, if_block_anchor);
1091				}
1092			} else if (if_block) {
1093				group_outros();
1094
1095				transition_out(if_block, 1, 1, () => {
1096					if_block = null;
1097				});
1098
1099				check_outros();
1100			}
1101		},
1102		i(local) {
1103			if (current) return;
1104			transition_in(if_block);
1105			current = true;
1106		},
1107		o(local) {
1108			transition_out(if_block);
1109			current = false;
1110		},
1111		d(detaching) {
1112			if (if_block) if_block.d(detaching);
1113			if (detaching) detach(if_block_anchor);
1114		}
1115	};
1116}
1117
1118function create_fragment(ctx) {
1119	let current_block_type_index;
1120	let if_block;
1121	let if_block_anchor;
1122	let current;
1123	const if_block_creators = [create_if_block, create_if_block_2, create_else_block];
1124	const if_blocks = [];
1125
1126	function select_block_type(ctx, dirty) {
1127		if (/*vcs*/ ctx[1].length > 0) return 0;
1128		if (/*vpr*/ ctx[0]) return 1;
1129		return 2;
1130	}
1131
1132	current_block_type_index = select_block_type(ctx);
1133	if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
1134
1135	return {
1136		c() {
1137			if_block.c();
1138			if_block_anchor = empty();
1139		},
1140		l(nodes) {
1141			if_block.l(nodes);
1142			if_block_anchor = empty();
1143		},
1144		m(target, anchor) {
1145			if_blocks[current_block_type_index].m(target, anchor);
1146			insert_hydration(target, if_block_anchor, anchor);
1147			current = true;
1148		},
1149		p(ctx, [dirty]) {
1150			let previous_block_index = current_block_type_index;
1151			current_block_type_index = select_block_type(ctx);
1152
1153			if (current_block_type_index === previous_block_index) {
1154				if_blocks[current_block_type_index].p(ctx, dirty);
1155			} else {
1156				group_outros();
1157
1158				transition_out(if_blocks[previous_block_index], 1, 1, () => {
1159					if_blocks[previous_block_index] = null;
1160				});
1161
1162				check_outros();
1163				if_block = if_blocks[current_block_type_index];
1164
1165				if (!if_block) {
1166					if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
1167					if_block.c();
1168				} else {
1169					if_block.p(ctx, dirty);
1170				}
1171
1172				transition_in(if_block, 1);
1173				if_block.m(if_block_anchor.parentNode, if_block_anchor);
1174			}
1175		},
1176		i(local) {
1177			if (current) return;
1178			transition_in(if_block);
1179			current = true;
1180		},
1181		o(local) {
1182			transition_out(if_block);
1183			current = false;
1184		},
1185		d(detaching) {
1186			if_blocks[current_block_type_index].d(detaching);
1187			if (detaching) detach(if_block_anchor);
1188		}
1189	};
1190}
1191
1192function instance($$self, $$props, $$invalidate) {
1193	let $page;
1194	component_subscribe($$self, page, $$value => $$invalidate(10, $page = $$value));
1195	let url;
1196	let vpr;
1197	let vcs = [];
1198	let handled;
1199	let client;
1200
1201	onMount(async () => {
1202		url = $page.url.searchParams.get('url');
1203		requestCredentials();
1204	});
1205
1206	const requestCredentials = async (did, suite) => {
1207		try {
1208			const offer = JSON.parse(new URL(url).searchParams.get('credential_offer'));
1209			client = await OID4Client.fromCredentialOffer({ offer });
1210
1211			const response = await client.requestCredentials({
1212				requests: offer.credentials.map(({ credential_definition }) => ({ format: 'ldp_vc', credential_definition })),
1213				did,
1214				didProofSigner: suite
1215			});
1216
1217			if (response.credential_responses) {
1218				$$invalidate(1, vcs = response.credential_responses.map(c => c.credential));
1219			} else {
1220				$$invalidate(1, vcs = [response.credential]);
1221			}
1222
1223			$$invalidate(2, handled = vcs.map(() => false));
1224		} catch(e) {
1225			if (e.cause.toString().includes('DID authentication is required')) {
1226				$$invalidate(0, vpr = {
1227					query: {
1228						type: 'DIDAuthentication',
1229						acceptedMethods: [{ method: 'key' }]
1230					},
1231					domain: 'https://qa.veresexchanger.dev',
1232					challenge: 'z1AAorBYuL3KMeNYkaEKzUpAq'
1233				});
1234			} else {
1235				console.error(e.cause);
1236			}
1237		}
1238	};
1239
1240	const addVC = async (index, vc) => {
1241		const magic = await findTheMagic(vc);
1242		await wallet.addVC(magic, vc);
1243		$$invalidate(2, handled[index] = true, handled);
1244		checkCompleted();
1245	};
1246
1247	const skipVC = index => {
1248		$$invalidate(2, handled[index] = true, handled);
1249		checkCompleted();
1250	};
1251
1252	const checkCompleted = () => {
1253		if (handled.every(value => value === true)) {
1254			if ($page.url.searchParams.get('respondToCHAPI')) {
1255				const evt = get_store_value(chapiEvent);
1256
1257				if (evt) {
1258					evt.respondWith({ dataType: 'OutOfBand' });
1259				}
1260			} else {
1261				goto('/credentials');
1262			}
1263		}
1264	};
1265
1266	const respondToVPR = async vp => {
1267		console.log(vp);
1268		const key = await get_store_value(getVerificationKeyForDID(vp.holder, wallet));
1269		requestCredentials(key?.controller, key);
1270	};
1271
1272	const click_handler = (index, vc) => addVC(index, vc);
1273	const click_handler_1 = index =>
1273 skipVC(index);
1274	return [vpr, vcs, handled, addVC, skipVC, respondToVPR, click_handler, click_handler_1];
1275}
1276
1277class Page extends SvelteComponent {
1278	constructor(options) {
1279		super();
1280		init(this, options, instance, create_fragment, safe_not_equal, {});
1281	}
1282}
1283
1284export { Page as default };

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.