Company ID proof request using Crypto X

Hello support, we are currently debugging after transitioning to the mainnet. Using Android Crypto X version 1.2.0, we are trying to reveal company IDs, specifically the following details from a Global Finreg identity:

  • Business Number
  • Legal Jurisdiction Country
  • Legal Name
  • Registration Authority

Everything works fine on the testnet, but after connecting and we request the same proof on the mainnet, we receive the following message in the Crypto X app: “You do not hold any credentials from the issuer that the verifier requests.”

Since it works perfectly on the testnet and we have a valid Global Finreg (Issuer ID: 4) identity on the mainnet with the required commitments/attributes, I want to confirm whether there currently should be any differences between how this works on the testnet versus the mainnet. Could you clarify if any differences exist?

Dear NHS, it should work with (Issuer ID:3) on mainnet

concordium-client identity show identity-providers --grpc-ip grpc.mainnet.concordium.software --grpc-port 20000 --secure
Identity providers
------------------
Identifier:     0
Description:    NAME Identity Provider 0
                URL https://idp.concordium.com/0
                Genesis IDP.
Identifier:     1
Description:    NAME Notabene
                URL https://notabene.id
                Notabene Identity Issuer
Identifier:     2
Description:    NAME Digital Trust Solutions
                URL https://www.digitaltrustsolutions.nl
                Identity verified by Digital Trust Solutions on behalf of Concordium
Identifier:     3
Description:    NAME Global FinReg
                URL https://globalfinreg.com/
                Providing identities for companies and individuals

on testnet:

concordium-client identity show identity-providers --grpc-ip grpc.testnet.concordium.com --grpc-port 20000 --secure
Identity providers
------------------
Identifier:     0
Description:    NAME Concordium testnet IP
                URL 
                Concordium testnet identity provider
Identifier:     1
Description:    NAME Notabene (Staging)
                URL https://notabene.studio
                Notabene Identity Issuer (Staging Service)
Identifier:     3
Description:    NAME Digital Trust Solutions TestNet
                URL https://www.digitaltrustsolutions.nl
                Identity verified by Digital Trust Solutions on behalf of Concordium
Identifier:     4
Description:    NAME Global FinReg Testnet
                URL https://globalfinreg.com/
                Providing identities for companies and individuals

Dear Doris,

Thank you for your response. Using 3 this brings up the proof request statement, but for some reason, we are only able to see and decline, not approve. Please see the attached below for reference. Do you have any additional details? The same code works on the test-net, as mentioned. Also for the LEI code unkown on testnet.

Does your identity on mainnet has a LEI code attribute? You can remove the attribueReveal of the LEI-code request from the proof request (so that the wallet does not try to proof it).

We can approve if we remove the LEI code from the request — it’s odd because it works on the test net, which also doesn’t have the LEI.

Not all the verified businesses have LEI. Make its reveal optional, perhaps by asking “Do you have LEI?” in the web app before constructing the proof request.

Yes, that is possible - just strange it works on testnet. But moving on to verify the proof we get POST https://web3id-verifier.mainnet.concordium.software/v0/verify 400 (Bad Request).

Interestingly, this works on the testnet as expected. Below is the code snippet and console:

let account = await walletProvider.connect();

// Define the attributes to be revealed
const attributesToReveal = [
AttributeKeyString.legalName,
AttributeKeyString.legalCountry,
AttributeKeyString.businessNumber,
AttributeKeyString.registrationAuth,
];

// Create the reveal statement for each attribute
const statement = attributesToReveal.map((attributeTag) => ({
type: StatementTypes.RevealAttribute,
attributeTag,
}));

const credentialStatement = {
statement,
idQualifier: {
type: ‘cred’,
issuers: [issuerId],
},
};

const challenge = […crypto.getRandomValues(new Uint8Array(32))]
.map((b) => b.toString(16).padStart(2, ‘0’))
.join(‘’);

const proof = await walletProvider.requestVerifiablePresentation(challenge, [credentialStatement]);

if (!proof) {
throw new Error(‘Failed to retrieve proof from wallet provider.’);
}

// Base64 encode the proof JSON
const proofBase64 = btoa(JSON.stringify(proof));

const revealedAttributes = { account, proofBase64 };
const verifiableCredential = proof?.verifiableCredential?.[0];
const proofValues = verifiableCredential?.credentialSubject?.proof?.proofValue;

