Skip to content

Commit 25215bf

Browse files
committed
fix: provide a way to pass the anchor and issuance events when creating credential
1 parent 5801e63 commit 25215bf

File tree

5 files changed

+108
-70
lines changed

5 files changed

+108
-70
lines changed

examples/integration-scripts/multisig-holder.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -460,23 +460,23 @@ async function createRegistry(
460460
async function issueCredential(
461461
client: SignifyClient,
462462
name: string,
463-
data: CredentialData
463+
acdc: CredentialData
464464
) {
465-
const result = await client.credentials().issue(name, data);
465+
const result = await client.credentials().issue(name, { acdc });
466466

467467
await waitOperation(client, result.op);
468468

469469
const creds = await client.credentials().list();
470470
assert.equal(creds.length, 1);
471-
assert.equal(creds[0].sad.s, data.s);
471+
assert.equal(creds[0].sad.s, acdc.s);
472472
assert.equal(creds[0].status.s, '0');
473473

474474
const dt = createTimestamp();
475475

476-
if (data.a.i) {
476+
if (acdc.a.i) {
477477
const [grant, gsigs, end] = await client.ipex().grant({
478478
senderName: name,
479-
recipient: data.a.i,
479+
recipient: acdc.a.i,
480480
datetime: dt,
481481
acdc: result.acdc,
482482
anc: result.anc,
@@ -485,7 +485,7 @@ async function issueCredential(
485485

486486
let op = await client
487487
.ipex()
488-
.submitGrant(name, grant, gsigs, end, [data.a.i]);
488+
.submitGrant(name, grant, gsigs, end, [acdc.a.i]);
489489
op = await waitOperation(client, op);
490490
}
491491

examples/integration-scripts/multisig.test.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ import {
99
assertOperations,
1010
getOrCreateClient,
1111
getOrCreateIdentifier,
12-
markNotification,
1312
waitAndMarkNotification,
14-
waitForNotifications,
1513
waitOperation,
1614
warnNotifications,
1715
} from './utils/test-util';
@@ -882,12 +880,14 @@ test('multisig', async function run() {
882880

883881
const TIME = new Date().toISOString().replace('Z', '000+00:00');
884882
const credRes = await client1.credentials().issue('multisig', {
885-
ri: regk,
886-
s: SCHEMA_SAID,
887-
a: {
888-
i: holder,
889-
dt: TIME,
890-
...vcdata,
883+
acdc: {
884+
ri: regk,
885+
s: SCHEMA_SAID,
886+
a: {
887+
i: holder,
888+
dt: TIME,
889+
...vcdata,
890+
},
891891
},
892892
});
893893
op1 = credRes.op;
@@ -906,7 +906,7 @@ test('multisig', async function run() {
906906
exn = res[0].exn;
907907

908908
const credentialSaid = exn.e.acdc.d;
909-
const credRes2 = await client2.credentials().issue('multisig', exn.e.acdc);
909+
const credRes2 = await client2.credentials().issue('multisig', exn.e);
910910

911911
op2 = credRes2.op;
912912
await multisigIssue(client2, 'member2', 'multisig', credRes2);
@@ -920,7 +920,7 @@ test('multisig', async function run() {
920920
res = await client3.groups().getRequest(msgSaid);
921921
exn = res[0].exn;
922922

923-
const credRes3 = await client3.credentials().issue('multisig', exn.e.acdc);
923+
const credRes3 = await client3.credentials().issue('multisig', exn.e);
924924

925925
op3 = credRes3.op;
926926
await multisigIssue(client3, 'member3', 'multisig', credRes3);

examples/integration-scripts/utils/test-util.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -318,16 +318,18 @@ export async function getOrIssueCredential(
318318
}
319319

320320
const issResult = await issuerClient.credentials().issue(issuerAid.name, {
321-
ri: issuerRegistry.regk,
322-
s: schema,
323-
u: privacy ? new Salter({}).qb64 : undefined,
324-
a: {
325-
i: recipientAid.prefix,
321+
acdc: {
322+
ri: issuerRegistry.regk,
323+
s: schema,
326324
u: privacy ? new Salter({}).qb64 : undefined,
327-
...credData,
325+
a: {
326+
i: recipientAid.prefix,
327+
u: privacy ? new Salter({}).qb64 : undefined,
328+
...credData,
329+
},
330+
r: rules,
331+
e: source,
328332
},
329-
r: rules,
330-
e: source,
331333
});
332334

333335
await waitOperation(issuerClient, issResult.op);

src/keri/app/credentialing.ts

Lines changed: 77 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
} from '../core/utils';
2222
import { Operation } from './coring';
2323
import { HabState } from '../core/state';
24+
import { CesrNumber } from '../core/number';
2425

2526
/** Types of credentials */
2627
export class CredentialTypes {
@@ -85,6 +86,29 @@ export interface CredentialData {
8586
r?: { [key: string]: unknown };
8687
}
8788

89+
export interface IssueCredentialArgs {
90+
/**
91+
* The credential data.
92+
*/
93+
acdc: CredentialData;
94+
95+
/**
96+
* The issuance event to be anchored to the credential registry. If not provided, the issuance event will be derived
97+
* from the credential data.
98+
*
99+
* If a credential is created as part of a multisig exchanged, the anchoring event can be found in the exchange message.
100+
*/
101+
iss?: Record<string, unknown>;
102+
103+
/**
104+
* The anchoring event for the credential issuance. If not provided, the anchor event will be calculated from
105+
* from the credential data and the issuance event.
106+
*
107+
* If a credential is created as part of a multisig exchanged, the anchoring event can be found in the exchange message.
108+
*/
109+
anc?: Record<string, unknown>;
110+
}
111+
88112
export interface IssueCredentialResult {
89113
acdc: Serder;
90114
anc: Serder;
@@ -290,7 +314,7 @@ export class Credentials {
290314
*/
291315
async issue(
292316
name: string,
293-
args: CredentialData
317+
args: IssueCredentialArgs
294318
): Promise<IssueCredentialResult> {
295319
const hab = await this.client.identifiers().get(name);
296320
const estOnly = hab.state.c !== undefined && hab.state.c.includes('EO');
@@ -306,55 +330,65 @@ export class Credentials {
306330

307331
const [, subject] = Saider.saidify({
308332
d: '',
309-
...args.a,
310-
dt: args.a.dt ?? new Date().toISOString().replace('Z', '000+00:00'),
333+
...args.acdc.a,
334+
dt:
335+
args.acdc.a.dt ??
336+
new Date().toISOString().replace('Z', '000+00:00'),
311337
});
312338

313-
const [, acdc] = Saider.saidify({
314-
v: versify(Ident.ACDC, undefined, Serials.JSON, 0),
315-
d: '',
316-
u: args.u,
317-
i: args.i ?? hab.prefix,
318-
ri: args.ri,
319-
s: args.s,
320-
a: subject,
321-
e: args.e,
322-
r: args.r,
323-
});
339+
const acdc = new Serder(
340+
Saider.saidify({
341+
v: versify(Ident.ACDC, undefined, Serials.JSON, 0),
342+
d: '',
343+
u: args.acdc.u,
344+
i: args.acdc.i ?? hab.prefix,
345+
ri: args.acdc.ri,
346+
s: args.acdc.s,
347+
a: subject,
348+
e: args.acdc.e,
349+
r: args.acdc.r,
350+
})[1]
351+
);
324352

325-
const [, iss] = Saider.saidify({
326-
v: versify(Ident.KERI, undefined, Serials.JSON, 0),
327-
t: Ilks.iss,
328-
d: '',
329-
i: acdc.d,
330-
s: '0',
331-
ri: args.ri,
332-
dt: subject.dt,
333-
});
353+
const iss = new Serder(
354+
args.iss ??
355+
Saider.saidify({
356+
v: versify(Ident.KERI, undefined, Serials.JSON, 0),
357+
t: Ilks.iss,
358+
d: '',
359+
i: acdc.ked.d,
360+
s: '0',
361+
ri: args.acdc.ri,
362+
dt: subject.dt,
363+
})[1]
364+
);
334365

335-
const sn = parseInt(hab.state.s, 16);
336-
const anc = interact({
337-
pre: hab.prefix,
338-
sn: sn + 1,
339-
data: [
340-
{
341-
i: iss.i,
342-
s: iss.s,
343-
d: iss.d,
344-
},
345-
],
346-
dig: hab.state.d,
347-
version: undefined,
348-
kind: undefined,
349-
});
366+
const sn = new CesrNumber({}, parseInt(hab.state.s, 16) + 1);
367+
const anc = new Serder(
368+
args.anc ??
369+
Saider.saidify({
370+
v: versify(Ident.KERI, undefined, Serials.JSON, 0),
371+
t: Ilks.ixn,
372+
d: '',
373+
i: hab.prefix,
374+
s: sn.numh,
375+
p: hab.state.d,
376+
a: [
377+
{
378+
i: iss.ked.i,
379+
s: iss.ked.s,
380+
d: iss.ked.d,
381+
},
382+
],
383+
})[1]
384+
);
350385

351386
const sigs = await keeper.sign(b(anc.raw));
352-
353387
const path = `/identifiers/${hab.name}/credentials`;
354388
const method = 'POST';
355389
const body = {
356-
acdc: acdc,
357-
iss: iss,
390+
acdc: acdc.ked,
391+
iss: iss.ked,
358392
ixn: anc.ked,
359393
sigs,
360394
[keeper.algo]: keeper.params(),
@@ -368,8 +402,8 @@ export class Credentials {
368402
const op = await res.json();
369403

370404
return {
371-
acdc: new Serder(acdc),
372-
iss: new Serder(iss),
405+
acdc,
406+
iss,
373407
anc,
374408
op,
375409
};

test/app/credentialing.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,11 @@ describe('Credentialing', () => {
263263
const schema = 'EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao';
264264
const isuee = 'EG2XjQN-3jPN5rcR4spLjaJyM4zA6Lgg-Hd5vSMymu5p';
265265
await credentials.issue('aid1', {
266-
ri: registry,
267-
s: schema,
268-
a: { i: isuee, LEI: '1234' },
266+
acdc: {
267+
ri: registry,
268+
s: schema,
269+
a: { i: isuee, LEI: '1234' },
270+
},
269271
});
270272
lastCall = fetchMock.mock.calls[fetchMock.mock.calls.length - 1]!;
271273
lastBody = JSON.parse(lastCall[1]!.body!.toString());

0 commit comments

Comments
 (0)