Wallets

Create wallets and use them to sign and issue Verifiable Credentials to Affinidi Vault users.

Wallet is an essential component that allows you to sign and issue Verifiable Credentials that users can claim and store in their Affinidi Vault. Each wallet is created with a unique Decentralised Identifier (DID) value that is used to represent a particular subject. It is used to sign the credentials to prevent tampering with information and allow the verifier to validate its authenticity cryptographically.

The Decentralised Identifier (DID) could represent a user, a company, or a device/machine.

Example: did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK.

Supported DID methods

Every Decentralised Identifier (DID) is prefixed with a DID method that defines the mechanism to resolve and get the associated DID document used for verifying the credential.

The Affinidi Trust Network supports the following DID methods when creating a wallet:

did:key

The did:key method represents individuals.

One of the key benefits of did:key is the implementation of “the right to be forgotten” to stay compliant with privacy policies like GDPR, which is impossible with the methods that rely on blockchains.

It is a scalable DID method that doesn’t require a lot of surrounding infrastructure and blockchains. The challenges with did:key arise when you start looking into concerns like key management, which is why relying solely on did:key for all interactions, especially business, is not advisable.

The Affinidi Vault assigns did:key to users when they register for an account. Read more about the did:key method here.

Example: did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK

did:web

The did:web method represents a host or a fully qualified domain name.

It requires the implementation of TLS/SSL certificate on the domain that hosts the DID document and allows rotation of the verification key while keeping the same DID value, making it more secure.

Additionally, credentials signed by did:web is traceable back to the source, like a website, making this method suitable to represent a business entity that owns the domain, enabling verifiers to validate the credential’s authenticity.

Domain Verification service uses did:web to represent the domain when verifying the domain ownership and display a verified checkmark in the Affinidi Vault consent screen. Read more about the did:web method here.

Example: did:web:mywebsite.com

Multi-key support

did:web wallets support multiple cryptographic keys within the same DID document. You can add keys using the secp256k1, ed25519, or p256 algorithms and assign each key specific verification relationships:

Verification relationshipPurpose
authenticationAuthenticate as the DID subject.
assertionMethodSign Verifiable Credentials.
keyAgreementKey agreement protocols, such as encrypted messaging.
capabilityInvocationInvoke a cryptographic capability.
capabilityDelegationDelegate a cryptographic capability to another key.

Use the Affinidi TDK to add, list, update, and remove keys from a did:web wallet. See the Add keys to a did:web wallet section below for code examples.

Create a wallet using Affinidi Portal

To create a wallet, go to the Wallets page under Tools section in the .

  1. Once you are on the Wallets page, click on Create Wallet button.
Wallets page
  1. Set the name and description to help you identify the purpose of the Wallet. Select the DID method that will be use to create the Wallet. If you select did:web, you have to provide the domain that support HTTPS protocol.
Create Wallet
  1. Click on Submit and your wallet will be created with the DID information.

Wallet is used to sign the Verifiable Credentials in Credential Issuance and claim the credential into the Affinidi Vault.

Create a wallet using the Affinidi TDK

In addition to the Affinidi Portal, you can create and manage wallets programmatically using the Wallets Client of the Affinidi TDK.

For the full list of available methods, see the Wallets Client reference for TypeScript, Python, Java, Dart, .NET, or PHP.

Prerequisites

Generate a Personal Access Token (PAT) using the Affinidi CLI Token command.

Install the libraries

Install the Wallets client and Auth Provider.

npm install @affinidi-tdk/auth-provider @affinidi-tdk/wallets-client
pip install affinidi_tdk_auth_provider affinidi_tdk_wallets_client
<dependency>
    <groupId>com.affinidi.tdk</groupId>
    <artifactId>wallets.client</artifactId>
    <version><version_number></version>
</dependency>
dart pub add affinidi_tdk_auth_provider affinidi_tdk_wallets_client
dotnet add package AffinidiTdk.AuthProvider
dotnet add package AffinidiTdk.WalletsClient
composer require affinidi-tdk/affinidi-tdk-php

Create a wallet