if (proofValues) {
attributesToReveal.forEach((attributeTag, index) => {
const proofValue = proofValues[index];
const attributeValue = proofValue?.attribute || ‘No value provided’;
revealedAttributes[attributeTag] = attributeValue;
});
} else {
throw new Error(‘No proof values found.’);
}

console.log(‘Proof:’, proof);
console.log(‘Revealed attributes:’, revealedAttributes);
console.log(‘Backend API:’, backendAPI);

// Submit the proof to the backend
const resp = await fetch(${backendAPI}, {
method: ‘POST’,
headers: { ‘Content-Type’: ‘application/json’ },
body: JSON.stringify(proof),
});

if (!resp.ok) {
const errorBody = await resp.json();
throw new Error(Proof submission failed: ${resp.status} - ${errorBody.message});
}

console of the Proof: Proof:

  1. Yu {presentationContext: ‘4b1d8b82b5dc653ffc7cb24457cb5ae8b1122f59a35ce24f61fb15a22aa16e90’, proof: {…}, type: ‘VerifiablePresentation’, verifiableCredential: Array(1)}

  2. presentationContext: “4b1d8b82b5dc653ffc7cb24457cb5ae8b1122f59a35ce24f61fb15a22aa16e90”

  3. proof:

1. created: "2024-10-24T13:19:57.598545422Z"
2. proofValue: Array(0)

  1. length: 0
  2. [[Prototype]]: Array(0)

3. type: "ConcordiumWeakLinkingProofV1"
  1. type: “VerifiablePresentation”
  2. verifiableCredential: Array(1)
1. 0: {credentialSubject: {…}, issuer: 'did:ccd:mainnet:idp:3', type: Array(2)}
2. length: 1
3. [[Prototype]]: Array(0)
  1. [[Prototype]]: Object
1. constructor: class Yu
2. toString: ƒ toString()
3. [[Prototype]]: Object

Has any code or example been tested in relation to this on mainnet? If so, could you please share the example? With everything running smoothly on testnet, we didn’t expect to encounter any differences.

Dear NHS,
the response bad request usually means that the information sent to the backend is in a format not expected. Do you get any additional errors since the backend has several different error cases when it responds with a bad request error:

Dear Doris,

Thank you! We’ve added more debugging and encountered this error from the backend:

“Proof submission failed: 400 - Invalid presentation format: Failed to deserialize the JSON body into the target type.”

The presentation is retrieved directly from the wallet provider and appears to include the revealed attributes.

Versions:

@concordium/browser-wallet-api-helpers”: “^3.0.0”,
@concordium/web-sdk”: “^8.1.0”,
@walletconnect/qrcode-modal”: “^1.8.0”,
@walletconnect/sign-client”: “^2.1.5”,
@walletconnect/types”: “^2.1.5”,

Code:

let account = await walletProvider.connect();

// Define the attributes to be revealed
const attributesToReveal = [
  AttributeKeyString.legalName,
  AttributeKeyString.legalCountry,
  AttributeKeyString.businessNumber,
  AttributeKeyString.registrationAuth,
];

// Create the reveal statement for each attribute
const statement = attributesToReveal.map((attributeTag) => ({
  type: StatementTypes.RevealAttribute,
  attributeTag,
}));

const credentialStatement = {
  statement,
  idQualifier: {
    type: 'cred',
    issuers: [issuerId],
  },
};

const challenge = [...crypto.getRandomValues(new Uint8Array(32))]
  .map((b) => b.toString(16).padStart(2, '0'))
  .join('');

const proof = await walletProvider.requestVerifiablePresentation(challenge, [credentialStatement]);

if (!proof) {
  throw new Error('Failed to retrieve proof from wallet provider.');
}

// Base64 encode the proof JSON
const proofBase64 = btoa(JSON.stringify(proof));

const revealedAttributes = { account, proofBase64 };
revealedAttributes['account'] = account;
revealedAttributes['proof'] = proofBase64;

const verifiableCredential = proof?.verifiableCredential?.[0];
const proofValues = verifiableCredential?.credentialSubject?.proof?.proofValue;

if (proofValues) {
  attributesToReveal.forEach((attributeTag, index) => {
    const proofValue = proofValues[index];
    const attributeName = attributeTag;
    const attributeValue = proofValue?.attribute || 'No value provided';
    revealedAttributes[attributeName] = attributeValue;
  });
} else {
  throw new Error('No proof values found.');
}

console.log('Proof:', proof);
console.log('Revealed attributes:', revealedAttributes);
console.log("Backend API:", backendAPI);

