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.