Web3Id issuer schema specification error

We get the following error:

We have build a test component to add a web3 id credential and our contract has a schema embedded. We are stuck, we can’t find any documentation.

import {
  AttributeType,
  ConcordiumGRPCClient,
  ConcordiumGRPCWebClient,
  CredentialWithMetadata,
  Network,
  createWeb3CommitmentInput,
  createWeb3IdDID,
  verifyCredentialMetadata,
} from "@concordium/web-sdk";
import {
  CredentialProof,
  detectConcordiumProvider,
} from "@concordium/browser-wallet-api-helpers";
import React, { useState } from "react";

import Heading from "@/components/BestBank/Heading";

interface IssuerResponse {
  txHash: string;
  credential: {
    proof: CredentialProof;
    randomness: Record<string, string>;
  };
}

interface CredentialInfo {
  holderId: string;
  holderRevocable: boolean;
  validFrom: string;
  metadataUrl: { url: string };
}

interface IssueRequest {
  credential: CredentialInfo;
}

const index = () => {
  const network = "Testnet";
  const publicKey = "hidden";
  const schema = "https://json-schema.org/draft/2020-12/schema";
  const metadataUrl = {
    url: "hidden",
  };
  const ISSUER_URL = "https://localhost:3000";

  const createweb3ID = () => {
    if (publicKey) {
      const id = createWeb3IdDID(network, publicKey, BigInt(10189), BigInt(0));

      return id;
    }
  };

  const credential = {
    $schema: schema,
    type: [
      "demoCredential",
      "VerifiableCredential",
      "ConcordiumVerifiableCredential",
      "SoMeCredential",
    ],
    issuer: createweb3ID() || "",
    issuanceDate: new Date().toISOString(),
    credentialSubject: {
      id: "hidden",
      attributes: {
        CountryOfIssue: "US",
        CardType: "Driving License",
        Issuer: "DMV",
        CardNumber: "123456789",
        LastName: "Doe",
        FirstName: "John",
        MiddleName: "A",
        DOB: "1990-01-01",
        Sex: "Male",
        Nationality: "American",
        Address: "123 Main St",
        Street: "Main St",
        City: "Somewhere",
        State: "CA",
        ZipCode: "90210",
        LicenceNumber: "D1234567",
        LicenceClass: "C",
        LicenceCondition: "None",
        LicenceType: "Full",
        LicenceVersion: "V1",
        Donor: "No",
        Entitlements: "None",
        IssueDate: "2020-01-01",
        ExpiryDate: "2030-01-01",
      },
    },
    credentialSchema: {
      id: "hidden",
      type: "object",
    },
  };

  const addCredential = async () => {
    let txHash: string | undefined;
    const api = await detectConcordiumProvider();
    await api.addWeb3IdCredential(credential, metadataUrl, async (id) => {
      const parts = id.split(":");
      const holderId = parts[parts.length - 1];

      const body: IssueRequest = {
        credential: {
          holderId,
          holderRevocable: true,
          validFrom: new Date().toISOString(),
          metadataUrl,
        },
      };

      const endpoint = ISSUER_URL + "credential";
      const response = await fetch(endpoint, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },

        credentials: "include",
        body: JSON.stringify(body),
      });

      if (!response.ok) {
        if (response.status == 429)
          throw new Error(
            "Sorry, too many credentials have been issued for this account."
          );
        throw new Error("Error getting credential: " + (await response.text()));
      }

      const { txHash: hash, credential } =
        (await response.json()) as IssuerResponse;
      txHash = hash;
      const { proof, randomness } = credential;
      return { proof, randomness };
    });
  };

  return (
    <>
      <button
        className="bg-BestBank-primary p-6 rounded-xl"
        onClick={addCredential}
      >
        test button 2
      </button>
    </>
  );
};

export default index;

It’s switching between the previous error and this one:

We fixed our previous errors, but get stuck on the part where we have to create the proof and randomness.

provider.addWeb3IdCredential(credential, metadataUrl, async (id) => {
    const randomness = createRandomness(attributes); // Choose some randomness for the attribute commitments.
    const proof = createCredentialProof(credential, id, randomness); // Create a proof to prove that the commitments are created by the issuer.
    return { proof, randomness };
});

This is code of the documentation. Can we find these functions anywhere?

If we use random values for proof and randomness we get the next error after we press add credential:

Error: Odd number of digits at line 1 column 49494

Dear DTS-Jovanni,

In this repo are some examples front-end related to web3id credential issuing.

The provider.addWeb3IdCredential call added your web3id credential to the wallet. The next outstanding step is that someone needs to register the credential in the smart contract (usually this someone is the issuer since the issuer is usually the only actor who can write to its own deployed smart contract).

You can see that second step here where a smart contract transaction is sent on chain (different to this test example, this step would be usually done by the backend by the issuer).

The third step and related to your question about randomness and proof is the step where the issuer generates at the backend a cryptographic commitment and signs it with its issuer key. This proves that the verifiable credential was issued to the user by the issuer and since it is a cryptographic commitment the user can generate ZK proofs proving statements about its verifiable credential in the future.

This step is shown here (the seed (usually this would be just the private key of the issuer)) would other than in this example be only accessible at the backend to protect the keys of the issuer - not be passed from front-end to back-end):

The backend for the third step is here: The randomness is part of the generation of the pedersen commitment at the backend.

We are having some trouble with registering the credential in the wallet:

When we press “add credential” we get the following error:

image (1)

This is the call we use:

const attributes = {
    FullName: "John Doe",
    DateOfBirth: "1990-01-01",
    Nationality: "American",
    IssueDate: "2020-01-01",
    ExpiryDate: "2030-01-01",
  };

  const addCredential = async () => {
    const api = await detectConcordiumProvider();
    try {
      await api.addWeb3IdCredential(credential, metadataUrl, async (id) => {
        const publicKeyOfCredential = id.replace("did:ccd:testnet:pkc:", "");
        
        const commitments = {
          attributes,
          holderId: publicKeyOfCredential,
          issuer: {
            index: index,
            subindex: 0,
          },
        };

        const requestSignatureResponse = (await requestSignature(
          seed,
          stringify(commitments)
        )) as RequestSignatureResponse;

        const proofObject = {
          type: "Ed25519Signature2020" as const,
          verificationMethod: id,
          proofPurpose: "assertionMethod" as const,
          proofValue: requestSignatureResponse.signedCommitments.signature,
        };

        const proof = proofObject;
        const { randomness } = requestSignatureResponse;

        return { proof, randomness };
      });
    } catch (error) {
      console.log(error);
    }
  };

The error says that the proof is invalid. Could you check if the seed (from where the issuer public-private key is derived at the backend) when generating the proof, is the same public key that was inserted as issuer public key into the smart contract registry when the contract was deployed? The registered issuer public key in the smart contract registry must match the key pair during proof generation.