const resp = await fetch(`${backendAPI}`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(proof),
});

if (!resp.ok) {
  const errorBody = await resp.json();
  console.error(`Proof submission failed: ${resp.status} - ${errorBody}`);
  throw new Error(`Proof submission failed: ${resp.status} - ${errorBody}`);
}

Console:
Proof: Yu {presentationContext: ‘b37e98aa5e39346c6ea7cde4fe5979944a0ab8693dcc6b9e8af2d57361cdeb19’, proof: {…}, type: ‘VerifiablePresentation’, verifiableCredential: Array(1)}presentationContext: "b37e98aa5e39346c6ea7cde4fe5979944a0ab8693dcc6b9e8af2d57361cdeb19"proof: {created: ‘2024-10-27T03:24:44.525879478Z’, proofValue: Array(0), type: ‘ConcordiumWeakLinkingProofV1’}type: "VerifiablePresentation"verifiableCredential: Array(1)0: credentialSubject: {id: ‘did:ccd:mainnet:cred:8f023b244a863518acccd247debef…d90352061b4433162dfe22aae061554cd22294fbdb4e17d1e’, proof: {…}, statement: Array(4)}issuer: "did:ccd:mainnet:idp:3"type: (2) [‘VerifiableCredential’, ‘ConcordiumVerifiableCredential’]length: 1[[Prototype]]: Array(0)at: ƒ at()concat: ƒ concat()constructor: ƒ Array()copyWithin: ƒ copyWithin()entries: ƒ entries()every: ƒ every()fill: ƒ fill()filter: ƒ filter()find: ƒ find()findIndex: ƒ findIndex()findLast: ƒ findLast()findLastIndex: ƒ findLastIndex()flat: ƒ flat()flatMap: ƒ flatMap()forEach: ƒ forEach()includes: ƒ includes()indexOf: ƒ indexOf()join: ƒ join()keys: ƒ keys()lastIndexOf: ƒ lastIndexOf()length: 0map: ƒ map()pop: ƒ pop()push: ƒ push()reduce: ƒ reduce()reduceRight: ƒ reduceRight()reverse: ƒ reverse()shift: ƒ shift()slice: ƒ slice()some: ƒ some()sort: ƒ sort()splice: ƒ splice()toLocaleString: ƒ toLocaleString()toReversed: ƒ toReversed()toSorted: ƒ toSorted()toSpliced: ƒ toSpliced()toString: ƒ toString()unshift: ƒ unshift()values: ƒ values()with: ƒ with()Symbol(Symbol.iterator): ƒ values()Symbol(Symbol.unscopables): {at: true, copyWithin: true, entries: true, fill: true, find: true, …}[[Prototype]]: Object[[Prototype]]: Object

