# updating/versions/0.3-to-0.4

# Migrating from Credo 0.3.x to 0.4.x

This document describes everything you need to know for updating Credo 0.3.x to 0.4.x. If you're not aware of how updating in Credo works make sure to first read the guide on [Updating Credo](https://credo.js.org/guides/next/updating.md).

First of all, update you dependencies to the 0.4.x versions. This will also update the needed peer dependencies. **Extension packages are not updated with this command**. You need to update these manually, and make sure they're up to date with the latest version of Credo.

Credo 0.4.0 is a major release that introduces a lot of new features and changes to the public API. Specifically, this release removed the dependency on the Indy SDK from the `@aries-framework/core` package. Agent setup is more flexible, but it also means the setup is more complex. Follow the mentioned steps in this document carefully to make the upgrade as smooth as possible.

:::caution

The migration guide only covers how to migrate from 0.3.x to 0.4.x while keeping the same behavior and dependencies. Credo 0.4.0 introduced a lot of new features and adds support for [Aries Askar](https://github.com/hyperledger/aries-askar), [Indy VDR](https://github.com/hyperledger/indy-vdr) and [AnonCreds RS](https://github.com/hyperledger/anoncreds-rs) as a replacement for the Indy SDK.

Migrating to these new components requires additional migration steps, which need to be closely followed to prevent loss of data. These can be found at the [Update Indy SDK to Askar guide](https://credo.js.org/guides/next/updating/update-indy-sdk-to-askar.md).

As noted in the [Update Indy SDK to Askar guide](https://credo.js.org/guides/next/updating/update-indy-sdk-to-askar.md), it is very important that the 0.3.x to 0.4.x update is started after migrating from the Indy SDK to Aries Askar.

:::

:::caution

Multi-tenancy is not covered in the 0.3.x to 0.4.x migration guide. If you're using multi-tenancy in 0.3.x and want to migrate to 0.4.x, please open an issue on [Github](https://github.com/openwallet-foundation/credo-ts).

:::

:::caution

The following APIs, modules and features are experimental and therefore not covered by the semver versioning in Credo. If you're using any of these features, make sure to use an exact version of Credo (`0.4.0`) instead of a range (`^0.4.0`):

- Implementing your own `AnonCredsRegistry` and AnonCreds service implementation. Using the default implementations (Indy SDK, AnonCreds RS) is fine.
- Using the shared component libraries from `@aries-framework/aries-askar`, `@aries-framework/indy-vdr` and `@aries-framework/anoncreds-rs`
- Using OpenID4VC from the `@aries-framework/openid4vc-client` module
- W3C JWT Verifiable Credentials
- Using multi-tenancy from the `@aries-framework/tenants` module

:::

**React Native**

First install the updated dependencies. Make sure to also install the new `@aries-framework/indy-sdk` package, which is a wrapper around the Indy SDK and install the `indy-sdk-react-native` package.

```bash
yarn add @aries-framework/react-native@^0.4.0 @aries-framework/core@^0.4.0 @aries-framework/indy-sdk@^0.4.0 @aries-framework/anoncreds@^0.4.0 indy-sdk-react-native@^0.3.1

# or NPM
npn install @aries-framework/react-native@^0.4.0 @aries-framework/core@^0.4.0 @aries-framework/indy-sdk@^0.4.0 @aries-framework/anoncreds@^0.4.0 indy-sdk-react-native@^0.3.1
```

We also need to install types for the `indy-sdk-react-native` package, which we take from the `@types/indy-sdk` package.

```bash
yarn add --dev @types/indy-sdk-react-native@npm:@types/indy-sdk

# or NPM
npm install --save-dev @types/indy-sdk-react-native@npm:@types/indy-sdk
```

**Node**

First install the updated dependencies. Make sure to also install the new `@aries-framework/indy-sdk` package, which is a wrapper around the Indy SDK and install the `indy-sdk` package itself.

```bash
yarn add @aries-framework/node@^0.4.0 @aries-framework/core@^0.4.0  @aries-framework/indy-sdk@^0.4.0 @aries-framework/anoncreds@^0.4.0 indy-sdk

# or NPM
npm install @aries-framework/node@^0.4.0 @aries-framework/core@^0.4.0  @aries-framework/indy-sdk@^0.4.0 @aries-framework/anoncreds@^0.4.0 indy-sdk
```

We also need to install types for the `indy-sdk` package, which are available in the `@types/indy-sdk` package.

```bash
yarn add --dev @types/indy-sdk

# or NPM
npm install --save-dev @types/indy-sdk
```

## Breaking Code Changes

This section will list all breaking changes made to the public API of Credo between version 0.3.x and 0.4.0.

:::info

If you have custom modules take into account there could be a lot more breaking changes that aren't documented here. We try to make sure that the biggest breaking changes to the internal API are also documented here, but it is possible some breaking changes are not documented here (feel free to open a pull request).

:::

### Agent Creation

With the dependency on the Indy SDK removed from the `@aries-framework/core` package, we now need to register the `IndySdkModule` to still leverage the functionality the Indy SDK provides.

**0.3.x**

```ts
import { Agent } from '@aries-framework/core'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

const agent = new Agent({
  config: {
    /* ... */
  },
  dependencies: agentDependencies,
})
```

**0.4.x**

```ts
import { Agent } from '@aries-framework/core'
import { IndySdkModule } from '@aries-framework/indy-sdk'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

// Import from indy-sdk-react-native in React Native
import indySdk from 'indy-sdk'

const agent = new Agent({
  config: {
    /* ... */
  },
  dependencies: agentDependencies,
  modules: {
    // Register the IndySdkModule and provide the indySdk dependency
    indySdk: new IndySdkModule({
      indySdk,
    }),
  },
})
```

### Indy Network Configuration

With the Indy SDK being extracted out of core, the `indyLedger` configuration option is no longer available on the `AgentConfig` interface. Instead, the `networks` configuration option is now available on the `IndySdkModule` configuration.

In addition the `connectToIndyLedgersOnStartup` property has been removed in favor of a per-network `connectOnStartup` property that allows more fine-grained control over which networks to connect to on startup.

**0.3.x**

```ts
import { Agent } from '@aries-framework/core'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

const agent = new Agent({
  config: {
    connectToIndyLedgersOnStartup: true,
    indyLedgers: [
      {
        id: 'Sovrin Mainnet',
        indyNamespace: 'sovrin',
        isProduction: true,
        genesisPath: './genesis/sovrin-genesis.txn',
      },
    ],
  },
  dependencies: agentDependencies,
})
```

**0.4.x**

```ts
import { Agent } from '@aries-framework/core'
import { IndySdkModule } from '@aries-framework/indy-sdk'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

// Import from indy-sdk-react-native in React Native
import indySdk from 'indy-sdk'

const agent = new Agent({
  config: {
    /* ... */
  },
  dependencies: agentDependencies,
  modules: {
    // Register the IndySdkModule and provide the indySdk dependency
    indySdk: new IndySdkModule({
      indySdk,

      // add networks as a replacement for indyLedgers
      networks: [
        {
          id: 'Sovrin Mainnet',
          indyNamespace: 'sovrin',
          isProduction: true,
          genesisPath: './genesis/sovrin-genesis.txn',
          // new connectOnStartup property
          connectOnStartup: true,
        },
      ],
    }),
  },
})
```

### Changes to wallet

Throughout the framework it was possible to provide a `seed` for deterministic key generation. Recently it was discovered that the `seed` property in the Indy SDK was not actually used as a seed, but directly as the private key.

Therefore a new `privateKey` property was added to the `Wallet` interface in addition to the `seed` property. When using the `IndySdkModule` this now means you can **only** provide the `privateKey` property. The `seed` property is no longer supported **by the `IndySdkModule`**.

The type of the `seed` property has also been changed to `Buffer` to make it more consistent with `privateKey` property, and remove the ambiguity of what the encoding of the string variant of the `seed` property should be.

### Did Resolver and Registrar

The `did:sov` resolver and registrar were registered by default in 0.3.x of the agent. In 0.4.0 they've been moved to the `@aries-framework/indy-sdk` package and are thus not registered by default on the DIDs module anymore. In addition, the `IndySdkSovDidRegistrar` has been replaced in favor of the `IndySdkIndyDidRegistrar` which provides similar behavior, but leverages the new [`did:indy` method](https://hyperledger.github.io/indy-did-method/#indy-did-method-identifiers), which removes ambiguity about which network to use. You can still use the `IndySdkSovDidResolver` to resolve `did:sov` DIDs.

Note that the `IndySdkModule` MUST be registered when using the Indy SDK did resolvers and registrars (see [Agent Creation](#agent-creation)). The networks supported by the resolvers and registrar is determined by the `networks` registered on the `IndySdkModule` (see [Indy Network Configuration](#indy-network-configuration)).

Also note that by default the `WebDidResolver`, `KeyDidResolver` and `PeerDidResolver` are registered, and setting the `resolvers` property on the `DidsModule` configuration will override the default resolvers (an exception is the `PeerDidResolver` as it is required for creating connections, and thus will always be registered).

The same thing is true for the `registrars`, for which the `KeyDidRegistrar` and `PeerDidRegistrar` are registered by default. If defining the `resolvers` and `registrars`, make sure to include the default registrars if you want to keep the previous behavior.

**0.3.x**

```ts
import { Agent } from '@aries-framework/core'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

const agent = new Agent({
  config: {
    /* ... */
  },
  dependencies: agentDependencies,
})
```

**0.4.x**

```ts
import { Agent, DidsModule } from '@aries-framework/core'
import { IndySdkModule } from '@aries-framework/indy-sdk'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

const agent = new Agent({
  config: {
    /* ... */
  },
  dependencies: agentDependencies,
  modules: {
    // note that the IndySdkModule MUST be registered for the resolvers and registrars to work
    // they are left out for brevity and can bee
    dids: new DidsModule({
      registrars: [new IndySdkIndyDidRegistrar()],
      resolvers: [new IndySdkSovDidResolver(), new IndySdkIndyDidResolver()],
    }),
  },
})
```

### Removal of `publicDidSeed` and `publicDid`

To make Credo more generic, and less focused on Hyperledger Indy, and Indy dids, the `publicDidSeed` and `publicDid` properties have been removed from the agent configuration, the agent class, and the `Wallet` interface.

The `publicDid` property was used as the did to register items in the ledger module. The approach had some limitations:

- An agent could only have a single `publicDid` property. This means that if you wanted to write to multiple ledgers you would have to create multiple agents
- The property assumed only Indy ledgers would be used, and didn't take into account the possibility of other ledgers.

Credo now provides generic APIs that can work with any ledger, and thus the `publicDid` property is no longer needed. Different sections of this migration guide will explain the different parts of how to use the new APIs, this section just focuses on how to replace the `publicDid` property.

The most common use case for the `publicDid` property was for registering an endorser did that can endorse (read: pay for) transactions on the ledger. This can now be done by importing the did into agent, after which it can be used by the AnonCreds module to register schemas and credential definitions, and the did registrar to register DIDs.

There's a **one-time import** that needs to be done to import the did into the agent using the `DidsApi.import` method. If you've previously used the `publicDidSeed` property, providing the private key is optional, as it is already stored in the wallet. Note that the `privateKey` is the same as the `publicDidSeed`, see [Changes to Wallet](#changes-to-wallet) for context). The `import` method will resolve the did passed to the `import` method (so make sure to register the `IndySdkIndyDidResolver`). It is recommended to import the endorser did as an `did:indy` did rather than a `did:sov` did, as the `did:sov` method is deprecated for creation. The `did:indy` did can be constructed by replacing `sov` with `indy:<indyNamespace>`, where `<indyNamespace>` should be replaced with a namespace as registered in the `networks` property of the `IndySdkModule` (see [Indy Network Configuration](#indy-network-configuration)).

An initial list of namespace identifiers can be found in an [issue in the Indy Did Networks Repository](https://github.com/hyperledger/indy-did-networks/issues/3). In the future this list will be maintained in the [Indy DID Networks repository](https://github.com/hyperledger/indy-did-networks) itself.

**0.3.x**

```ts
import { Agent } from '@aries-framework/core'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

const agent = new Agent({
  config: {
    publicDidSeed: '01eafa4de4e22ed4fc2ee522b6ce2731',
  },
  dependencies: agentDependencies,
})
```

**0.4.x**

```ts
import { Agent, DidsModule, KeyType, TypedArrayEncoder } from '@aries-framework/core'
import { IndySdkModule, IndySdkIndyDidResolver } from '@aries-framework/indy-sdk'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

// Import from indy-sdk-react-native in React Native
import indySdk from 'indy-sdk'

const agent = new Agent({
  config: {
    /* ... */
  },
  dependencies: agentDependencies,
  modules: {
    indySdk: new IndySdkModule({
      indySdk,
      networks: [
        {
          id: 'Sovrin Mainnet',
          // Important: make sure to pick the correct indy namespace for the network you're connecting to
          // See: https://github.com/hyperledger/indy-did-networks/issues/3
          indyNamespace: 'sovrin',
          isProduction: true,
          genesisPath: './genesis/sovrin-genesis.txn',
        },
      ],
    }),
    dids: new DidsModule({
      // Important: Make sure to register the IndySdkIndyDidResolver
      resolvers: [new IndySdkIndyDidResolver()],
    }),
  },
})

// Important: the `import` method only has to be called once, and the agent MUST be initialized before calling it.
// The private key is optional if you've used the publicDidSeed property before (as the key will already be in the wallet),
await agent.initialize()
await agent.dids.import({
  did: 'did:indy:sovrin:KEPUoXHcswsfsHkXGfmXB7',
  privateKeys: [
    {
      keyType: KeyType.Ed25519,
      privateKey: TypedArrayEncoder.fromString('01eafa4de4e22ed4fc2ee522b6ce2731'),
    },
  ],
})
```

### More Granular Usage of Legacy `did:sov` Prefix in DIDComm Messages

Credo 0.3.0 used the `useLegacyDidSovPrefix` to use the legacy `did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/` as the prefix in the `@type` of DIDComm message instead of the new `https://didcomm.org` prefix. Over time it has proven that this approach leads to undesired behavior as all messages (even protocols that were defined after the new prefix was the default) would use the legacy prefix. However, due to not all implementations having support for new prefix, disabling the legacy prefixes proved to be a problem.

Therefore, in Credo 0.4.0 the `useLegacyDidSovPrefix` property has been replaced with the `useDidSovPrefixWhereAllowed` property. This property will only use the legacy prefix for protocols that were defined before the new prefix was the default. This means that protocols that were defined after the new prefix was the default will use the new prefix independent of the value of the `useDidSovPrefixWhereAllowed` property. We hope this will allow us to slowly migrate away from the legacy prefix as new protocols are defined without breaking backwards compatibility.

**0.3.x**

```ts
import { Agent } from '@aries-framework/core'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

const agent = new Agent({
  config: {
    useLegacyDidSovPrefix: true,
  },
  dependencies: agentDependencies,
})
```

**0.4.x**

```ts
import { Agent } from '@aries-framework/core'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

const agent = new Agent({
  config: {
    useDidSovPrefixWhereAllowed: true,
  },
  dependencies: agentDependencies,
})
```

### Removal of `injectionContainer` property from the agent

The `injectionContainer` property on the `Agent` has been replaced by the `dependencyManager` property. The `dependencyManager` property is an instance of the `DependencyManager` class and wraps the injection container from `tsyringe`.

The `DependencyManager` _should_ provide all functionality that is needed, and it is recommended to not use the injection directly. If you need to use the injection container directly, you can access it via the `container` property on the `DependencyManager` instance, but please raise an issue to discuss if the functionality you need should be added to the `DependencyManager` class.

### `connection` has been updated to `connectionId` in `TransportSession`

The `connection` property on the `TransportSession` has been changed to `connectionId` and now only holds a reference to the connection id instead of the connection record itself.

Accessing the connection on a transport session is an advanced case that is mostly only relevant when implementing a custom transport. If you are using the default transports, you should not be affected by this change.

### Replacement of Ledger Module with new AnonCreds Module

The ledger module has been available in Credo since the very beginning, and was due for a big overhaul. With the addition of the dids module a while ago we already had a replacement for the `registerPublicDid` and `getPublicDid` methods on the ledger module. The other methods of the ledger module have been replaced by the AnonCreds module.

In Credo 0.4.0 AnonCreds credential support is not part of the core framework anymore, and needs to be manually registered on the agent. The first part is enabling the AnonCreds module, which allows to manage AnonCreds objects, interact with the ledger, and issuer, hold and verify AnonCreds credentials and is explained in this section. The second part is actually allowing AnonCreds credentials to be exchanged in the Issue Credential and Present Proof protocols, which is explained in the [Manually Register AnonCreds Support in Credentials and Proofs Modules](#changes-to-the-credentials-and-proofs-modules) section.

There's a few important takeaways based on the code example below:

- The `anoncreds` module can be accessed under the `agent.modules.anoncreds` property.
- The interfaces are set up as generically as possible based on the [DID Registration](https://identity.foundation/did-registration/) and [DID Resolution](https://w3c-ccg.github.io/did-resolution/) specifications.
- AnonCreds registries need to be manually registered so it's important to register the `IndySdkAnonCredsRegistry` on the `AnonCredsModule`.
- It is now required to pass an `issuerId` when registering AnonCreds objects, according to the [AnonCreds Specification](https://hyperledger.github.io/anoncreds-spec/). Only `did:indy` issuer identifiers are allowed (based on the [`did:indy` AnonCreds Method](https://hyperledger.github.io/anoncreds-methods-registry/#didindy-anoncreds-method)), so the network can be inferred from the issuer identifier.

As will be explained in the [Manually Register AnonCreds Support in Credentials and Proofs Modules](#changes-to-the-credentials-and-proofs-modules), you can still use the unqualified issuer identifiers (best known as the [Hyperledger Indy Legacy AnonCreds Method](https://hyperledger.github.io/anoncreds-methods-registry/#hyperledger-indy-legacy-anoncreds-method)) in credential and proof exchanges.

**0.3.x**

```ts
import { Agent } from '@aries-framework/core'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

const agent = new Agent({
  config: {
    /* ... */
    publicDidSeed: '01eafa4de4e22ed4fc2ee522b6ce2731',
    indyLedgers: [
      {
        id: 'Sovrin Mainnet',
        indyNamespace: 'sovrin',
        isProduction: true,
        genesisPath: './genesis/sovrin-genesis.txn',
      },
    ],
  },
  dependencies: agentDependencies,
})

await agent.initialize()

const schema = await agent.ledger.registerSchema({
  attributes: ['name'],
  name: 'Example Schema',
  version: '1.0.1',
})

const credentialDefinition = await agent.ledger.registerCredentialDefinition({
  schema,
  supportRevocation: false,
  tag: 'default',
})
```

**0.4.x**

```ts
import { AnonCredsModule } from '@aries-framework/anoncreds'
import { Agent, DidsModule, KeyType, TypedArrayEncoder } from '@aries-framework/core'
import { IndySdkAnonCredsRegistry, IndySdkModule, IndySdkIndyDidResolver } from '@aries-framework/indy-sdk'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

// Import from indy-sdk-react-native in React Native
import indySdk from 'indy-sdk'

const agent = new Agent({
  config: {
    /* ... */
  },
  dependencies: agentDependencies,
  modules: {
    indySdk: new IndySdkModule({
      indySdk,
      networks: [
        {
          id: 'Sovrin Mainnet',
          indyNamespace: 'sovrin',
          isProduction: true,
          genesisPath: './genesis/sovrin-genesis.txn',
        },
      ],
    }),
    // Important: register the IndySdkAnonCredsRegistry so that the anoncreds module can resolver/register anoncreds objects based on the networks configured in the IndySdkModule
    anoncreds: new AnonCredsModule({
      registries: [new IndySdkAnonCredsRegistry()],
    }),
    // Important: register the IndySdkIndyDidResolver so that the anoncreds module can resolve DIDs based on the networks configured in the IndySdkModule
    dids: new DidsModule({
      resolvers: [new IndySdkIndyDidResolver()],
    }),
  },
})

// Agent MUST be initialized before the anoncreds module can be used
await agent.initialize()

// Important: the issuerId (did) MUST be available to the dids module in the agent. You can either create the did using the dids module, or import it as described in this migration guide.
const schemaResult = await agent.modules.anoncreds.registerSchema({
  schema: {
    attrNames: ['name'],
    issuerId: 'did:indy:sovrin:KEPUoXHcswsfsHkXGfmXB7',
    name: 'Example Schema',
    version: '1.0.0',
  },
  options: {},
})

// The resolver and registrar follow the same pattern as the Did Registration
// and Did Resolver interfaces as used by the did module.
if (schemaResult.schemaState.state !== 'finished') {
  console.error(schemaResult)
  throw new Error(`Error creating schema`)
}

const credentialDefinitionResult = await agent.modules.anoncreds.registerCredentialDefinition({
  credentialDefinition: {
    issuerId: 'did:indy:sovrin:KEPUoXHcswsfsHkXGfmXB7',
    schemaId: schemaResult.schemaState.schemaId,
    tag: 'default',
  },
  options: {},
})
```

### Changes to the Credentials and Proofs modules

A lot of small, and some bigger changes have been made to the Credentials, and primarily, the Proofs modules. These changes have been made to make the modules more consistent and generic so that they can be used in a wider range of use cases, removing any focus on AnonCreds and Indy credentials.

Changes to the Proofs module include:

- `getRequestedCredentialsForProofRequest` has been renamed to `getCredentialsForRequest`
- `autoSelectCredentialsForProofRequest` has been renamed to `selectCredentialsForRequest`
- The `config` parameter for both methods has been removed and those have been replaced by proof format specific configuration options. In this case, the `config.filterByNonRevocationRequirements` has been added as `proofFormats.indy.filterByNonRevocationRequirements` (if the `indy` format is registered as explained in the next section). The `config.filterByPresentationPreview` has been removed as the presentation preview was only present in the present proof V1 protocol, and due to it's limited applicability (the holder starts with a proposal) we've decided to remove this method for now. You can still filter the credentials yourself by using the `getCredentialsForRequest` method.
- Interfaces have been renamed to be more consistent with the method names. Please refer to the [`CredentialsApiOptions`](https://github.com/openwallet-foundation/credo-ts/blob/v0.4.0/packages/core/src/modules/credentials/CredentialsApiOptions.ts) and [`ProofsApiOptions`](https://github.com/openwallet-foundation/credo-ts/blob/v0.4.0/packages/core/src/modules/proofs/ProofsApiOptions.ts) for the interface names that can be imported.

If you encounter any other breaking changes in the Proofs and Credentials modules, please open an issue in the [Credo Docs](https://github.com/openwallet-foundation/credo-ts-docs) repository.

### Changes to the AnonCreds Credential and Proof Format

With the 0.4.0 release, Credo now provides a pluggable AnonCreds interface, and requires support AnonCreds credentials to be explicitly registered on the agent. This is also the case for registering the credential and proof formats.

In 0.3.x, the `IndyProofFormatService` and `IndyCredentialFormatService` were registered by default. In 0.4.x, these services are no longer registered by default and they should be imported from the `@aries-framework/anoncreds` package as `LegacyIndyProofFormatService` and `LegacyIndyCredentialFormatService` and are based on [Aries RFC 0592](https://github.com/hyperledger/aries-rfcs/blob/main/features/0592-indy-attachments/README.md). In a future version the new `AnonCredsCredentialFormatService` and `AnonCredsProofFormatService` will be added to the AnonCreds package, which are based on [Aries RFC 0771](https://github.com/hyperledger/aries-rfcs/pull/771) and allow for AnonCreds credentials to be exchanged based on the new ledger agnostic [AnonCreds Specification](https://hyperledger.github.io/anoncreds-spec/).

In addition, the `V1CredentialProtocol` and `V1ProofProtocol` have been extracted into the `@aries-framework/anoncreds` package, as they only support exchange of (legacy Indy) AnonCreds credentials.

**0.3.x**

```ts
import { Agent } from '@aries-framework/core'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

const agent = new Agent({
  config: {
    /* ... */
    indyLedgers: [
      {
        id: 'Sovrin Mainnet',
        indyNamespace: 'sovrin',
        isProduction: true,
        genesisPath: './genesis/sovrin-genesis.txn',
      },
    ],
  },
  dependencies: agentDependencies,
})
```

**0.4.x**

```ts
import {
  AnonCredsModule,
  LegacyIndyCredentialFormatService,
  LegacyIndyProofFormatService,
  V1CredentialProtocol,
  V1ProofProtocol,
} from '@aries-framework/anoncreds'
import { Agent, CredentialsModule, ProofsModule, V2CredentialProtocol, V2ProofProtocol } from '@aries-framework/core'
import { IndySdkAnonCredsRegistry, IndySdkModule } from '@aries-framework/indy-sdk'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

// Import from indy-sdk-react-native in React Native
import indySdk from 'indy-sdk'

const legacyIndyCredentialFormat = new LegacyIndyCredentialFormatService()
const legacyIndyProofFormat = new LegacyIndyProofFormatService()

const agent = new Agent({
  config: {
    /* ... */
  },
  dependencies: agentDependencies,
  modules: {
    indySdk: new IndySdkModule({
      indySdk,
      networks: [
        {
          id: 'Sovrin Mainnet',
          indyNamespace: 'sovrin',
          isProduction: true,
          genesisPath: './genesis/sovrin-genesis.txn',
        },
      ],
    }),
    // Important: the AnonCreds module MUST be registered with a registry that can resolve
    // legacy unqualified Indy anoncreds identifiers
    anoncreds: new AnonCredsModule({
      registries: [new IndySdkAnonCredsRegistry()],
    }),
    // Define the proofs module with support for both v1 and v2 of the proof protocols
    // both of which support the legacy Indy proof format
    proofs: new ProofsModule({
      proofProtocols: [
        new V1ProofProtocol({
          indyProofFormat: legacyIndyProofFormat,
        }),
        new V2ProofProtocol({
          proofFormats: [legacyIndyProofFormat],
        }),
      ],
    }),
    // Define the credentials module with support for both v1 and v2 of the credential protocols
    // both of which support the legacy Indy proof format
    credentials: new CredentialsModule({
      credentialProtocols: [
        new V1CredentialProtocol({
          indyCredentialFormat: legacyIndyCredentialFormat,
        }),
        new V2CredentialProtocol({
          credentialFormats: [legacyIndyCredentialFormat],
        }),
      ],
    }),
  },
})
```

### Removal of AnonCreds Master Secret management from `Wallet`

The `Wallet` class no longer manages the creation and deletion of AnonCreds master secrets (which are now called Link Secrets in AnonCreds module and specification). If you haven't provided a custom `masterSecretId` to the `walletConfig` before, the storage migration script should have automatically created an `AnonCredsLinkSecretRecord` for you based on the `walletConfig.id`.

For new agents however, you now need to explicitly create a link secret before you can create requests for AnonCreds credential offers. You can do this using the `AnonCredsApi.createLinkSecret` method.

:::caution

If you previously used a custom `masterSecretId` in the `walletConfig` the migration script will have created an incorrect `AnonCredsLinkSecretRecord` based on the `walletConfig.id`. You will need to manually override the link secret record with the correct `linkSecretId`.

You **ONLY** need to do this if you're not migrating from Indy SDK to Askar, as in that case the migration script will have created the correct `AnonCredsLinkSecretRecord` for you.

```ts
import { AnonCredsLinkSecretRepository } from '@aries-framework/anoncreds'

const linkSecretRepository = agent.dependencyManager.resolve(AnonCredsLinkSecretRepository)
const defaultLinkSecret = await linkSecretRepository.findDefault(agent.context)

if (defaultLinkSecret) {
  defaultLinkSecret.linkSecretId = 'my-custom-link-secret-id'
  await linkSecretRepository.update(agent.context, defaultLinkSecret)
}
```

:::

```ts
import { AnonCredsModule } from '@aries-framework/anoncreds'
import { Agent } from '@aries-framework/core'
import { IndySdkAnonCredsRegistry, IndySdkModule } from '@aries-framework/indy-sdk'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

// Import from indy-sdk-react-native in React Native
import indySdk from 'indy-sdk'

const agent = new Agent({
  config: {
    /* ... */
  },
  dependencies: agentDependencies,
  modules: {
    indySdk: new IndySdkModule({
      indySdk,
    }),
    anoncreds: new AnonCredsModule({
      registries: [new IndySdkAnonCredsRegistry()],
    }),
  },
})

// the agent MUST be initialized before calling it.
await agent.wallet.initialize({
  id: 'wallet-id',
  key: 'wallet-key',
})

await agent.modules.anoncreds.createLinkSecret({
  // first one will be set to default automatically
  setAsDefault: true,

  // will be generated if not provided.
  // linkSecretId: 'link-secret-id'
})
```

### Default Outbound DIDComm Content Type now `application/didcomm-envelope-enc`

The default outbound DIDComm content type has been changed from `DidCommMimeType.V0` (`application/ssi-agent-wire`) to `DidCommMimeType.V1` (`application/didcomm-envelope-enc`). V1 is the default for DIDComm V1 (as [defined in Aries RFC 0044](https://github.com/hyperledger/aries-rfcs/blob/main/features/0044-didcomm-file-and-mime-types/README.md#detecting-didcomm-versions)). In the past, V0 resulted in better interoperability, but since it has been the default for so long it makes sense to change the default behavior.

It is advised to use the default value as configured by the agent (V1). If you want to keep the old behavior, you can [configure the `didCommMimeType` property in the agent configuration](https://credo.js.org/guides/next/protocols/didcomm.md).

**0.3.x**

```ts
import { Agent } from '@aries-framework/core'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

const agent = new Agent({
  config: {
    /* ... */
  },
  dependencies: agentDependencies,
})
```

**0.4.x**

```ts
import { Agent, DidCommMimeType } from '@aries-framework/core'

// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'

const agent = new Agent({
  config: {
    didCommMimeType: DidCommMimeType.V0,
  },
  dependencies: agentDependencies,
})
```

### Generalizing Indy properties in `CredentialExchangeRecord`

With AnonCreds credentials now being generalized to support multiple ledgers, the properties specific to Hyperledger Indy have now been generalized into a generic AnonCreds properties.

#### `credentialRecordType`

First off, the `credentialRecordType` that was used to reference stored AnonCreds credentials has been renamed from `indy` to `anoncreds`. The migration script takes care of the update to the storage, but you need to make sure to update all places that expect a `credentialRecordType` of `indy` to be defined.

**0.3.x**

```json
{
  "credentials": [
    {
      "credentialRecordType": "indy",
      "credentialRecordId": "credential-id"
    }
  ]
}
```

**0.4.x**

```json
{
  "credentials": [
    {
      "credentialRecordType": "anoncreds",
      "credentialRecordId": "credential-id"
    }
  ]
}
```

#### Metadata

Second, the metadata keys and values have been renamed to be AnonCreds specific rather than Indy specific. The `CredentialMetadataKeys` have been replaced by the `AnonCredsCredentialMetadataKey` and `AnonCredsCredentialRequestMetadataKey` constants which can be imported from the `@aries-framework/anoncreds` package.

**0.3.x**

```json
{
  "metadata": {
    "_internal/indyCredential": {
      "schemaId": "schema-id",
      "credentialDefinitionId": "cred-def-id",
      "indyRevocationRegistryId": "rev-reg-id",
      "indyCredentialRevocationId": "cred-rev-id"
    },
    "_internal/indyRequest": {
      "master_secret_blinding_data": {
        "v_prime": "string",
        "vr_prime": "string"
      },
      "master_secret_name": "string",
      "nonce": "string"
    }
  }
}
```

**0.4.x**

```json
{
  "metadata": {
    "_anoncreds/credential": {
      "schemaId": "schema-id",
      "credentialDefinitionId": "cred-def-id",
      "revocationRegistryId": "rev-reg-id",
      "credentialRevocationId": "cred-rev-id"
    },
    "_anoncreds/credentialRequest": {
      "master_secret_blinding_data": {
        "v_prime": "string",
        "vr_prime": "string"
      },
      "master_secret_name": "string",
      "nonce": "string"
    }
  }
}
```

### More paths in `FileSystem`

The `FileSystem` interface has been extended to support multiple base paths. The previous interface had a single `basePath` property which was used for storing of files across the framework.

With the different lifetimes of different objects, the `FileSystem` interface has been extended to now support three different base paths:

- `cachePath` - files used for caching purposes. It's okay if the files are cleared from time to time.
- `dataPath` - files that are used for long-term reliable storage purposes. These files will never be cleared.
- `tempPath` - files that are used for temporary storage purposes. It's okay if the files are cleared from time to time.

If you're using the framework, you don't need to worry about this change. The agent may need to download some objects again after the update. If you've made a custom implementation of the `FileSystem`, make sure to support all three base paths, and make sure to correctly handle the life-cycle of the files. Items stored under the `dataPath` **should never be cleared**.

:::caution

Indy SDK SQLite wallets do not use the paths defined by the `FileSystem` interface, and thus will not be influenced by this change. When upgrading to Aries Askar, the `dataPath` will be used as the base path for storing the SQLite wallet data.

:::

## Breaking Storage Changes

The 0.4.0 release introduces some breaking changes to the storage format.

Below all breaking storage changes are explained in as much detail as possible. The update assistant provides all tools to migrate without a hassle, but it is important to know what has changed. All examples only show the keys that have changed, unrelated keys in records have been omitted.

See the [Update Assistant](https://credo.js.org/guides/next/updating/update-assistant.md) documentation for a guide on how to use the update assistant.

There are no configuration parameters to be provided to the update assistant to migrate from 0.3.x to 0.4.x.

> TODO
