<link rel="stylesheet" href="/digital-building-blocks/sites/download/attachments/475267168/conformant-wallets-style.css">
<h1 class="heading-deco terciary">Conformant Wallets</h1>
<p>Welcome to the EBSI conformant wallets page! Here, you will find information about the different types of digital wallets that are available and conformant with EBSI specifications. The three main types of wallets include Holder, Issuer, and Verifier wallets, each with their own unique capabilities.</p>
<p><a href="#become-conformant" class="btn secondary anchor-smooth-scroll"><span>Test your wallet</span><span class="ico-arrow-south"></span></a><span class="spc-btns"></span><a href="#find-your-wallet" class="btn secondary outline anchor-smooth-scroll"><span>Find your wallet</span><span class="ico-arrow-south"></span></a></p>

<h1 class="heading-deco terciary">Wallets</h1>
<p>Welcome to the EBSI conformant wallets page! Here, you will find information about the different types of digital wallets that are available and conformant with EBSI specifications. The three main types of wallets include Holder, Issuer, and Verifier wallets, each with their own unique capabilities.</p>

<p class="column-buttons" ><a href="#become-conformant" class="btn secondary outline anchor-smooth-scroll"><span>Test your wallet</span><span class="ico-arrow-south"></span></a><a href="#find-your-wallet" class="btn secondary anchor-smooth-scroll"><span>Find your wallet</span><span class="ico-arrow-south"></span></a></p>
<img aria-hidden="true" src="https://ec.europa.eu/digital-building-blocks/sites/download/attachments/468026266/shape-curve-simple-white.svg" alt="">

<h3 class="heading-deco terciary">What is a digital wallet?</h3>
<p>A digital wallet in the context of EBSI is a type of online storage that lets you securely keep track of your digital assets and information, like digital certificates and digital identity information. It's like a traditional wallet but storing digital information.</p>

<h3 class="heading-deco terciary">What is a conformant wallet?</h3>
<p>A conformant wallet is a type of wallet that has successfully passed the Conformance Test. The test verifies that the wallet meets certain standards for performance and functionality, whether it is a holder, issuer, or verifier wallet. 
The Conformance Test assesses the wallet's ability to handle credentials assigned by a mock issuer and return them to a mock verifier.</p> 
<img aria-hidden="true" src="https://ec.europa.eu/digital-building-blocks/sites/download/attachments/468026266/shape-wave-white.svg" alt="">
<h2 class="heading-deco terciary">Which wallet do I need?</h2>
<p>Different wallets offer different functionalities. Under EBSI's Verifiable Credentials exchange framework, we distinguish three different types of functionalities, which an individual wallet may chose to offer alone, or in combination:</p>
<div>
	<p class="number-blue">01</p>
	<p><strong>Wallets for holders:</strong> Can request issuance of Verifiable Credentials (VCs) and receive them instantly or deferred.</p>
</div>
<div>
	<p class="number-blue">02</p>
	<p><strong>Wallet for issuer:</strong> these wallets allow organisations like universities or ministries to manage their accreditations on the blockchain ledger, and issue Verifiable Credentials to Holders.</p>
</div>
<div>
	<p class="number-blue">03</p>
	<p><strong>Wallet for Verifiers:</strong> these wallets allow organisations like companies (e.g. employer), or universties to verify the authenticity of a Verifiable Credential presented by a Holder.</p>
</div>

