> For the complete documentation index, see [llms.txt](https://docs.indicio.tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.indicio.tech/developer/mobile-solutions/mobile-sdk/proofs.md).

# Proofs

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.

{% stepper %}
{% step %}

### Auto Accepting

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.

#### Kotlin

{% code title="Auto-accept proof (Kotlin)" %}

```kotlin
// 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}")
}
```

{% endcode %}

#### React Native

{% code title="Auto-accept proof (React Native / TypeScript)" %}

```typescript
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}`)
        }
    }
)
```

{% endcode %}

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.
{% endstep %}

{% step %}

### Manual Acceptance

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.

#### Kotlin

{% code title="Manual acceptance - autoSelect or getCredentials (Kotlin)" %}

```kotlin
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
)
```

{% endcode %}

#### React Native

{% code title="Manual acceptance - autoSelect or getCredentials (React Native / TypeScript)" %}

```typescript
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
    )
})
```

{% endcode %}

The return from both of these functions is a `PresentationData` object. With the auto-select function having some data already filled in.

<details>

<summary>PresentationData structure and helpers</summary>

The `PresentationData` object contains four properties: `proofId`, `exchangeId`, `attributes`, and `predicates` (the last two being arrays). It also contains helper functions:

* `getRemaining` — returns an array of the remaining `proofReferent` that do not have a selection.
* `isReady` — returns a boolean that indicates if a valid selection has been made for all `proofReferent`s.
* `autoSelect` — does an in-place auto selection of the provided credentials and returns a boolean indicating if it successfully made selections for all request referents.
* `getRequiredSelfAttested` — returns a list of all the attributes that are required to be self-attested.

The `attributes` and `predicates` arrays contain objects called `attributeReferent` and `predicateReferent` (two types of `proofReferent`). These objects contain the properties `canSelfAttest`, `requiredSelfAttest`, and `selfAttestedValue`. These properties pertain to self-attesting during a proof (only available with an attribute and not a predicate).

* `canSelfAttest` indicates if the value can be self-attested.
* `requiredSelfAttest` indicates if the value must be self-attested.
* `selfAttestedValue` is a mutable string that should be set to data not in a credential (e.g., user input or from elsewhere in the app).

Each `proofReferent` also has three object properties: `selection`, `credentials`, and `request`.

* `selection` is the credential match you want to use to satisfy the `proofReferent`. It can be set using the `selectCredential` function which takes a `credentialMatch` object or an index corresponding to a value in the `credentials` array.
* `credentials` is an array of all the credentials that satisfy the `proofReferent`.
* `request` is the actual object that indicates what data is being requested from the wallet.

Differences between `attributeReferent` and `predicateReferent`:

* `predicateReferent` also has a `requirement` string that indicates the relational requirement for the requested data.
* Predicates should not be self-attested and thus should always return false for self-attested values.

Filling in self-attested values is intended to be done in place. If an optional self-attested attribute is supplied it will be given priority over any supplied credential value.

</details>

#### Auto selection flow (processing returned PresentationData)

Kotlin:

{% code title="Auto-selection handling (Kotlin)" %}

```kotlin
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)
```

{% endcode %}

React Native / TypeScript:

{% code title="Auto-selection handling (React Native / TypeScript)" %}

```typescript
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)
```

{% endcode %}

#### Manual Selection

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:

{% code title="Manual selection (Kotlin)" %}

```kotlin
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)
```

{% endcode %}

React Native / TypeScript:

{% code title="Manual selection (React Native / TypeScript)" %}

```typescript
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)
```

{% endcode %}
{% endstep %}
{% endstepper %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.indicio.tech/developer/mobile-solutions/mobile-sdk/proofs.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
