Skip to main content

Trinsic

The Trinsic option in the EASSI walllet makes heavy use of the Trinsic API.

Information

The Trinsic API can be found here: https://docs.trinsic.id/

To make it work you need to have an API key which can be obtained by creating an account at https://studio.trinsic.id/. With the API key you can also test the different features of the API on their website mentioned above. Using a free API key you get 50 credential exchanges per month. If you want more you'll have to upgrade your plan. More information can be found at https://trinsic.id/pricing/.

More development examples can also be found at the Trinsic verifier reference app: https://github.com/trinsic-id/verifier-reference-app

Steps

The following steps are needed to set up a working issue and verify connection using Trinsic.

Create invitation

Can be found here: https://docs.trinsic.id/reference/createconnection

  async createInvitation() {
const invitation = new TrinsicInvitation();
invitation.connectionId = TrinsicInvitation.randomIdentifier();

const headersRequest = {
'Authorization': this.configService.getTrinsicAPIKey(),
};

const response = await this.httpService
.post<TrinsicConnectionResponse>(
this.trinsicUrl('/credentials/v1/connections'),
{
connectionId: invitation.connectionId,
},
{
headers: headersRequest
})
.toPromise();

invitation.connectionId = response.data.connectionId;
invitation.name = response.data.connectionId;
invitation.multiParty = response.data.multiParty;
invitation.connectionResponse = response.data;
await this.invitationsRepository.save(invitation);

return {
invitation,
qr: await QRCode.toDataURL(invitation.connectionResponse.invitationUrl),
};
}

Create schema and credential definition

Can be found here: https://docs.trinsic.id/reference/createcredentialdefinition
and here: https://docs.trinsic.id/reference/createcredentialdefinitionforschemaid

protected async createSchemaAndCredDef(
schema: TrinsicSchema,
schemaData: Partial<TrinsicSchema>,
) {
if (schemaData.trinsicSchemaId) {
this.logger.debug('Existing Trinsic schema', schema.name);
schema.trinsicSchemaId = schemaData.trinsicSchemaId;
} else {
this.logger.debug('Creating Trinsic schema', schema.name);

const headersRequest = {
'Authorization': this.configService.getTrinsicAPIKey(),
};

const schemaResponse = await this.httpService
.post<TrinsicSchemaResponse>(this.trinsicUrl('/credentials/v1/definitions/schemas'), {

attributeNames: schema.attributeNames,
name: schema.name,
version: schema.version,
},
{
headers: headersRequest
})
.toPromise();

this.logger.debug('Created Trinsic schema', schemaResponse.data.toString());

schema.trinsicSchemaId = schemaResponse.data.toString();

// If we don't have a schemaId we can't have a credDefId.
schemaData.trinsicCredentialDefinitionId = null;
}

if (schemaData.trinsicCredentialDefinitionId) {
schema.trinsicCredentialDefinitionId = schemaData.trinsicCredentialDefinitionId;
} else {
this.logger.debug('Creating Trinsic credDef', schema.trinsicSchemaId);

const headersRequest = {
'Authorization': this.configService.getTrinsicAPIKey(),
};

const credDefResponse = await this.httpService
.post<TrinsicCredDefResponse>(this.trinsicUrl('/credentials/v1/definitions/credentials/' + schema.trinsicSchemaId), {
supportRevocation: false,
tag: 'default',
},
{
headers: headersRequest
})
.toPromise();

this.logger.debug(
'Created Trinsic credDef',
credDefResponse.data.definitionId,
);

schema.trinsicCredentialDefinitionId =
credDefResponse.data.definitionId;
}

return schema;
}

Issue

Can be found here: https://docs.trinsic.id/reference/createcredential

  async handleIssueCredentialRequestForConnection(issueRequest: CredentialIssueRequest, identifier: string,) {
const invitation = await this.getInvitationByIdentifier(identifier);

const schema = issueRequest.type.trinsicSchema;

console.log(schema.trinsicCredentialDefinitionId)

const headersRequest = {
'Authorization': this.configService.getTrinsicAPIKey(),
};

const proposal = {};
schema.attributeNames.forEach((att) => {
proposal[att] = (issueRequest.data[att] || '').toString();
})

this.logger.debug('Proposing', inspect(proposal, false, 7));
this.logger.debug('dict', inspect({
[schema.attributeNames[0]]: "test",
}, false, 7));


const response = await this.httpService
.post(this.trinsicUrl('/credentials/v1/credentials'), {
connectionId: invitation.connectionId,
definitionId: schema.trinsicCredentialDefinitionId,
automaticIssuance: true,
credentialValues: proposal,
},
{
headers: headersRequest
})
.toPromise();

return response.data;
}

Verify

Can be found here https://docs.trinsic.id/reference/sendverificationfromparameters

  async handleVerifyCredentialRequestForConnection(
verifyRequest: CredentialVerifyRequest,
identifier: string,
) {
const invitation = await this.getInvitationByIdentifier(identifier);
const schema = verifyRequest.type.trinsicSchema;

const headersRequest = {
'Authorization': this.configService.getTrinsicAPIKey(),
};

console.log(invitation.connectionId);

const response = await this.httpService
.post(this.trinsicUrl('/credentials/v1/verifications/policy/connections/' + invitation.connectionId), {
name: schema.name,
version: schema.version,
attributes: [{
attributeNames: schema.attributeNames,
policyName: schema.name
}]
},
{
headers: headersRequest
}).toPromise();

return response.data;
}

You will now need to do something with the response coming back from the Trinsic API.

Issue Credential Disclosure

Can be found here https://docs.trinsic.id/reference/getcredential

  public async handleIssueCredentialDisclosure(
issueRequest: CredentialIssueRequest,
data
) {
const headersRequest = {
'Authorization': this.configService.getTrinsicAPIKey(),
};

let credentialId = data.response.data.credentialId;
let issueData = null;
let issueState = "Offered";
let timedOut = false;
setTimeout(() => timedOut = true, 1000 * 60);

while (!timedOut && issueState === "Offered") {
const response = await this.httpService
.get(this.trinsicUrl('/credentials/v1/credentials/' + credentialId),
{
headers: headersRequest
}).toPromise();

issueState = response.data.state;
issueData = response.data
}

// Sometimes the state "Requested" pops up in between " Offered" and "Issued", not sure why...
setTimeout(() => timedOut = true, 1000 * 60);
while (!timedOut && issueState === "Requested") {
const response = await this.httpService
.get(this.trinsicUrl('/credentials/v1/credentials/' + credentialId),
{
headers: headersRequest
}).toPromise();

issueState = response.data.state;
issueData = response.data
}

if (issueState === "Issued") {
return issueState
}
}

Verify Credential Disclosure

Can be found here https://docs.trinsic.id/reference/getverification

  public async handleVerifyCredentialDisclosure(
verifyRequest: CredentialVerifyRequest,
data,
) {
const headersRequest = {
'Authorization': this.configService.getTrinsicAPIKey(),
};

let verificationId = data.response.data.verificationId;
let verificationData = null;
let verificationState = "Requested";
let timedOut = false;
setTimeout(() => timedOut = true, 1000 * 60);

while (!timedOut && verificationState === "Requested") {
const response = await this.httpService
.get(this.trinsicUrl('/credentials/v1/verifications/' + verificationId),
{
headers: headersRequest
}).toPromise();

verificationState = response.data.state;
verificationData = response.data
}

if (verificationState === "Accepted") {

return verificationData.proof[Object.keys(verificationData.proof)[0]].attributes
}
}