<h2 class="heading-deco terciary">Find your wallet</h2>
    <div id="type-of-wallet">
      <div class="f-block-section">
        <img
          src="https://ec.europa.eu/digital-building-blocks/sites/download/attachments/475267168/illu-num-1.png"
        />
        <h3>Select which type of wallet you need</h3>
      </div>
      <div class="s-block-section">
        <div id="organisation-card" class="card-wallet-cta">
          <div class="container-h-f">
            <div class="card-wallet-header">
              <img
                aria-hidden="true"
                src="https://ec.europa.eu/digital-building-blocks/sites/download/attachments/475267168/verifier-icon.png"
                alt=""
              />
            </div>
            <div class="card-wallet-body">
              <h4>Organisation wallet</h4>
              <p>A wallet that is controlled by an organisation,
				such as an issuer or verifier, and is used to provide 
				digital credentials or other services to users.
              </p>
            </div>
          </div>
          <div class="card-wallet-footer">
            <p>
              <strong>Select the capabilities you are interested in</strong>
            </p>
            <div id="org-tabs" class="tabs pick-type">
              <a href="#pick-your-wallet" class="tab anchor-smooth-scroll" data-type="accredit-authorise" data-index="0" >
                <p>Accredit & Authorise</p>
                <div class="box-checker"><div></div></div>
              </a>
              <a  data-type="issue" data-index="1" href="#pick-your-wallet" class="tab anchor-smooth-scroll">
                <p>Issue</p>
                <div class="box-checker"><div></div></div>
              </a>
              <a href="#pick-your-wallet" class="tab anchor-smooth-scroll" data-type="verify" data-index="2">
                <p>Verify</p>
                <div class="box-checker"><div></div></div>
              </a>
            </div>
          </div>
        </div>
        <div id="individual-card" class="card-wallet-cta">
          <div class="container-h-f">
            <div class="card-wallet-header">
              <img
                aria-hidden="true"
                src="https://ec.europa.eu/digital-building-blocks/sites/download/attachments/475267168/holder-icon.png"
                alt=""
              />
            </div>
            <div class="card-wallet-body">
              <h4>Individual wallet</h4>
              <p>A digital wallet that is used by natural persons
				 to store and manage their verifiable credentials.</p>
            </div>
          </div>
          <div class="card-wallet-footer">
            <p>
              <strong>Select the capabilities you are interested in</strong>
            </p>
            <div class="tabs pick-type">
              <a href="#pick-your-wallet" class="tab anchor-smooth-scroll" data-type="request-present-credentials" data-index="4" id="request-present_credentials" >
                <p>Request & present credentials</p>
                <div class="box-checker"><div></div></div>
             </a>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div id="pick-your-wallet">
      <div class="f-block-section">
        <img
          src="https://ec.europa.eu/digital-building-blocks/sites/download/attachments/475267168/illu-num-2.png"
        />
        <h3>Pick your wallet</h3>
      </div>
      <div class="s-block-section">
<img src="https://ec.europa.eu/digital-building-blocks/sites/download/attachments/475267168/loader-low.gif" alt=""/>
<div class="default-state-container">
	<div><img src="https://ec.europa.eu/digital-building-blocks/sites/download/attachments/475267168/info-icon.png?version=1&modificationDate=1688642091828&api=v2"/></div>
	<div><p><strong>You need to select a type of wallet first,</strong> then the wallets will be automatically generated</p></div>