Revealed attributes: {account: Array(1), proofBase64: ‘eyJwcmVzZW50YXRpb25Db250ZXh0IjoiYjM3ZTk4YWE1ZTM5Mz…Db25jb3JkaXVtVmVyaWZpYWJsZUNyZWRlbnRpYWwiXX1dfQ==’, proof: ‘eyJwcmVzZW50YXRpb25Db250ZXh0IjoiYjM3ZTk4YWE1ZTM5Mz…Db25jb3JkaXVtVmVyaWZpYWJsZUNyZWRlbnRpYWwiXX1dfQ==’, legalName: ‘Provenance Tags ApS’, legalCountry: ‘DK’, …}account: Array(1)0: "3evoZW2d6PP46fxgJiBG5k6ANgv3S9o1fJ8uaq1a1uShzLqJ8p"length: 1[[Prototype]]: Array(0)businessNumber: "43395963"legalCountry: "DK"legalName: "Provenance Tags ApS"proof: "eyJwcmVzZW50YXRpb25Db250ZXh0IjoiYjM3ZTk4YWE1ZTM5MzQ2YzZlYTdjZGU0ZmU1OTc5OTQ0YTBhYjg2OTNkY2M2YjllOGFmMmQ1NzM2MWNkZWIxOSIsInByb29mIjp7ImNyZWF0ZWQiOiIyMDI0LTEwLTI3VDAzOjI0OjQ0LjUyNTg3OTQ3OFoiLCJwcm9vZlZhbHVlIjpbXSwidHlwZSI6IkNvbmNvcmRpdW1XZWFrTGlua2luZ1Byb29mVjEifSwidHlwZSI6IlZlcmlmaWFibGVQcmVzZW50YXRpb24iLCJ2ZXJpZmlhYmxlQ3JlZGVudGlhbCI6W3siY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJkaWQ6Y2NkOm1haW5uZXQ6Y3JlZDo4ZjAyM2IyNDRhODYzNTE4YWNjY2QyNDdkZWJlZjE5ZDZjNzJkZmYzOWMxMDE5ZmQ5MDM1MjA2MWI0NDMzMTYyZGZlMjJhYWUwNjE1NTRjZDIyMjk0ZmJkYjRlMTdkMWUiLCJwcm9vZiI6eyJjcmVhdGVkIjoiMjAyNC0xMC0yN1QwMzoyNDo0NC41MjU3MzkzMjRaIiwicHJvb2ZWYWx1ZSI6W3siYXR0cmlidXRlIjoiUHJvdmVuYW5jZSBUYWdzIEFwUyIsInByb29mIjoiMDEzOTE5YzVhYjQ1ZWQ4MzE3ZjM0NGU2Yzg3NmU3OGQyMTA4ZmI2Yzc4N2NjNWJiOWNhZGQ1YjhjZmQ5Mzc1MTM4ZDgzNGFjNmQ4ZmRiMzgzZGZjOGNlOGY1NjkzMDE3MWEwMGRiZmY4NTA4YTY3ZTVkZjBiN2UzYmI2ZmIwOWEiLCJ0eXBlIjoiUmV2ZWFsQXR0cmlidXRlIn0seyJhdHRyaWJ1dGUiOiJESyIsInByb29mIjoiNDk1Mzk5OTVlMjljNDFiYmYyYTRmMzcwMjQ5MzZkZDc4MTMwNGNmYWY3NThiNGUxMjQ3ODliZTUyNzRhNDQ0NzNmMzEzOWM5YmQyYTY2YjYyYjQzZmM4ZDM4NGVmZGIzOGEyN2YyYTRkY2UzZjc0NTNjMjgxZjA1YTAxNTVjNTQiLCJ0eXBlIjoiUmV2ZWFsQXR0cmlidXRlIn0seyJhdHRyaWJ1dGUiOiI0MzM5NTk2MyIsInByb29mIjoiOTMyZTEzYmYxNGM4Y2ZhYzc1MjRkM2ZlNjgzMTVmZTZmZjA2MzUyYTRmNTA2M2Q3NTczMjlhZjAwMDQ5YjdiYjI2ZTNmZjhkZmRjYjA2MDdkOGIyOTY3OGQzMjc4NWZmMjRmYWVhZDk1Y2IyYzA2NzJmYmJiNzY4Zjg2ZWM3MGEiLCJ0eXBlIjoiUmV2ZWFsQXR0cmlidXRlIn0seyJhdHRyaWJ1dGUiOiJDZW50cmFsIEJ1c2luZXNzIFJlZ2lzdGVyIiwicHJvb2YiOiIwZDk4MGNlMTJhNTc5NTBjM2NiMDEwMThlZjEzNDNlOTU5ZGYyNTg5MjdlYTIzYWU5NGUxNjZhNGMyYjgwY2RjMzllMjI5MzI3YWM1ZTgwMGFiMGM5YTQxNjRkOWQxYTc5YjZkNDk1NDM2OTQyMDNiMTc5N2VjMTA4NTZkOWYwMyIsInR5cGUiOiJSZXZlYWxBdHRyaWJ1dGUifV0sInR5cGUiOiJDb25jb3JkaXVtWktQcm9vZlYzIn0sInN0YXRlbWVudCI6W3siYXR0cmlidXRlVGFnIjoibGVnYWxOYW1lIiwidHlwZSI6IlJldmVhbEF0dHJpYnV0ZSJ9LHsiYXR0cmlidXRlVGFnIjoibGVnYWxDb3VudHJ5IiwidHlwZSI6IlJldmVhbEF0dHJpYnV0ZSJ9LHsiYXR0cmlidXRlVGFnIjoiYnVzaW5lc3NOdW1iZXIiLCJ0eXBlIjoiUmV2ZWFsQXR0cmlidXRlIn0seyJhdHRyaWJ1dGVUYWciOiJyZWdpc3RyYXRpb25BdXRoIiwidHlwZSI6IlJldmVhbEF0dHJpYnV0ZSJ9XX0sImlzc3VlciI6ImRpZDpjY2Q6bWFpbm5ldDppZHA6MyIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJDb25jb3JkaXVtVmVyaWZpYWJsZUNyZWRlbnRpYWwiXX1dfQ=="proofBase64: "eyJwcmVzZW50YXRpb25Db250ZXh0IjoiYjM3ZTk4YWE1ZTM5MzQ2YzZlYTdjZGU0ZmU1OTc5OTQ0YTBhYjg2OTNkY2M2YjllOGFmMmQ1NzM2MWNkZWIxOSIsInByb29mIjp7ImNyZWF0ZWQiOiIyMDI0LTEwLTI3VDAzOjI0OjQ0LjUyNTg3OTQ3OFoiLCJwcm9vZlZhbHVlIjpbXSwidHlwZSI6IkNvbmNvcmRpdW1XZWFrTGlua2luZ1Byb29mVjEifSwidHlwZSI6IlZlcmlmaWFibGVQcmVzZW50YXRpb24iLCJ2ZXJpZmlhYmxlQ3JlZGVudGlhbCI6W3siY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJkaWQ6Y2NkOm1haW5uZXQ6Y3JlZDo4ZjAyM2IyNDRhODYzNTE4YWNjY2QyNDdkZWJlZjE5ZDZjNzJkZmYzOWMxMDE5ZmQ5MDM1MjA2MWI0NDMzMTYyZGZlMjJhYWUwNjE1NTRjZDIyMjk0ZmJkYjRlMTdkMWUiLCJwcm9vZiI6eyJjcmVhdGVkIjoiMjAyNC0xMC0yN1QwMzoyNDo0NC41MjU3MzkzMjRaIiwicHJvb2ZWYWx1ZSI6W3siYXR0cmlidXRlIjoiUHJvdmVuYW5jZSBUYWdzIEFwUyIsInByb29mIjoiMDEzOTE5YzVhYjQ1ZWQ4MzE3ZjM0NGU2Yzg3NmU3OGQyMTA4ZmI2Yzc4N2NjNWJiOWNhZGQ1YjhjZmQ5Mzc1MTM4ZDgzNGFjNmQ4ZmRiMzgzZGZjOGNlOGY1NjkzMDE3MWEwMGRiZmY4NTA4YTY3ZTVkZjBiN2UzYmI2ZmIwOWEiLCJ0eXBlIjoiUmV2ZWFsQXR0cmlidXRlIn0seyJhdHRyaWJ1dGUiOiJESyIsInByb29mIjoiNDk1Mzk5OTVlMjljNDFiYmYyYTRmMzcwMjQ5MzZkZDc4MTMwNGNmYWY3NThiNGUxMjQ3ODliZTUyNzRhNDQ0NzNmMzEzOWM5YmQyYTY2YjYyYjQzZmM4ZDM4NGVmZGIzOGEyN2YyYTRkY2UzZjc0NTNjMjgxZjA1YTAxNTVjNTQiLCJ0eXBlIjoiUmV2ZWFsQXR0cmlidXRlIn0seyJhdHRyaWJ1dGUiOiI0MzM5NTk2MyIsInByb29mIjoiOTMyZTEzYmYxNGM4Y2ZhYzc1MjRkM2ZlNjgzMTVmZTZmZjA2MzUyYTRmNTA2M2Q3NTczMjlhZjAwMDQ5YjdiYjI2ZTNmZjhkZmRjYjA2MDdkOGIyOTY3OGQzMjc4NWZmMjRmYWVhZDk1Y2IyYzA2NzJmYmJiNzY4Zjg2ZWM3MGEiLCJ0eXBlIjoiUmV2ZWFsQXR0cmlidXRlIn0seyJhdHRyaWJ1dGUiOiJDZW50cmFsIEJ1c2luZXNzIFJlZ2lzdGVyIiwicHJvb2YiOiIwZDk4MGNlMTJhNTc5NTBjM2NiMDEwMThlZjEzNDNlOTU5ZGYyNTg5MjdlYTIzYWU5NGUxNjZhNGMyYjgwY2RjMzllMjI5MzI3YWM1ZTgwMGFiMGM5YTQxNjRkOWQxYTc5YjZkNDk1NDM2OTQyMDNiMTc5N2VjMTA4NTZkOWYwMyIsInR5cGUiOiJSZXZlYWxBdHRyaWJ1dGUifV0sInR5cGUiOiJDb25jb3JkaXVtWktQcm9vZlYzIn0sInN0YXRlbWVudCI6W3siYXR0cmlidXRlVGFnIjoibGVnYWxOYW1lIiwidHlwZSI6IlJldmVhbEF0dHJpYnV0ZSJ9LHsiYXR0cmlidXRlVGFnIjoibGVnYWxDb3VudHJ5IiwidHlwZSI6IlJldmVhbEF0dHJpYnV0ZSJ9LHsiYXR0cmlidXRlVGFnIjoiYnVzaW5lc3NOdW1iZXIiLCJ0eXBlIjoiUmV2ZWFsQXR0cmlidXRlIn0seyJhdHRyaWJ1dGVUYWciOiJyZWdpc3RyYXRpb25BdXRoIiwidHlwZSI6IlJldmVhbEF0dHJpYnV0ZSJ9XX0sImlzc3VlciI6ImRpZDpjY2Q6bWFpbm5ldDppZHA6MyIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJDb25jb3JkaXVtVmVyaWZpYWJsZUNyZWRlbnRpYWwiXX1dfQ=="registrationAuth: “Central Business Register”[[Prototype]]: Object

