When a proof request is received an event will be emitted. There are two options for handling proofs: attempt to auto-accept and process the proof, or manually select credentials. A proof request can be automatically accepted if the request does not have any attributes that need to be self-attested (provided manually from the user) and there are sufficient credentials in the wallet.
A single proof request can contain multiple proofs that need to be satisfied and in turn can make manual selection complicated.
A proof event contains the proof record and the didExchangeId of the contact that it came from. The initial state for the proof record is requestReceived.
This flow attempts to automatically select credentials and accept the proof. It only succeeds if there are no required self-attested attributes and the wallet contains sufficient credentials.
// Gets the first proof event received, blocks whatever thread it is ran on.
val proofEvent = agent.events.getProofEvents().first()
try {
agent.proofs.autoAcceptProof(proofEvent.proofRecord.id, proofEvent.didExchangeId)
} catch (e: Throwable) {
println("An error occurred auto-accepting proof, message: ${e.message}")
}const removeProofHandler = agent.events.registerProofHandler(
(event) => {
try {
if (event.proofRecord.state === ProofState.REQUEST_RECEIVED) {
await agent.proofs.autoAcceptProof(
event.proofRecord.id,
event.exchangeId
);
}
} catch (error) {
console.log(`An error ocurred auto-accepting proof, message ${error.message}`)
}
}
)That is all it takes to fulfill an automatic proof request.
Reminder: this only works if there are not self-attested attributes for the request and the wallet contains sufficient credentials.
Manual acceptance has two possible flows:
Let the agent auto-select credentials and return them to you so you can fill in any self-attested values.
Have the agent return all potential credentials that satisfy the proof, so you manually choose which to use.
Both options will throw if the wallet does not contain sufficient credentials for the proof request.
The return from both of these functions is a PresentationData
Kotlin:
React Native / TypeScript:
Self-attested attributes function the same way for manual selection.
Manual selection requires that a credential from the returned list be selected for each referent in the proof. This allows the end user to select exactly what credentials are shared but is more complex to process.
Kotlin:
React Native / TypeScript:
val proofEvent = agent.events.getProofEvents().first()
// Returns a list of pairs containing first the proof and then the credential(s) selected
val proofAttributes: SelectedCredentialsForProof = agent.proofs.autoSelectCredentialsForProof(
proofEvent.proofRecord.id,
proofEvent.didExchangeId,
nonRevoked = false
) // nonRevoked indicates if you care if the credentials selected are revoked or not
// Or
// Returns a similar object but can potentially contain multiple credentials that need to be selected from
val proofAttributes: SelectedCredentials = agent.proofs.getCredentialsForProofRequest(
proofEvent.proofRecord.id,
proofEvent.didExchangeId,
nonRevoked = false
)const removeProofHandler = agent.events.registerProofHandler(async (event) => {
const proofAttributes = await agent.proofs.autoSelectCredentialsForProof(
event.proofRecord.id,
event.didExchangeId,
false
)
// Or
const proofAttributes = await agent.proofs.getCredentialsForProofRequest(
event.proofRecord.id,
event.didExchangeId,
false
)
})val proofData = agent.proofs.autoSelectCredentialsForProof(
proofEvent.proofRecord.id,
proofEvent.didExchangeId,
nonRevoked = false
)
// Check if there are any required self-attested attributes
val selfAttested = proofData.getRequiredSelfAttested()
if(selftAttested.size != 0){
selfAttested.forEach{ referent ->
referent.selfAttestedValue = "Data from somewhere else"
}
}
// Supply the originally returned object that has been modified in place
agent.proofs.acceptProofs(proofData)const proofData = await agent.proofs.autoSelectCredentialsForProof(
event.proofRecord.id,
event.didExchangeId,
false
)
const selfAttested = proofData.getRequiredSelfAttested()
if(selfAttested.size != 0) {
selfAttested.forEach((referent) => {
referent.selfAttestedValue = "Data from somewhere else"
})
}
await agent.proofs.acceptProofs(proofData)val proofData = agent.proofs.getCredentialsForProofRequest(
proofEvent.proofRecord.id,
proofEvent.didExchangeId,
nonRevoked = false
)
// Goes through all attributes and picks the first credential that matches
proofData.attributes.forEach{ attribute =>
attribute.selectCredential(0)
}
proofData.predicates.forEach{ predicate =>
predicate.selectCredential(0)
}
agent.proofs.acceptProofs(proofData)const proofData = await agent.proofs.getCredentialsForProofRequest(
proofEvent.proofRecord.id,
proofEvent.didExchangeId,
nonRevoked = false
)
proofData.attributes.forEach((attribute) => {
attribute.selectCredential(0)
})
proofData.predicates.forEach((predicate) => {
predicate.selectCredential(0)
})
await agent.proofs.acceptProofs(proofData)request is the actual object that indicates what data is being requested from the wallet.