</div>
<div class="no-results-container"><img class="img-fluid" src="https://ec.europa.eu/digital-building-blocks/sites/download/attachments/475267168/no-results-isometric.png"/>
<div><h4>No results found :(</h4><p>Sorry, there are no wallets that match your request at the moment.</p></div>
</div>

</div>
</div>
<h2 class="heading-deco terciary">Previous versions - version 2</h2>
<p>Here is a list of wallets that have been tested and certified as conformant with a deprecated version of the EBSI specifications. Please note that while these wallets may still function in some capacity, they may not be able to take full advantage of all the features and benefits of the latest EBSI specifications. </p>
<div class="collapse" id="accordionGroup" data-allow-multiple>

<!--FAQ 1-->
<div class="collapse-item">

<h3>
<button class="collapse-trigger" id="faq1" aria-expanded="false" aria-controls="sect1"> 
<span class="collapse-title h4">Conformant with versions 2<span class="collapse-icon"></span> </span> </button>
</h3>

<div class="collapse-panel" id="sect1" role="region" aria-labelledby="faq1" hidden="">
<p style="margin-bottom:40px;">Wallets conformant with WCT v2 which is focused on testing holder wallets.</p> 

<div class="loadmore-container"><a id="loadmore-cta" class="btn secondary outline"><span><strong>Load more</strong></span></a></div>
</div>
</div>
<!---->
</div>
<img aria-hidden="true" src="https://ec.europa.eu/digital-building-blocks/sites/download/attachments/468026266/shape-curve-simple-white.svg" alt="">
<h3>Do you want to become conformant ?</h3>
<p>Join the EBSI family and achieve wallet conformance today!</p>
<p><a class="btn secondary" href="https://hub.ebsi.eu/wallet-conformance" target="_blank"><span>Become conformant</span><span class="ico-external"></span></a></p>
<script>  

$(".smalltext")
  .contents()
  .filter(function () {
    return this.nodeType === 3
  })
  .remove()



const defSt = document.querySelector("#default-state-cards")
const noRes = document.querySelector("#no-results-cards")
const liCa = document.querySelector("#list-wallet-cards")
defSt.setAttribute("hidden", "")
noRes.setAttribute("hidden", "")
liCa.setAttribute("hidden", "")

window.addEventListener('load', function() {
	const loader = document.querySelector("#loader-section")
    loader.setAttribute("hidden","")
	loader.style.display = "none"
	defSt.removeAttribute("hidden")
	noRes.removeAttribute("hidden")
	liCa.removeAttribute("hidden")
})


document.addEventListener("DOMContentLoaded", function () {
	const tabs = document.querySelectorAll(".card-wallet-footer > .tabs > .tab")
	const defaultState = document.querySelector("#default-state-cards")
	const notFound = document.querySelector("#no-results-cards")
	const cardList = document.querySelector("#list-wallet-cards")
	const wallets = document.querySelectorAll(
		"#pick-your-wallet .wallet-container-info"
	  )

	try {
		const walletsSorted = walletsStructure(wallets)
		sortWallets(walletsSorted)
		walletsImpl(tabs, defaultState, notFound, cardList)
	} catch (error) {
		const errorContainer = document.querySelector("#pick-your-wallet > .s-block-section")
		errorContainer.innerHTML = `<h4 style="color: #CD1D8B"><strong>An error occurred while trying loading the wallets. Please try again later!</strong></h4>`
		console.error(error)
	}




})

const stateSection = (element, state) => {
  if (element) {
    element.style.display = state ? `${state}` : "none"
  }
}

const stateClassSwitcher = (elementFinder, action, classTrigger) => {
  const element = document.querySelector(`${elementFinder}`)
  if (action == "add") {
    element.classList.add(`${classTrigger}`)
  } else {
    element.classList.remove(`${classTrigger}`)
  }
}

const switchWalletRefs = () => {
  const tabs = document.querySelectorAll(".tab")
  tabs.forEach((tab) => {
    tab.classList.contains("activated")
      ? tab.setAttribute("href", "#pick-your-wallet")
      : tab.setAttribute("href", "#type-of-wallet")
  })
}

const walletsImpl = (tabs, defaultState, notFound, cardList) => {
  stateSection(defaultState, "block")
  stateSection(notFound, "none")
  stateSection(cardList, "none")

  tabs.forEach((tab) => {
    tab.classList.remove("activated")
    tab.addEventListener("click", function (e) {
      const parentId = this.closest("div").getAttribute("id")
      const thisId = this.getAttribute("id")
      stateSection(defaultState, "none")
      stateSection(cardList, "block")
      let counter = 0
      e.stopPropagation()
      this.classList.toggle("activated")
      switchWalletRefs()
      if (parentId == "org-tabs") {
        stateClassSwitcher("#organisation-card", "add", "activated")
        stateClassSwitcher("#individual-card", "remove", "activated")
        stateClassSwitcher(
          "#request-present_credentials",
          "remove",
          "activated"
        )
      }
      if (thisId == "request-present_credentials") {
        stateClassSwitcher("#organisation-card", "remove", "activated")
        stateClassSwitcher("#individual-card", "add", "activated")
        document.querySelectorAll("#org-tabs > a").forEach((tab) => {
          tab.classList.remove("activated")
        })
      }
      cardsSwitcher(counter, defaultState, notFound, cardList)
      e.preventDefault()
    })
  })
}

const cardsSwitcher = (counter, defaultState, notFound, cardList) => {
  const allWallets = document.querySelectorAll(
    "#pick-your-wallet .wallet-container-info"
  )

  let activeTabsTypes = document.querySelectorAll(
    "#type-of-wallet .tabs .tab.activated"
  )
  if (activeTabsTypes.length === 0) {
    stateClassSwitcher("#organisation-card", "remove", "activated")
    stateClassSwitcher("#individual-card", "remove", "activated")
  }
  let activeDataTypes = Array.from(activeTabsTypes).map((tab) => {
    return tab.getAttribute("data-type")
  })
  allWallets.forEach((wallet) => {
    const walletDataType = wallet.getAttribute("data-type")
    const dataTypeMatch = activeDataTypes.every((dataType) => {
      return walletDataType.includes(dataType)
    })
    if (dataTypeMatch) {
      counter++
      wallet.closest("li").style.display = "block"
    } else {
      wallet.closest("li").style.display = "none"
    }
    if (counter === 0) {
      stateSection(cardList, "none")
      stateSection(defaultState, "none")
      stateSection(notFound, "block")
    } else {
      if (activeTabsTypes.length === 0) {
        stateSection(defaultState, "block")
        stateSection(cardList, "none")
        stateSection(notFound, "none")
      } else {
        stateSection(cardList, "block")
        stateSection(notFound, "none")
        stateSection(defaultState, "none")
      }
    }
  })
}

const walletsStructure = (wallets) => {
  let dataWallet = ""
  const walletsSorted = []
  wallets.forEach((wallet, index) => {
    dataWallet =
      wallet.getAttribute("data-type") == "request-present-credentials"
        ? "a"
        : "b"

    walletsSorted.push({
      wallet,
      dataWallet,
      "data-type": wallet.getAttribute("data-type").split(",").length,
    })
  })
  return walletsSorted
}

const sortWallets = (walletsSorted) => {
  const finalizingWallets = []
  walletsSorted.sort(function (attrX, attrY) {
    if (attrX.dataWallet > attrY.dataWallet) return -1
    if (attrX.dataWallet < attrY.dataWallet) return 1

    if (attrX["data-type"] > attrY["data-type"]) return -1
    if (attrX["data-type"] < attrY["data-type"]) return 1
  })
  walletsSorted.forEach((obj) => {
    finalizingWallets.push(obj.wallet)
  })
  finalizingWallets.flat(1).forEach((wallet, index) => {
    let html = ""
    html = wallet
    const Uli = `#pick-your-wallet ul > li:nth-child(${
      index + 1
    }) > div.details > span`
    $(Uli).html(wallet)
  })
}






</script>
<script>

/*
*   This content is licensed according to the W3C Software License at
*   https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
*
*   Simple accordion pattern example
*/

'use strict';

Array.prototype.slice.call(document.querySelectorAll('.collapse')).forEach(function (accordion) {

  // Allow for multiple accordion sections to be expanded at the same time
  var allowMultiple = accordion.hasAttribute('data-allow-multiple');
  // Allow for each toggle to both open and close individually
  var allowToggle = (allowMultiple) ? allowMultiple : accordion.hasAttribute('data-allow-toggle');

  // Create the array of toggle elements for the accordion group
  var triggers = Array.prototype.slice.call(accordion.querySelectorAll('.collapse-trigger'));
  var panels = Array.prototype.slice.call(accordion.querySelectorAll('.collapse-panel'));


  accordion.addEventListener('click', function (event) {
    var target = event.target;

    if (target.classList.contains('collapse-trigger')) {
      // Check if the current toggle is expanded.
      var isExpanded = target.getAttribute('aria-expanded') == 'true';
      var active = accordion.querySelector('[aria-expanded="true"]');

      // without allowMultiple, close the open accordion
      if (allowMultiple && active && active !== target) {
        // Set the expanded state on the triggering element
        active.setAttribute('aria-expanded', 'false');
        // Hide the accordion sections, using aria-controls to specify the desired section
        document.getElementById(active.getAttribute('aria-controls')).setAttribute('hidden', '');

        // When toggling is not allowed, clean up disabled state
        if (!allowToggle) {
          active.removeAttribute('aria-disabled');
        }
      }

      if (!isExpanded) {
        // Set the expanded state on the triggering element
        target.setAttribute('aria-expanded', 'true');
        // Hide the accordion sections, using aria-controls to specify the desired section
        document.getElementById(target.getAttribute('aria-controls')).removeAttribute('hidden');

        // If toggling is not allowed, set disabled state on trigger
        if (!allowToggle) {
          target.setAttribute('aria-disabled', 'true');
        }
      }
      else if (allowToggle && isExpanded) {
        // Set the expanded state on the triggering element
        target.setAttribute('aria-expanded', 'false');
         // Hide the accordion sections, using aria-controls to specify the desired section
        document.getElementById(target.getAttribute('aria-controls')).setAttribute('hidden', '');
      }

      event.preventDefault();
    }
  });

  // Bind keyboard behaviors on the main accordion container
  accordion.addEventListener('keydown', function (event) {
    var target = event.target;
    var key = event.which.toString();

    var isExpanded = target.getAttribute('aria-expanded') == 'true';
    var allowToggle = (allowMultiple) ? allowMultiple : accordion.hasAttribute('data-allow-toggle');

    // 33 = Page Up, 34 = Page Down
    var ctrlModifier = (event.ctrlKey && key.match(/33|34/));

    // Is this coming from an accordion header?
    if (target.classList.contains('collapse-trigger')) {
      // Up/ Down arrow and Control + Page Up/ Page Down keyboard operations
      // 38 = Up, 40 = Down
      if (key.match(/38|40/) || ctrlModifier) {
        var index = triggers.indexOf(target);
        var direction = (key.match(/34|40/)) ? 1 : -1;
        var length = triggers.length;
        var newIndex = (index + length + direction) % length;

        triggers[newIndex].focus();

        event.preventDefault();
      }
      else if (key.match(/35|36/)) {
        // 35 = End, 36 = Home keyboard operations
        switch (key) {
          // Go to first accordion
          case '36':
            triggers[0].focus();
            break;
            // Go to last accordion
          case '35':
            triggers[triggers.length - 1].focus();
            break;
        }
        event.preventDefault();

      }

    }
  });

  // These are used to style the accordion when one of the buttons has focus
  accordion.querySelectorAll('.collapse-trigger').forEach(function (trigger) {

    trigger.addEventListener('focus', function (event) {
      accordion.classList.add('focus');
    });

    trigger.addEventListener('blur', function (event) {
      accordion.classList.remove('focus');
    });

  });

  // Minor setup: will set disabled state, via aria-disabled, to an
  // expanded/ active accordion which is not allowed to be toggled close
  if (!allowToggle) {
    // Get the first expanded/ active accordion
    var expanded = accordion.querySelector('[aria-expanded="true"]');

    // If an expanded/ active accordion is found, disable
    if (expanded) {
      expanded.setAttribute('aria-disabled', 'true');
    }
  }

});



if ($(window).width() < 550) {

const storeCards = document.querySelectorAll("#previous-versions .wallet-container-info")
const cardLimit = document.querySelectorAll("#previous-versions .wallet-container-info").length;
const buttonLoadMore = document.querySelector("#loadmore-cta")
const cardInc = 3;
let tempArr = []
const allWallets = [...document.querySelectorAll("#previous-versions li")]
const showOnLoadPage = () => {
	
    cardLimit > 3 ? buttonLoadMore.style.display = 'flex' : buttonLoadMore.style.display = 'none'
	Array.from(storeCards).forEach((wallet, index) => {
	  let html = ""
	  html = wallet
	  const Uli = `#previous-versions ul > li:nth-child(${index + 1}) > div.details > span`
	  $(Uli).html(wallet)
        if( index > 2 ) {
            tempArr.push({[index] : wallet})
            $(`#previous-versions li:nth-child(${index + 1})`).hide();
        } else {
             $(`#previous-versions li:nth-child(${index + 1})`).show();
        }
	})
	
}

const showCardsOnLoadMore = () => {
	const hiddenCards = allWallets.filter(card => card.style.display === 'none')
	const nextThree = hiddenCards.slice(0,3)
	nextThree.forEach( card => card.style.display = 'block')

	if(hiddenCards.length <= 3 ){
		document.querySelector("#loadmore-cta").style = 'none';
	}
}

showOnLoadPage()
document.querySelector("#loadmore-cta").addEventListener('click', showCardsOnLoadMore)



document.querySelector("#faq1").addEventListener("click", function(e) {
	if (this.getAttribute('aria-expanded') == 'true' ) {
		showOnLoadPage()
	}
})

	
	
}

 </script>