From efb6f0036339cf9cd80d33f1944d3583edaf36c1 Mon Sep 17 00:00:00 2001 From: Patrik Stas Date: Fri, 30 Dec 2022 14:11:16 +0100 Subject: [PATCH] Integrate new APIs in node-wrapper Signed-off-by: Patrik Stas --- aries_vcx/src/handlers/issuance/issuer.rs | 2 + .../api-node/src/api/credential.rs | 12 +- wrappers/node-napi-rs/api-node/src/error.rs | 1 + wrappers/node-napi-rs/index.d.ts | 5 +- wrappers/node/package.json | 2 +- wrappers/node/src/api/credential.ts | 504 ++---------------- wrappers/node/src/api/issuer-credential.ts | 84 +-- .../node/src/api/vcx-base-with-state-1.ts | 1 + wrappers/node/test/helpers/entities.ts | 23 - .../test/suite1/ariesvcx-credential.test.ts | 77 +-- .../suite1/ariesvcx-issuer-credential.test.ts | 254 +++++---- ...s => ariesvcx-mediated-connection.test.ts} | 16 - 12 files changed, 213 insertions(+), 768 deletions(-) rename wrappers/node/test/suite1/{ariesvcx-connection.test.ts => ariesvcx-mediated-connection.test.ts} (91%) diff --git a/aries_vcx/src/handlers/issuance/issuer.rs b/aries_vcx/src/handlers/issuance/issuer.rs index 2f5e0a9d41..fcf14d3deb 100644 --- a/aries_vcx/src/handlers/issuance/issuer.rs +++ b/aries_vcx/src/handlers/issuance/issuer.rs @@ -38,6 +38,7 @@ fn _build_credential_preview(credential_json: &str) -> VcxResult>> credential_json: {:?}", secret!(credential_json) ); + let cred_values: serde_json::Value = serde_json::from_str(credential_json).map_err(|err| { AriesVcxError::from_msg( AriesVcxErrorKind::InvalidJson, @@ -48,6 +49,7 @@ fn _build_credential_preview(credential_json: &str) -> VcxResult { diff --git a/wrappers/node-napi-rs/api-node/src/api/credential.rs b/wrappers/node-napi-rs/api-node/src/api/credential.rs index 3933b7bd61..4f517e59fc 100644 --- a/wrappers/node-napi-rs/api-node/src/api/credential.rs +++ b/wrappers/node-napi-rs/api-node/src/api/credential.rs @@ -43,7 +43,7 @@ fn credential_deserialize(data: String) -> napi::Result { // todo: flip order of arguments #[napi] -async fn v2_credential_update_state( +async fn v2_credential_update_state_with_message( handle_credential: u32, message: Option, connection_handle: u32, @@ -53,6 +53,16 @@ async fn v2_credential_update_state( .map_err(to_napi_err) } +#[napi] +async fn v2_credential_update_state( + handle_credential: u32, + connection_handle: u32, +) -> napi::Result { + credential::update_state(handle_credential, None, connection_handle) + .await + .map_err(to_napi_err) +} + #[napi] fn credential_get_state(handle: u32) -> napi::Result { credential::get_state(handle).map_err(to_napi_err) diff --git a/wrappers/node-napi-rs/api-node/src/error.rs b/wrappers/node-napi-rs/api-node/src/error.rs index f758ab4ee4..9920900410 100644 --- a/wrappers/node-napi-rs/api-node/src/error.rs +++ b/wrappers/node-napi-rs/api-node/src/error.rs @@ -3,6 +3,7 @@ use vcx::errors::error::LibvcxError; use vcx::serde_json::json; pub fn to_napi_err(err: LibvcxError) -> napi::Error { + warn!("to_napi_err: {:?}", err); let reason = json!({ "vcxErrKind": err.kind().to_string(), "vcxErrCode": u32::from(err.kind()), diff --git a/wrappers/node-napi-rs/index.d.ts b/wrappers/node-napi-rs/index.d.ts index d7358af933..0f31f27106 100644 --- a/wrappers/node-napi-rs/index.d.ts +++ b/wrappers/node-napi-rs/index.d.ts @@ -7,13 +7,15 @@ export function updateWebhookUrl(webhookUrl: string): Promise export function createAgencyClientForMainWallet(config: string): void export function provisionCloudAgent(config: string): Promise export function messagesUpdateStatus(statusCode: string, uidsByConns: string): Promise +export function generatePublicInvitation(publicDid: string, label: string): string export function credentialCreateWithOffer(sourceId: string, offer: string): number export function credentialRelease(handle: number): void export function credentialSendRequest(handle: number, handleConnection: number): Promise export function credentialDeclineOffer(handle: number, handleConnection: number, comment?: string | undefined | null): Promise export function credentialSerialize(handle: number): string export function credentialDeserialize(data: string): number -export function v2CredentialUpdateState(handleCredential: number, message: string | undefined | null, connectionHandle: number): Promise +export function v2CredentialUpdateStateWithMessage(handleCredential: number, message: string | undefined | null, connectionHandle: number): Promise +export function v2CredentialUpdateState(handleCredential: number, connectionHandle: number): Promise export function credentialGetState(handle: number): number export function credentialGetOffers(handleConnection: number): Promise export function credentialGetAttributes(handle: number): string @@ -168,4 +170,3 @@ export function getVerkeyFromWallet(did: string): Promise export function rotateVerkey(did: string): Promise export function rotateVerkeyStart(did: string): Promise export function rotateVerkeyApply(did: string, tempVk: string): Promise -export function generatePublicInvitation(publicDid: string, label: string): string diff --git a/wrappers/node/package.json b/wrappers/node/package.json index 910e0b554a..b94db4753d 100644 --- a/wrappers/node/package.json +++ b/wrappers/node/package.json @@ -72,7 +72,7 @@ "lint-fix": "npm run lint -- --fix", "jslint:fix": "standard --fix", "test": "npm run test:connection && npm run test:credentialDef && npm run test:credential && npm run test:disclosedProof && npm run test:issuerCredential && npm run test:proof && npm run test:oob && npm run test:schema && npm run test:utils && npm run test:wallet && npm run test:ffi", - "test:connection": " TS_NODE_PROJECT=./test/tsconfig.json NODE_ENV=test RUST_BACKTRACE=full ./node_modules/.bin/mocha --timeout 60000 --v8-expose-gc --v8-use-strict --exit --recursive --require ts-node/register ./test/suite1/ariesvcx-connection.test.ts", + "test:connection": " TS_NODE_PROJECT=./test/tsconfig.json NODE_ENV=test RUST_BACKTRACE=full ./node_modules/.bin/mocha --timeout 60000 --v8-expose-gc --v8-use-strict --exit --recursive --require ts-node/register test/suite1/ariesvcx-mediated-connection.test.ts", "test:credentialDef": " TS_NODE_PROJECT=./test/tsconfig.json NODE_ENV=test RUST_BACKTRACE=full ./node_modules/.bin/mocha --timeout 60000 --v8-expose-gc --v8-use-strict --exit --recursive --require ts-node/register ./test/suite1/ariesvcx-credential-def.test.ts", "test:credential": " TS_NODE_PROJECT=./test/tsconfig.json NODE_ENV=test RUST_BACKTRACE=full ./node_modules/.bin/mocha --timeout 60000 --v8-expose-gc --v8-use-strict --exit --recursive --require ts-node/register ./test/suite1/ariesvcx-credential.test.ts", "test:disclosedProof": " TS_NODE_PROJECT=./test/tsconfig.json NODE_ENV=test RUST_BACKTRACE=full ./node_modules/.bin/mocha --timeout 60000 --v8-expose-gc --v8-use-strict --exit --recursive --require ts-node/register ./test/suite1/ariesvcx-disclosed-proof.test.ts", diff --git a/wrappers/node/src/api/credential.ts b/wrappers/node/src/api/credential.ts index 82cb33344a..f0b403cb66 100644 --- a/wrappers/node/src/api/credential.ts +++ b/wrappers/node/src/api/credential.ts @@ -1,47 +1,8 @@ -import { Callback } from 'ffi-napi'; - -import { VCXInternalError } from '../errors'; -import { rustAPI } from '../rustlib'; -import { createFFICallbackPromise } from '../utils/ffi-helpers'; +import * as ffi from 'node-napi-rs'; import { ISerializedData, HolderStateType } from './common'; import { Connection } from './mediated-connection'; -import { VCXBaseWithState } from './vcx-base-with-state'; - -/** - * The object of the VCX API representing a Holder side in the credential issuance process. - * Assumes that pairwise connection between Issuer and Holder is already established. - * - * # State - * - * The set of object states and transitions depends on communication method is used. - * The communication method can be specified as config option on one of *_init function. - * - * VcxStateType::VcxStateRequestReceived - once `vcx_credential_create_with_offer` (create Credential object) is called. - * - * VcxStateType::VcxStateOfferSent - once `vcx_credential_send_request` (send `CredentialRequest` message) is called. - * - * VcxStateType::VcxStateAccepted - once `Credential` messages is received. - * VcxStateType::None - once `ProblemReport` messages is received. - * use `vcx_credential_update_state` or `vcx_credential_update_state_with_message` functions for state updates. - * - * # Transitions - * - * aries: RFC - https://github.com/hyperledger/aries-rfcs/tree/7b6b93acbaf9611d3c892c4bada142fe2613de6e/features/0036-issue-credential - * VcxStateType::None - `vcx_credential_create_with_offer` - VcxStateType::VcxStateRequestReceived - * - * VcxStateType::VcxStateRequestReceived - `vcx_issuer_send_credential_offer` - VcxStateType::VcxStateOfferSent - * - * VcxStateType::VcxStateOfferSent - received `Credential` - VcxStateType::VcxStateAccepted - * VcxStateType::VcxStateOfferSent - received `ProblemReport` - VcxStateType::None - * - * # Messages - * CredentialProposal - https://github.com/hyperledger/aries-rfcs/tree/7b6b93acbaf9611d3c892c4bada142fe2613de6e/features/0036-issue-credential#propose-credential - * CredentialOffer - https://github.com/hyperledger/aries-rfcs/tree/7b6b93acbaf9611d3c892c4bada142fe2613de6e/features/0036-issue-credential#offer-credential - * CredentialRequest - https://github.com/hyperledger/aries-rfcs/tree/7b6b93acbaf9611d3c892c4bada142fe2613de6e/features/0036-issue-credential#request-credential - * Credential - https://github.com/hyperledger/aries-rfcs/tree/7b6b93acbaf9611d3c892c4bada142fe2613de6e/features/0036-issue-credential#issue-credential - * ProblemReport - https://github.com/hyperledger/aries-rfcs/tree/7b6b93acbaf9611d3c892c4bada142fe2613de6e/features/0035-report-problem#the-problem-report-message-type - * Ack - https://github.com/hyperledger/aries-rfcs/tree/master/features/0015-acks#explicit-acks - */ +import { VCXBaseWithState1 } from './vcx-base-with-state-1'; +import { VCXInternalErrorNapirs } from '../errors-napirs'; export interface ICredentialStructData { source_id: string; @@ -50,157 +11,28 @@ export interface ICredentialStructData { // eslint-disable-next-line @typescript-eslint/ban-types export type ICredentialOffer = [object, object]; -/** - * @description Interface that represents the parameters for `Credential.create` function. - * @interface - */ export interface ICredentialCreateWithOffer { - // Institution's personal identification for the credential, should be unique. sourceId: string; - // Credential offer received via "getOffers" offer: string; - // We're going to need it in the future - connection: Connection; -} - -/** - * @description Interface that represents the parameters for `Credential.createWithMsgId` function. - * @interface - */ -export interface ICredentialCreateWithMsgId { - // Institution's personal identification for the credential, should be unique. - sourceId: string; - // Id of the message that contains the credential offer - msgId: string; - // Connection to query for credential offer connection: Connection; } -/** - * @description Interface that represents the parameters for `Credential.sendRequest` function. - * @interface - */ export interface ICredentialSendData { - // Connection to send credential request connection: Connection; } -export interface ICredentialGetRequestMessageData { - // Use Connection api (vcx_connection_get_pw_did) with specified connection_handle to retrieve your pw_did - myPwDid: string; - // Use Connection api (vcx_connection_get_their_pw_did) with specified connection_handle to retrieve their pw_did - theirPwDid?: string; -} - -/** - * A Credential Object, which is issued by the issuing party to the prover and stored in the prover's wallet. - */ -export class Credential extends VCXBaseWithState { - /** - * Creates a credential with an offer. - * - * * Requires a credential offer to be submitted to prover. - * - * ``` - * credentialOffer = [ - * { - * claim_id: 'defaultCredentialId', - * claim_name: 'Credential', - * cred_def_id: 'id', - * credential_attrs: { - * address1: ['101 Tela Lane'], - * address2: ['101 Wilson Lane'], - * city: ['SLC'], - * state: ['UT'], - * zip: ['87121'] - * }, - * from_did: '8XFh8yBzrpJQmNyZzgoTqB', - * libindy_offer: '{}', - * msg_ref_id: '123', - * msg_type: 'CLAIM_OFFER', - * schema_seq_no: 1487, - * to_did: '8XFh8yBzrpJQmNyZzgoTqB', - * version: '0.1' - * }] - * - * { - * JSON.stringify(credentialOffer), - * 'testCredentialSourceId' - * } - * credential = Credential.create(data) - * ``` - * - */ - public static async create({ sourceId, offer }: ICredentialCreateWithOffer): Promise { - const credential = new Credential(sourceId); +export class Credential extends VCXBaseWithState1 { + public static create({ sourceId, offer }: ICredentialCreateWithOffer): Credential { try { - await credential._create((cb) => - rustAPI().vcx_credential_create_with_offer(0, sourceId, offer, cb), - ); + const credential = new Credential(sourceId); + const handle = ffi.credentialCreateWithOffer(sourceId, offer); + credential._setHandle(handle); return credential; } catch (err: any) { - throw new VCXInternalError(err); + throw new VCXInternalErrorNapirs(err); } } - /** - * Create a Credential object based off of a known message id for a given connection. - * - * ``` - * credential = Credential.createWithMsgId({ - * connection, - * msgId: 'testCredentialMsgId', - * sourceId: 'testCredentialSourceId' - * }) - * ``` - */ - public static async createWithMsgId({ - connection, - sourceId, - msgId, - }: ICredentialCreateWithMsgId): Promise { - try { - return await createFFICallbackPromise( - (resolve, reject, cb) => { - const rc = rustAPI().vcx_credential_create_with_msgid( - 0, - sourceId, - connection.handle, - msgId, - cb, - ); - if (rc) { - reject(rc); - } - }, - (resolve, reject) => - Callback( - 'void', - ['uint32', 'uint32', 'uint32', 'string'], - (xHandle: number, err: number, handleNum: number, credOffer: string) => { - if (err) { - reject(err); - return; - } - const newObj = new Credential(sourceId); - newObj._setHandle(handleNum); - newObj._credOffer = credOffer; - resolve(newObj); - }, - ), - ); - } catch (err: any) { - throw new VCXInternalError(err); - } - } - - /** - * Create an object from a JSON Structured data produced from the objects serialize method - * - * ``` - * data = credential.deserialize() - * ``` - */ public static async deserialize( credentialData: ISerializedData, ): Promise { @@ -208,344 +40,86 @@ export class Credential extends VCXBaseWithState { try { - const offersStr = await createFFICallbackPromise( - (resolve, reject, cb) => { - const rc = rustAPI().vcx_credential_get_offers(0, connection.handle, cb); - if (rc) { - reject(rc); - } - }, - (resolve, reject) => - Callback( - 'void', - ['uint32', 'uint32', 'string'], - (handle: number, err: number, messages: string) => { - if (err) { - reject(err); - return; - } - resolve(messages); - }, - ), - ); + const offersStr = await ffi.credentialGetOffers(connection.handle); const offers: ICredentialOffer[] = JSON.parse(offersStr); return offers; } catch (err: any) { - throw new VCXInternalError(err); + throw new VCXInternalErrorNapirs(err); } } - protected _releaseFn = rustAPI().vcx_credential_release; - protected _updateStFnV2 = rustAPI().vcx_v2_credential_update_state; - protected _getStFn = rustAPI().vcx_credential_get_state; - protected _serializeFn = rustAPI().vcx_credential_serialize; - protected _deserializeFn = rustAPI().vcx_credential_deserialize; - protected _credOffer = ''; - - /** - * Approves the credential offer and submits a credential request. - * The result will be a credential stored in the prover's wallet. - * - * ``` - * connection = await Connection.create({id: 'foobar'}) - * inviteDetails = await connection.connect() - * credential = Credential.create(data) - * await credential.sendRequest({ connection, 1000 }) - * ``` - * - */ public async sendRequest({ connection }: ICredentialSendData): Promise { try { - await createFFICallbackPromise( - (resolve, reject, cb) => { - const rc = rustAPI().vcx_credential_send_request( - 0, - this.handle, - connection.handle, - 0, - cb, - ); - if (rc) { - reject(rc); - } - }, - (resolve, reject) => - Callback('void', ['uint32', 'uint32'], (xcommandHandle: number, err: number) => { - if (err) { - reject(err); - return; - } - resolve(); - }), - ); - } catch (err: any) { - throw new VCXInternalError(err); - } - } - /** - * Gets the credential request message for sending to the specified connection. - * - * ``` - * connection = await Connection.create({id: 'foobar'}) - * inviteDetails = await connection.connect() - * credential = Credential.create(data) - * await credential.getRequestMessage({ '44x8p4HubxzUK1dwxcc5FU', 1000 }) - * ``` - * - */ - public async getRequestMessage({ - myPwDid, - theirPwDid, - }: ICredentialGetRequestMessageData): Promise { - try { - return await createFFICallbackPromise( - (resolve, reject, cb) => { - const rc = rustAPI().vcx_credential_get_request_msg( - 0, - this.handle, - myPwDid, - theirPwDid, - 0, - cb, - ); - if (rc) { - reject(rc); - } - }, - (resolve, reject) => - Callback( - 'void', - ['uint32', 'uint32', 'string'], - (xHandle: number, err: number, message: string) => { - if (err) { - reject(err); - return; - } - if (!message) { - reject(`Credential ${this.sourceId} returned empty string`); - return; - } - resolve(message); - }, - ), - ); + return await ffi.credentialSendRequest(this.handle, connection.handle); } catch (err: any) { - throw new VCXInternalError(err); + throw new VCXInternalErrorNapirs(err); } } - public async getAttributes(): Promise { + public getAttributes(): string { try { - const attrs = await createFFICallbackPromise( - (resolve, reject, cb) => { - const rc = rustAPI().vcx_credential_get_attributes(0, this.handle, cb); - if (rc) { - reject(rc); - } - }, - (resolve, reject) => - Callback( - 'void', - ['uint32', 'uint32', 'string'], - (handle: number, err: number, _attrs: string) => { - if (err) { - reject(err); - return; - } - resolve(_attrs); - }, - ), - ); - return attrs; + return ffi.credentialGetAttributes(this.handle); } catch (err: any) { - throw new VCXInternalError(err); + throw new VCXInternalErrorNapirs(err); } } - public async getAttachment(): Promise { + public getAttachment(): string { try { - const attach = await createFFICallbackPromise( - (resolve, reject, cb) => { - const rc = rustAPI().vcx_credential_get_attachment(0, this.handle, cb); - if (rc) { - reject(rc); - } - }, - (resolve, reject) => - Callback( - 'void', - ['uint32', 'uint32', 'string'], - (handle: number, err: number, _attach: string) => { - if (err) { - reject(err); - return; - } - resolve(_attach); - }, - ), - ); - return attach; + return ffi.credentialGetAttachment(this.handle); } catch (err: any) { - throw new VCXInternalError(err); + throw new VCXInternalErrorNapirs(err); } } - public async getTailsLocation(): Promise { + public getTailsLocation(): string { try { - const location = await createFFICallbackPromise( - (resolve, reject, cb) => { - const rc = rustAPI().vcx_credential_get_tails_location(0, this.handle, cb); - if (rc) { - reject(rc); - } - }, - (resolve, reject) => - Callback( - 'void', - ['uint32', 'uint32', 'string'], - (handle: number, err: number, _location: string) => { - if (err) { - reject(err); - return; - } - resolve(_location); - }, - ), - ); - return location; + return ffi.credentialGetTailsLocation(this.handle); } catch (err: any) { - throw new VCXInternalError(err); + throw new VCXInternalErrorNapirs(err); } } - public async getTailsHash(): Promise { + public getTailsHash(): string { try { - const hash = await createFFICallbackPromise( - (resolve, reject, cb) => { - const rc = rustAPI().vcx_credential_get_tails_hash(0, this.handle, cb); - if (rc) { - reject(rc); - } - }, - (resolve, reject) => - Callback( - 'void', - ['uint32', 'uint32', 'string'], - (handle: number, err: number, _hash: string) => { - if (err) { - reject(err); - return; - } - resolve(_hash); - }, - ), - ); - return hash; + return ffi.credentialGetTailsHash(this.handle); } catch (err: any) { - throw new VCXInternalError(err); + throw new VCXInternalErrorNapirs(err); } } - public async getRevRegId(): Promise { + public getRevRegId(): string { try { - const revRegId = await createFFICallbackPromise( - (resolve, reject, cb) => { - const rc = rustAPI().vcx_credential_get_rev_reg_id(0, this.handle, cb); - if (rc) { - reject(rc); - } - }, - (resolve, reject) => - Callback( - 'void', - ['uint32', 'uint32', 'string'], - (handle: number, err: number, _revRegId: string) => { - if (err) { - reject(err); - return; - } - resolve(_revRegId); - }, - ), - ); - return revRegId; + return ffi.credentialGetRevRegId(this.handle); } catch (err: any) { - throw new VCXInternalError(err); + throw new VCXInternalErrorNapirs(err); } } - public async getThreadId(): Promise { + public getThreadId(): string { try { - const threadId = await createFFICallbackPromise( - (resolve, reject, cb) => { - const rc = rustAPI().vcx_credential_get_thread_id(0, this.handle, cb); - if (rc) { - reject(rc); - } - }, - (resolve, reject) => - Callback( - 'void', - ['uint32', 'uint32', 'string'], - (handle: number, err: number, threadId: string) => { - if (err) { - reject(err); - return; - } - resolve(threadId); - }, - ), - ); - return threadId; + return ffi.credentialGetThreadId(this.handle); } catch (err: any) { - throw new VCXInternalError(err); + throw new VCXInternalErrorNapirs(err); } } public async declineOffer(connection: Connection, comment: string): Promise { try { - await createFFICallbackPromise( - (resolve, reject, cb) => { - const rc = rustAPI().vcx_credential_decline_offer( - 0, - this.handle, - connection.handle, - comment, - cb, - ); - if (rc) { - reject(rc); - } - }, - (resolve, reject) => - Callback('void', ['uint32', 'uint32'], (xcommandHandle: number, err: number) => { - if (err) { - reject(err); - return; - } - resolve(); - }), - ); + await ffi.credentialDeclineOffer(this.handle, connection.handle, comment); } catch (err: any) { - throw new VCXInternalError(err); + throw new VCXInternalErrorNapirs(err); } } - get credOffer(): string { - return this._credOffer; - } - protected _setHandle(handle: number): void { super._setHandle(handle); } diff --git a/wrappers/node/src/api/issuer-credential.ts b/wrappers/node/src/api/issuer-credential.ts index 364dd3c6a7..38a8b5ae7c 100644 --- a/wrappers/node/src/api/issuer-credential.ts +++ b/wrappers/node/src/api/issuer-credential.ts @@ -1,48 +1,11 @@ -import * as ffiNapi from 'node-napi-rs'; +import * as ffi from 'node-napi-rs'; import { ISerializedData, IssuerStateType } from './common'; -import { Connection, IConnectionData } from './mediated-connection'; +import { Connection } from './mediated-connection'; import { CredentialDef } from './credential-def'; import { RevocationRegistry } from './revocation-registry'; import { VCXBaseWithState1 } from './vcx-base-with-state-1'; import { VCXInternalErrorNapirs } from '../errors-napirs'; - -/** - * @description Interface that represents the parameters for `IssuerCredential.create` function. - * @interface - */ -export interface IIssuerCredentialCreateData { - // Enterprise's personal identification for the user. - sourceId: string; - // Handle of the correspondent credential definition object - credDefHandle: number; - // Data attributes offered to person in the credential ('{"state":"UT"}') - attr: { - [index: string]: string; - }; - // Name of the credential - ex. Drivers Licence - credentialName: string; - // price of credential - price: string; - issuerDid: string; -} - -export interface IIssuerCredentialOfferSendData { - connection: Connection; - credDef: CredentialDef; - attr: { - [index: string]: string; - }; -} - -export interface IIssuerCredentialBuildOfferData { - credDef: CredentialDef; - attr: { - [index: string]: string; - }; - comment: string; -} - export interface IIssuerCredentialBuildOfferDataV2 { credDef: CredentialDef; revReg?: RevocationRegistry; @@ -52,17 +15,6 @@ export interface IIssuerCredentialBuildOfferDataV2 { comment?: string; } -export interface IIssuerCredentialVCXAttributes { - [index: string]: string; -} - -export interface IIssuerCredentialParams { - credDefHandle: number; - credentialName: string; - attr: IIssuerCredentialVCXAttributes; - price: string; -} - /** * Interface that represents the attributes of an Issuer credential object. * This interface is expected as the type for deserialize's parameter and serialize's return value @@ -80,7 +32,7 @@ export class IssuerCredential extends VCXBaseWithState1 { try { const connection = new IssuerCredential(sourceId); - connection._setHandle(await ffiNapi.issuerCredentialCreate(sourceId)); + connection._setHandle(await ffi.issuerCredentialCreate(sourceId)); return connection; } catch (err: any) { throw new VCXInternalErrorNapirs(err); @@ -97,11 +49,11 @@ export class IssuerCredential extends VCXBaseWithState1 { try { - return await ffiNapi.issuerCredentialUpdateStateWithMessageV2( + return await ffi.issuerCredentialUpdateStateWithMessageV2( this.handle, connection.handle, message, @@ -121,7 +73,7 @@ export class IssuerCredential extends VCXBaseWithState1 { try { - return await ffiNapi.issuerCredentialSendOfferV2(this.handle, connection.handle); + return await ffi.issuerCredentialSendOfferV2(this.handle, connection.handle); } catch (err: any) { throw new VCXInternalErrorNapirs(err); } @@ -129,7 +81,7 @@ export class IssuerCredential extends VCXBaseWithState1 { try { - return await ffiNapi.issuerCredentialMarkOfferMsgSent(this.handle); + return await ffi.issuerCredentialMarkOfferMsgSent(this.handle); } catch (err: any) { throw new VCXInternalErrorNapirs(err); } @@ -142,7 +94,7 @@ export class IssuerCredential extends VCXBaseWithState1 { try { - return await ffiNapi.issuerCredentialBuildOfferMsgV2( + return await ffi.issuerCredentialBuildOfferMsgV2( this.handle, credDef.handle, revReg?.handle || 0, @@ -156,7 +108,7 @@ export class IssuerCredential extends VCXBaseWithState1 { try { - return await ffiNapi.issuerCredentialGetOfferMsg(this.handle); + return await ffi.issuerCredentialGetOfferMsg(this.handle); } catch (err: any) { throw new VCXInternalErrorNapirs(err); } @@ -164,7 +116,7 @@ export class IssuerCredential extends VCXBaseWithState1 { try { - return await ffiNapi.issuerCredentialGetThreadId(this.handle); + return await ffi.issuerCredentialGetThreadId(this.handle); } catch (err: any) { throw new VCXInternalErrorNapirs(err); } @@ -172,7 +124,7 @@ export class IssuerCredential extends VCXBaseWithState1 { try { - return await ffiNapi.issuerCredentialSendCredential(this.handle, connection.handle); + return await ffi.issuerCredentialSendCredential(this.handle, connection.handle); } catch (err: any) { throw new VCXInternalErrorNapirs(err); } @@ -184,7 +136,7 @@ export class IssuerCredential extends VCXBaseWithState1 { try { - return await ffiNapi.issuerCredentialRevokeLocal(this.handle); + return await ffi.issuerCredentialRevokeLocal(this.handle); } catch (err: any) { throw new VCXInternalErrorNapirs(err); } @@ -192,7 +144,7 @@ export class IssuerCredential extends VCXBaseWithState1 { try { - return await ffiNapi.issuerCredentialIsRevokable(this.handle); + return await ffi.issuerCredentialIsRevokable(this.handle); } catch (err: any) { throw new VCXInternalErrorNapirs(err); } @@ -200,7 +152,7 @@ export class IssuerCredential extends VCXBaseWithState1 { try { - return await ffiNapi.issuerCredentialGetRevRegId(this.handle); + return await ffi.issuerCredentialGetRevRegId(this.handle); } catch (err: any) { throw new VCXInternalErrorNapirs(err); } diff --git a/wrappers/node/src/api/vcx-base-with-state-1.ts b/wrappers/node/src/api/vcx-base-with-state-1.ts index 2fc2b31e1f..3e25fdabfe 100644 --- a/wrappers/node/src/api/vcx-base-with-state-1.ts +++ b/wrappers/node/src/api/vcx-base-with-state-1.ts @@ -34,3 +34,4 @@ export abstract class VCXBaseWithState1 extends VcxBa } } } + diff --git a/wrappers/node/test/helpers/entities.ts b/wrappers/node/test/helpers/entities.ts index d317a19ef9..2ed939af9f 100644 --- a/wrappers/node/test/helpers/entities.ts +++ b/wrappers/node/test/helpers/entities.ts @@ -9,7 +9,6 @@ import { CredentialDef, DisclosedProof, IConnectionCreateData, - ICredentialCreateWithMsgId, ICredentialCreateWithOffer, ICredentialDefCreateDataV2, IDisclosedProofCreateData, @@ -113,28 +112,6 @@ export const credentialCreateWithOffer = async ( return credential; }; -export const dataCredentialCreateWithMsgId = async (): Promise => { - const connection = await createConnectionInviterRequested(); - return { - connection, - msgId: 'testCredentialMsgId', - sourceId: 'testCredentialSourceId', - }; -}; - -export const credentialCreateWithMsgId = async ( - data?: ICredentialCreateWithMsgId, -): Promise => { - if (!data) { - data = await dataCredentialCreateWithMsgId(); - } - const credential = await Credential.createWithMsgId(data); - assert.notEqual(credential.handle, undefined); - assert.equal(credential.sourceId, data.sourceId); - assert.ok(credential.credOffer); - return credential; -}; - export const dataDisclosedProofCreateWithRequest = async (): Promise => { const connection = await createConnectionInviterRequested(); return { diff --git a/wrappers/node/test/suite1/ariesvcx-credential.test.ts b/wrappers/node/test/suite1/ariesvcx-credential.test.ts index 781d5c52d5..b2b9709491 100644 --- a/wrappers/node/test/suite1/ariesvcx-credential.test.ts +++ b/wrappers/node/test/suite1/ariesvcx-credential.test.ts @@ -3,13 +3,11 @@ import '../module-resolver-helper'; import { assert } from 'chai'; import { createConnectionInviterRequested, - credentialCreateWithMsgId, credentialCreateWithOffer, - dataCredentialCreateWithMsgId, dataCredentialCreateWithOffer, } from 'helpers/entities'; import { initVcxTestMode, shouldThrow } from 'helpers/utils'; -import { Credential, HolderStateType, VCXCode, VCXMock, VCXMockMessage } from 'src'; +import { Credential, HolderStateType, VCXCode } from 'src'; describe('Credential:', () => { before(() => initVcxTestMode()); @@ -22,20 +20,13 @@ describe('Credential:', () => { it('throws: missing sourceId', async () => { const { sourceId, ...data } = await dataCredentialCreateWithOffer(); const error = await shouldThrow(() => Credential.create(data as any)); - assert.equal(error.vcxCode, VCXCode.INVALID_OPTION); + assert.equal(error.napiCode, 'StringExpected'); }); it('throws: missing offer', async () => { const { offer, ...data } = await dataCredentialCreateWithOffer(); const error = await shouldThrow(() => Credential.create(data as any)); - assert.equal(error.vcxCode, VCXCode.INVALID_OPTION); - }); - - // Enable when we start utilizing connection prop - it.skip('throws: missing connection', async () => { - const { connection, ...data } = await dataCredentialCreateWithOffer(); - const error = await shouldThrow(() => Credential.create({ connection: {} as any, ...data })); - assert.equal(error.vcxCode, VCXCode.INVALID_OPTION); + assert.equal(error.napiCode, 'StringExpected'); }); it('throws: invalid offer', async () => { @@ -57,7 +48,7 @@ describe('Credential:', () => { it('throws: not initialized', async () => { const credential = new Credential(null as any); const error = await shouldThrow(() => credential.serialize()); - assert.equal(error.vcxCode, VCXCode.INVALID_OBJ_HANDLE); + assert.equal(error.napiCode, 'NumberExpected'); }); }); @@ -76,6 +67,7 @@ describe('Credential:', () => { data: { source_id: 'Invalid' }, } as any), ); + assert.equal(error.napiCode, 'GenericFailure'); assert.equal(error.vcxCode, VCXCode.INVALID_JSON); }); }); @@ -98,13 +90,6 @@ describe('Credential:', () => { await credential.sendRequest({ connection: data.connection }); assert.equal(await credential.getState(), HolderStateType.RequestSent); }); - - it('success: with message id', async () => { - const data = await dataCredentialCreateWithMsgId(); - const credential = await credentialCreateWithMsgId(data); - await credential.sendRequest({ connection: data.connection }); - assert.equal(await credential.getState(), HolderStateType.RequestSent); - }); }); describe('getOffers:', () => { @@ -134,10 +119,15 @@ describe('Credential:', () => { offer: JSON.stringify(offer), sourceId: 'credentialGetAttributesTestSourceId', }); - const attrs = JSON.parse(await credential.getAttributes()); - const expectedAttrs = JSON.parse( - '{"last_name":"clark","sex":"female","degree":"maths","date":"05-2018","age":"25","name":"alice"}', - ); + const attrs = JSON.parse(credential.getAttributes()); + const expectedAttrs = { + last_name: 'clark', + sex: 'female', + degree: 'maths', + date: '05-2018', + age: '25', + name: 'alice', + }; assert.deepEqual(attrs, expectedAttrs); }); }); @@ -154,45 +144,8 @@ describe('Credential:', () => { offer: JSON.stringify(offer), sourceId: 'credentialGetAttributesTestSourceId', }); - const attach = JSON.parse(await credential.getAttachment()); + const attach = JSON.parse(credential.getAttachment()); assert.deepEqual(attach.schema_id, 'V4SGRU86Z58d6TV7PBUe6f:2:FaberVcx:83.23.62'); }); }); - - describe('createWithMsgId', () => { - // TODO: to enable this test, credential offer must be mocked in aries code of get_credential_offer_msg - it.skip('createWithMsgIdsuccess', async () => { - await credentialCreateWithMsgId(); - }); - - it('throws: missing sourceId', async () => { - const { connection, msgId } = await dataCredentialCreateWithMsgId(); - const error = await shouldThrow(() => - Credential.createWithMsgId({ connection, msgId } as any), - ); - assert.equal(error.vcxCode, VCXCode.INVALID_OPTION); - }); - - it('throws: missing offer', async () => { - const { connection, sourceId } = await dataCredentialCreateWithMsgId(); - const error = await shouldThrow(() => - Credential.createWithMsgId({ connection, sourceId } as any), - ); - assert.equal(error.vcxCode, VCXCode.INVALID_OPTION); - }); - - it('throws: missing connection', async () => { - const { connection, ...data } = await dataCredentialCreateWithMsgId(); - const error = await shouldThrow(() => Credential.createWithMsgId(data as any)); - assert.equal(error.vcxCode, VCXCode.UNKNOWN_ERROR); - }); - - it('throws: missing connection handle', async () => { - const { connection, ...data } = await dataCredentialCreateWithMsgId(); - const error = await shouldThrow(() => - Credential.createWithMsgId({ connection: {} as any, ...data }), - ); - assert.equal(error.vcxCode, VCXCode.INVALID_OBJ_HANDLE); - }); - }); }); diff --git a/wrappers/node/test/suite1/ariesvcx-issuer-credential.test.ts b/wrappers/node/test/suite1/ariesvcx-issuer-credential.test.ts index 0f7ddf7f5e..fa6270ca83 100644 --- a/wrappers/node/test/suite1/ariesvcx-issuer-credential.test.ts +++ b/wrappers/node/test/suite1/ariesvcx-issuer-credential.test.ts @@ -2,11 +2,13 @@ import '../module-resolver-helper'; import { assert } from 'chai'; import { - createConnectionInviterRequested, credentialDefCreate, + createConnectionInviterRequested, + credentialDefCreate, + dataCredentialCreateWithOffer, issuerCredentialCreate, -} from 'helpers/entities' +} from 'helpers/entities'; import { initVcxTestMode, shouldThrow } from 'helpers/utils'; -import { Connection, IssuerCredential, IssuerStateType, VCXCode } from 'src'; +import { Connection, Credential, IssuerCredential, IssuerStateType, VCXCode } from 'src'; describe('IssuerCredential:', () => { before(() => initVcxTestMode()); @@ -15,137 +17,125 @@ describe('IssuerCredential:', () => { it('success', async () => { await issuerCredentialCreate(); }); + }); + + describe('serialize:', () => { + it('success', async () => { + const issuerCredential = await issuerCredentialCreate(); + const serialized = await issuerCredential[0].serialize(); + assert.ok(serialized); + assert.property(serialized, 'version'); + assert.property(serialized, 'data'); + const { data, version } = serialized; + assert.ok(data); + assert.ok(version); + }); - // it('throws: missing sourceId', async () => { - // const error = await shouldThrow(() => IssuerCredential.create('')); - // assert.equal(error.vcxCode, VCXCode.INVALID_OPTION); - // }); + it('throws: not initialized', async () => { + const issuerCredential = new IssuerCredential('foo'); + const error = await shouldThrow(() => issuerCredential.serialize()); + assert.equal(error.napiCode, 'NumberExpected'); + }); }); - // describe('serialize:', () => { - // it('success', async () => { - // const issuerCredential = await issuerCredentialCreate(); - // const serialized = await issuerCredential[0].serialize(); - // assert.ok(serialized); - // assert.property(serialized, 'version'); - // assert.property(serialized, 'data'); - // const { data, version } = serialized; - // assert.ok(data); - // assert.ok(version); - // }); - // - // it('throws: not initialized', async () => { - // const issuerCredential = new IssuerCredential(''); - // const error = await shouldThrow(() => issuerCredential.serialize()); - // assert.equal(error.vcxCode, VCXCode.INVALID_OBJ_HANDLE); - // }); - // }); - // - // describe('deserialize:', () => { - // it('success', async () => { - // const [issuerCredential1, data] = await issuerCredentialCreate(); - // const data1 = await issuerCredential1.serialize(); - // const issuerCredential2 = await IssuerCredential.deserialize(data1); - // const data2 = await issuerCredential2.serialize(); - // assert.deepEqual(data1, data2); - // }); - // - // it('throws: incorrect data', async () => { - // const error = await shouldThrow(async () => - // IssuerCredential.deserialize({ source_id: 'Invalid' } as any), - // ); - // assert.equal(error.vcxCode, VCXCode.UNKNOWN_ERROR); - // }); - // - // it('throws: incomplete data', async () => { - // const error = await shouldThrow(async () => - // IssuerCredential.deserialize({ - // version: '2.0', - // data: { - // issuer_sm: { - // state: { - // SomeUnknown: {}, - // }, - // source_id: 'alice_degree', - // }, - // }, - // } as any), - // ); - // assert.equal(error.vcxCode, VCXCode.INVALID_JSON); - // }); - // }); - // - // describe('updateState:', () => { - // it(`returns state offer sent`, async () => { - // const [issuerCredential, data] = await issuerCredentialCreate(); - // await issuerCredential.buildCredentialOfferMsgV2(data) - // assert.equal(await issuerCredential.getState(), IssuerStateType.OfferSet); - // const connection = await createConnectionInviterRequested(); - // await issuerCredential.sendOfferV2(connection); - // assert.equal(await issuerCredential.getState(), IssuerStateType.OfferSent); - // }); - // - // it('build offer and mark as sent', async () => { - // const [issuerCredential, data] = await issuerCredentialCreate(); - // await issuerCredential.buildCredentialOfferMsgV2(data) - // const offer = JSON.parse(await issuerCredential.getCredentialOfferMsg()) - // assert.equal(await issuerCredential.getState(), IssuerStateType.OfferSet); - // // @ts-ignore - // assert.isDefined(offer['@id']); - // assert.equal(offer.comment, 'foo'); - // assert.isDefined(offer.credential_preview); - // assert.equal(offer.credential_preview['@type'], 'https://didcomm.org/issue-credential/1.0/credential-preview'); - // - // await issuerCredential.markCredentialOfferMsgSent(); - // assert.equal(await issuerCredential.getState(), IssuerStateType.OfferSent); - // }); - // - // it('throws: not initialized', async () => { - // const [_issuerCredential, data] = await issuerCredentialCreate(); - // const issuerCredential = new IssuerCredential(''); - // const error = await shouldThrow(() => issuerCredential.buildCredentialOfferMsgV2(data)); - // assert.equal(error.vcxCode, VCXCode.INVALID_OBJ_HANDLE); - // }); - // - // it('throws: connection not initialized', async () => { - // const [issuerCredential, data] = await issuerCredentialCreate(); - // await issuerCredential.buildCredentialOfferMsgV2(data) - // assert.equal(await issuerCredential.getState(), IssuerStateType.OfferSet); - // const connection = new (Connection as any)(); - // const error = await shouldThrow(() => issuerCredential.sendOfferV2(connection)); - // assert.equal(error.vcxCode, VCXCode.INVALID_OBJ_HANDLE); - // }); - // - // it('throws: missing attr', async () => { - // const [issuerCredential, _data] = await issuerCredentialCreate(); - // const { attr, ...data } = _data; - // const error = await shouldThrow(() => issuerCredential.buildCredentialOfferMsgV2(data as any)); - // assert.equal(error.vcxCode, VCXCode.INVALID_OPTION); - // }); - // - // it('throws: invalid credDefHandle', async () => { - // const [issuerCredential, _data] = await issuerCredentialCreate(); - // const { credDef, ...data } = _data; - // const error = await shouldThrow(() => issuerCredential.buildCredentialOfferMsgV2(data as any)); - // assert.equal(error.vcxCode, VCXCode.UNKNOWN_ERROR); - // }); - // }); + describe('deserialize:', () => { + it('success', async () => { + const [issuerCredential1, data] = await issuerCredentialCreate(); + const data1 = await issuerCredential1.serialize(); + const issuerCredential2 = await IssuerCredential.deserialize(data1); + const data2 = await issuerCredential2.serialize(); + assert.deepEqual(data1, data2); + }); - // describe('revoke:', () => { - // it('throws: invalid revocation details', async () => { - // const issuerCredential = await issuerCredentialCreate() - // const error = await shouldThrow(() => issuerCredential.revokeCredential()) - // assert.equal(error.vcxCode, VCXCode.INVALID_REVOCATION_DETAILS) - // }) - // - // it('success', async () => { - // const issuerCredential1 = await issuerCredentialCreate() - // const data = await issuerCredential1[0].serialize() - // data.data.cred_rev_id = '123' - // data.data.rev_reg_id = '456' - // data.data.tails_file = 'file' - // const issuerCredential2 = await IssuerCredential.deserialize(data) - // await issuerCredential2.revokeCredential() - // }) - // }) + it('throws: incorrect data', async () => { + const error = await shouldThrow(async () => + IssuerCredential.deserialize({ source_id: 'Invalid' } as any), + ); + assert.equal(error.napiCode, 'GenericFailure'); + assert.equal(error.vcxCode, VCXCode.INVALID_JSON); + }); + + it('throws: incomplete data', async () => { + const error = await shouldThrow(async () => + IssuerCredential.deserialize({ + version: '2.0', + data: { + issuer_sm: { + state: { + SomeUnknown: {}, + }, + source_id: 'alice_degree', + }, + }, + } as any), + ); + assert.equal(error.napiCode, 'GenericFailure'); + assert.equal(error.vcxCode, VCXCode.INVALID_JSON); + }); + }); + + describe('updateState:', () => { + it(`returns state offer sent`, async () => { + const [issuerCredential, data] = await issuerCredentialCreate(); + await issuerCredential.buildCredentialOfferMsgV2(data); + assert.equal(await issuerCredential.getState(), IssuerStateType.OfferSet); + const connection = await createConnectionInviterRequested(); + await issuerCredential.sendOfferV2(connection); + assert.equal(await issuerCredential.getState(), IssuerStateType.OfferSent); + }); + + it('build offer and mark as sent', async () => { + const [issuerCredential, data] = await issuerCredentialCreate(); + await issuerCredential.buildCredentialOfferMsgV2(data); + const offer = JSON.parse(await issuerCredential.getCredentialOfferMsg()); + assert.equal(await issuerCredential.getState(), IssuerStateType.OfferSet); + assert.isDefined(offer['@id']); + assert.equal(offer.comment, 'foo'); + assert.isDefined(offer.credential_preview); + assert.equal( + offer.credential_preview['@type'], + 'https://didcomm.org/issue-credential/1.0/credential-preview', + ); + + await issuerCredential.markCredentialOfferMsgSent(); + assert.equal(await issuerCredential.getState(), IssuerStateType.OfferSent); + }); + + it('throws: not initialized', async () => { + const [, data] = await issuerCredentialCreate(); + const issuerCredential = new IssuerCredential(''); + const error = await shouldThrow(() => issuerCredential.buildCredentialOfferMsgV2(data)); + assert.equal(error.napiCode, 'NumberExpected'); + }); + + it('throws: connection not initialized', async () => { + const [issuerCredential, data] = await issuerCredentialCreate(); + await issuerCredential.buildCredentialOfferMsgV2(data); + assert.equal(await issuerCredential.getState(), IssuerStateType.OfferSet); + const connection = { handle: 123 } as Connection; + const error = await shouldThrow(() => issuerCredential.sendOfferV2(connection)); + assert.equal(error.napiCode, 'GenericFailure'); + assert.equal(error.vcxCode, VCXCode.INVALID_OBJ_HANDLE); + }); + + // todo: _build_credential_preview should throw if attr is not JSON Array or Object + it.skip('throws: missing attr', async () => { + const [issuerCredential, buildOfferData] = await issuerCredentialCreate(); + buildOfferData.attr = '{{{' as any; + const error = await shouldThrow(() => + issuerCredential.buildCredentialOfferMsgV2(buildOfferData), + ); + assert.equal(error.napiCode, 'GenericFailure'); + assert.equal(error.vcxCode, VCXCode.INVALID_JSON); + }); + + it('throws: invalid credDefHandle', async () => { + const [issuerCredential, buildOfferData] = await issuerCredentialCreate(); + buildOfferData.credDef = {} as any + const error = await shouldThrow(() => + issuerCredential.buildCredentialOfferMsgV2(buildOfferData), + ); + assert.equal(error.napiCode, 'NumberExpected'); + }); + }); }); diff --git a/wrappers/node/test/suite1/ariesvcx-connection.test.ts b/wrappers/node/test/suite1/ariesvcx-mediated-connection.test.ts similarity index 91% rename from wrappers/node/test/suite1/ariesvcx-connection.test.ts rename to wrappers/node/test/suite1/ariesvcx-mediated-connection.test.ts index e2f2f8242a..c81a248224 100644 --- a/wrappers/node/test/suite1/ariesvcx-connection.test.ts +++ b/wrappers/node/test/suite1/ariesvcx-mediated-connection.test.ts @@ -95,22 +95,6 @@ describe('Connection:', () => { assert.ok(source_id); assert.equal(source_id, connection.sourceId); }); - - // TODO: restore for aries - it.skip('throws: not initialized', async () => { - const connection = new (Connection as any)(); - const error = await shouldThrow(() => connection.serialize()); - assert.equal(error.vcxCode, VCXCode.INVALID_CONNECTION_HANDLE); - }); - - // TODO: Is this op supported in 3.0? - it.skip('throws: connection deleted', async () => { - const connection = await connectionCreateInviterNull(); - await connection.connect(); - connection.delete(); - const error = await shouldThrow(() => connection.serialize()); - assert.equal(error.vcxCode, VCXCode.INVALID_CONNECTION_HANDLE); - }); }); describe('deserialize:', () => {