Skip to main content

CDD with the SDK


You ought to look at the previous chapter on KYC with the SDK first.

A CDD service provider is a privileged KYC service provider with a permissioned role to create DID's and add CDD claims to DID's.


See the introduction on identity for a refresher.

In particular:

  1. For brand new users of Polymesh, the CDD provider needs to:
    1. Create a new account controlled by the primary key asked by the user, and return the DID to the user;
    2. Add a CDD claim to that DID to verify they have gone through verification with them;
  2. For existing users that need a new CDD attestation, the CDD provider needs to re-verify the individual or entity and attach a new CDD claim to their existing DID;

See distribute with the SDK for a reminder of the process.

We assume the CDD service provider is named EzCdd and has a way to instantiate a Polymesh client.

const signingManagerEzCdd: LocalSigningManager =
await LocalSigningManager.create({
accounts: [
mnemonic: 'word51 word52 ...',

const apiEzCdd: Polymesh = await Polymesh.connect({
nodeUrl: 'wss://', // or your preferred node
signingManager: signingManagerEzCdd,

How to create a new account

This part only applies if the user, say Bob, is brand new to Polymesh, or if Bob wants to create another account for himself.

In that case, the CDD provider needs to create an account. This is a privileged operation, too, one that only a CDD service provider can accomplish. The CDD provider needs to ask Bob for the public key, or address, he wishes to associate with the account.

Information collection

Bob creates a private key and returns the computed address. For instance:

const bobAddress: string = '5ED27JHWh9dPVnhvRfazMRNqrfMgcAUdvgD7hs3969PBuxqe'; // For instance

The provider needs to confirm that this key is not yet assigned to any other account.

const bobKeyInfo: Account = apiEzCdd.accountManagement.getAccount({
address: bobAddress,
const bob: Identity = await bobKeyInfo.getIdentity();
assert(bob === null);

Create the account

With the certainty that the key is not associated with any existing account, it is time to create a new account with this key:

const newAccountQueue: TransactionQueue<Identity> =
await apiEzCdd.identities.registerIdentity({
targetAccount: bobAddress,
const bob: Identity = await;

So does Bob have a new account on-chain? Not yet, sadly. Or rather, fortunately. You see, it is worth repeating that all actions of consequence need approval on both ends, and this is no different here. Bob needs to use his private key to approve having it associated with this new account.

So, either Bob goes to his Portal, and looks for incoming authorisation requests, or Bob fires up his own apiBob and uses the SDK. We assume that EzCdd gave him their const ezCddDid: string.

const bobAccount: Account = apiBob.accountManagement.getSigningAccount();
const pendingAuthorizations: AuthorizationRequest[] =
await bobAccount.authorizations.getReceived();
const ezCddAuthorization: AuthorizationRequest = pendingAuthorizations.find(
(pendingAuthorization: AuthorizationRequest) => {
return pendingAuthorization.issuer.did === ezCddDid;
const acceptQueue: TransactionQueue<void> = await ezCddAuthorization.accept();

There is only a slight problem with the above. Bob has not yet received his CDD attestation, and therefore cannot publish a transaction to the Polymesh network. So we showed the above to stay in context, but really, Bob has to wait for the below CDD attestation to be published before he can approve, or reject, the account association.

Additionally, the address needs some POLYX to pay for transaction fees. Bob can purchase them from an exchange, or he can have an agreement with EzCdd to send some to his address. Once again, only after the CDD attestation has been published.

The CDD attestation

Before an account can transact on chain it requires a valid CDD claim to be added to the DID. The CDD provider constructs a transaction to add a claim type of CustomerDueDiligence providing Bob's DID as the target and an expiry date for the claim. The claim can include an optional cddId should the CDD provider wish to use it as a reference.

const nextYear: Date = new Date();
nextYear.setFullYear(nextYear.getFullYear() + 1);
const cddClaimQueue: TransactionQueue<void> = await{
claims: [
claim: {
type: ClaimType.CustomerDueDiligence,
id: cddId,
target: bob.did,
expiry: nextYear,

With this transaction submitted Bob is now CDD'd and can transact in materially-significant ways, including, as mentioned earlier by accepting the authorisation request.


We have seen how a CDD service provider needs to:

  • create new accounts on Polymesh, and
  • publish CDD attestations.