Migrating from Credo 0.4.x to 0.5.x
This document describes everything you need to know for updating Credo 0.4.x to 0.5.x. If you're not aware of how updating in Credo works make sure to first read the guide on Updating Credo, and the Update Assistant. Starting from Credo 0.5, we now support migration of tenant storage in addition to the root wallet. If you're using the tenants module, make sure to read the guides carefully.
See Pull Request 1747 for more information.).
First of all, update your dependencies to the 0.5.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.5.0 is a major release, but there haven't been a lot of breaking changes to the stable API, most of the changes are related to OpenID4VC, SD-JWT VC and DIF Presentation Exchange. One notable change is that the Indy SDK has been fully deprecated and removed from Credo. This means that starting from 0.5, you cannot use Credo with the Indy SDK. If you need to migrate your storage from Indy SDK to Aries Askar, see the note below for instructions. Another notable change is the migration of all AnonCreds credential records to be stored as W3cCredentialRecord
instead of AnonCredsCredentialRecord
.
Follow the mentioned steps in this document carefully to make the upgrade as smooth as possible.
The migration guide only covers how to migrate from 0.4.x to 0.5.x while keeping the same behavior and dependencies. Credo 0.4.0 added support for Aries Askar, Indy VDR and 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.
As noted in the Update Indy SDK to Askar guide, it is very important that the 0.3.x or 0.4x to 0.5.x update is started after migrating from the Indy SDK to Aries Askar.
The rest of this guides will assume you have already migrated from the Indy SDK to Aries Askar, AnonCreds and Indy VDR.
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.5.0
) instead of a range (^0.5.0
):
- Issuance of revocable AnonCreds credentials and revocation of AnonCreds credentials
- Using any of the OpenID4VC from the
@credo-ts/openid4vc
package - SD-JWT Verifiable Credentials
- DIF Presentation Exchange
- Issuance and verification of AnonCreds in W3C Verifiable Credential format
First install the updated dependencies. For all dependencies you have in package.json
, update them to the following versions, for your platform. If you don't use a package, you don't have to add it here.
In the upgrade from 0.4 to 0.5, Aries Framework JavaScript has been renamed to Credo, and therefore the package scope has also changed. The scope for all packages starting with @aries-framework
should be updated to @credo-ts
. So @aries-framework/core
becomes @credo-ts/core
, etc..
If you were using @aries-framework/anoncreds
and @aries-framework/anoncreds-rs
, these have been combined into @credo-ts/anoncreds
. So @aries-framework/anoncreds-rs
can be removed from the dependencies.
- React Native
- Node
"@credo-ts/*": "^0.5.3"
- except for packages starting with@credo-ts
listed below."@credo-ts/react-hooks": "^0.6.1"
"@credo-ts/push-notifications": "^0.7.1"
"@hyperledger/anoncreds-react-native": "^0.2.2"
"@hyperledger/indy-vdr-react-native": "^0.2.2"
"@hyperledger/aries-askar-react-native": "^0.2.1"
In addition, if you were using @aries-framework/anoncreds
and @aries-framework/anoncreds-rs
, these have been combined into @credo-ts/anoncreds
. So @aries-framework/anoncreds-rs
can be removed from the dependencies.
"@credo-ts/*": "^0.5.3"
- except for packages starting with@credo-ts
listed below."@credo-ts/react-hooks": "^0.6.1"
"@credo-ts/push-notifications": "^0.7.1"
"@hyperledger/anoncreds-nodejs": "^0.2.1"
"@hyperledger/indy-vdr-nodejs": "^0.2.1"
"@hyperledger/aries-askar-nodejs": "^0.2.0"
Breaking Code Changes
This section will list all breaking changes made to the public API of Credo between version 0.4.x and 0.5.x.
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).
Node 16 deprecated
Starting from Credo 0.5, Node 16 has been deprecated and is no longer supported. The supported versions for Credo are Node 18 and 20. We aim to keep support for all LTS releases (the even version numbers) that are either Current, Active, or in Maintenance. Other versions may work, but are not part of our testing and release process.
See the Release Schedule on the Node.js website for information on past and upcoming Node.js releases.
Aries to Credo
With the move from Aries Framework JavaScript to Credo, several classes and imports have been renamed to match the new name. The following imports should be updated:
AriesFrameworkError
->CredoError
Label optional in OutOfBandInvitation
A small change, but the label
property on an OutOfBandInvitation
is now optional.
Caching in DidResolver
interface
Did resolving within Credo now support caching of resolved did documents. Especially in some flows where the did document is resolved several times, this can improve performance a lot.
If you haven't implemented a custom DidResolver
, you don't have to do anything to benefit from the new caching behavior, this is enabled by default. If you want to opt out of caching (and have the same behavior as 0.4), you can tweak it using the following properties in the did resolver options:
const didResult = await agent.dids.resolve('did:example:123', {
// how long to cache the resolved did document in seconds
cacheDurationInSeconds: 400,
// whether to persist the resolved did document in the cache
persistInCache: true,
// whether to use the cache for resolving the did document
useCache: true,
})
If you have implemented a custom did resolver, you need to set the allowsCaching
property to indicate whether the did resolver allows the documents it resolves to be cached. For example, for local resolvers it's often easier to resolve the document than to have it cached, so you can set allowsCaching
to false
(example are did:key
, did:jwk
, did:peer
). For resolvers that resolve documents from a remote source, it's often better to cache the resolved document, so you can set allowsCaching
to true
(example are did:web
, did:cheqd
, did:indy
).
export class ExampleDidResolver implements DidResolver {
public readonly supportedMethods = ['example']
// whether to allow caching
public readonly allowsCaching = true
public async resolve() {
// ... resolver implementation
}
}
Out Of Band Handshake Protocols enum updated to not include minor version
The HandshakeProtocol
enum, which you can provide when creating out of band invitations, has been updated to not include the minor version in the values anymore. The minor version has instead been replaced by an x
, indicating it can be any value. If you were only using the enum, this should not cause issues. But if you were relying on the values within the enum to have a specific format, this could cause some issues.
For example the value for HandshakeProtocol.DidExchange
has been updated from https://didcomm.org/didexchange/1.1
to https://didcomm.org/didexchange/1.x
.
AnonCreds RS and AnonCreds package combined
With the removal of the Indy SDK from Credo, we have made the setup for AnonCreds easier.
In 0.4 you had to provide both the AnonCredsModule
(from @aries-framework/anoncreds
) as well as the AnonCredsRsModule
(from @aries-framework/anoncreds-rs
). In 0.5 these have been combined into a single AnonCredsModule
(from @credo-ts/anoncreds
).
- 0.4.x
- 0.5.x
import { Agent } from '@aries-framework/core'
import { AnonCredsModule } from '@aries-framework/anoncreds'
// or import from @hyperledger/anoncreds-react-native in React Native
import { anoncreds } from '@hyperledger/anoncreds-nodejs'
const agent = new Agent({
/* ... rest of agent setup */
modules: {
anoncreds: new AnonCredsModule({
registries: [
/* registries */
],
}),
anoncredsRs: new AnonCredsRsModule({
anoncreds,
}),
},
})
import { Agent } from 'credo-ts/core'
import { AnonCredsModule } from 'credo-ts/anoncreds'
// or import from @hyperledger/anoncreds-react-native in React Native
import { anoncreds } from '@hyperledger/anoncreds-nodejs'
const agent = new Agent({
/* ... rest of agent setup */
modules: {
anoncreds: new AnonCredsModule({
registries: [
/* registries */
],
// anoncreds has been moved to AnonCredsModule
anoncreds,
}),
},
})
OpenId4VC Holder module
The @aries-framework/openid4vc-client
has been deprecated in favour of the new @credo-ts/openid4vc
package.
The OpenID4VC Client from Credo/AFJ 0.4 only supported receiving credential using OpenID for Verifiable Credentials Issuance. The new package now also support issuance, proving and verification. This section covers how to update the existing functionality to Credo 0.5, but for a detailed guide on how to use the new OpenID4VC features in Credo, see OpenID4VC Guide.
First update the import of @aries-framework/openid4vc-client
to @credo-ts/openid4vc
, and change the module to the new OpenId4VcHolderModule
:
- 0.4.x
- 0.5.x
import { Agent } from '@aries-framework/core'
import { OpenId4VcClientModule } from '@aries-framework/openid4vc-client'
// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'
const agent = new Agent({
config: {
/* ... */
},
dependencies: agentDependencies,
modules: {
/* ... other modules */
openId4VcClient: new OpenId4VcClientModule(),
},
})
import { Agent } from '@aries-framework/core'
import { OpenId4VcHolderModule } from '@aries-framework/openid4vc'
// Import from @aries-framework/react-native in React Native
import { agentDependencies } from '@aries-framework/node'
const agent = new Agent({
config: {
/* ... */
},
dependencies: agentDependencies,
modules: {
/* ... other modules */
openId4VcHolder: new OpenId4VcHolderModule(),
},
})
Next, update your credential receiving logic to first resolve the credential offer (using agent.modules.openId4VcHolder.resolveCredentialOffer
), and then accept the credential offer (using agent.modules.openId4VcHolder.acceptCredentialOfferUsingPreAuthorizedCode
).
- 0.4.x
- 0.5.x
import { DidKey, KeyDidCreateOptions, JwaSignatureAlgorithm } from '@aries-framework/core'
import { OpenIdCredentialFormatProfile } from '@aries-framework/openid4vc-client'
// Example uri
const data = 'openid-credential-offer://?credential_offer_uri=...'
await agent.modules.openId4VcClient.requestCredentialUsingPreAuthorizedCode({
uri: data,
proofOfPossessionVerificationMethodResolver: async ({ supportedDidMethods, keyType, supportsAllDidMethods }) => {
if (supportsAllDidMethods || supportedDidMethods?.includes('did:key')) {
const didResult = await agent.dids.create<KeyDidCreateOptions>({
method: 'key',
options: {
keyType,
},
})
if (didResult.didState.state !== 'finished') {
throw new Error('DID creation failed.')
}
const didKey = DidKey.fromDid(didResult.didState.did)
return didResult.didState.didDocument.dereferenceKey(`${didKey.did}#${didKey.key.fingerprint}`)
}
throw new Error(`Unable to create a key binding`)
},
verifyCredentialStatus: false,
allowedCredentialFormats: [OpenIdCredentialFormatProfile.JwtVcJson],
allowedProofOfPossessionSignatureAlgorithms: [JwaSignatureAlgorithm.EdDSA, JwaSignatureAlgorithm.ES256],
})
import { DidKey, KeyDidCreateOptions, JwaSignatureAlgorithm, getJwkFromKey } from '@credo-ts/core'
import { OpenId4VciCredentialFormatProfile } from '@credo-ts/openid4vc'
// Example uri
const data = 'openid-credential-offer://?credential_offer_uri=...'
const resolvedCredentialOffer = await agent.modules.openId4VcHolder.resolveCredentialOffer(data)
await agent.modules.openId4VcHolder.acceptCredentialOfferUsingPreAuthorizedCode(
// First parameter is now the resolved credential offer
resolvedCredentialOffer,
{
// has been renamed from proofOfPossessionVerificationMethodResolver to credentialBindingResolver
credentialBindingResolver: async ({
supportedDidMethods,
keyType,
supportsAllDidMethods,
// supportsJwk now also passed
supportsJwk,
credentialFormat,
}) => {
// NOTE: example implementation. Adjust based on your needs
// Return the binding to the credential that should be used. Either did or jwk is supported
if (supportsAllDidMethods || supportedDidMethods?.includes('did:key')) {
const didResult = await agent.dids.create<KeyDidCreateOptions>({
method: 'key',
options: {
keyType,
},
})
if (didResult.didState.state !== 'finished') {
throw new Error('DID creation failed.')
}
const didKey = DidKey.fromDid(didResult.didState.did)
// you now need to return an object instead of VerificationMethod instance
// and method 'did' or 'jwk'
return {
method: 'did',
didUrl: `${didKey.did}#${didKey.key.fingerprint}`,
}
}
// we also support plain jwk for sd-jwt only
if (supportsJwk && credentialFormat === OpenId4VciCredentialFormatProfile.SdJwtVc) {
const key = await agent.wallet.createKey({
keyType,
})
// you now need to return an object instead of VerificationMethod instance
// and method 'did' or 'jwk'
return {
method: 'jwk',
jwk: getJwkFromKey(key),
}
}
throw new Error('Unable to create a key binding')
},
verifyCredentialStatus: false,
allowedProofOfPossessionSignatureAlgorithms: [JwaSignatureAlgorithm.EdDSA, JwaSignatureAlgorithm.ES256],
}
)
Message Pickup
TODO: write migration guide for message pickup https://github.com/openwallet-foundation/credo-ts/pull/1638
Askar short-lived sessions
This is an internal change, but Askar now only uses short-lived sessions. Before a session was created and kept alive until the agent was shutdown or the tenant session was closed (in case of multi-tenancy). Now a session is created for each read and write operation to your wallet.
Askar manages a connection pool internally and aligns more with how Askar is supposed to be used, and makes the multi-tenancy implementation more robust. This is also in preparation for some bigger wallet and storage API changes in future versions, where we want to support transactions (batching multiple read/writes operations), record locking (to prevent race condition updates), and more.
See Pull Request 1743 for more information.
AnonCreds W3C format
AnonCreds credentials in Credo now support the W3c Verifiable Credential format. Using the new Aries RFC 0809: W3C Verifiable Credential Data Integrity Attachment format you can issue AnonCreds credentials in W3C VC Data Integrity format, and verify them in W3C VC Data Integrity using Aries RFC 0510: Presentation-Exchange Attachment format.
With the change, we've updated the storage of all AnonCreds credentials to be stored as W3cCredentialRecord
instead of AnonCredsCredentialRecord
. The AnonCredsCredentialRecord
is still used for some legacy records which we were not able to migrate to the new format yes (because they rely on resolving objects from the ledger to properly migrate). However in future versions, also these records will be migrated and the AnonCredsCredentialRecord
will be removed from the codebase.
This means some AnonCreds credentials are stored in W3cCredentialRecord
format, and some in AnonCredsCredentialRecord
format. Make sure to use the designated methods on the AnonCredsModule
as well as on the ProofsModule
to find and query for AnonCreds records, to make sure all record types are returned.
See Pull Request 1744 for more information.