# Credential Exchanges

A credential exchange, represented by `AIPCredentialExchange`, is an encapsulation of the cloud agent's progress in either issuing or receiving a credential over an established DIDComm connection.

## Credential Exchange Roles & States

An `AIPCredentialExchange` has a role (known as `myRole`) and a `state` associated with it.

### Role

The role indicates which role the cloud agent plays in the credential exchange protocol. The role is fixed for the lifetime of the credential exchange.

Role is either:

`ISSUER` or `HOLDER`

### State

The state indicates the current state of the cloud agent in the credential exchange protocol. The state transitions over time in a forward direction and cannot transition to previous states.

State transitions to success:

`OFFER` -> `REQUEST` -> `ISSUED` -> `DONE`

`PROPOSAL` -> `OFFER` -> `REQUEST` -> `ISSUED` -> `DONE`

### Summary

The following table provides a description of each role and each role+state combination.

| Role     | State       | Description                                                                                                                                                                                                              |
| -------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `ISSUER` |             | The cloud agent is acting as the credential issuer.                                                                                                                                                                      |
|          | `PROPOSAL`  | The connection proposed that the cloud agent issue it a credential.                                                                                                                                                      |
|          | `OFFER`     | The cloud agent sent a credential offer. If this state was preceded by `PROPOSAL`, then the offered credential may be based on the connection's proposal.                                                                |
|          | `REQUEST`   | The connection requested that the cloud agent issue the offered credential.                                                                                                                                              |
|          | `ISSUED`    | The cloud agent issued the offered credential to the connection.                                                                                                                                                         |
|          | `DONE`      | Terminal state for a successful credential exchange. The credential was issued.                                                                                                                                          |
|          | `ABANDONED` | Terminal state for an unsuccessful credential exchange. The credential was ***not*** issued.                                                                                                                             |
| `HOLDER` |             | The cloud agent is acting as the credential holder, and the connection is acting as the credential issuer. Technically, the cloud agent only holds the credential once the credential exchange reaches the `DONE` state. |
|          | `PROPOSAL`  | The cloud agent proposed that the connection issue it a credential.                                                                                                                                                      |
|          | `OFFER`     | The cloud agent received a credential offer. If this state was preceded by `PROPOSAL`, then the offered credential may be based on the cloud agent's proposal.                                                           |
|          | `REQUEST`   | The cloud agent requested that the connection issue the offered credential.                                                                                                                                              |
|          | `ISSUED`    | The connection issued the offered credential to the cloud agent.                                                                                                                                                         |
|          | `DONE`      | Terminal state for a successful credential exchange. A `Credential` was created.                                                                                                                                         |
|          | `ABANDONED` | Terminal state for an unsuccessful credential exchange. A `Credential` was ***not*** created.                                                                                                                            |

## Supported credential formats

The cloud agent supports credential exchanges for both Anoncreds Verifiable Credentials and W3C Verifiable Credentials. The credential format for the specific credential exchange is specified using the `format` nested object.

## Offer a credential

The cloud agent creates a new `AIPCredentialExchange` with role `ISSUER` and sends a credential offer to the specified `connectionId`. The `format` input object must be filled with the details of the credential to offer.

```graphql
mutation MyMutation {
  sendAipCredentialOffer(
    connectionId: "001fe530-3562-41d6-a631-3df9c7ae1f38"
    offer: {
      format: {
        # INSERT DETAILS OF THE CREDENTIAL TO OFFER
      }
      autoAcceptRequest: true
    }
  ) {
    id
    myRole
    state
    connectionId
  }
}
```

If instead the cloud agent *receives* a credential offer, a new `AIPCredentialExchange` is created with role `HOLDER`.

{% hint style="info" %}
Anoncreds credentials

In order to offer and issue an [Anoncreds credential](https://docs.sudoplatform.com/guides/decentralized-identity/cloud-agent/cloud-agent-admin-api/credentials/anoncreds-credentials), a `credDefId` must be provided. This value must reference a [credential definition](https://docs.sudoplatform.com/guides/decentralized-identity/cloud-agent/cloud-agent-admin-api/credentials/anoncreds-credentials/credential-definitions) which is already written to the ledger.
{% endhint %}

## View received credential offers

View credential exchanges in any state, with pagination and filtering options. Returns a `nextToken` which can be passed into the same query in order to fetch subsequent pages.

As an example, the filter options can be used to find received credential offers, even from a specific connection.

```graphql
query MyQuery {
  aipCredentialExchanges(
    page: {
      nextToken: null
    }
    filter: {
      myCredExRole: HOLDER
      credExStates: [OFFER]
      connectionIds: ["001fe530-3562-41d6-a631-3df9c7ae1f38"]
    }
  ) {
    items {
      id
      myRole
      state
      messages {
        offer {
          comment
          format {
            __typename
            ... on AnoncredsCredOffer {
              credDefId
              schemaId
              attributeValues {
                name
                value
              }
            }
            ... on W3CCredNegotiation {
              credentialJson
            }
          }
        }
      }
      connectionId
    }
    nextToken
  }
}
```

Alternatively, view a single credential exchange, referenced by its unique ID.

```graphql
query MyQuery {
  aipCredentialExchange(
    credExId: "225d12f5-f5fa-43d0-ba83-bf602f729fd6"
  ) {
    id
    myRole
    state
    connectionId
  }
}
```

## Accept a credential offer

The cloud agent accepts the offer by requesting the offered credential from the connection. The input param `credExId` must match the ID of an `AIPCredentialExchange` which has the `HOLDER` role and is in the `OFFER` state. When the cloud agent finally receives the issued credential, the credential will be automatically stored as a new `Credential`.

```graphql
mutation MyMutation {
  acceptAipCredentialOffer(
    credExId: "225d12f5-f5fa-43d0-ba83-bf602f729fd6"
    acceptOffer: {}
  ) {
    id
    myRole
    state
    connectionId
  }
}
```

## Issue a credential

The cloud agent accepts a request for a credential by issuing the credential to the connection. The input param `credExId` must match the ID of an `AIPCredentialExchange` which has the `ISSUER` role and is in the `REQUEST` state.

```graphql
mutation MyMutation {
  acceptAipCredentialRequest(
    credExId: "33c3cfe6-3377-44eb-a357-bce11b2f9c17"
    acceptRequest: {}
  ) {
    id
    myRole
    state
    connectionId
  }
}
```

## Delete a credential exchange

Delete a credential exchange. If the credential exchange is not in the `DONE` state, then this operation will also send a "problem report" to the associated connection to inform them that the cloud agent has abandoned the credential exchange. Note that if the credential exchange has role `HOLDER` and is in the `DONE` state, the exchange will have resulted in a new `Credential`, which is ***not*** deleted by this operation.

```graphql
mutation MyMutation {
  deleteAipCredentialExchange(
    credExId: "225d12f5-f5fa-43d0-ba83-bf602f729fd6"
  )
}
```