Initialise the Auth Provider using your PAT credentials, then create a wallet. The example below creates a did:web wallet.

import { WalletApi, Configuration } from '@affinidi-tdk/wallets-client'
import { AuthProvider } from '@affinidi-tdk/auth-provider'

const authProvider = new AuthProvider({
    privateKey: "<PAT_PRIVATE_KEY_STRING>",
    passphrase: "<PAT_KEY_PAIR_PASSPHRASE>",
    tokenId: "<PAT_ID>",
    projectId: "<PROJECT_ID>"
})

const walletApi = new WalletApi(new Configuration({
    apiKey: authProvider.fetchProjectScopedToken.bind(authProvider)
}))

// Create a did:web wallet — didWebUrl is required
const { data: wallet } = await walletApi.createWallet({
    name: "My did:web Wallet",
    description: "Wallet for credential signing",
    didMethod: "web",
    didWebUrl: "https://<DOMAIN>"
})

console.log(data.wallet?.did)
import affinidi_tdk_auth_provider
import affinidi_tdk_wallets_client

stats = {
    "privateKey": "<PAT_PRIVATE_KEY_STRING>",
    "passphrase": "<PAT_KEY_PAIR_PASSPHRASE>",
    "tokenId": "<PAT_ID>",
    "projectId": "<PROJECT_ID>"
}

auth_provider = affinidi_tdk_auth_provider.AuthProvider(stats)
project_scoped_token = auth_provider.fetch_project_scoped_token()

configuration = affinidi_tdk_wallets_client.Configuration()
configuration.api_key['ProjectTokenAuth'] = project_scoped_token

with affinidi_tdk_wallets_client.ApiClient(configuration) as api_client:
    api_instance = affinidi_tdk_wallets_client.WalletApi(api_client)

    # Create a did:web wallet — didWebUrl is required
    new_wallet_json = {
        "name": "My did:web Wallet",
        "description": "Wallet for credential signing",
        "didMethod": "web",
        "didWebUrl": "https://<DOMAIN>"
    }

    create_wallet_input = affinidi_tdk_wallets_client.CreateWalletInput.from_dict(new_wallet_json)
    api_response = api_instance.create_wallet(create_wallet_input=create_wallet_input)
    print(api_response)
import com.affinidi.tdk.authProvider.AuthProvider;
import com.affinidi.tdk.wallets.client.Configuration;
import com.affinidi.tdk.wallets.client.ApiClient;
import com.affinidi.tdk.wallets.client.apis.WalletApi;
import com.affinidi.tdk.wallets.client.auth.ApiKeyAuth;
import com.affinidi.tdk.wallets.client.models.CreateWalletInput;
import com.affinidi.tdk.wallets.client.models.CreateWalletResponse;
import com.affinidi.tdk.wallets.client.models.CreateWalletInput.DidMethodEnum;

try {

    AuthProvider authProvider = new AuthProvider.Configurations()
        .projectId("<PROJECT_ID>")
        .privateKey("<PAT_PRIVATE_KEY_STRING>")
        .passphrase("<PAT_KEY_PAIR_PASSPHRASE>")
        .tokenId("<PAT_ID>")
        .build();

    ApiClient defaultClient = Configuration.getDefaultApiClient();
    ApiKeyAuth ProjectTokenAuth = (ApiKeyAuth) defaultClient.getAuthentication("ProjectTokenAuth");
    ProjectTokenAuth.setApiKey(authProvider.fetchProjectScopedToken());

    WalletApi apiInstance = new WalletApi(defaultClient);

    // Create a did:web wallet — didWebUrl is required
    CreateWalletInput requestInput = new CreateWalletInput()
            .name("My did:web Wallet")
            .description("Wallet for credential signing")
            .didMethod(DidMethodEnum.WEB)
            .didWebUrl("https://<DOMAIN>");

    CreateWalletResponse result = apiInstance.createWallet(requestInput);
    System.out.println(result.toString());

} catch (Exception e) {
    e.printStackTrace();
}
import 'package:dio/dio.dart';
import 'package:affinidi_tdk_auth_provider/affinidi_tdk_auth_provider.dart';
import 'package:affinidi_tdk_wallets_client/affinidi_tdk_wallets_client.dart';

