diff --git a/examples/integration-scripts/credentials.test.ts b/examples/integration-scripts/credentials.test.ts index 65b521c1..61f9a124 100644 --- a/examples/integration-scripts/credentials.test.ts +++ b/examples/integration-scripts/credentials.test.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import signify from 'signify-ts'; +import { Saider, Serder, SignifyClient } from 'signify-ts'; import { resolveEnvironment } from './utils/resolve-env'; import { resolveOobi, @@ -7,331 +7,444 @@ import { waitOperation, } from './utils/test-util'; import { retry } from './utils/retry'; -const { url, bootUrl, vleiServerUrl, witnessIds } = resolveEnvironment(); - -const boot_url = bootUrl; -const WAN_WITNESS_AID = witnessIds[0]; -const WIL_WITNESS_AID = witnessIds[1]; -const WES_WITNESS_AID = witnessIds[2]; +import { + getOrCreateClients, + getOrCreateContact, + getOrCreateIdentifier, +} from './utils/test-setup'; +import { randomUUID } from 'crypto'; +import { step } from './utils/test-step'; -const KLI_WITNESS_DEMO_PREFIXES = [ - WAN_WITNESS_AID, - WIL_WITNESS_AID, - WES_WITNESS_AID, -]; +const { vleiServerUrl } = resolveEnvironment(); -// Credential Schema discovery through credential schema OOBI resolution -const qviSchemaSAID = 'EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao'; +const QVI_SCHEMA_SAID = 'EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao'; +const LE_SCHEMA_SAID = 'ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY'; const vLEIServerHostUrl = `${vleiServerUrl}/oobi`; -const schemaOobiUrl = `${vLEIServerHostUrl}/${qviSchemaSAID}`; - -// Boots an agent and connects to it, returning the connected SignifyClient -async function bootAndConnect( - bran: string = signify.randomPasscode(), - agentUrl: string = url, - bootUrl: string = boot_url, - tier: signify.Tier = signify.Tier.low -) { - const client = new signify.SignifyClient(agentUrl, bran, tier, bootUrl); - await client.boot(); - await client.connect(); - return client; +const QVI_SCHEMA_URL = `${vLEIServerHostUrl}/${QVI_SCHEMA_SAID}`; +const LE_SCHEMA_URL = `${vLEIServerHostUrl}/${LE_SCHEMA_SAID}`; + +interface Aid { + name: string; + prefix: string; + oobi: string; } -// utility function for making a correctly formatted timestamp function createTimestamp() { return new Date().toISOString().replace('Z', '000+00:00'); } -test('credentials', async () => { - await signify.ready(); - // Boot three clients one each for issuer, holder, and verifier - const issuerClient = await bootAndConnect(signify.randomPasscode()); - const holderClient = await bootAndConnect(signify.randomPasscode()); - const verifierClient = await bootAndConnect(signify.randomPasscode()); - - const state1 = await issuerClient.state(); - const state2 = await holderClient.state(); - const state3 = await verifierClient.state(); - console.log( - 'Issuer connected.\n\tHolder Controller AID:', - state1.controller.state.i, - '\n\tIssuer Agent AID: ', - state1.agent.i - ); - console.log( - 'Holder connected.\n\tHolder Controller AID:', - state2.controller.state.i, - '\n\tHolder Agent AID: ', - state2.agent.i - ); - console.log( - 'Verifier connected.\n\tVerifier Controller AID:', - state3.controller.state.i, - '\n\tVerifier Agent AID: ', - state3.agent.i - ); +async function createAid(client: SignifyClient, name: string): Promise { + const [prefix, oobi] = await getOrCreateIdentifier(client, name); + return { prefix, oobi, name }; +} + +let issuerClient: SignifyClient; +let holderClient: SignifyClient; +let verifierClient: SignifyClient; +let legalEntityClient: SignifyClient; + +let issuerAid: Aid; +let holderAid: Aid; +let verifierAid: Aid; +let legalEntityAid: Aid; + +beforeAll(async () => { + [issuerClient, holderClient, verifierClient, legalEntityClient] = + await getOrCreateClients(4); +}); + +beforeAll(async () => { + [issuerAid, holderAid, verifierAid, legalEntityAid] = await Promise.all([ + createAid(issuerClient, 'issuer'), + createAid(holderClient, 'holder'), + createAid(verifierClient, 'verifier'), + createAid(legalEntityClient, 'legal-entity'), + ]); +}); + +beforeAll(async () => { + await Promise.all([ + getOrCreateContact(issuerClient, 'holder', holderAid.oobi), + getOrCreateContact(issuerClient, 'verifier', verifierAid.oobi), + getOrCreateContact(holderClient, 'issuer', issuerAid.oobi), + getOrCreateContact(holderClient, 'verifier', verifierAid.oobi), + getOrCreateContact(holderClient, 'legal-entity', legalEntityAid.oobi), + getOrCreateContact(verifierClient, 'issuer', issuerAid.oobi), + getOrCreateContact(verifierClient, 'holder', holderAid.oobi), + getOrCreateContact(legalEntityClient, 'holder', holderAid.oobi), + ]); +}); + +test('single signature credentials', async () => { + await step('Resolve schema oobis', async () => { + await Promise.all([ + resolveOobi(issuerClient, QVI_SCHEMA_URL), + resolveOobi(issuerClient, LE_SCHEMA_URL), + resolveOobi(holderClient, QVI_SCHEMA_URL), + resolveOobi(holderClient, LE_SCHEMA_URL), + resolveOobi(verifierClient, QVI_SCHEMA_URL), + resolveOobi(verifierClient, LE_SCHEMA_URL), + resolveOobi(legalEntityClient, QVI_SCHEMA_URL), + resolveOobi(legalEntityClient, LE_SCHEMA_URL), + ]); + }); + + const registry = await step('Create registry', async () => { + const registryName = 'vLEI-test-registry'; + const regResult = await issuerClient + .registries() + .create({ name: issuerAid.name, registryName: registryName }); + + await waitOperation(issuerClient, await regResult.op()); + const registries = await issuerClient.registries().list(issuerAid.name); + const registry: { name: string; regk: string } = registries[0]; + assert.equal(registries.length, 1); + assert.equal(registry.name, registryName); + return registry; + }); + + await step('issuer can get schemas', async () => { + const issuerQviSchema = await issuerClient + .schemas() + .get(QVI_SCHEMA_SAID); - const issuerAidName = 'issuer'; - const holderAidName = 'holder'; - const verifierAidName = 'verifier'; + assert.equal(issuerQviSchema.$id, QVI_SCHEMA_SAID); - // Create two identifiers, one for each client - const issuerIcpRes = await issuerClient - .identifiers() - .create(issuerAidName, { - toad: 3, - wits: [...KLI_WITNESS_DEMO_PREFIXES], + const issuerLeSchema = await issuerClient.schemas().get(LE_SCHEMA_SAID); + + assert.equal(issuerLeSchema.$id, LE_SCHEMA_SAID); + }); + + await step('holder can list schemas', async () => { + const holderSchemas = await holderClient.schemas().list(); + assert.equal(holderSchemas.length, 2); + }); + + const qviCredentialId = await step('create QVI credential', async () => { + const vcdata = { + LEI: '5493001KJTIIGC8Y1R17', + }; + + const issResult = await issuerClient.credentials().issue({ + issuerName: issuerAid.name, + registryId: registry.regk, + schemaId: QVI_SCHEMA_SAID, + recipient: holderAid.prefix, + data: vcdata, }); - await waitOperation(issuerClient, await issuerIcpRes.op()); - const issAidResp = await issuerClient.identifiers().get(issuerAidName); - const issuerAID = issAidResp.prefix; - await issuerClient - .identifiers() - .addEndRole(issuerAidName, 'agent', issuerClient!.agent!.pre); - console.log("Issuer's AID:", issuerAID); - - const holderIcpRes = await holderClient - .identifiers() - .create(holderAidName, { - toad: 3, - wits: [...KLI_WITNESS_DEMO_PREFIXES], + + await waitOperation(issuerClient, issResult.op); + return issResult.acdc.ked.d as string; + }); + + await step('issuer list credentials', async () => { + const issuerCredentials = await issuerClient.credentials().list(); + assert(issuerCredentials.length >= 1); + assert.equal(issuerCredentials[0].sad.s, QVI_SCHEMA_SAID); + assert.equal(issuerCredentials[0].sad.i, issuerAid.prefix); + assert.equal(issuerCredentials[0].status.s, '0'); + }); + + await step('issuer list credentials with filter', async () => { + expect( + await issuerClient + .credentials() + .list({ filter: { '-i': issuerAid.prefix } }) + ).toHaveLength(1); + + expect( + await issuerClient + .credentials() + .list({ filter: { '-s': QVI_SCHEMA_SAID } }) + ).toHaveLength(1); + + expect( + await issuerClient + .credentials() + .list({ filter: { '-a-i': holderAid.prefix } }) + ).toHaveLength(1); + + expect( + await issuerClient.credentials().list({ + filter: { + '-i': issuerAid.prefix, + '-s': QVI_SCHEMA_SAID, + '-a-i': holderAid.prefix, + }, + }) + ).toHaveLength(1); + + expect( + await issuerClient.credentials().list({ + filter: { + '-i': randomUUID(), + '-s': QVI_SCHEMA_SAID, + '-a-i': holderAid.prefix, + }, + }) + ).toHaveLength(0); + }); + + await step('issuer get credential by id', async () => { + const issuerCredential = await issuerClient + .credentials() + .get(issuerAid.name, qviCredentialId); + assert.equal(issuerCredential.sad.s, QVI_SCHEMA_SAID); + assert.equal(issuerCredential.sad.i, issuerAid.prefix); + assert.equal(issuerCredential.status.s, '0'); + }); + + await step('issuer IPEX grant', async () => { + const dt = createTimestamp(); + const issuerCredential = await issuerClient + .credentials() + .get(issuerAid.name, qviCredentialId); + assert(issuerCredential !== undefined); + + const [grant, gsigs, gend] = await issuerClient.ipex().grant({ + senderName: issuerAid.name, + acdc: new Serder(issuerCredential.sad), + anc: new Serder(issuerCredential.anc), + iss: new Serder(issuerCredential.iss), + ancAttachment: issuerCredential.ancAttachment, + recipient: holderAid.prefix, + datetime: dt, + }); + + await issuerClient + .ipex() + .submitGrant(issuerAid.name, grant, gsigs, gend, [ + holderAid.prefix, + ]); + }); + + await step('holder IPEX admit', async () => { + const holderNotifications = await waitForNotifications( + holderClient, + '/exn/ipex/grant' + ); + const grantNotification = holderNotifications[0]; // should only have one notification right now + + const [admit, sigs, aend] = await holderClient + .ipex() + .admit( + holderAid.name, + '', + grantNotification.a.d!, + createTimestamp() + ); + await holderClient + .ipex() + .submitAdmit(holderAid.name, admit, sigs, aend, [issuerAid.prefix]); + + await holderClient.notifications().mark(grantNotification.i); + }); + + await step('holder has credential', async () => { + const holderCredential = await retry(async () => { + const result = await holderClient + .credentials() + .get(holderAid.name, qviCredentialId); + assert(result !== undefined); + return result; }); - await waitOperation(holderClient, await holderIcpRes.op()); - const hldAidResp = await holderClient.identifiers().get(holderAidName); - const holderAID = hldAidResp.prefix; - await holderClient - .identifiers() - .addEndRole(holderAidName, 'agent', holderClient!.agent!.pre); - console.log("Recipient's AID:", holderAID); - - const verifierIcpRes = await verifierClient - .identifiers() - .create(verifierAidName, { - toad: 3, - wits: [...KLI_WITNESS_DEMO_PREFIXES], + assert.equal(holderCredential.sad.s, QVI_SCHEMA_SAID); + assert.equal(holderCredential.sad.i, issuerAid.prefix); + assert.equal(holderCredential.status.s, '0'); + assert(holderCredential.atc !== undefined); + }); + + await step('holder IPEX present', async () => { + const holderCredential = await holderClient + .credentials() + .get(holderAid.name, qviCredentialId); + + const [grant2, gsigs2, gend2] = await holderClient.ipex().grant({ + senderName: holderAid.name, + recipient: verifierAid.prefix, + acdc: new Serder(holderCredential.sad), + anc: new Serder(holderCredential.anc), + iss: new Serder(holderCredential.iss), + acdcAttachment: holderCredential.atc, + ancAttachment: holderCredential.ancatc, + issAttachment: holderCredential.issAtc, + datetime: createTimestamp(), }); - await waitOperation(verifierClient, await verifierIcpRes.op()); - const vfyAidResp = await verifierClient.identifiers().get(verifierAidName); - const verifierAID = vfyAidResp.prefix; - await verifierClient - .identifiers() - .addEndRole(verifierAidName, 'agent', verifierClient!.agent!.pre); - console.log("Verifier's AID:", verifierAID); - - const schemaSAID = 'EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao'; - - // OOBIs for credential schema and agent discovery - console.log('Resolving Schema and Agent OOBIs...'); - - console.log(`Resolving schema OOBIs with ${schemaOobiUrl}`); - await resolveOobi(issuerClient, schemaOobiUrl, 'schema'); - await resolveOobi(holderClient, schemaOobiUrl, 'schema'); - await resolveOobi(verifierClient, schemaOobiUrl, 'schema'); - - const issSchema = await issuerClient.schemas().get(schemaSAID); - assert.equal(issSchema.$id, schemaSAID); - const hldSchemas = await holderClient.schemas().list(); - assert.equal(hldSchemas.length, 1); - assert.equal(hldSchemas[0].$id, schemaSAID); - console.log('Resolved QVI Schema OOBI for issuer, holder, and verifier'); - - // Agent discovery through OOBI exchange between issuer, holder, and verifier - console.log('Getting Agent OOBIs for issuer, holder, and verifier'); - const issAgentOOBI = await issuerClient.oobis().get(issuerAidName, 'agent'); - const hldAgentOOBI = await holderClient.oobis().get(holderAidName, 'agent'); - const vfyAgentOOBI = await verifierClient - .oobis() - .get(verifierAidName, 'agent'); - - // issuer -> holder, verifier - await resolveOobi(issuerClient, hldAgentOOBI.oobis[0], holderAidName); - await resolveOobi(issuerClient, vfyAgentOOBI.oobis[0], verifierAidName); - console.log('Issuer resolved 2 OOBIs: [holder, verifier]'); - - // holder -> issuer, verifier - await resolveOobi(holderClient, issAgentOOBI.oobis[0], issuerAidName); - await resolveOobi(holderClient, vfyAgentOOBI.oobis[0], verifierAidName); - console.log('Holder resolved 2 OOBIs: [issuer, verifier]'); - - // verifier -> issuer, holder - await resolveOobi(verifierClient, issAgentOOBI.oobis[0], issuerAidName); - await resolveOobi(verifierClient, hldAgentOOBI.oobis[0], holderAidName); - console.log('Verifier resolved 2 OOBIs: [issuer, holder]'); - - // Create registry for issuer - const registryName = 'vLEI-test-registry'; - const regResult = await issuerClient - .registries() - .create({ name: issuerAidName, registryName: registryName }); - await waitOperation(issuerClient, await regResult.op()); - const registries = await issuerClient.registries().list(issuerAidName); - const registry = registries[0]; - assert.equal(registries.length, 1); - assert.equal(registry.name, registryName); - console.log(`Registry created: ${registry.name}`); - - // - // IPEX - // - - // Issue credential from the issuer's perspective - create credential, - // then perform IPEX grant as EXN message - const vcdata = { - LEI: '5493001KJTIIGC8Y1R17', - }; - const issResult = await issuerClient.credentials().issue({ - issuerName: issuerAidName, - registryId: registry.regk, - schemaId: schemaSAID, - recipient: holderAID, - data: vcdata, + await holderClient + .exchanges() + .sendFromEvents( + holderAid.name, + 'presentation', + grant2, + gsigs2, + gend2, + [verifierAid.prefix] + ); }); - await waitOperation(issuerClient, issResult.op); - let issCreds = await issuerClient.credentials().list(); - assert.equal(issCreds.length, 1); - assert.equal(issCreds[0].sad.s, schemaSAID); - assert.equal(issCreds[0].sad.i, issuerAID); - assert.equal(issCreds[0].status.s, '0'); // 0 = issued - console.log( - `Issuer: credential created with data: ${JSON.stringify(vcdata)}` - ); - // prepare IPEX GRANT message - const dt = createTimestamp(); // grant datetime - const [grant, gsigs, gend] = await issuerClient.ipex().grant({ - senderName: issuerAidName, - acdc: issResult.acdc, - anc: issResult.anc, - iss: issResult.iss, - recipient: holderAID, - datetime: dt, + await step('verifier receives IPEX grant', async () => { + const verifierNotifications = await waitForNotifications( + verifierClient, + '/exn/ipex/grant' + ); + + const verifierGrantNote = verifierNotifications[0]; + + const [admit3, sigs3, aend3] = await verifierClient + .ipex() + .admit( + verifierAid.name, + '', + verifierGrantNote.a.d!, + createTimestamp() + ); + + await verifierClient + .ipex() + .submitAdmit(verifierAid.name, admit3, sigs3, aend3, [ + holderAid.prefix, + ]); + + await verifierClient.notifications().mark(verifierGrantNote.i); + + const verifierCredential = await retry(async () => + verifierClient.credentials().get(verifierAid.name, qviCredentialId) + ); + + assert.equal(verifierCredential.sad.s, QVI_SCHEMA_SAID); + assert.equal(verifierCredential.sad.i, issuerAid.prefix); + assert.equal(verifierCredential.status.s, '0'); // 0 = issued }); - await issuerClient - .exchanges() - .sendFromEvents(issuerAidName, 'credential', grant, gsigs, gend, [ - holderAID, - ]); - console.log('Issuer: IPEX GRANT sent to holder'); - // from the holder's perspective - wait for GRANT notification, - // perform admit, then mark GRANT notification as read - const holderNotifications = await waitForNotifications( - holderClient, - '/exn/ipex/grant' + const holderRegistry: { regk: string } = await step( + 'holder create registry for LE credential', + async () => { + const registryName = 'vLEI-test-registry'; + const regResult = await holderClient + .registries() + .create({ name: holderAid.name, registryName: registryName }); + + await waitOperation(holderClient, await regResult.op()); + const registries = await holderClient + .registries() + .list(holderAid.name); + assert(registries.length >= 1); + return registries[0]; + } ); - const grantNotification = holderNotifications[0]; // should only have one notification right now - - // Note: Credentials are no longer automatically accepted into a wallet. - // Pending an implementation in KERIA there will be the ability to - // auto-add credentials by automatically admitting credentials. - const [admit, sigs, aend] = await holderClient - .ipex() - .admit(holderAidName, '', grantNotification.a.d!, createTimestamp()); - await holderClient - .ipex() - .submitAdmit(holderAidName, admit, sigs, aend, [issuerAID]); - console.log('Holder: IPEX ADMIT sent'); - - await holderClient.notifications().mark(grantNotification.i); - console.log('Holder: IPEX GRANT notification marked'); - - // list credentials to show new credential received through IPEX GRANT+ADMIT - const holderCreds = await retry(async () => { - const result = await holderClient.credentials().list(); - expect(result.length).toBeGreaterThanOrEqual(1); - return result; + + const leCredentialId = await step( + 'holder create LE (chained) credential', + async () => { + const qviCredential = await holderClient + .credentials() + .get(holderAid.name, qviCredentialId); + + const result = await holderClient.credentials().issue({ + issuerName: holderAid.name, + recipient: legalEntityAid.prefix, + registryId: holderRegistry.regk, + schemaId: LE_SCHEMA_SAID, + data: { + LEI: '5493001KJTIIGC8Y1R17', + }, + rules: Saider.saidify({ + d: '', + usageDisclaimer: { + l: 'Usage of a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, does not assert that the Legal Entity is trustworthy, honest, reputable in its business dealings, safe to do business with, or compliant with any laws or that an implied or expressly intended purpose will be fulfilled.', + }, + issuanceDisclaimer: { + l: 'All information in a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, is accurate as of the date the validation process was complete. The vLEI Credential has been issued to the legal entity or person named in the vLEI Credential as the subject; and the qualified vLEI Issuer exercised reasonable care to perform the validation process set forth in the vLEI Ecosystem Governance Framework.', + }, + })[1], + source: Saider.saidify({ + d: '', + qvi: { + n: qviCredential.sad.d, + s: qviCredential.sad.s, + }, + })[1], + }); + + await waitOperation(holderClient, result.op); + return result.acdc.ked.d; + } + ); + + await step('LE credential IPEX grant', async () => { + const dt = createTimestamp(); + const leCredential = await holderClient + .credentials() + .get(holderAid.name, leCredentialId); + assert(leCredential !== undefined); + + const [grant, gsigs, gend] = await holderClient.ipex().grant({ + senderName: holderAid.name, + acdc: new Serder(leCredential.sad), + anc: new Serder(leCredential.anc), + iss: new Serder(leCredential.iss), + ancAttachment: leCredential.ancAttachment, + recipient: legalEntityAid.prefix, + datetime: dt, + }); + + await holderClient + .ipex() + .submitGrant(holderAid.name, grant, gsigs, gend, [ + legalEntityAid.prefix, + ]); + }); + + await step('Legal Entity IPEX admit', async () => { + const notifications = await waitForNotifications( + legalEntityClient, + '/exn/ipex/grant' + ); + const grantNotification = notifications[0]; + + const [admit, sigs, aend] = await legalEntityClient + .ipex() + .admit( + legalEntityAid.name, + '', + grantNotification.a.d!, + createTimestamp() + ); + + await legalEntityClient + .ipex() + .submitAdmit(legalEntityAid.name, admit, sigs, aend, [ + holderAid.prefix, + ]); + + await legalEntityClient.notifications().mark(grantNotification.i); }); - const hldVleiAcdc = holderCreds[0]; - assert.equal(holderCreds.length, 1); - assert.equal(hldVleiAcdc.sad.s, schemaSAID); - assert.equal(hldVleiAcdc.sad.i, issuerAID); - assert.equal(hldVleiAcdc.status.s, '0'); // 0 = issued - console.log('Credential received by recipient'); - - // Present credential - const [grant2, gsigs2, gend2] = await holderClient.ipex().grant({ - senderName: holderAidName, - recipient: verifierAID, - acdc: issResult.acdc, - anc: issResult.anc, - iss: issResult.iss, - datetime: createTimestamp(), + + await step('Legal Entity has chained credential', async () => { + const legalEntityCredential = await retry(async () => + legalEntityClient + .credentials() + .get(legalEntityAid.name, leCredentialId) + ); + + assert.equal(legalEntityCredential.sad.s, LE_SCHEMA_SAID); + assert.equal(legalEntityCredential.sad.i, holderAid.prefix); + assert.equal(legalEntityCredential.sad.a.i, legalEntityAid.prefix); + assert.equal(legalEntityCredential.status.s, '0'); + assert.equal(legalEntityCredential.chains[0].sad.d, qviCredentialId); + assert(legalEntityCredential.atc !== undefined); }); - await holderClient - .exchanges() - .sendFromEvents(holderAidName, 'presentation', grant2, gsigs2, gend2, [ - verifierAID, - ]); - console.log('Holder: Grant message sent for presentation'); - // Verifier check issued credential - const verifierNotifications = await waitForNotifications( - verifierClient, - '/exn/ipex/grant' - ); - const verifierGrantNote = verifierNotifications[0]; - - const [admit3, sigs3, aend3] = await verifierClient - .ipex() - .admit(verifierAidName, '', verifierGrantNote.a.d!, createTimestamp()); - await verifierClient - .ipex() - .submitAdmit(verifierAidName, admit3, sigs3, aend3, [holderAID]); - console.log('Verifier: Admit sent for presentation'); - - await verifierClient.notifications().mark(verifierGrantNote.i); - console.log('Verifier: Notification marked for presentation'); - - // list credentials for verifier - const verifierCreds = await retry(async () => { - const result = await verifierClient.credentials().list(); - expect(result.length).toBeGreaterThanOrEqual(1); - return result; + await step('Issuer revoke QVI credential', async () => { + const revokeOperation = await issuerClient + .credentials() + .revoke(issuerAid.name, qviCredentialId); + + await waitOperation(issuerClient, revokeOperation); + const issuerCredential = await issuerClient + .credentials() + .get(issuerAid.name, qviCredentialId); + + assert.equal(issuerCredential.status.s, '1'); }); - assert.equal(verifierCreds.length, 1); - assert.equal(verifierCreds[0].sad.s, schemaSAID); - assert.equal(verifierCreds[0].sad.i, issuerAID); - assert.equal(verifierCreds[0].status.s, '0'); // 0 = issued - console.log('Credential presented and received by verifier'); - - // Revoke credential - const revokeOperation = await issuerClient - .credentials() - .revoke(issuerAidName, issCreds[0].sad.d); - await waitOperation(issuerClient, revokeOperation); - issCreds = await issuerClient.credentials().list(); - const issVleiAcdc = issCreds[0]; - assert.equal(issCreds.length, 1); - assert.equal(issVleiAcdc.sad.s, schemaSAID); - assert.equal(issVleiAcdc.sad.i, issuerAID); - assert.equal(issVleiAcdc.status.s, '1'); // 1 = revoked - console.log('Issuer Credential revoked'); - - // Recipient check revoked credential - // let revoked = false - // while (!revoked) { - // let cred2 = await client2.credentials().get(holderAidName, creds1[0].sad.d) - // if (cred2.status.s == "1") { - // revoked = true - // } - // await new Promise((resolve) => setTimeout(resolve, 250)); - // } - // assert.equal(creds2.length, 1) - // assert.equal(creds2[0].sad.s, schemaSAID) - // assert.equal(creds2[0].sad.i, aid1.prefix) - // assert.equal(creds2[0].status.s, "1") // 1 = revoked - // console.log("Revocation received by recipient") - - // Present revoked credential - // await client1 - // .credentials() - // .present(issuerAidName, creds1[0].sad.d, verifierAidName, true); - // await new Promise((resolve) => setTimeout(resolve, 5000)); - // creds3 = await client3.credentials().list(verifierAidName); - // assert.equal(creds3.length, 1); - // assert.equal(creds3[0].sad.s, schemaSAID); - // assert.equal(creds3[0].sad.i, aid1.prefix); - // assert.equal(creds3[0].status.s, '1'); // 1 = revoked - // console.log('Revocation presented and received by verifier'); -}, 60000); +}, 90000); diff --git a/examples/integration-scripts/request-present.test.ts b/examples/integration-scripts/request-present.test.ts deleted file mode 100644 index 54166b3f..00000000 --- a/examples/integration-scripts/request-present.test.ts +++ /dev/null @@ -1,218 +0,0 @@ -import { strict as assert } from 'assert'; -import signify from 'signify-ts'; -import { - resolveOobi, - waitForNotifications, - waitOperation, -} from './utils/test-util'; -import { resolveEnvironment } from './utils/resolve-env'; - -const { url, bootUrl, vleiServerUrl } = resolveEnvironment(); - -const schemaSAID = 'EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao'; -const schemaOobi = `${vleiServerUrl}/oobi/${schemaSAID}`; - -// TODO: Marked as skipped because request/present changes -test.skip('request-present', async () => { - await signify.ready(); - // Boot three clients - const bran1 = signify.randomPasscode(); - const bran2 = signify.randomPasscode(); - const bran3 = signify.randomPasscode(); - const client1 = new signify.SignifyClient( - url, - bran1, - signify.Tier.low, - bootUrl - ); - const client2 = new signify.SignifyClient( - url, - bran2, - signify.Tier.low, - bootUrl - ); - const client3 = new signify.SignifyClient( - url, - bran3, - signify.Tier.low, - bootUrl - ); - - const [state1, state2, state3] = await Promise.all([ - client1 - .boot() - .then(() => client1.connect()) - .then(() => client1.state()), - client2 - .boot() - .then(() => client2.connect()) - .then(() => client2.state()), - client3 - .boot() - .then(() => client3.connect()) - .then(() => client3.state()), - ]); - console.log( - 'Client 1 connected. Client AID:', - state1.controller.state.i, - 'Agent AID: ', - state1.agent.i - ); - console.log( - 'Client 2 connected. Client AID:', - state2.controller.state.i, - 'Agent AID: ', - state2.agent.i - ); - console.log( - 'Client 3 connected. Client AID:', - state3.controller.state.i, - 'Agent AID: ', - state3.agent.i - ); - - // Create two identifiers, one for each client - const op1 = await client1.identifiers().create('issuer', { - toad: 3, - wits: [ - 'BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha', - 'BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM', - 'BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX', - ], - }); - await waitOperation(client1, await op1.op()); - const aid1 = await client1.identifiers().get('issuer'); - await client1 - .identifiers() - .addEndRole('issuer', 'agent', client1!.agent!.pre); - console.log("Issuer's AID:", aid1.prefix); - - const op2 = await client2.identifiers().create('recipient', { - toad: 3, - wits: [ - 'BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha', - 'BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM', - 'BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX', - ], - }); - await waitOperation(client2, await op2.op()); - const aid2 = await client2.identifiers().get('recipient'); - await client2 - .identifiers() - .addEndRole('recipient', 'agent', client2!.agent!.pre); - console.log("Recipient's AID:", aid2.prefix); - - const op3 = await client3.identifiers().create('verifier', { - toad: 3, - wits: [ - 'BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha', - 'BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM', - 'BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX', - ], - }); - await waitOperation(client3, await op3.op()); - - const aid3 = await client3.identifiers().get('verifier'); - await client3 - .identifiers() - .addEndRole('verifier', 'agent', client3!.agent!.pre); - console.log("Verifier's AID:", aid3.prefix); - - // Exchenge OOBIs - console.log('Resolving OOBIs...'); - const [oobi1, oobi2, oobi3] = await Promise.all([ - client1.oobis().get('issuer', 'agent'), - client2.oobis().get('recipient', 'agent'), - client3.oobis().get('verifier', 'agent'), - ]); - - await Promise.all([ - resolveOobi(client1, oobi2.oobis[0], 'recipient'), - resolveOobi(client1, oobi3.oobis[0], 'verifier'), - resolveOobi(client1, schemaOobi, 'schema'), - ]); - - console.log('Issuer resolved 3 OOBIs'); - - await Promise.all([ - resolveOobi(client2, oobi1.oobis[0], 'issuer'), - resolveOobi(client2, oobi3.oobis[0], 'verifier'), - resolveOobi(client2, schemaOobi, 'schema'), - ]); - console.log('Recipient resolved 3 OOBIs'); - - await Promise.all([ - resolveOobi(client3, oobi1.oobis[0], 'issuer'), - resolveOobi(client3, oobi2.oobis[0], 'recipient'), - resolveOobi(client3, schemaOobi, 'schema'), - ]); - console.log('Verifier resolved 3 OOBIs'); - - // Create registry for issuer - const vcpResult = await client1 - .registries() - .create({ name: 'issuer', registryName: 'vLEI' }); - await waitOperation(client1, await vcpResult.op()); - const registries = await client1.registries().list('issuer'); - assert.equal(registries.length, 1); - assert.equal(registries[0].name, 'vLEI'); - const schema = await client1.schemas().get(schemaSAID); - assert.equal(schema.$id, schemaSAID); - const schemas = await client2.schemas().list(); - assert.equal(schemas.length, 1); - assert.equal(schemas[0].$id, schemaSAID); - console.log('Registry created'); - - // Issue credential - const vcdata = { - LEI: '5493001KJTIIGC8Y1R17', - }; - const credRes = await client1.credentials().issue({ - issuerName: 'issuer', - registryId: registries[0].regk, - schemaId: schemaSAID, - recipient: aid2.prefix, - data: vcdata, - }); - await waitOperation(client1, credRes.op); - - const creds1 = await client1.credentials().list(); - assert.equal(creds1.length, 1); - assert.equal(creds1[0].sad.s, schemaSAID); - assert.equal(creds1[0].sad.i, aid1.prefix); - assert.equal(creds1[0].status.s, '0'); // 0 = issued - console.log('Credential issued'); - - // Recipient check issued credential - const creds2 = await client2.credentials().list(); - assert.equal(creds2.length, 1); - assert.equal(creds2[0].sad.s, schemaSAID); - assert.equal(creds2[0].sad.i, aid1.prefix); - assert.equal(creds2[0].status.s, '0'); // 0 = issued - console.log('Credential received by recipient'); - - // Verifier request credential to recipient - await client3.credentials().request('verifier', aid2.prefix, schemaSAID); - - // Recipient checks for a presentation request notification - const notes2 = await waitForNotifications(client2, '/presentation/request'); - await Promise.all(notes2.map((n) => client2.notifications().mark(n.i))); - - // Recipient present credential to verifier - await client1 - .credentials() - .present('issuer', creds1[0].sad.d, 'verifier', true); - - // Verifier checks for a presentation notification - const notes3 = await waitForNotifications(client3, '/presentation'); - await Promise.all(notes3.map((n) => client3.notifications().mark(n.i))); - - const creds3 = await client3 - .credentials() - .list({ filter: { '-i': { $eq: aid1.prefix } } }); // filter by issuer - assert.equal(creds3.length, 1); - assert.equal(creds3[0].sad.s, schemaSAID); - assert.equal(creds3[0].sad.i, aid1.prefix); - assert.equal(creds3[0].status.s, '0'); // 0 = issued - assert.equal(creds3[0].sad.a.i, aid2.prefix); // verify that the issuee is the same as the presenter -}, 60000); diff --git a/examples/integration-scripts/single-issuer-chained-credential.test.ts b/examples/integration-scripts/single-issuer-chained-credential.test.ts deleted file mode 100644 index 092f76a1..00000000 --- a/examples/integration-scripts/single-issuer-chained-credential.test.ts +++ /dev/null @@ -1,240 +0,0 @@ -import assert from 'node:assert'; -import signify, { SignifyClient, Saider } from 'signify-ts'; -import { resolveEnvironment } from './utils/resolve-env'; -import { - resolveOobi, - waitForNotifications, - waitOperation, -} from './utils/test-util'; -import { retry } from './utils/retry'; - -const { bootUrl, url, vleiServerUrl } = resolveEnvironment(); - -const QVI_SCHEMA_SAID = 'EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao'; -const LE_SCHEMA_SAID = 'ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY'; -const WITNESS_AIDS: string[] = ['BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha']; - -const QVI_SCHEMA_OOBI = `${vleiServerUrl}/oobi/${QVI_SCHEMA_SAID}`; -const LE_SCHEMA_OOBI = `${vleiServerUrl}/oobi/${LE_SCHEMA_SAID}`; - -function createTimestamp() { - const dt = new Date().toISOString().replace('Z', '000+00:00'); - return dt; -} - -async function connect(url: string, bootUrl: string) { - const client = new signify.SignifyClient( - url, - signify.randomPasscode(), - signify.Tier.low, - bootUrl - ); - - await client.boot(); - await client.connect(); - - return client; -} - -async function createIdentifier( - client: signify.SignifyClient, - name: string, - witnesses: string[] -) { - const icpResult1 = await client.identifiers().create(name, { - toad: witnesses.length, - wits: witnesses, - }); - await waitOperation(client, await icpResult1.op()); - const aid = await client.identifiers().get(name); - - if (!client.agent) { - throw new Error('No agent on client'); - } - - await client.identifiers().addEndRole(name, 'agent', client.agent.pre); - - return aid.prefix; -} - -async function getAgentOobi( - client: signify.SignifyClient, - name: string -): Promise { - const result = await client.oobis().get(name, 'agent'); - return result.oobis[0]; -} - -async function createRegistry( - client: SignifyClient, - name: string, - registryName: string -) { - const result = await client.registries().create({ name, registryName }); - await waitOperation(client, await result.op()); - - const registries = await client.registries().list(name); - assert.equal(registries.length, 1); - assert.equal(registries[0].name, registryName); - - return registries[0]; -} - -async function issueCredential( - client: SignifyClient, - name: string, - args: { - registry: string; - schema: string; - recipient: string; - data: Record; - source?: Record; - rules?: Record; - } -) { - const result = await client.credentials().issue({ - issuerName: name, - registryId: args.registry, - schemaId: args.schema, - recipient: args.recipient, - data: args.data, - rules: args.rules && Saider.saidify({ d: '', ...args.rules })[1], - source: args.source && Saider.saidify({ d: '', ...args.source })[1], - }); - - await waitOperation(client, result.op); - - const creds = await client.credentials().list(); - const dt = createTimestamp(); - - const [grant, gsigs, end] = await client.ipex().grant({ - senderName: name, - anc: result.anc, - iss: result.iss, - acdc: result.acdc, - recipient: args.recipient, - datetime: dt, - }); - - await client.ipex().submitGrant(name, grant, gsigs, end, [args.recipient]); - return creds[0]; -} - -async function admitCredential( - client: SignifyClient, - name: string, - said: string, - recipient: string -) { - const dt = createTimestamp(); - - const [admit, sigs, end] = await client.ipex().admit(name, '', said, dt); - - await client.ipex().submitAdmit(name, admit, sigs, end, [recipient]); -} - -test('single issuer chained credentials', async () => { - await signify.ready(); - const issuerClient = await connect(url, bootUrl); - const holderClient = await connect(url, bootUrl); - - await issuerClient.state(); - await holderClient.state(); - const issuerPrefix = await createIdentifier( - issuerClient, - 'issuer', - WITNESS_AIDS - ); - const holderPrefix = await createIdentifier( - holderClient, - 'holder', - WITNESS_AIDS - ); - - // Exchange OOBIs - const issuerOobi = await getAgentOobi(issuerClient, 'issuer'); - const holderOobi = await getAgentOobi(holderClient, 'holder'); - await resolveOobi(issuerClient, holderOobi, 'holder'); - await resolveOobi(issuerClient, QVI_SCHEMA_OOBI, 'qvi-schema'); - await resolveOobi(issuerClient, LE_SCHEMA_OOBI, 'le-schema'); - await resolveOobi(holderClient, issuerOobi, 'issuer'); - await resolveOobi(holderClient, QVI_SCHEMA_OOBI, 'qvi-schema'); - await resolveOobi(holderClient, LE_SCHEMA_OOBI, 'le-schema'); - - await createRegistry(issuerClient, 'issuer', 'vLEI'); - - const registires = await issuerClient.registries().list('issuer'); - const result = await issuerClient.credentials().issue({ - issuerName: 'issuer', - registryId: registires[0].regk, - schemaId: QVI_SCHEMA_SAID, - recipient: issuerPrefix, - data: { - LEI: '5493001KJTIIGC8Y1R17', - }, - }); - - await waitOperation(issuerClient, result.op); - const sourceCredential = await retry(async () => { - const result = await issuerClient.credentials().list(); - assert(result.length >= 1); - return result[0]; - }); - - await issueCredential(issuerClient, 'issuer', { - registry: registires[0].regk, - schema: LE_SCHEMA_SAID, - // schema: QVI_SCHEMA_SAID, - recipient: holderPrefix, - data: { - LEI: '5493001KJTIIGC8Y1R17', - }, - source: { - qvi: { - n: sourceCredential.sad.d, - s: sourceCredential.sad.s, - }, - }, - rules: { - usageDisclaimer: { - l: 'Usage of a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, does not assert that the Legal Entity is trustworthy, honest, reputable in its business dealings, safe to do business with, or compliant with any laws or that an implied or expressly intended purpose will be fulfilled.', - }, - issuanceDisclaimer: { - l: 'All information in a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, is accurate as of the date the validation process was complete. The vLEI Credential has been issued to the legal entity or person named in the vLEI Credential as the subject; and the qualified vLEI Issuer exercised reasonable care to perform the validation process set forth in the vLEI Ecosystem Governance Framework.', - }, - }, - }); - - const grantNotifications = await waitForNotifications( - holderClient, - '/exn/ipex/grant' - ); - - await admitCredential( - holderClient, - 'holder', - grantNotifications[0].a.d!, - issuerPrefix - ); - - await holderClient.notifications().mark(grantNotifications[0].i); - - const holderCredential = await retry(async () => { - const creds = await holderClient.credentials().list(); - const lei = creds.find( - (cred: { schema: { $id: string } }) => - cred.schema.$id === LE_SCHEMA_SAID - ); - - expect(lei).toBeDefined(); - return lei; - }); - - expect(holderCredential).toMatchObject({ - sad: { a: { LEI: '5493001KJTIIGC8Y1R17' } }, - }); - expect(holderCredential.chains).toHaveLength(1); - expect(holderCredential.chains[0]).toMatchObject({ - sad: { a: { LEI: '5493001KJTIIGC8Y1R17' } }, - }); -}, 30000); diff --git a/examples/integration-scripts/single-issuer-holder.test.ts b/examples/integration-scripts/single-issuer-holder.test.ts deleted file mode 100644 index b9b5e877..00000000 --- a/examples/integration-scripts/single-issuer-holder.test.ts +++ /dev/null @@ -1,301 +0,0 @@ -import assert from 'node:assert'; -import signify, { - SignifyClient, - IssueCredentialArgs, - Serder, -} from 'signify-ts'; -import { resolveEnvironment } from './utils/resolve-env'; -import { waitForNotifications, waitOperation } from './utils/test-util'; -import { retry } from './utils/retry'; - -const SCHEMA_SAID = 'EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao'; -const { bootUrl, url, vleiServerUrl, witnessIds } = resolveEnvironment(); - -function createTimestamp() { - const dt = new Date().toISOString().replace('Z', '000+00:00'); - return dt; -} - -async function connect(url: string, bootUrl: string) { - const client = new signify.SignifyClient( - url, - signify.randomPasscode(), - signify.Tier.low, - bootUrl - ); - - await client.boot(); - await client.connect(); - - return client; -} - -async function createIdentifier( - client: signify.SignifyClient, - name: string, - witnesses: string[] -) { - const icpResult1 = await client.identifiers().create(name, { - toad: witnesses.length, - wits: witnesses, - }); - const op = await icpResult1.op(); - await waitOperation(client, op); - const aid = await client.identifiers().get(name); - - if (!client.agent) { - throw new Error('No agent on client'); - } - - await client.identifiers().addEndRole(name, 'agent', client.agent.pre); - - return aid.prefix; -} - -async function getAgentOobi( - client: signify.SignifyClient, - name: string -): Promise { - const result = await client.oobis().get(name, 'agent'); - return result.oobis[0]; -} - -async function resolveOobi(client: SignifyClient, oobi: string, alias: string) { - console.log(`Resolve ${alias} -> ${oobi}`); - const op = await client.oobis().resolve(oobi, alias); - const result = await waitOperation<{ i: string }>(client, op); - return result.response; -} - -async function createRegistry( - client: SignifyClient, - name: string, - registryName: string -) { - const result = await client.registries().create({ name, registryName }); - const op = await result.op(); - await waitOperation(client, op); - - const registries = await client.registries().list(name); - assert.equal(registries.length, 1); - assert.equal(registries[0].name, registryName); - - return registries[0]; -} - -async function issueCredential( - client: SignifyClient, - args: IssueCredentialArgs -) { - const result = await client.credentials().issue(args); - - await waitOperation(client, result.op); - - const creds = await client.credentials().list(); - assert.equal(creds.length, 1); - assert.equal(creds[0].sad.s, args.schemaId); - assert.equal(creds[0].status.s, '0'); - - const dt = createTimestamp(); - - if (args.recipient) { - const [grant, gsigs, end] = await client.ipex().grant({ - senderName: args.issuerName, - recipient: args.recipient, - datetime: dt, - acdc: result.acdc, - anc: result.anc, - iss: result.iss, - }); - - await client - .exchanges() - .sendFromEvents(args.issuerName, 'credential', grant, gsigs, end, [ - args.recipient, - ]); - } - - console.log('Grant message sent'); - - return creds[0]; -} - -async function grantCredential( - client: SignifyClient, - issuerName: string, - recipient: string, - acdc: Serder, - acdcAttachment: string, - anc: Serder, - ancAttachment: string, - iss: Serder, - issAttachment: string -) { - const dt = createTimestamp(); - - const [grant, gsigs, end] = await client.ipex().grant({ - senderName: issuerName, - recipient: recipient, - datetime: dt, - acdc: acdc, - acdcAttachment: acdcAttachment, - anc: anc, - ancAttachment: ancAttachment, - iss: iss, - issAttachment: issAttachment, - }); - - await client.ipex().submitGrant(issuerName, grant, gsigs, end, [recipient]); -} - -async function admitCredential( - client: SignifyClient, - name: string, - said: string, - recipient: string -) { - const dt = createTimestamp(); - - const [admit, sigs, end] = await client.ipex().admit(name, '', said, dt); - - await client.ipex().submitAdmit(name, admit, sigs, end, [recipient]); -} - -test( - 'Single issuer holder', - async () => { - await signify.ready(); - const issuerClient = await connect(url, bootUrl); - const holderClient = await connect(url, bootUrl); - const verifierClient = await connect(url, bootUrl); - - await issuerClient.state(); - await holderClient.state(); - await verifierClient.state(); - - // Create two identifiers, one for each client - const issuerPrefix = await createIdentifier( - issuerClient, - 'issuer', - witnessIds - ); - const holderPrefix = await createIdentifier( - holderClient, - 'holder', - witnessIds - ); - const verifierPrefix = await createIdentifier( - verifierClient, - 'verifier', - witnessIds - ); - - // Exchange OOBIs - const issuerOobi = await getAgentOobi(issuerClient, 'issuer'); - const holderOobi = await getAgentOobi(holderClient, 'holder'); - const verifierOobi = await getAgentOobi(verifierClient, 'verifier'); - await resolveOobi(issuerClient, holderOobi, 'holder'); - await resolveOobi( - issuerClient, - vleiServerUrl + '/oobi/' + SCHEMA_SAID, - 'schema' - ); - await resolveOobi(holderClient, issuerOobi, 'issuer'); - await resolveOobi( - holderClient, - vleiServerUrl + '/oobi/' + SCHEMA_SAID, - 'schema' - ); - await resolveOobi(verifierClient, holderOobi, 'holder'); - await resolveOobi(holderClient, verifierOobi, 'verifier'); - await resolveOobi( - verifierClient, - vleiServerUrl + '/oobi/' + SCHEMA_SAID, - 'schema' - ); - - await createRegistry(issuerClient, 'issuer', 'vLEI'); - - const registires = await issuerClient.registries().list('issuer'); - await issueCredential(issuerClient, { - issuerName: 'issuer', - registryId: registires[0].regk, - schemaId: SCHEMA_SAID, - recipient: holderPrefix, - data: { - LEI: '5493001KJTIIGC8Y1R17', - }, - }); - - const grantNotifications = await waitForNotifications( - holderClient, - '/exn/ipex/grant' - ); - - await admitCredential( - holderClient, - 'holder', - grantNotifications[0].a.d!, - issuerPrefix - ); - - await holderClient.notifications().mark(grantNotifications[0].i); - - const c = await retry(async () => { - const creds = await holderClient.credentials().list(); - assert(creds.length >= 1); - return creds[0]; - }); - - console.log('Loading full credential'); - const cred = await holderClient - .credentials() - .get('holder', c['sad']['d']); - - const acdc = new Serder(cred['sad']); - const iss = new Serder(cred['iss']); - const anc = new Serder(cred['anc']); - - console.log(`Presenting credential to verifier: ${c['sad']['d']}`); - await grantCredential( - holderClient, - 'holder', - verifierPrefix, - acdc, - cred['atc'], - anc, - cred['ancatc'], - iss, - cred['issatc'] - ); - - const verifierGrantNotifications = await waitForNotifications( - verifierClient, - '/exn/ipex/grant' - ); - - console.log( - `Notifcation of grant received by verifier ${verifierGrantNotifications[0].a.d}` - ); - await admitCredential( - verifierClient, - 'verifier', - verifierGrantNotifications[0].a.d!, - holderPrefix - ); - - await verifierClient - .notifications() - .mark(verifierGrantNotifications[0].i); - - console.log('Checking for credential'); - const p = await retry(async () => { - const creds = await verifierClient.credentials().list(); - assert(creds.length >= 1); - return creds[0]; - }); - - console.log(`Credential ${p.sad.d} received by Verifier`); - }, - 1000 * 60 * 5 -); diff --git a/examples/integration-scripts/utils/test-step.ts b/examples/integration-scripts/utils/test-step.ts new file mode 100644 index 00000000..172b0fe6 --- /dev/null +++ b/examples/integration-scripts/utils/test-step.ts @@ -0,0 +1,28 @@ +/** + * Provides a way to group logically related test steps in an integration test + * + * Can be useful to provide logging when a step succeeds, or to be able to use + * locally scoped variables. + * + * In long tests it can also be useful to create visual groups. + * @param description + * @param fn + * @returns + */ +export async function step( + description: string, + fn: () => Promise +): Promise { + try { + const start = Date.now(); + const response = await fn(); + + // Bypassing console.log to avoid the verbose log output from jest + process.stdout.write( + `Step - ${description} - finished (${Date.now() - start}ms)\n` + ); + return response; + } catch (error) { + throw new Error(`Step - ${description} - failed`, { cause: error }); + } +} diff --git a/examples/integration-scripts/utils/test-util.ts b/examples/integration-scripts/utils/test-util.ts index 354bf2ba..dbb4260f 100644 --- a/examples/integration-scripts/utils/test-util.ts +++ b/examples/integration-scripts/utils/test-util.ts @@ -29,7 +29,7 @@ export async function waitOperation( export async function resolveOobi( client: SignifyClient, oobi: string, - alias: string + alias?: string ) { const op = await client.oobis().resolve(oobi, alias); await waitOperation(client, op);