Migrating from AFJ 0.3.x to 0.4.x
This document describes everything you need to know for updating AFJ 0.3.x to 0.4.x. If you're not aware of how updating in AFJ works make sure to first read the guide on Updating AFJ.
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 AFJ.
Aries Framework JavaScript 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.
The migration guide only covers how to migrate from 0.3.x to 0.4.x while keeping the same behavior and dependencies. AFJ 0.4.0 introduced a lot of new features and adds 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 to 0.4.x update is started after migrating from the Indy SDK to Aries Askar.
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.
The following APIs, modules and features are experimental and therefore not covered by the semver versioning in Aries Framework JavaScript. If you're using any of these features, make sure to use an exact version of AFJ (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
- 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-react-native
package.
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.
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
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.
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.
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 AFJ between version 0.3.x and 0.4.0.
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
- 0.4.x
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,
})
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
- 0.4.x
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,
})
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, 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). The networks supported by the resolvers and registrar is determined by the networks
registered on the IndySdkModule
(see 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
- 0.4.x
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,
})
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 AFJ 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.
AFJ 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 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).
An initial list of namespace identifiers can be found in an issue in the Indy Did Networks Repository. In the future this list will be maintained in the Indy DID Networks repository itself.
- 0.3.x
- 0.4.x
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,
})
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
AFJ 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 AFJ 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
- 0.4.x
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,
})
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 AFJ 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 AFJ 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 section.
There's a few important takeaways based on the code example below:
- The
anoncreds
module can be accessed under theagent.modules.anoncreds
property. - The interfaces are set up as generically as possible based on the DID Registration and DID Resolution specifications.
- AnonCreds registries need to be manually registered so it's important to register the
IndySdkAnonCredsRegistry
on theAnonCredsModule
. - It is now required to pass an
issuerId
when registering AnonCreds objects, according to the AnonCreds Specification. Onlydid:indy
issuer identifiers are allowed (based on thedid:indy
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, you can still use the unqualified issuer identifiers (best known as the Hyperledger Indy Legacy AnonCreds Method) in credential and proof exchanges.
- 0.3.x
- 0.4.x
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',
})
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 togetCredentialsForRequest
autoSelectCredentialsForProofRequest
has been renamed toselectCredentialsForRequest
- The
config
parameter for both methods has been removed and those have been replaced by proof format specific configuration options. In this case, theconfig.filterByNonRevocationRequirements
has been added asproofFormats.indy.filterByNonRevocationRequirements
(if theindy
format is registered as explained in the next section). Theconfig.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 thegetCredentialsForRequest
method. - Interfaces have been renamed to be more consistent with the method names. Please refer to the
CredentialsApiOptions
andProofsApiOptions
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 Aries JavaScript Docs repository.
Changes to the AnonCreds Credential and Proof Format
With the 0.4.0 release, AFJ 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. In a future version the new AnonCredsCredentialFormatService
and AnonCredsProofFormatService
will be added to the AnonCreds package, which are based on Aries RFC 0771 and allow for AnonCreds credentials to be exchanged based on the new ledger agnostic AnonCreds Specification.
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
- 0.4.x
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,
})
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.
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.
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)
}
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). 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.
- 0.3.x
- 0.4.x
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,
})
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
- 0.4.x
{
"credentials": [
{
"credentialRecordType": "indy",
"credentialRecordId": "credential-id"
}
]
}
{
"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
- 0.4.x
{
"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"
}
}
}
{
"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.
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 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