void main(List<String> arguments) async {
  try {
    final authProvider = AuthProvider(
      privateKey: "<PAT_PRIVATE_KEY_STRING>",
      passphrase: "<PAT_KEY_PAIR_PASSPHRASE>",
      tokenId: "<PAT_ID>",
      projectId: "<PROJECT_ID>",
    );

    final dio = Dio(
      BaseOptions(
        baseUrl: AffinidiTdkWalletsClient.basePath,
        connectTimeout: const Duration(seconds: 5),
        receiveTimeout: const Duration(seconds: 5),
      ),
    );

    final apiClient = AffinidiTdkWalletsClient(
      dio: dio,
      authTokenHook: authProvider.fetchProjectScopedToken,
    );
    final walletApi = apiClient.getWalletApi();

    // Create a did:web wallet — didWebUrl is required
    final walletInputBuilder = CreateWalletInputBuilder()
      ..name = "My did:web Wallet"
      ..description = "Wallet for credential signing"
      ..didMethod = CreateWalletInputDidMethodEnum.web
      ..didWebUrl = "https://<DOMAIN>";

    final createdWallet = (await walletApi.createWallet(
      createWalletInput: walletInputBuilder.build(),
    )).data;

    print(createdWallet);
  } catch (e) {
    print('Error: $e');
  }
}
using AffinidiTdk.AuthProvider;
using AffinidiTdk.WalletsClient.Api;
using AffinidiTdk.WalletsClient.Client;
using AffinidiTdk.WalletsClient.Model;

AuthProvider authProvider = new AuthProvider(new AuthProviderParams
{
    ProjectId = "<PROJECT_ID>",
    TokenId = "<PAT_ID>",
    PrivateKey = "<PAT_PRIVATE_KEY_STRING>",
    Passphrase = "<PAT_KEY_PAIR_PASSPHRASE>"
});

string projectScopedToken = await authProvider.FetchProjectScopedTokenAsync();

Configuration config = new Configuration();
config.AddApiKey("authorization", projectScopedToken);

WalletApi walletApi = new WalletApi(config);

// Create a did:web wallet — didWebUrl is required
CreateWalletInput input = new CreateWalletInput(
    name: "My did:web Wallet",
    description: "Wallet for credential signing",
    didMethod: CreateWalletInput.DidMethodEnum.Web,
    didWebUrl: "https://<DOMAIN>"
);

CreateWalletResponse wallet = walletApi.CreateWallet(input);
Console.WriteLine(wallet.Did);
require_once 'vendor/autoload.php';

use AffinidiTdk\AuthProvider\AuthProvider;
use AffinidiTdk\Clients\WalletsClient;
use AffinidiTdk\Clients\WalletsClient\Model\CreateWalletInput;

$authProvider = new AuthProvider([
    'privateKey' => '<PAT_PRIVATE_KEY_STRING>',
    'passphrase' => '<PAT_KEY_PAIR_PASSPHRASE>',
    'tokenId' => '<PAT_ID>',
    'projectId' => '<PROJECT_ID>',
]);

$tokenCallback = [$authProvider, 'fetchProjectScopedToken'];

$config = WalletsClient\Configuration::getDefaultConfiguration()->setApiKey('authorization', '', $tokenCallback);
$apiInstance = new WalletsClient\Api\WalletApi(new GuzzleHttp\Client(), $config);

// Create a did:web wallet — did_web_url is required
$input = new CreateWalletInput([
    'name' => 'My did:web Wallet',
    'description' => 'Wallet for credential signing',
    'did_method' => 'web',
    'did_web_url' => 'https://<DOMAIN>'
]);

$wallet = $apiInstance->createWallet($input);
echo $wallet->getDid();

Add keys to a did:web wallet

did:web wallets support multiple cryptographic keys. Use the createWalletKey method to add a key to an existing wallet and define its verification relationships.