Backend API: https://web3id-verifier.mainnet.concordium.software/v0/verify

I just tested this with the new 1.7.1 Browser Wallet and encountered the same error. The error reads:

"Proof submission failed: 400 - Invalid presentation format: Failed to deserialize the JSON body into the target type.

The error means that the JSON object that you sent to the backend is malformed compared to what the backend expects. May I ask you, if the request that you sent on testnet is identical (in terms of structure/fields) to the request that you sent on mainnet?

It’s the exact same code, and the code does not do anything with the json - so we would expect the JSON format to be identical on testnet vs mainnet, as it’s received from the wallet provider and sent directly to the backend. I see two possibilities: either the wallet provider on the mainnet is returning something different than expected, or the verification backend has different expectations.

Dear NHS, we updated the mainnet-verifier to the newest version (it was running an older version which caused the problem). Can you please try again, the format of the request should be as follows (Note: the below proof does not verify since it is from testnet because we don’t want to leak mainnet proofs but the proof request is correctly parsed):

curl -POST "https://web3id-verifier.mainnet.concordium.software/v0/verify" -H "Content-Type: application/json" --data '{"presentationContext":"24042609e1767cb6d60c73ab0e7e5127d93896684fb4069c3c5809f50f726177","proof":{"created":"2024-11-05T11:04:07.413Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation","verifiableCredential":[{"credentialSubject":{"id":"did:ccd:testnet:cred:8280babfd0a412ea2aeb2f707193e804a6104d150c5e095343c8b225ba496ad6c208a9e6bf54990a966f7d0b54cfed2e","proof":{"created":"2024-11-05T11:04:07.413Z","proofValue":[{"attribute":"John","proof":"7c5d2c94c5618aa5a30958a25ba0695d9985ea7d46fac3be89cff0b33418bdcf5415d995c35900935beb50c00b4f9df5bcc7bfa5cdd8e27b07148e487d93c521","type":"RevealAttribute"}],"type":"ConcordiumZKProofV3"},"statement":[{"attributeTag":"firstName","type":"RevealAttribute"}]},"issuer":"did:ccd:testnet:idp:0","type":["VerifiableCredential","ConcordiumVerifiableCredential"]}]}'

Hi Doris, perfect! That update solved the issue, and the flow now works on the mainnet as well. Thanks!

Hi Doris,

We’ve got it working with the Android wallet - as stated just before, and now I’m testing with the 1.7.1 Browser extension on the main-net using the same Identity. We’re running into that same original issue again—where the identity shows no active credentials from the issuer. However, the identity does have all the required credentials, and everything works fine on Android. Please see the attached details. We’re using issuer ID 3. See attached. Just to confirm there hasn’t been any changes that should prevent the Browser wallet from working on this? The only change I know since it worked is P7 - assuming this can’t be related.


Just to double-check, is the network in the browser wallet set to Mainnet when you connect to the dapp as well while you request the ZK proof.

Yes, please also check the attached allowlist. It’s the same dApp, just switching between browser and Android.

It was actually working just before P7—I can see in this thread that I successfully tested it 6 days ago.

Hello support, any update on this issue?

Dear NHS,
are you using a custom front-end to generate the proof request or our proof-explorer front-end made for testnet?

Our testnet proof explorer front-end would need some small adjustments in the drop-down to handle the mainnet IDPs order correctly: