Vault
Affinidi Vault TDK for Dart provides the libraries and tools to integrate Affinidi Vault into your Flutter/Dart application for implementing Decentralised Identity solution to securely manage Decentralised Identifiers (DIDs), Verifiable Credentials, and other data that represents the user’s identity based on different context, for example, you can create an identity for shopping, personal finance, and work.
Create and Initialise Vault
Initialise vault with wallet, storage, and profile interface. To create a wallet, you must generate a Seed and store it on the selected storage layer. The profile is initialised using the VFS option which is the cloud profile supported by Affinidi Vault.
Refer to the published SSI Dart package to know more about different types of wallet supported.
Important Note
The sample code usesInMemoryVaultStore
as the storage option for demonstration purposes only and must not be used in production; instead, use a secure storage option like FlutterSecureVaultStore
from affinidi_tdk_vault_flutter_utils package.Import
import 'dart:typed_data';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:ssi/ssi.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
Example
// Initialise InMemory storage
final accountIndex = 32;
final vaultStore = InMemoryVaultStore();
await vaultStore.writeAccountIndex(accountIndex);
// Generate seed from the storage layer
final seed = vaultStore.getRandomSeed();
// Initialise profile interface
const vfsRepositoryId = 'vfs';
final profileRepositories = <String, ProfileRepository>{
vfsRepositoryId: VfsProfileRepository(vfsRepositoryId),
};
// Create a wallet
// In this example, we are using Bip32 type wallet from SSI package
final wallet = await Bip32Wallet.fromSeed(seed, vaultStore);
final vault = Vault(
wallet: wallet,
vaultStore: vaultStore,
profileRepositories: profileRepositories,
defaultProfileRepositoryId: vfsRepositoryId,
);
// Ensure vault is initialised before being able to access any of the repositories
await vault.ensureInitialized();
Manage Vault Profiles
Create and manage profiles associated with the vault.
Create Vault Profile
Create a profile to store credentials and documents. A profile represents a user’s identity.
Currently, vault only supports cloud profile from Affinidi Vault.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:ssi/ssi.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
// Create Profile
try {
final profileRepository = vault.defaultProfileRepository;
// alternatively can be accessed via profile repository identifier
// final ProfileRepository profileRepository = vault.profileRepositories[vfsRepositoryId];
await profileRepository.createProfile(name: 'Work Profile');
} on TdkException catch (error) {
print([error.code, error.message, error.originalMessage].join('\n'));
} catch (e) {
print('Error: $e');
}
List Vault Profiles
Retrieve list of profiles associated with the vault.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:ssi/ssi.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
// Retrieve list of profiles from the vault
var profiles = await vault.listProfiles();
// Check if we have list of profiles
if (!profiles.isEmpty) {
profiles.forEach((profile) {
print('${profile.id} : ${profile.name}');
});
} else {
print('Vault profiles is empty.');
}
Update Vault Profile
Update a profile associated with the vault.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:ssi/ssi.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
if (profile != null) {
// Update profile name
profile.name = 'Test Profile 123';
// Update profile
await profileRepository.updateProfile(profile);
} else {
print('Profile not found.');
}
Delete Vault Profile
Delete a profile associated with the vault.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:ssi/ssi.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
if (profile != null) {
// Delete profile
await profileRepository.deleteProfile(profile);
} else {
print('Profile not found.');
}
Manage Vault Files
Create folders and upload files to manage documents associated with the vault.
Create Folder
Create a folder in the vault’s profile.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:ssi/ssi.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
if (profile != null) {
// We'll create a folder under a profile (root folder)
final rootFolderId = profile.id;
await profile.defaultFileStorage!.createFolder(
folderName: '<Folder_Name>',
parentFolderId: rootFolderId,
);
} else {
print('Profile not found.');
}
Get Folder
Get the folder in the vault’s profile.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:ssi/ssi.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
if (profile != null) {
// We'll retrieve the folders under a profile (root folder)
final rootFolderId = profile.id;
// List folders
final files = await profile.defaultFileStorage?.getFolder(folderId: rootFolderId);
files?.forEach((file) {
print('${file.id} : ${file.name}');
});
} else {
print('Profile not found.');
}
Rename Folder
Rename a folder in the vault’s profile.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:ssi/ssi.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
if (profile != null) {
// Rename the file object
await profile.defaultFileStorage!.renameFolder(
folderId: '<File_ID>',
newName: '<File_Name>'
);
} else {
print('Profile not found.');
}
Delete Folder
Delete a folder in the vault’s profile.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:ssi/ssi.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
if (profile != null) {
try {
// We'll retrieve the folders under a profile (root folder)
final rootFolderId = profile.id;
// List folders
await profile.defaultFileStorage?.deleteFolder(folderId: '<Folder_ID>');
} on TdkException catch (error) {
print([error.code, error.message, error.originalMessage].join('\n'));
} catch (e) {
print('Error: $e');
}
} else {
print('Profile not found.');
}
Create File
Create a file in a folder in the vault’s profile.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:ssi/ssi.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
if (profile != null) {
// We'll retrieve the folders under a profile (root folder)
final rootFolderId = profile.id;
// Create a dummy file
final fileContent = Uint8List.fromList([1, 2, 3]);
try {
// create a file, we'll create a file in the root folder, instead of subfolder.
await profile.defaultFileStorage!.createFile(
fileName: 'Doc Test File 1',
data: fileContent,
parentFolderId: rootFolderId,
);
} on TdkException catch (error) {
print([error.code, error.message, error.originalMessage].join('\n'));
} catch (e) {
print('Error: $e');
}
} else {
print('Profile not found.');
}
Get File
Get the file in the vault’s profile.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:ssi/ssi.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
if (profile != null) {
// Retrieve the file object
final file = await profile.defaultFileStorage!.getFile(
fileId: '<File_ID>'
);
print(file.name);
} else {
print('Profile not found.');
}
Get File Content
Get the content of the file in the vault’s profile.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:ssi/ssi.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
if (profile != null) {
// Retrieve the file content
final fileData = await profile.defaultFileStorage!.getFileContent(
fileId: '<File_ID>'
);
print(fileData);
} else {
print('Profile not found.');
}
Rename File
Rename a file in the vault’s profile.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:ssi/ssi.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
if (profile != null) {
// Rename the file object
await profile.defaultFileStorage!.renameFile(
fileId: '<File_ID>',
newName: '<File_Name>'
);
} else {
print('Profile not found.');
}
Delete File
Delete a file from the vault’s profile.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:ssi/ssi.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
if (profile != null) {
try {
// Rename the file object
await profile.defaultFileStorage!.deleteFile(
fileId: '<File_ID>'
);
} on TdkException catch (error) {
print([error.code, error.message, error.originalMessage].join('\n'));
} catch (e) {
print('Error: $e');
}
} else {
print('Profile not found.');
}
Manage Vault Credentials
Manage credentials claimed from credential issuers into the vault.
Claim Credential
Claim the credential from the issuer.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_claim_verifiable_credential/oid4vci_claim_verifiable_credential.dart';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
import 'package:ssi/ssi.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
try {
final keyDerivationPath = "m/44'/60'/0'/0/0";
final keyPair = await wallet.deriveKey(derivationPath: keyDerivationPath);
final didDocument = DidKey.generateDocument(keyPair.publicKey);
final signer = DidSigner(
didDocument: didDocument,
didKeyId: didDocument.verificationMethod.first.id,
keyPair: keyPair,
signatureScheme: SignatureScheme.ecdsa_secp256k1_sha256,
);
// Create a new instance of ClaimVerifiableCredentialService
final claimVerifiableCredentialService =
OID4VCIClaimVerifiableCredentialService(
didSigner: signer,
);
final uri = Uri.parse(
'https://example.com/callback?credential_offer_uri=https://issuer.example.com/offer/123',
);
final context = await claimVerifiableCredentialService.loadCredentialOffer(uri);
VerifiableCredential? credential;
String? txCode = '<TX_CODE_FROM_ISSER>';
// Check if the credential offer is issued with Transaction Code
if (context.credentialOffer.isTxCodeRequired) {
// Claim credential with Transaction Code
// Transaction Code is generated and must be provided by the issuer
credential = await claimVerifiableCredentialService.claimCredential(
claimContext: context,
txCode: txCode,
);
} else {
// Claim credential without Transaction Code
credential = await claimVerifiableCredentialService.claimCredential(
claimContext: context,
);
}
print('Credential: $credential');
} on TdkException catch (error) {
print([error.code, error.message, error.originalMessage].join('\n'));
} catch (e) {
print('Error: $e');
}
Save Credential
Store a claimed credential into the vault’s profile.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_claim_verifiable_credential/oid4vci_claim_verifiable_credential.dart';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
import 'package:ssi/ssi.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
try {
final keyDerivationPath = "m/44'/60'/0'/0/0";
final keyPair = await wallet.deriveKey(derivationPath: keyDerivationPath);
final didDocument = DidKey.generateDocument(keyPair.publicKey);
final signer = DidSigner(
didDocument: didDocument,
didKeyId: didDocument.verificationMethod.first.id,
keyPair: keyPair,
signatureScheme: SignatureScheme.ecdsa_secp256k1_sha256,
);
// Create a new instance of ClaimVerifiableCredentialService
final claimVerifiableCredentialService =
OID4VCIClaimVerifiableCredentialService(
didSigner: signer,
);
final uri = Uri.parse(
'https://example.com/callback?credential_offer_uri=https://issuer.example.com/offer/123',
);
final context = await claimVerifiableCredentialService.loadCredentialOffer(uri);
VerifiableCredential? credential;
String? txCode = '<TX_CODE_FROM_ISSER>';
// Check if the credential offer is issued with Transaction Code
if (context.credentialOffer.isTxCodeRequired) {
// Claim credential with Transaction Code
// Transaction Code is generated and must be provided by the issuer
credential = await claimVerifiableCredentialService.claimCredential(
claimContext: context,
txCode: txCode,
);
} else {
// Claim credential without Transaction Code
credential = await claimVerifiableCredentialService.claimCredential(
claimContext: context,
);
}
// Did we claim successfully the credential from the issuer?
if (credential.id != null) {
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
// do we have a profile selected?
if (profile != null) {
// Save credential on the selected vault profile
await profile.defaultCredentialStorage?.saveCredential(
verifiableCredential: credential,
);
}
}
} on TdkException catch (error) {
print([error.code, error.message, error.originalMessage].join('\n'));
} catch (e) {
print('Error: $e');
}
List Credentials
List credentials from the vault’s profile.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_claim_verifiable_credential/oid4vci_claim_verifiable_credential.dart';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
import 'package:ssi/ssi.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
try {
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
// do we have a profile selected?
if (profile != null) {
// List credentials from the selected vault profile
final credentials = await profile.defaultCredentialStorage?.listCredentials();
print('Credentials: $credentials');
}
} on TdkException catch (error) {
print([error.code, error.message, error.originalMessage].join('\n'));
} catch (e) {
print('Error: $e');
}
Get Credential
Get a credential from the vault’s profile.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_claim_verifiable_credential/oid4vci_claim_verifiable_credential.dart';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
import 'package:ssi/ssi.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
try {
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
// do we have a profile selected?
if (profile != null) {
// Get credential from the selected vault profile
final credential = await profile.defaultCredentialStorage?.getCredential(
digitalCredentialId: '<Credential_ID>'
);
print('Credential: $credential');
}
} on TdkException catch (error) {
print([error.code, error.message, error.originalMessage].join('\n'));
} catch (e) {
print('Error: $e');
}
Delete Credential
Delete a credential from the vault’s profile.
Import
import 'dart:typed_data';
import 'package:affinidi_tdk_claim_verifiable_credential/oid4vci_claim_verifiable_credential.dart';
import 'package:affinidi_tdk_vault_storages/affinidi_tdk_vault_storages.dart';
import 'package:affinidi_tdk_vault/affinidi_tdk_vault.dart';
import 'package:ssi/ssi.dart';
Example
// Must initialize vault before being able to access any of the repositories
await vault.ensureInitialized();
try {
// Get the list of available profiles from the vault
var profiles = await vault.listProfiles();
// For demonstration purposes, we always get the last profile from the list
var profile = profiles.lastOrNull;
// do we have a profile selected?
if (profile != null) {
// Delete credential from the selected vault profile
await profile.defaultCredentialStorage?.deleteCredential(
digitalCredentialId: '<Credential_ID>'
);
}
} on TdkException catch (error) {
print([error.code, error.message, error.originalMessage].join('\n'));
} catch (e) {
print('Error: $e');
}
Glad to hear it! Please tell us how we can improve more.
Sorry to hear that. Please tell us how we can improve.
Thank you for sharing your feedback so we can improve your experience.