import { WalletApi, Configuration, CreateWalletKeyInput } from '@affinidi-tdk/wallets-client'
import { AuthProvider } from '@affinidi-tdk/auth-provider'

const authProvider = new AuthProvider({
    privateKey: "<PAT_PRIVATE_KEY_STRING>",
    passphrase: "<PAT_KEY_PAIR_PASSPHRASE>",
    tokenId: "<PAT_ID>",
    projectId: "<PROJECT_ID>"
})

const walletApi = new WalletApi(new Configuration({
    apiKey: authProvider.fetchProjectScopedToken.bind(authProvider)
}))

const keyRequest: CreateWalletKeyInput = {
    keyType: "ed25519",
    relationships: ["authentication", "assertionMethod"]
}

const { data: newKey } = await walletApi.createWalletKey("<WALLET_ID>", keyRequest)
console.log(newKey.keyId)
import affinidi_tdk_auth_provider
import affinidi_tdk_wallets_client

stats = {
    "privateKey": "<PAT_PRIVATE_KEY_STRING>",
    "passphrase": "<PAT_KEY_PAIR_PASSPHRASE>",
    "tokenId": "<PAT_ID>",
    "projectId": "<PROJECT_ID>"
}

auth_provider = affinidi_tdk_auth_provider.AuthProvider(stats)
project_scoped_token = auth_provider.fetch_project_scoped_token()

configuration = affinidi_tdk_wallets_client.Configuration()
configuration.api_key['ProjectTokenAuth'] = project_scoped_token

with affinidi_tdk_wallets_client.ApiClient(configuration) as api_client:
    api_instance = affinidi_tdk_wallets_client.WalletApi(api_client)

    wallet_id = "<WALLET_ID>"
    create_key_json = {
        "keyType": "ed25519",
        "relationships": ["authentication", "assertionMethod"]
    }

    create_wallet_key_input = affinidi_tdk_wallets_client.CreateWalletKeyInput.from_dict(create_key_json)
    api_response = api_instance.create_wallet_key(wallet_id, create_wallet_key_input=create_wallet_key_input)
    print(api_response)
import com.affinidi.tdk.authProvider.AuthProvider;
import com.affinidi.tdk.wallets.client.Configuration;
import com.affinidi.tdk.wallets.client.ApiClient;
import com.affinidi.tdk.wallets.client.apis.WalletApi;
import com.affinidi.tdk.wallets.client.auth.ApiKeyAuth;
import java.util.List;
import com.affinidi.tdk.wallets.client.models.CreateWalletKeyInput;
import com.affinidi.tdk.wallets.client.models.WalletKeyDto;
import com.affinidi.tdk.wallets.client.models.VerificationRelationship;
import com.affinidi.tdk.wallets.client.models.CreateWalletKeyInput.KeyTypeEnum;

try {

    AuthProvider authProvider = new AuthProvider.Configurations()
        .projectId("<PROJECT_ID>")
        .privateKey("<PAT_PRIVATE_KEY_STRING>")
        .passphrase("<PAT_KEY_PAIR_PASSPHRASE>")
        .tokenId("<PAT_ID>")
        .build();

    ApiClient defaultClient = Configuration.getDefaultApiClient();
    ApiKeyAuth ProjectTokenAuth = (ApiKeyAuth) defaultClient.getAuthentication("ProjectTokenAuth");
    ProjectTokenAuth.setApiKey(authProvider.fetchProjectScopedToken());

    WalletApi apiInstance = new WalletApi(defaultClient);

    String walletId = "<WALLET_ID>";

    CreateWalletKeyInput requestInput = new CreateWalletKeyInput()
            .keyType(KeyTypeEnum.ED25519)
            .relationships(List.of(
                VerificationRelationship.AUTHENTICATION,
                VerificationRelationship.ASSERTION_METHOD
            ));

    WalletKeyDto result = apiInstance.createWalletKey(walletId, requestInput);
    System.out.println(result.toString());

} catch (Exception e) {
    e.printStackTrace();
}
import 'package:built_collection/built_collection.dart';
import 'package:dio/dio.dart';
import 'package:affinidi_tdk_auth_provider/affinidi_tdk_auth_provider.dart';
import 'package:affinidi_tdk_wallets_client/affinidi_tdk_wallets_client.dart';

