diff --git a/src/Agent.ts b/src/Agent.ts index 852b048..bcde484 100644 --- a/src/Agent.ts +++ b/src/Agent.ts @@ -12,7 +12,9 @@ export type ConnectionRef = {connection_id: string} export type Invitation = {invitation_url: string} & ConnectionRef export type CredentialOfferRef = {id: string} & ConnectionRef -export type AcceptProofArgs = {id: string} +export type HasId = {id: string} +export type HadConnectionId = {connection_id: string} +export type AcceptProofArgs = HasId | HadConnectionId export type ReceiveInvitationResponse = { outOfBandRecord?: OutOfBandRecord; connectionRecord?: ConnectionRef, invitationRequestsThreadIds?: string[] } export interface AriesAgent { readonly logger: Logger diff --git a/src/AgentCredo.ts b/src/AgentCredo.ts index 950272c..41cff2c 100644 --- a/src/AgentCredo.ts +++ b/src/AgentCredo.ts @@ -46,6 +46,7 @@ import { CredentialDefinitionBuilder, ProofRequestBuilder, SchemaBuilder, + waitFor, } from "./lib"; import { IndyVdrPoolConfig } from "@credo-ts/indy-vdr"; import { OutOfBandRecord } from "@credo-ts/core"; @@ -179,10 +180,6 @@ export const createAgent = async ( return agent; }; -function delay(ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - export class AgentCredo implements AriesAgent { config: any; ledgers: any[]; @@ -240,24 +237,28 @@ export class AgentCredo implements AriesAgent { await this.agent.credentials.acceptOffer({ credentialRecordId: offer.id }); } async acceptProof(proof: AcceptProofArgs): Promise { - while (true) { - const proofs = await this.agent.proofs.getAll(); - //console.log(`Proofs ${proofs.length}`) - for (let index = 0; index < proofs.length; index++) { - const p = proofs[index]; - console.log( - `[${index + 1}/${proofs.length}] - id:${p.id}, threadId:${ - p.threadId - }, arg:${proof.id}` - ); - console.dir(p.toJSON()); - if (p.threadId === proof.id) { - await this.agent.proofs.acceptRequest({ proofRecordId: p.id }); - return; + + while (true) { + const proofs = await this.agent.proofs.getAll(); + //console.log(`Proofs ${proofs.length}`) + for (let index = 0; index < proofs.length; index++) { + const p = proofs[index]; + //console.dir(p.toJSON()); + if ("id" in proof) { + //console.log(`[${index + 1}/${proofs.length}] - id:${p.id}, threadId:${p.threadId}, arg:${proof.id}`); + if (p.threadId === proof.id) { + await this.agent.proofs.acceptRequest({ proofRecordId: p.id }); + return; + } + } else if ("connection_id" in proof) { + if (p.connectionId === proof.connection_id){ + await this.agent.proofs.acceptRequest({ proofRecordId: p.id }); + return; + } + } } + waitFor(1000); } - delay(1000); - } } async findCredentialOffer(connectionId: string): Promise { let cred!: CredentialExchangeRecord; diff --git a/src/__snapshots__/basic.test.ts.snap b/src/__snapshots__/basic.test.ts.snap index 5875a99..57ce55c 100644 --- a/src/__snapshots__/basic.test.ts.snap +++ b/src/__snapshots__/basic.test.ts.snap @@ -1,5 +1,274 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Mandatory OOB/connectionless/present-proof-1.0/url-redirect 1`] = ` +[ + { + "baseUrl": "--redacted--", + "data": { + "auto_remove": false, + "auto_verify": true, + "comment": "string", + "proof_request": "{--redacted--}", + "trace": false, + }, + "headers": { + "Accept": "application/json, text/plain, */*", + "Authorization": "--redacted--", + "Content-Type": "application/json", + }, + "method": "post", + "params": {}, + "url": "/present-proof/create-request", + }, + { + "baseUrl": "--redacted--", + "data": { + "attachments": [ + { + "data": { + "json": { + "auto_present": false, + "auto_remove": false, + "auto_verify": true, + "created_at": "--redacted--", + "initiator": "self", + "presentation_exchange_id": "--redacted--", + "presentation_request": "{--redacted--}", + "presentation_request_dict": "{--redacted--}", + "role": "verifier", + "state": "request_sent", + "thread_id": "--redacted--", + "trace": false, + "updated_at": "--redacted--", + }, + }, + "id": "--redacted--", + "type": "present-proof", + }, + ], + "label": "vc-authn-oidc", + "use_public_did": false, + }, + "headers": { + "Accept": "application/json, text/plain, */*", + "Authorization": "--redacted--", + "Content-Type": "application/json", + }, + "method": "post", + "params": {}, + "url": "/out-of-band/create-invitation", + }, + { + "baseUrl": "--redacted--", + "headers": { + "Accept": "application/json, text/plain, */*", + "Authorization": "--redacted--", + "Content-Type": "application/json", + }, + "method": "get", + "url": "/present-proof/records/{record_id}", + }, +] +`; + +exports[`Mandatory OOB/connectionless/present-proof-2.0/encoded-payload 1`] = ` +[ + { + "baseUrl": "--redacted--", + "data": { + "auto_remove": false, + "auto_verify": true, + "comment": "string", + "presentation_request": "{--redacted--}", + "trace": false, + }, + "headers": { + "Accept": "application/json, text/plain, */*", + "Authorization": "--redacted--", + "Content-Type": "application/json", + }, + "method": "post", + "params": {}, + "url": "/present-proof-2.0/create-request", + }, + { + "baseUrl": "--redacted--", + "data": { + "attachments": [ + { + "data": { + "json": { + "auto_present": false, + "auto_remove": false, + "auto_verify": true, + "by_format": { + "pres_request": { + "indy": { + "name": "proof-request", + "nonce": "--redacted--", + "requested_attributes": { + "studentInfo": { + "names": [ + "given_names", + "family_name", + ], + "non_revoked": { + "from": "--redacted--", + "to": "--redacted--", + }, + "restrictions": [ + { + "issuer_did": "--redacted--", + "schema_name": "Person", + "schema_version": "1.1", + }, + ], + }, + }, + "requested_predicates": {}, + "version": "1.0", + }, + }, + }, + "created_at": "--redacted--", + "initiator": "self", + "pres_ex_id": "--redacted--", + "pres_request": "{--redacted--}", + "role": "verifier", + "state": "request-sent", + "thread_id": "--redacted--", + "trace": false, + "updated_at": "--redacted--", + }, + }, + "id": "--redacted--", + "type": "present-proof", + }, + ], + "label": "vc-authn-oidc", + "use_public_did": false, + }, + "headers": { + "Accept": "application/json, text/plain, */*", + "Authorization": "--redacted--", + "Content-Type": "application/json", + }, + "method": "post", + "params": {}, + "url": "/out-of-band/create-invitation", + }, + { + "baseUrl": "--redacted--", + "headers": { + "Accept": "application/json, text/plain, */*", + "Authorization": "--redacted--", + "Content-Type": "application/json", + }, + "method": "get", + "url": "/present-proof-2.0/records/{record_id}", + }, +] +`; + +exports[`Mandatory OOB/connectionless/present-proof-2.0/url-redirect 1`] = ` +[ + { + "baseUrl": "--redacted--", + "data": { + "auto_remove": false, + "auto_verify": true, + "comment": "string", + "presentation_request": "{--redacted--}", + "trace": false, + }, + "headers": { + "Accept": "application/json, text/plain, */*", + "Authorization": "--redacted--", + "Content-Type": "application/json", + }, + "method": "post", + "params": {}, + "url": "/present-proof-2.0/create-request", + }, + { + "baseUrl": "--redacted--", + "data": { + "attachments": [ + { + "data": { + "json": { + "auto_present": false, + "auto_remove": false, + "auto_verify": true, + "by_format": { + "pres_request": { + "indy": { + "name": "proof-request", + "nonce": "--redacted--", + "requested_attributes": { + "studentInfo": { + "names": [ + "given_names", + "family_name", + ], + "non_revoked": { + "from": "--redacted--", + "to": "--redacted--", + }, + "restrictions": [ + { + "issuer_did": "--redacted--", + "schema_name": "Person", + "schema_version": "1.1", + }, + ], + }, + }, + "requested_predicates": {}, + "version": "1.0", + }, + }, + }, + "created_at": "--redacted--", + "initiator": "self", + "pres_ex_id": "--redacted--", + "pres_request": "{--redacted--}", + "role": "verifier", + "state": "request-sent", + "thread_id": "--redacted--", + "trace": false, + "updated_at": "--redacted--", + }, + }, + "id": "--redacted--", + "type": "present-proof", + }, + ], + "label": "vc-authn-oidc", + "use_public_did": false, + }, + "headers": { + "Accept": "application/json, text/plain, */*", + "Authorization": "--redacted--", + "Content-Type": "application/json", + }, + "method": "post", + "params": {}, + "url": "/out-of-band/create-invitation", + }, + { + "baseUrl": "--redacted--", + "headers": { + "Accept": "application/json, text/plain, */*", + "Authorization": "--redacted--", + "Content-Type": "application/json", + }, + "method": "get", + "url": "/present-proof-2.0/records/{record_id}", + }, +] +`; + exports[`Mandatory connected/present-proof-1.0/encoded-payload 1`] = ` [ { @@ -148,7 +417,7 @@ exports[`Mandatory connectionless/present-proof-1.0/encoded-payload 1`] = ` "auto_remove": false, "auto_verify": true, "comment": "string", - "proof_request": "--redacted--", + "proof_request": "{--redacted--}", "trace": false, }, "headers": { @@ -192,7 +461,7 @@ exports[`Mandatory connectionless/present-proof-1.0/url-redirect 1`] = ` "auto_remove": false, "auto_verify": true, "comment": "string", - "proof_request": "--redacted--", + "proof_request": "{--redacted--}", "trace": false, }, "headers": { @@ -236,7 +505,51 @@ exports[`Mandatory connectionless/present-proof-2.0/encoded-payload 1`] = ` "auto_remove": false, "auto_verify": true, "comment": "string", - "presentation_request": "--redacted--", + "presentation_request": "{--redacted--}", + "trace": false, + }, + "headers": { + "Accept": "application/json, text/plain, */*", + "Authorization": "--redacted--", + "Content-Type": "application/json", + }, + "method": "post", + "params": {}, + "url": "/present-proof-2.0/create-request", + }, + { + "baseUrl": "--redacted--", + "headers": { + "Accept": "application/json, text/plain, */*", + "Authorization": "--redacted--", + "Content-Type": "application/json", + }, + "method": "get", + "url": "/present-proof-2.0/records/{record_id}", + }, +] +`; + +exports[`Mandatory connectionless/present-proof-2.0/url-redirect 1`] = ` +[ + { + "baseUrl": "--redacted--", + "headers": { + "Accept": "application/json, text/plain, */*", + "Authorization": "--redacted--", + "Content-Type": "application/json", + }, + "method": "get", + "params": {}, + "url": "/wallet/did/public", + }, + { + "baseUrl": "--redacted--", + "data": { + "auto_remove": false, + "auto_verify": true, + "comment": "string", + "presentation_request": "{--redacted--}", "trace": false, }, "headers": { @@ -431,7 +744,7 @@ exports[`Mandatory setup 1`] = ` "auto_remove": false, "connection_id": "{connection_id}", "cred_def_id": "{cred_def_id}", - "credential_preview": "--redacted--", + "credential_preview": "{--redacted--}", "trace": true, }, "headers": { diff --git a/src/basic.test.ts b/src/basic.test.ts index 74d7110..aab418e 100644 --- a/src/basic.test.ts +++ b/src/basic.test.ts @@ -92,15 +92,79 @@ describe("Mandatory", () => { req.data.cred_def_id = '{cred_def_id}' } if (req.method === 'post' && req.url === '/issue-credential/send-offer' && req.data) { - req.data.credential_preview = '--redacted--' + req.data.credential_preview = '{--redacted--}' req.data.cred_def_id = '{cred_def_id}' req.data.connection_id = '{connection_id}' } if (req.method === 'post' && req.url === '/present-proof/create-request' && req.data) { - req.data.proof_request = '--redacted--' + req.data.proof_request = '{--redacted--}' + } + if (req.method === 'post' && req.url === '/out-of-band/create-invitation' && req.data?.attachments) { + //req.data.attachments = '--redacted--' + for (const attachment of req.data.attachments) { + if (attachment?.id){ + attachment.id = '--redacted--' + } + if (attachment.data?.json){ + if (attachment?.data?.id){ + attachment.data.id = '--redacted--' + } + if (attachment?.data?.json?.id){ + attachment.data.json.id = '--redacted--' + } + if (attachment.data?.json?.thread_id) { + attachment.data.json.thread_id = '--redacted--' + } + if (attachment.data?.json?.created_at){ + attachment.data.json.created_at = '--redacted--' + } + if (attachment.data?.json?.updated_at){ + attachment.data.json.updated_at = '--redacted--' + } + if (attachment.data?.json?.presentation_exchange_id) { + attachment.data.json.presentation_exchange_id = '--redacted--' + } + if (attachment.data?.json?.pres_ex_id) { + attachment.data.json.pres_ex_id = '--redacted--' + } + if (attachment.data?.json?.presentation_request) { + attachment.data.json.presentation_request = '{--redacted--}' + } + if (attachment.data?.json?.presentation_request_dict) { + attachment.data.json.presentation_request_dict = '{--redacted--}' + } + if (attachment.data?.json?.by_format?.pres_request?.indy) { + attachment.data.json.by_format.pres_request.indy.nonce = '--redacted--' + const requested_attributes = attachment.data?.json?.by_format.pres_request?.indy?.requested_attributes + if (requested_attributes){ + for (const key in requested_attributes) { + if (Object.prototype.hasOwnProperty.call(requested_attributes, key)) { + const item = requested_attributes[key]; + if (item.non_revoked?.from) { + item.non_revoked.from = '--redacted--' + } + if (item.non_revoked?.to) { + item.non_revoked.to = '--redacted--' + } + if (item.restrictions) { + for (const restriction of item.restrictions) { + if (restriction.issuer_did) { + restriction.issuer_did = '--redacted--' + } + } + } + } + } + } + } + if (attachment.data?.json?.pres_request) { + attachment.data.json.pres_request = '{--redacted--}' + } + } + } } if (req.method === 'post' && req.url === '/present-proof-2.0/create-request' && req.data) { - req.data.presentation_request = '--redacted--' + req.data.presentation_request = '{--redacted--}' } if (req.method === 'post' && req.url === '/connections/{connection_id}' && req.data?.my_label) { const regex = /(- \d+$)/mg; @@ -201,6 +265,7 @@ describe("Mandatory", () => { .setNonRevoked(seconds_since_epoch(new Date())) ) const proofRequestSent = await verifier.sendProofRequestV1(remoteInvitation.payload.connection_id as string, proofRequest) + holder.acceptProof({connection_id:agentBConnectionRef1.connectionRecord?.connection_id as string}) await verifier.waitForPresentation(proofRequestSent.presentation_exchange_id) expect(requests).toMatchSnapshot(); }, shortTimeout); @@ -277,6 +342,7 @@ describe("Mandatory", () => { } } await verifier.waitForPresentationV2(remoteInvitation2.payload.presentation_exchange_id as string) + expect(requests).toMatchSnapshot(); }, shortTimeout); test("OOB/connectionless/present-proof-1.0/encoded-payload", async () => { logger.info(`Executing ${expect.getState().currentTestName}`) @@ -301,6 +367,7 @@ describe("Mandatory", () => { .setNonRevoked(seconds_since_epoch(new Date())) ) await verifyCredentialB2(agentA, agentB, proofRequest) + expect(requests).toMatchSnapshot(); }, shortTimeout); test("OOB/connectionless/present-proof-2.0/encoded-payload", async () => { const verifier = agentA @@ -329,6 +396,7 @@ describe("Mandatory", () => { } logger.info(`Verifier is waiting for proofs: ${remoteInvitation3.payload.presentation_exchange_id}`) await verifier.waitForPresentationV2(remoteInvitation3.payload.presentation_exchange_id as string) + expect(requests).toMatchSnapshot(); }, shortTimeout); test("OOB/connectionless/present-proof-2.0/url-redirect", async () => { const verifier = agentA @@ -357,5 +425,6 @@ describe("Mandatory", () => { } logger.info(`Verifier is waiting for proofs: ${remoteInvitation3.payload.presentation_exchange_id}`) await verifier.waitForPresentationV2(remoteInvitation3.payload.presentation_exchange_id as string) + expect(requests).toMatchSnapshot(); }, shortTimeout); }); diff --git a/src/lib.ts b/src/lib.ts index 6bdf3e9..adcfc81 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -65,6 +65,7 @@ const sanitize = (obj: any) => { export const waitFor = (ms:number) => { return new Promise ((resolve) => {setTimeout(() => {resolve(true)}, ms);}) } + function _randomString(length: number) { // Declare all characters const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; @@ -854,7 +855,7 @@ export const verifyCredentialA1 = async (verifier:AriesAgent, holder: AriesAgent //await holder.acceptProof({id: proofId}) } log(chalk.yellowBright(`> getting ready to send proof in 10s`)) - await waitFor(10_000) + //await waitFor(10_000) await holder.acceptProof({id: proofId}) } }