Skip to content

Commit

Permalink
fix server bug (#108)
Browse files Browse the repository at this point in the history
* many changes getting server working

* fix build and tests

* bump versions: applicant, issuer, server
  • Loading branch information
bnonni authored Aug 23, 2024
1 parent 044a2f8 commit c259d0f
Show file tree
Hide file tree
Showing 24 changed files with 698 additions and 655 deletions.
2 changes: 1 addition & 1 deletion packages/applicant/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dcx-protocol/applicant",
"version": "0.6.1",
"version": "0.7.0",
"description": "DCX Applicant protocol and server",
"type": "module",
"main": "./dist/cjs/index.js",
Expand Down
112 changes: 46 additions & 66 deletions packages/applicant/src/dcx-applicant.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import {
CreateCredentialApplicationParams,
CredentialApplication,
DcxAgent,
DcxAgentRecovery,
dcxConfig,
DcxConfig,
DcxDwnError,
DcxError,
DcxManager,
DcxManagerStatus,
dcxOptions,
DcxOptions,
DcxParams,
DcxValidated,
DwnError,
DwnUtils,
GetManifestsResponse,
Issuer,
Logger,
manifestSchema,
OptionsUtil,
Expand All @@ -28,7 +29,7 @@ import {
RecordsQueryResponse,
RecordsReadParams,
RecordsReadResponse,
responseSchema,
TrustedIssuer,
ValidateApplicationParams,
ValidateVerifiablePresentationResponse
} from '@dcx-protocol/common';
Expand All @@ -52,19 +53,22 @@ import { dcxApplicant } from './index.js';
* @returns DcxApplicant
* @example
* const applicant = new Dcxapplicant({ options: dcxOptions, config: dcxConfig });
* applicant.initializeWeb5();
* applicant.setupDwn();
* applicant.initialize();
* applicant.setup();
*/
export class DcxApplicant implements DcxManager {
options : DcxOptions = dcxOptions;
config : DcxConfig = dcxConfig;
[key: string]: any;

isSetup : boolean = false;
isInitialized : boolean = false;
public options: DcxOptions = dcxOptions;
public config: DcxConfig = dcxConfig;
public status: DcxManagerStatus = {
setup : false,
initialized : false,
};

public static did : string;
public static web5 : Web5;
public static agent : Web5PlatformAgent;
// public static did: string;
// public static web5: Web5;
// public static agent: Web5PlatformAgent;

constructor(params: DcxParams) {
this.options = params.options ? { ...this.options, ...params.options } : this.options;
Expand All @@ -77,7 +81,7 @@ export class DcxApplicant implements DcxManager {
*/
public async queryProtocols(): Promise<ProtocolsQueryResponse> {
// Query DWN for credential-applicant protocol
const { status: query, protocols = [] } = await DcxApplicant.web5.dwn.protocols.query({
const { status: query, protocols = [] } = await this.web5.dwn.protocols.query({
message : {
filter : {
protocol : dcxApplicant.protocol,
Expand All @@ -100,7 +104,7 @@ export class DcxApplicant implements DcxManager {
* @returns DwnResponseStatus; see {@link DwnResponseStatus}
*/
public async configureProtocols(): Promise<ProtocolsConfigureResponse> {
const { status: configure, protocol } = await DcxApplicant.web5.dwn.protocols.configure({
const { status: configure, protocol } = await this.web5.dwn.protocols.configure({
message : { definition: dcxApplicant },
});

Expand All @@ -110,7 +114,7 @@ export class DcxApplicant implements DcxManager {
throw new DwnError(code, detail);
}

const { status: send } = await protocol.send(DcxApplicant.did);
const { status: send } = await protocol.send(this.did);

if (DwnUtils.isFailure(send.code)) {
const { code, detail } = send;
Expand All @@ -122,27 +126,6 @@ export class DcxApplicant implements DcxManager {
return { status: send, protocol };
}

public static async queryRecords(): Promise<RecordsQueryResponse> {
const { status, records = [], cursor } = await DcxApplicant.web5.dwn.records.query({
message : {
filter : {
protocol : dcxApplicant.protocol,
protocolPath : 'application/response',
schema : responseSchema.$id,
dataFormat : 'application/json',
},
},
});

if (DwnUtils.isFailure(status.code)) {
const { code, detail } = status;
Logger.error('DWN manifest records query failed', status);
throw new DwnError(code, detail);
}

return { status, records, cursor };
}

public async readRecord({ record }: RecordReadParams): Promise<RecordsReadResponse> {
throw new DcxError('Method not implemented.', record);
}
Expand All @@ -152,7 +135,7 @@ export class DcxApplicant implements DcxManager {
): Promise<RecordsReadParams> {
const records = await Promise.all(
manifestRecords.map(async (manifestRecord: Record) => {
const { record: read } = await DcxApplicant.web5.dwn.records.read({
const { record: read } = await this.web5.dwn.records.read({
from : manifestRecord.author,
message : {
filter : {
Expand All @@ -171,7 +154,7 @@ export class DcxApplicant implements DcxManager {
): Promise<RecordsReadParams> {
const records = await Promise.all(
manifestRecords.map(async (manifestRecord: Record) => {
const { record: read } = await DcxApplicant.web5.dwn.records.read({
const { record: read } = await this.web5.dwn.records.read({
from : manifestRecord.author,
message : {
filter : {
Expand All @@ -193,7 +176,7 @@ export class DcxApplicant implements DcxManager {
public async readRecords({ records }: RecordsParams): Promise<RecordsReadResponse> {
const reads = await Promise.all(
records.map(async (record: Record) => {
const { record: read } = await DcxApplicant.web5.dwn.records.read({
const { record: read } = await this.web5.dwn.records.read({
from : record.author,
message : {
filter : {
Expand All @@ -210,14 +193,14 @@ export class DcxApplicant implements DcxManager {
/**
* Query records from DWN
*/
public async queryRecords({ from, protocolPath, options }: RecordsQueryParams): Promise<RecordsQueryResponse> {
const { status, records = [], cursor } = await DcxApplicant.web5.dwn.records.query({
public async queryRecords({ from, protocolPath, options, schema }: RecordsQueryParams): Promise<RecordsQueryResponse> {
const { status, records = [], cursor } = await this.web5.dwn.records.query({
from,
message : {
filter : {
protocolPath,
schema,
protocol : dcxApplicant.protocol,
schema : manifestSchema.$id,
dataFormat : 'application/json',
},
...options
Expand All @@ -237,7 +220,7 @@ export class DcxApplicant implements DcxManager {
* Query records from DWN
*/
public async queryManifestRecords({ from }: RecordsQueryParams): Promise<RecordsQueryResponse> {
const { status, records = [], cursor } = await DcxApplicant.web5.dwn.records.query({
const { status, records = [], cursor } = await this.web5.dwn.records.query({
from,
message : {
filter : {
Expand Down Expand Up @@ -267,7 +250,7 @@ export class DcxApplicant implements DcxManager {
});
Logger.log('Presentation Submission', presentationSubmission);
const vp = await VerifiablePresentation.create({
holder : DcxApplicant.did,
holder : this.did,
vcJwts : vcJwts,
additionalData : { presentationSubmission }
});
Expand All @@ -281,7 +264,7 @@ export class DcxApplicant implements DcxManager {
const app = {
id : crypto.randomUUID(),
spec_version : 'https://identity.foundation/credential-manifest/#versioning',
applicant : DcxApplicant.did,
applicant : this.did,
manifest_id : manifestId,
format : { jwt_vc: { alg: ['EdDSA'] }},
presentation_submission : presentationSubmission,
Expand Down Expand Up @@ -326,7 +309,7 @@ export class DcxApplicant implements DcxManager {
public async createRecord(
{ protocolPath, data, schema }: RecordCreateParams
): Promise<{record: Record}> {
const { record, status } = await DcxApplicant.web5.dwn.records.create({
const { record, status } = await this.web5.dwn.records.create({
data,
store : true,
message : {
Expand Down Expand Up @@ -378,49 +361,46 @@ export class DcxApplicant implements DcxManager {
* @param param.id the id of the issuer to find
* @returns RecordsReadParams; see {@link RecordsReadParams}
*/
public async getManifests({ name, id }: Partial<Issuer>): Promise<GetManifestsResponse> {
public async getManifests({ name, id }: Partial<TrustedIssuer>): Promise<GetManifestsResponse> {
const issuer = OptionsUtil.findIssuer({ issuers: this.options.issuers, name, id });
const { records: query } = await this.queryRecords({ from: issuer.id, protocolPath: 'manifest' });
const { records: query } = await this.queryRecords({ from: issuer.id, protocolPath: 'manifest', schema: manifestSchema.$id });
// TODO: application/response query
// const { records: query } = await this.queryRecords({ protocolPath: 'application/response', schema: responseSchema.$id, options: { author: issuer.id } });
Logger.log(`Found ${query.length} manifest records in ${issuer.name} dwn`);
const { records: manifests } = await this.readRecords({ records: query });
Logger.log(`Read ${manifests.length} manifest records from ${issuer.name} dwn`);
return { manifests };
}

/**
* Setup DWN with dcx applicant protocol
*
* @returns boolean indicating success or failure
* @throws DcxDwnError if the setup fails
* Setup Dwn associated with the DcxApplicant
*/
public async setupDwn(): Promise<void> {
// Logger.log('Setting up dwn ...');
public async setup(): Promise<void> {
try {
// Query DWN for credential-applicant protocols
const { protocols } = await this.queryProtocols();
Logger.log(`Found ${protocols.length} dcx applicant protocol in dwn`, protocols);
Logger.log(`Found ${protocols.length} DcxApplicant dwn protocol(s)`, protocols);

// Configure DWN with credential-applicant protocol if not found
if (!protocols.length) {
Logger.log('Configuring dwn with dcx applicant protocol ...');
Logger.log('Configuring DcxApplicant dwn protocol ...');
const { status, protocol } = await this.configureProtocols();
const { code, detail } = status;
Logger.log(`Configured dcx applicant protocol in applicant dwn: ${code} - ${detail}`, protocol?.definition.protocol);
Logger.log(`DcxApplicant dwn protocol configured: ${code} - ${detail}`, protocol?.definition.protocol);
}

Logger.log('Dcx applicant dwn setup complete');
this.isSetup = true;
this.status.setup = true;
} catch (error: any) {
Logger.error(`Dwn setup failed`, error);
Logger.error(`Failed to setup DcxApplicant dwn `, error);
throw error;
}
}

/**
* Initialize Web5 for DcxApplicant
* Initialize DcxApplicant with Web5 connection, DCX agent, and DCX Identity Vault
*/
public async initializeWeb5(): Promise<void> {
Logger.log('Initializing Web5 for DcxApplicant ... ');
public async initialize(): Promise<void> {
Logger.log('Initializing DcxApplicant ... ');

// Check the state of the password and recovery phrase
const { password, recoveryPhrase } = await DcxAgentRecovery.validate({
Expand All @@ -445,11 +425,11 @@ export class DcxApplicant implements DcxManager {
const agent = web5.agent as Web5PlatformAgent;

// Set the DcxManager properties
DcxApplicant.web5 = web5;
DcxApplicant.agent = agent;
DcxApplicant.did = did;
this.web5 = web5 as Web5;
this.agent = agent as DcxAgent;
this.did = did;

// Set the server initialized flag
this.isInitialized = true;
this.status.initialized = true;
}
}
8 changes: 4 additions & 4 deletions packages/applicant/tests/dcx-applicant.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ describe('DcxApplicant class', () => {
});

it('should initialize the DcxApplicant', () => {
expect(DcxApplicant.web5).to.not.be.null.and.not.be.undefined;
expect(DcxApplicant.web5).to.be.instanceof(Web5);
expect(applicant.web5).to.not.be.null.and.not.be.undefined;
expect(applicant.web5).to.be.instanceof(Web5);

expect(DcxApplicant.agent).to.not.be.null.and.not.be.undefined;
expect(DcxApplicant.agent).to.be.instanceof(Web5UserAgent);
expect(applicant.agent).to.not.be.null.and.not.be.undefined;
expect(applicant.agent).to.be.instanceof(Web5UserAgent);
});
});

Expand Down
18 changes: 4 additions & 14 deletions packages/common/src/dcx-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,18 @@ export type DcxApplicantConfig = {
web5RecoveryPhrase: string;
};

export const MX = {
name : 'mx',
id : 'did:dht:sa713dw7jyg44ejwcdf8iqcseh7jcz51wj6fjxbooj41ipeg76eo'
};
export const FORMFREE = {
name : 'formfree',
id : 'did:dht:hcf5e55bbm44s4oixp5z89wtxenxyk35su7f5pd4r5np93ikyowy'
};
export const MX = { name: 'mx', id: 'did:dht:kfcakjzahwimgo9zzjw6yknt9srdtkmfqbeybekcg3xzz1ztg95y' };
export const FF = { name: 'formfree', id: 'did:dht:hcf5e55bbm44s4oixp5z89wtxenxyk35su7f5pd4r5np93ikyowy' };

export const defaultTrustedIssuers = [MX, FORMFREE];
export const defaultTrustedIssuers = [MX, FF];

export const dcxConfig = {
...[DcxHandshakeManifest, PhoneNumberManifest, EmailAddressManifest],
issuers : defaultTrustedIssuers,
manifests : [DcxHandshakeManifest, PhoneNumberManifest, EmailAddressManifest],
dwnEndpoints : ['https://dwn.tbddev.org/beta'],
gatewayUris : ['https://diddht.tbddev.org/'],
endpoints : {
dwns : ['https://dwn.tbddev.org/beta'],
gateways : ['https://diddht.tbddev.org/'],
},
issuer : {
issuer : {
cursorFile : 'issuer-cursor.json',
lastRecordIdFile : 'lastRecordId.issuer',
web5Password : process.env.ISSUER_WEB5_PASSWORD ?? '',
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/dcx-dht-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export class DidDhtManager {
* @returns DidRegistrationResult; see {@link DidRegistrationResult}
*/
public async publishDidDoc(gatewayUri: string): Promise<DidRegistrationResult> {
gatewayUri ??= dcxConfig.endpoints.gateways[0];
gatewayUri ??= dcxConfig.gatewayUris[0];
return await DidDht.publish({ did: this.bearerDid, gatewayUri });
}

Expand Down
25 changes: 14 additions & 11 deletions packages/common/src/dcx-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,19 @@ import {
RecordsReadResponse
} from './index.js';

export type DcxManagerStatus = {
setup : boolean;
initialized : boolean;
}
export interface DcxManager {
options: DcxOptions;

queryProtocols(): Promise<ProtocolsQueryResponse>;
configureProtocols(): Promise<ProtocolsConfigureResponse>;
queryRecords(params?: RecordsQueryParams): Promise<RecordsQueryResponse>;
readRecords(params: RecordsReadParams): Promise<RecordsReadResponse>;
createRecord(params: RecordCreateParams): Promise<RecordCreateResponse>;
createRecords(params: RecordsCreateParams): Promise<RecordsCreateResponse>;

initializeWeb5(): Promise<void>;
setupDwn(): Promise<void>;
options : DcxOptions;
status : DcxManagerStatus;
setup() : Promise<void>;
initialize() : Promise<void>;
queryProtocols() : Promise<ProtocolsQueryResponse>;
configureProtocols() : Promise<ProtocolsConfigureResponse>;
queryRecords(params?: RecordsQueryParams) : Promise<RecordsQueryResponse>;
readRecords(params: RecordsReadParams) : Promise<RecordsReadResponse>;
createRecord(params: RecordCreateParams) : Promise<RecordCreateResponse>;
createRecords(params: RecordsCreateParams) : Promise<RecordsCreateResponse>;
}
Loading

0 comments on commit c259d0f

Please sign in to comment.