void main(List<String> arguments) async {
  try {
    final authProvider = AuthProvider(
      privateKey: "<PAT_PRIVATE_KEY_STRING>",
      passphrase: "<PAT_KEY_PAIR_PASSPHRASE>",
      tokenId: "<PAT_ID>",
      projectId: "<PROJECT_ID>",
    );

    final dio = Dio(
      BaseOptions(
        baseUrl: AffinidiTdkWalletsClient.basePath,
        connectTimeout: const Duration(seconds: 5),
        receiveTimeout: const Duration(seconds: 5),
      ),
    );

    final apiClient = AffinidiTdkWalletsClient(
      dio: dio,
      authTokenHook: authProvider.fetchProjectScopedToken,
    );
    final walletApi = apiClient.getWalletApi();

    final walletId = "<WALLET_ID>";

    final createWalletKeyInputBuilder = CreateWalletKeyInputBuilder()
      ..keyType = CreateWalletKeyInputKeyTypeEnum.ed25519
      ..relationships.replace([
        VerificationRelationship.authentication,
        VerificationRelationship.assertionMethod,
      ]);

    final result = (await walletApi.createWalletKey(
      walletId: walletId,
      createWalletKeyInput: createWalletKeyInputBuilder.build(),
    )).data;

    print(result);
  } catch (e) {
    print('Error: $e');
  }
}
using AffinidiTdk.AuthProvider;
using AffinidiTdk.WalletsClient.Api;
using AffinidiTdk.WalletsClient.Client;
using AffinidiTdk.WalletsClient.Model;

AuthProvider authProvider = new AuthProvider(new AuthProviderParams
{
    ProjectId = "<PROJECT_ID>",
    TokenId = "<PAT_ID>",
    PrivateKey = "<PAT_PRIVATE_KEY_STRING>",
    Passphrase = "<PAT_KEY_PAIR_PASSPHRASE>"
});

string projectScopedToken = await authProvider.FetchProjectScopedTokenAsync();

Configuration config = new Configuration();
config.AddApiKey("authorization", projectScopedToken);

WalletApi walletApi = new WalletApi(config);

CreateWalletKeyInput keyInput = new CreateWalletKeyInput
{
    KeyType = "ed25519",
    Relationships = new List<VerificationRelationship>
    {
        VerificationRelationship.Authentication,
        VerificationRelationship.AssertionMethod
    }
};

WalletKeyDto newKey = walletApi.CreateWalletKey("<WALLET_ID>", keyInput);
Console.WriteLine(newKey.KeyId);
require_once 'vendor/autoload.php';

use AffinidiTdk\AuthProvider\AuthProvider;
use AffinidiTdk\Clients\WalletsClient;
use AffinidiTdk\Clients\WalletsClient\Model\CreateWalletKeyInput;
use AffinidiTdk\Clients\WalletsClient\Model\VerificationRelationship;

$authProvider = new AuthProvider([
    'privateKey' => '<PAT_PRIVATE_KEY_STRING>',
    'passphrase' => '<PAT_KEY_PAIR_PASSPHRASE>',
    'tokenId' => '<PAT_ID>',
    'projectId' => '<PROJECT_ID>',
]);

$tokenCallback = [$authProvider, 'fetchProjectScopedToken'];

$config = WalletsClient\Configuration::getDefaultConfiguration()->setApiKey('authorization', '', $tokenCallback);
$apiInstance = new WalletsClient\Api\WalletApi(new GuzzleHttp\Client(), $config);

$input = new CreateWalletKeyInput([
    'key_type' => CreateWalletKeyInput::KEY_TYPE_ED25519,
    'relationships' => [
        VerificationRelationship::AUTHENTICATION,
        VerificationRelationship::ASSERTION_METHOD
    ]
]);

$newKey = $apiInstance->createWalletKey('<WALLET_ID>', $input);
echo $newKey->getKeyId();