diff --git a/src/keri/app/aiding.ts b/src/keri/app/aiding.ts index 4db9bbd3..7845c383 100644 --- a/src/keri/app/aiding.ts +++ b/src/keri/app/aiding.ts @@ -1,12 +1,12 @@ import { SignifyClient } from "./clienting" -import { Tier} from "../core/salter" -import {Algos} from '../core/manager' -import {incept, interact, reply, rotate} from "../core/eventing" -import {b,Serials, Versionage} from "../core/core" -import {Tholder} from "../core/tholder" -import {MtrDex} from "../core/matter" -import {Serder} from "../core/serder" -import {parseRangeHeaders} from "../core/httping" +import { Tier } from "../core/salter" +import { Algos } from '../core/manager' +import { incept, interact, reply, rotate } from "../core/eventing" +import { b, Serials, Versionage } from "../core/core" +import { Tholder } from "../core/tholder" +import { MtrDex } from "../core/matter" +import { Serder } from "../core/serder" +import { parseRangeHeaders } from "../core/httping" /** Arguments required to create an identfier */ export interface CreateIdentiferArgs { @@ -67,17 +67,17 @@ export class Identifier { * @param {number} [end=24] End index of list of notifications, defaults to 24 * @returns {Promise} A promise to the list of managed identifiers */ - async list(start:number=0, end:number=24): Promise { + async list(start: number = 0, end: number = 24): Promise { let extraHeaders = new Headers() extraHeaders.append('Range', `aids=${start}-${end}`) - + let path = `/identifiers` let data = null let method = 'GET' let res = await this.client.fetch(path, method, data, extraHeaders) let cr = res.headers.get('content-range') - let range = parseRangeHeaders(cr,"aids") + let range = parseRangeHeaders(cr, "aids") let aids = await res.json() return { @@ -109,7 +109,7 @@ export class Identifier { * @param {CreateIdentiferArgs} [kargs] Optional parameters to create the identifier * @returns {EventResult} The inception result */ - create(name: string, kargs:CreateIdentiferArgs={}): EventResult { + create(name: string, kargs: CreateIdentiferArgs = {}): EventResult { const algo = kargs.algo == undefined ? Algos.salty : kargs.algo @@ -163,7 +163,7 @@ export class Identifier { let keeper = this.client.manager!.new(algo, this.client.pidx, xargs) let [keys, ndigs] = keeper!.incept(transferable) wits = wits !== undefined ? wits : [] - let serder: Serder|undefined = undefined + let serder: Serder | undefined = undefined if (delpre == undefined) { serder = incept({ keys: keys!, @@ -209,7 +209,7 @@ export class Identifier { } jsondata[algo] = keeper.params() - this.client.pidx = this.client.pidx + 1 + this.client.pidx = this.client.pidx + 1 let res = this.client.fetch("/identifiers", "POST", jsondata) return new EventResult(serder, sigs, res) } @@ -232,7 +232,7 @@ export class Identifier { data = Array.isArray(data) ? data : [data] - let serder = interact({ pre: pre, sn: sn + 1, data: data, dig: dig, version: undefined, kind: undefined }) + let [ , serder] = interact({ pre: pre, sn: sn + 1, data: data, dig: dig, version: undefined, kind: undefined }) let keeper = this.client!.manager!.get(hab) let sigs = keeper.sign(b(serder.raw)) @@ -253,7 +253,7 @@ export class Identifier { * @param {RotateIdentifierArgs} [kargs] Optional parameters requiered to generate the rotation event * @returns {Promise} A promise to the rotation event result */ - async rotate(name: string, kargs: RotateIdentifierArgs={}): Promise { + async rotate(name: string, kargs: RotateIdentifierArgs = {}): Promise { let transferable = kargs.transferable ?? true let ncode = kargs.ncode ?? MtrDex.Ed25519_Seed @@ -277,16 +277,16 @@ export class Identifier { // if nsith is None: # compute default from newly rotated digers above if (nsith == undefined) nsith = `${Math.max(1, Math.ceil(ncount / 2)).toString(16)}` - let cst = new Tholder({sith: isith}).sith // current signing threshold - let nst = new Tholder({sith: nsith}).sith // next signing threshold + let cst = new Tholder({ sith: isith }).sith // current signing threshold + let nst = new Tholder({ sith: nsith }).sith // next signing threshold // Regenerate next keys to sign rotation event let keeper = this.client.manager!.get(hab) // Create new keys for next digests let ncodes = kargs.ncodes ?? new Array(ncount).fill(ncode) - let states = kargs.states == undefined? [] : kargs.states - let rstates = kargs.rstates == undefined? [] : kargs.rstates + let states = kargs.states == undefined ? [] : kargs.states + let rstates = kargs.rstates == undefined ? [] : kargs.rstates let [keys, ndigs] = keeper!.rotate(ncodes, transferable, states, rstates) let cuts = kargs.cuts ?? [] diff --git a/src/keri/app/clienting.ts b/src/keri/app/clienting.ts index 1fb3bd99..66beb198 100644 --- a/src/keri/app/clienting.ts +++ b/src/keri/app/clienting.ts @@ -6,7 +6,7 @@ import { KeyManager } from "../core/keeping" import { Identifier } from "./aiding" import { Contacts, Challenges } from "./contacting" import { Oobis, Operations, KeyEvents, KeyStates } from "./coring" -import { Credentials, Registries, Schemas, } from './credentialing' +import { Credentials, Registries, Schemas, Ipex } from './credentialing' import { Notifications } from "./notifying" import { Escrows } from "./escrowing" import { Groups } from "./grouping" @@ -425,4 +425,12 @@ export class SignifyClient { exchanges(): Exchanges { return new Exchanges(this) } + + /** + * Get ipex resource + * @returns {Ipex} + * */ + ipex(): Ipex { + return new Ipex(this) + } } \ No newline at end of file diff --git a/src/keri/app/controller.ts b/src/keri/app/controller.ts index 11740cb7..0234c90d 100644 --- a/src/keri/app/controller.ts +++ b/src/keri/app/controller.ts @@ -132,16 +132,18 @@ export class Controller { approveDelegation(_agent: Agent) { - let seqner = new Seqner({sn: _agent.sn}) - let anchor = {i: _agent.pre, s: seqner.snh, d: _agent.said} + let seqner = new Seqner({ sn: _agent.sn }) + let anchor = { i: _agent.pre, s: seqner.snh, d: _agent.said } let sn = new CesrNumber({}, undefined, this.serder.ked["s"]).num + 1 - this.serder = interact({ + let [ , serder] = interact({ pre: this.serder.pre, dig: this.serder.ked["d"], sn: sn, data: [anchor], version: Versionage, - kind: Serials.JSON}) + kind: Serials.JSON + }) + this.serder = serder return [this.signer.sign(this.serder.raw, 0).qb64] } @@ -221,13 +223,13 @@ export class Controller { // Now we have the AID salt, use it to verify against the current public keys let acreator = new SaltyCreator(dnxt, salty["tier"], salty["stem"]) let signers = acreator.create( - salty["icodes"], - undefined, - MtrDex.Ed25519_Seed, - salty["transferable"], - salty["pidx"], - 0, - salty["kidx"], + salty["icodes"], + undefined, + MtrDex.Ed25519_Seed, + salty["transferable"], + salty["pidx"], + 0, + salty["kidx"], false) let _signers = [] for (let signer of signers.signers) { @@ -262,7 +264,7 @@ export class Controller { for (let signer of signers) { _signers.push(signer.verfer.qb64) } - + if (pubs.join(",") != _signers.join(",")) { throw new Error(`unable to rotate, validation of encrypted public keys ${pubs} failed`) } diff --git a/src/keri/app/credentialing.ts b/src/keri/app/credentialing.ts index b6d2fb17..d58eda88 100644 --- a/src/keri/app/credentialing.ts +++ b/src/keri/app/credentialing.ts @@ -1,15 +1,11 @@ import { SignifyClient } from "./clienting" -import {Salter} from "../core/salter" -import { interact, messagize} from "../core/eventing" -import {b, Dict, Ident, Ilks, Serials, versify} from "../core/core" -import {MtrDex} from "../core/matter" -import {Saider} from "../core/saider" -import {Serder} from "../core/serder" -import {Siger} from "../core/siger" -import {Prefixer} from "../core/prefixer" -import {randomNonce} from "./coring" -import {TextDecoder} from "util" - +import { Salter } from "../core/salter" +import { interact } from "../core/eventing" +import { b, Dict, Ident, Ilks, Serials, versify } from "../core/core" +import { MtrDex } from "../core/matter" +import { Saider } from "../core/saider" +import { Prefixer } from "../core/prefixer" +import { randomNonce } from "./coring" /** Types of credentials */ export class CredentialTypes { @@ -19,9 +15,9 @@ export class CredentialTypes { /** Credential filter parameters */ export interface CredentialFilter { - filter?: object, - sort?: object[], - skip?: number, + filter?: object, + sort?: object[], + skip?: number, limit?: number } @@ -45,7 +41,7 @@ export class Credentials { * @param {CredentialFilter} [kargs] Optional parameters to filter the credentials * @returns {Promise} A promise to the list of credentials */ - async list(name: string, kargs:CredentialFilter ={}): Promise { + async list(name: string, kargs: CredentialFilter = {}): Promise { let path = `/identifiers/${name}/credentials/query` let filtr = kargs.filter === undefined ? {} : kargs.filter; let sort = kargs.sort === undefined ? [] : kargs.sort; @@ -75,26 +71,35 @@ export class Credentials { async get(name: string, said: string, includeCESR: boolean = false): Promise { let path = `/identifiers/${name}/credentials/${said}` let method = 'GET' - let headers = includeCESR? new Headers({'Accept': 'application/json+cesr'}) : new Headers({'Accept': 'application/json'}) + let headers = includeCESR ? new Headers({ 'Accept': 'application/json+cesr' }) : new Headers({ 'Accept': 'application/json' }) let res = await this.client.fetch(path, method, null, headers) - return includeCESR? await res.text() : await res.json() + return includeCESR ? await res.text() : await res.json() } - /** - * Issue a credential - * @async - * @param {string} name Name or alias of the identifier - * @param {string} registy qb64 AID of credential registry - * @param {string} schema SAID of the schema - * @param {string} [recipient] Optional prefix of recipient identifier - * @param {any} [credentialData] Optional credential data - * @param {any} [rules] Optional credential rules - * @param {any} [source] Optional credential sources - * @param {boolean} [priv=false] Flag to issue a credential with privacy preserving features - * @returns {Promise} A promise to the long-running operation - */ - async issue(name: string, registy: string, schema: string, recipient?: string, credentialData?: any, rules?: any, source?: any, priv: boolean=false): Promise { + /** + * Create a credential + * @async + * @param {any} name - Identifier + * @param {string} registry - Registry + * @param {Dict} credentialData - Data for the credential + * @param string schema - Schema + * @param {string} [recipient] - Recipient of the credential + * @param {Dict} [edges] - Edges for the credential + * @param {Dict} [rules] - Rules for the credential + * @param {boolean} [priv] - Private credential + * @param {string} [timestamp] - Timestamp for the credential + */ + + async create( + name: any, + registry: string, + credentialData: any, + schema: string, + recipient: string | undefined, + edges: Dict | undefined = undefined, + rules: Dict | undefined = undefined, + priv: boolean) { // Create Credential let hab = await this.client.identifiers().get(name) let pre: string = hab.prefix @@ -118,21 +123,21 @@ export class Credentials { subject.i = recipient } subject.dt = dt - subject = {...subject, ...credentialData} + subject = { ...subject, ...credentialData } - const [, a] = Saider.saidify(subject,undefined,undefined,"d") + const [, a] = Saider.saidify(subject, undefined, undefined, "d") - cred = {...cred, i:pre} - cred.ri = registy - cred = {...cred,...{s: schema}, ...{a: a}} + cred = { ...cred, i: pre } + cred.ri = registry + cred = { ...cred, ...{ s: schema }, ...{ a: a } } - if (source !== undefined ) { - cred.e = source + if (edges !== undefined) { + cred.e = edges } if (rules !== undefined) { cred.r = rules } - const [, vc] = Saider.saidify(cred) + const [vcSaid, vc] = Saider.saidify(cred) // Create iss let _iss = { @@ -141,20 +146,19 @@ export class Credentials { d: "", i: vc.d, s: "0", - ri: registy, + ri: registry, dt: dt } - let [, iss] = Saider.saidify(_iss) + let [issSaid, iss] = Saider.saidify(_iss) // Create paths and sign - let cpath = '6AABAAA-' let keeper = this.client!.manager!.get(hab) - let csigs = keeper.sign(b(JSON.stringify(vc))) // Create ixn let ixn = {} + let ixnSaid = undefined let sigs = [] let state = hab.state @@ -167,7 +171,7 @@ export class Credentials { let sn = Number(state.s) let dig = state.d - let data:any = [{ + let data: any = [{ i: iss.i, s: iss.s, d: iss.d @@ -178,232 +182,66 @@ export class Credentials { throw new Error("Establishment only not implemented") } else { - let serder = interact({ pre: pre, sn: sn + 1, data: data, dig: dig, version: undefined, kind: undefined }) - sigs = keeper.sign(b(serder.raw)) - ixn = serder.ked + let [_ixnSaid, ixnSerder] = interact({ pre: pre, sn: sn + 1, data: data, dig: dig, version: undefined, kind: undefined }) + ixnSaid = _ixnSaid + sigs = keeper.sign(b(ixnSerder.raw)) + ixn = ixnSerder.ked } + let res = await this.createFromEvents(name, vc, iss, ixn, sigs) - let body = { - cred: vc, - csigs: csigs, - path: cpath, + return [vcSaid, vc, issSaid, iss, ixnSaid, ixn, sigs, res] + + } + + async createFromEvents(name: string, creder: any, iss: any, anc: any, sigs: any[]) { + let data: any = { iss: iss, - ixn: ixn, + acdc: creder, + ixn: anc, sigs: sigs } + console.log(data) let path = `/identifiers/${name}/credentials` let method = 'POST' let headers = new Headers({ - 'Accept': 'application/json+cesr' - + 'Accept': 'application/json' }) - let res = await this.client.fetch(path, method, body, headers) + let res = await this.client.fetch(path, method, data, headers) return await res.json() } +} +export class Ipex { + public client: SignifyClient /** - * Revoke credential - * @async - * @param {string} name Name or alias of the identifier - * @param {string} said SAID of the credential - * @returns {Promise} A promise to the long-running operation + * Ipex + * @param {SignifyClient} client */ - async revoke(name: string, said: string): Promise { - let hab = await this.client.identifiers().get(name) - let pre: string = hab.prefix - - const vs = versify(Ident.KERI, undefined, Serials.JSON, 0) - const dt = new Date().toISOString().replace('Z', '000+00:00') - - let cred = await this.get(name, said) - - // Create rev - let _rev = { - v: vs, - t: Ilks.rev, - d: "", - i: said, - s: "1", - p: cred.status.d, - ri: cred.sad.ri, - dt: dt - } - - let [, rev] = Saider.saidify(_rev) - - // create ixn - let ixn = {} - let sigs = [] - - let state = hab.state - if (state.c !== undefined && state.c.includes("EO")) { - var estOnly = true - } - else { - var estOnly = false - } - - let sn = Number(state.s) - let dig = state.d - - let data:any = [{ - i: rev.i, - s: rev.s, - d: rev.d - }] - if (estOnly) { - // TODO implement rotation event - throw new Error("Establishment only not implemented") - - } else { - let serder = interact({ pre: pre, sn: sn + 1, data: data, dig: dig, version: undefined, kind: undefined }) - let keeper = this.client!.manager!.get(hab) - sigs = keeper.sign(b(serder.raw)) - ixn = serder.ked - } - - let body = { - rev: rev, - ixn: ixn, - sigs: sigs - } - - let path = `/identifiers/${name}/credentials/${said}` - let method = 'DELETE' - let headers = new Headers({ - 'Accept': 'application/json+cesr' - - }) - let res = await this.client.fetch(path, method, body, headers) - return await res.json() - + constructor(client: SignifyClient) { + this.client = client } - /** - * Present a credential - * @async - * @param {string} name Name or alias of the identifier - * @param {string} said SAID of the credential - * @param {string} recipient Identifier prefix of the receiver of the presentation - * @param {boolean} [include=true] Flag to indicate whether to stream credential alongside presentation exchange message - * @returns {Promise} A promise to the long-running operation - */ - async present(name: string, said: string, recipient: string, include: boolean=true): Promise { - + async grant(name: string, recp: string, message: string, acdc: any, iss: any, anc: any, date: string) { + let exchanges = this.client.exchanges() let hab = await this.client.identifiers().get(name) - let pre: string = hab.prefix + let sender = hab.prefix - let cred = await this.get(name, said) let data = { - i: cred.sad.i, - s: cred.sad.s, - n: said - } - - const vs = versify(Ident.KERI, undefined, Serials.JSON, 0) - - const _sad = { - v: vs, - t: Ilks.exn, - d: "", - dt: new Date().toISOString().replace("Z","000+00:00"), - r: "/presentation", - q: {}, - a: data + m: message, + i: recp } - const [, sad] = Saider.saidify(_sad) - const exn = new Serder(sad) - - let keeper = this.client!.manager!.get(hab) - - let sig = keeper.sign(b(exn.raw),true) - - let siger = new Siger({qb64:sig[0]}) - let seal = ["SealLast" , {i:pre}] - let ims = messagize(exn,[siger],seal, undefined, undefined, true) - ims = ims.slice(JSON.stringify(exn.ked).length) - - - let body = { - exn: exn.ked, - sig: new TextDecoder().decode(ims), - recipient: recipient, - include: include + let embeds = { + acdc: acdc, + iss: iss, + anc: anc } + let [grant, gsigs, end] = exchanges.createExchangeMessage(sender, "/ipex/grant", data, embeds, date) - let path = `/identifiers/${name}/credentials/${said}/presentations` - let method = 'POST' - let headers = new Headers({ - 'Accept': 'application/json+cesr' - - }) - let res = await this.client.fetch(path, method, body, headers) - return await res.text() - + return [grant, gsigs, end] } - /** - * Request a presentation of a credential - * @async - * @param {string} name Name or alias of the identifier - * @param {string} recipient Identifier prefix of the receiver of the presentation - * @param {string} schema SAID of the schema - * @param {string} [issuer] Optional prefix of the issuer of the credential - * @returns {Promise} A promise to the long-running operation - */ - async request(name: string, recipient: string, schema: string, issuer?: string): Promise { - let hab = await this.client.identifiers().get(name) - let pre: string = hab.prefix - - let data:any = { - s: schema - } - if (issuer !== undefined) { - data["i"] = issuer - } - - const vs = versify(Ident.KERI, undefined, Serials.JSON, 0) - - const _sad = { - v: vs, - t: Ilks.exn, - d: "", - dt: new Date().toISOString().replace("Z","000+00:00"), - r: "/presentation/request", - q: {}, - a: data - } - const [, sad] = Saider.saidify(_sad) - const exn = new Serder(sad) - - let keeper = this.client!.manager!.get(hab) - - let sig = keeper.sign(b(exn.raw),true) - - let siger = new Siger({qb64:sig[0]}) - let seal = ["SealLast" , {i:pre}] - let ims = messagize(exn,[siger],seal, undefined, undefined, true) - ims = ims.slice(JSON.stringify(exn.ked).length) - - - let body = { - exn: exn.ked, - sig: new TextDecoder().decode(ims), - recipient: recipient, - } - - let path = `/identifiers/${name}/requests` - let method = 'POST' - let headers = new Headers({ - 'Accept': 'application/json+cesr' - - }) - let res = await this.client.fetch(path, method, body, headers) - return await res.text() - - } } /** @@ -425,7 +263,7 @@ export class Registries { * @param {string} name Name or alias of the identifier * @returns {Promise} A promise to the list of registries */ - async list(name:string): Promise { + async list(name: string): Promise { let path = `/identifiers/${name}/registries` let method = 'GET' let res = await this.client.fetch(path, method, null) @@ -441,7 +279,7 @@ export class Registries { * @param {string} [nonce] Nonce used to generate the registry. If not provided a random nonce will be generated * @returns {Promise} A promise to the long-running operation */ - async create(name: string, registryName: string, nonce?:string): Promise { + async create(name: string, registryName: string, nonce?: string): Promise { // TODO add backers option // TODO get estOnly from get_identifier ? @@ -464,7 +302,7 @@ export class Registries { n: nonce } - let prefixer = new Prefixer({code: MtrDex.Blake3_256}, vcp) + let prefixer = new Prefixer({ code: MtrDex.Blake3_256 }, vcp) vcp.i = prefixer.qb64 vcp.d = prefixer.qb64 @@ -492,7 +330,7 @@ export class Registries { d: prefixer.qb64 }] - let serder = interact({pre: pre, sn: sn + 1, data: data, dig: dig, version: undefined, kind: undefined}) + let [, serder] = interact({ pre: pre, sn: sn + 1, data: data, dig: dig, version: undefined, kind: undefined }) let keeper = this.client!.manager!.get(hab) sigs = keeper.sign(b(serder.raw)) ixn = serder.ked diff --git a/src/keri/app/exchanging.ts b/src/keri/app/exchanging.ts index 56554534..c9cd686b 100644 --- a/src/keri/app/exchanging.ts +++ b/src/keri/app/exchanging.ts @@ -29,11 +29,11 @@ export class Exchanges { * @param payload * @param embeds */ - createExchangeMessage(sender: Dict, route: string, payload: Dict, embeds: Dict): [Serder, string[], string] { + createExchangeMessage(sender: Dict, route: string, payload: Dict, embeds: Dict, date: string | undefined): [Serder, string[], string] { let keeper = this.client.manager!.get(sender) let [exn, end] = exchange(route, payload, - sender["prefix"], undefined, undefined, undefined, undefined, embeds) + sender["prefix"], undefined, date, undefined, undefined, embeds) let sigs = keeper.sign(b(exn.raw)) return [exn, sigs, d(end)] @@ -52,9 +52,9 @@ export class Exchanges { * @param recipients */ async send(name: string, topic: string, sender: Dict, route: string, payload: Dict, embeds: Dict, - recipients: string[]): Promise { + recipients: string[], date: string | undefined): Promise { - let [exn, sigs, atc] = this.createExchangeMessage(sender, route, payload, embeds) + let [exn, sigs, atc] = this.createExchangeMessage(sender, route, payload, embeds, date) return await this.sendFromEvents(name, topic, exn, sigs, atc, recipients) } @@ -92,7 +92,7 @@ export function exchange(route: string, payload: Dict, sender: string, recipient?: string, - date?: string, + date?: string | undefined, dig?: string, modifiers?: Dict, embeds?: Dict): [Serder, Uint8Array] { @@ -100,7 +100,7 @@ export function exchange(route: string, const vs = versify(Ident.KERI, undefined, Serials.JSON, 0) const ilk = Ilks.exn - const dt = date !== undefined ? date : nowUTC().toISOString() + const dt = date !== undefined ? date : nowUTC().toISOString().replace("Z", "000+00:00") const p = dig !== undefined ? dig : "" const q = modifiers !== undefined ? modifiers : {} const ems = embeds != undefined ? embeds : {} diff --git a/src/keri/core/eventing.ts b/src/keri/core/eventing.ts index 58648b2c..a0c79e4a 100644 --- a/src/keri/core/eventing.ts +++ b/src/keri/core/eventing.ts @@ -427,7 +427,7 @@ interface InteractArgs { kind: Serials | undefined } -export function interact(args: InteractArgs): Serder { +export function interact(args: InteractArgs): [Saider, Serder] { let { pre, dig, sn, data, version, kind } = args let vs = versify(Ident.KERI, version, kind, 0) let ilk = Ilks.ixn @@ -448,10 +448,10 @@ export function interact(args: InteractArgs): Serder { p: dig, a: data } as Dict + let kedSaid: Saider + [kedSaid, ked] = Saider.saidify(ked) - [, ked] = Saider.saidify(ked) - - return new Serder(ked) + return [kedSaid, new Serder(ked)] } export function reply(route: string="", data: any|undefined, stamp:string|undefined, version: Version|undefined, kind:Serials= Serials.JSON){ diff --git a/src/keri/core/saider.ts b/src/keri/core/saider.ts index 21715731..9a9875b4 100644 --- a/src/keri/core/saider.ts +++ b/src/keri/core/saider.ts @@ -1,9 +1,9 @@ -import {DigiDex, Matter, MatterArgs, MtrDex} from "./matter"; -import {deversify, Dict, Serials} from "./core"; -import {EmptyMaterialError} from "./kering"; -import {dumps, sizeify} from "./serder"; +import { DigiDex, Matter, MatterArgs, MtrDex } from "./matter"; +import { deversify, Dict, Serials } from "./core"; +import { EmptyMaterialError } from "./kering"; +import { dumps, sizeify } from "./serder"; -import {createHash} from "blake3" +import { createHash } from "blake3" const Dummy = "#" @@ -29,9 +29,10 @@ export class Saider extends Matter { [MtrDex.Blake3_256, new Digestage(Saider._derive_blake3_256, undefined, undefined)] ]) - constructor({raw, code, qb64b, qb64, qb2}: MatterArgs, sad?: Dict, kind?: Serials, label: string = Ids.d) { + constructor({ raw, code, qb64b, qb64, qb2 }: MatterArgs, sad?: Dict, kind?: Serials, label: string = Ids.d) { try { - super({raw, code, qb64b, qb64, qb2}); + super({ raw, code, qb64b, qb64, qb2 }); + } catch (e) { if (e instanceof EmptyMaterialError) { if (sad == undefined || !(label in sad)) { @@ -40,7 +41,7 @@ export class Saider extends Matter { if (code == undefined) { if (sad[label] != "") { - super({qb64: sad[label], code: code}) + super({ qb64: sad[label], code: code }) code = this.code } else { code = MtrDex.Blake3_256 @@ -50,9 +51,8 @@ export class Saider extends Matter { if (!DigiDex.has(code)) { throw new Error(`Unsupported digest code = ${code}`) } - - [raw] = Saider._derive({...sad}, code, kind, label) - super({raw: raw, code: code}) + [raw] = Saider._derive({ ...sad }, code, kind, label) + super({ raw: raw, code: code }) } else { throw e } @@ -75,13 +75,13 @@ export class Saider extends Matter { throw new Error(`Unsupported digest code = ${code}.`) } - sad = {...sad} + sad = { ...sad } sad[label] = "".padStart(Matter.Sizes.get(code)!.fs!, Dummy) if ('v' in sad) { - [, , kind, sad, ] = sizeify(sad, kind) + [, , kind, sad,] = sizeify(sad, kind) } - let ser = {...sad} + let ser = { ...sad } let digestage = Saider.Digests.get(code) @@ -98,16 +98,16 @@ export class Saider extends Matter { return [digestage!.klas(cpa, ...args), sad] } - public derive(sad: Dict, code: string, kind: Serials | undefined, label: string) : [Uint8Array, Dict]{ + public derive(sad: Dict, code: string, kind: Serials | undefined, label: string): [Uint8Array, Dict] { code = code != undefined ? code : this.code return Saider._derive(sad, code, kind, label) } public verify(sad: Dict, prefixed: boolean = false, versioned: boolean = false, kind?: Serials, - label: string = Ids.d): boolean { + label: string = Ids.d): boolean { try { let [raw, dsad] = Saider._derive(sad, this.code, kind, label) - let saider = new Saider({raw: raw, code: this.code}) + let saider = new Saider({ raw: raw, code: this.code }) if (this.qb64 != saider.qb64) { return false } @@ -132,7 +132,7 @@ export class Saider extends Matter { private static _serialze(sad: Dict, kind?: Serials): string { let knd = Serials.JSON if ('v' in sad) { - [,knd] = deversify(sad['v']) + [, knd] = deversify(sad['v']) } if (kind == undefined) { @@ -143,13 +143,13 @@ export class Saider extends Matter { } public static saidify(sad: Dict, code: string = MtrDex.Blake3_256, kind: Serials = Serials.JSON, - label: string = Ids.d): [Saider, Dict] { + label: string = Ids.d): [Saider, Dict] { if (!(label in sad)) { throw new Error(`Missing id field labeled=${label} in sad.`) } let raw - [raw, sad]= Saider._derive(sad, code, kind, label) - let saider = new Saider({raw: raw, code: code}, undefined, kind, label) + [raw, sad] = Saider._derive(sad, code, kind, label) + let saider = new Saider({ raw: raw, code: code }, undefined, kind, label) sad[label] = saider.qb64 return [saider, sad] } diff --git a/src/keri/core/utils.ts b/src/keri/core/utils.ts index fe68254b..03b29ada 100644 --- a/src/keri/core/utils.ts +++ b/src/keri/core/utils.ts @@ -1,4 +1,4 @@ - +import { Counter, CtrDex } from "./counter"; export function pad(n: any, width = 3, z = 0) { return (String(z).repeat(width) + String(n)).slice(String(n).length); } @@ -117,3 +117,28 @@ export function bytesToInt(ar: Uint8Array): number { return value; } + + +// def serialize(creder, prefixer, seqner, saider): +// craw = bytearray(creder.raw) +// craw.extend(coring.Counter(coring.CtrDex.SealSourceTriples, count=1).qb64b) +// craw.extend(prefixer.qb64b) +// craw.extend(seqner.qb64b) +// craw.extend(saider.qb64b) + +// return bytes(craw) + +export function seralize(creder: any, prefixer: any, seqner: any, saider: any) { + let craw =creder.raw; + let ctr = new Counter({code:CtrDex.SealSourceTriples, count:1}).qb64b; + let prefix = prefixer.qb64b; + let seq = seqner.qb64b; + let said = saider.qb64b; + let newCraw = new Uint8Array(craw.length + ctr.length + prefix.length + seq.length + said.length); + newCraw.set(craw); + newCraw.set(ctr, craw.length); + newCraw.set(prefix, craw.length + ctr.length); + newCraw.set(seq, craw.length + ctr.length + prefix.length); + newCraw.set(said, craw.length + ctr.length + prefix.length + seq.length); + return newCraw; +} \ No newline at end of file diff --git a/test/app/credentialing.test.ts b/test/app/credentialing.test.ts index 921baedf..f7010f3f 100644 --- a/test/app/credentialing.test.ts +++ b/test/app/credentialing.test.ts @@ -144,69 +144,26 @@ describe('Credentialing', () => { const registry = "EP10ooRj0DJF0HWZePEYMLPl-arMV-MAoTKK-o3DXbgX" const schema = "EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao" const isuee = "EG2XjQN-3jPN5rcR4spLjaJyM4zA6Lgg-Hd5vSMymu5p" - await credentials.issue('aid1',registry,schema,isuee,{LEI: '1234'},{},{},false) + + await credentials.create('aid1',registry,{LEI: '1234'},schema,isuee,{},{},false) lastCall = fetchMock.mock.calls[fetchMock.mock.calls.length-1]! lastBody = JSON.parse(lastCall[1]!.body!.toString()) assert.equal(lastCall[0]!,url+'/identifiers/aid1/credentials') assert.equal(lastCall[1]!.method,'POST') - assert.equal(lastBody.cred.ri,registry) - assert.equal(lastBody.cred.s,schema) - assert.equal(lastBody.cred.a.i,isuee) - assert.equal(lastBody.cred.a.LEI,'1234') + assert.equal(lastBody.acdc.ri,registry) + assert.equal(lastBody.acdc.s,schema) + assert.equal(lastBody.acdc.a.i,isuee) + assert.equal(lastBody.acdc.a.LEI,'1234') assert.equal(lastBody.iss.s,"0") assert.equal(lastBody.iss.t,"iss") assert.equal(lastBody.iss.ri,registry) - assert.equal(lastBody.iss.i,lastBody.cred.d) - assert.equal(lastBody.ixn.t,"ixn") - assert.equal(lastBody.ixn.i,lastBody.cred.i) - assert.equal(lastBody.ixn.p,lastBody.cred.i) - assert.equal(lastBody.path,'6AABAAA-') - assert.equal(lastBody.csigs[0].substring(0,2),'AA') - assert.equal(lastBody.csigs[0].length,88) - assert.equal(lastBody.sigs[0].substring(0,2),'AA') - assert.equal(lastBody.sigs[0].length,88) - - const credential = lastBody.cred.i - await credentials.revoke('aid1',credential) - lastCall = fetchMock.mock.calls[fetchMock.mock.calls.length-1]! - lastBody = JSON.parse(lastCall[1]!.body!.toString()) - assert.equal(lastCall[0]!,url+'/identifiers/aid1/credentials/'+credential) - assert.equal(lastCall[1]!.method,'DELETE') - assert.equal(lastBody.rev.s,"1") - assert.equal(lastBody.rev.t,"rev") - assert.equal(lastBody.rev.ri,"EGK216v1yguLfex4YRFnG7k1sXRjh3OKY7QqzdKsx7df") - assert.equal(lastBody.rev.i,"ELUvZ8aJEHAQE-0nsevyYTP98rBbGJUrTj5an-pCmwrK") + assert.equal(lastBody.iss.i,lastBody.acdc.d) assert.equal(lastBody.ixn.t,"ixn") - assert.equal(lastBody.ixn.i,"ELUvZ8aJEHAQE-0nsevyYTP98rBbGJUrTj5an-pCmwrK") - assert.equal(lastBody.ixn.p,"ELUvZ8aJEHAQE-0nsevyYTP98rBbGJUrTj5an-pCmwrK") + assert.equal(lastBody.ixn.i,lastBody.acdc.i) + assert.equal(lastBody.ixn.p,lastBody.acdc.i) assert.equal(lastBody.sigs[0].substring(0,2),'AA') assert.equal(lastBody.sigs[0].length,88) - await credentials.present('aid1',credential, "EP10ooRj0DJF0HWZePEYMLPl-arMV-MAoTKK-o3DXbgX",false) - lastCall = fetchMock.mock.calls[fetchMock.mock.calls.length-1]! - lastBody = JSON.parse(lastCall[1]!.body!.toString()) - assert.equal(lastCall[0]!,url+'/identifiers/aid1/credentials/'+credential+'/presentations') - assert.equal(lastCall[1]!.method,'POST') - assert.equal(lastBody.exn.t,"exn") - assert.equal(lastBody.exn.r,"/presentation") - assert.equal(lastBody.exn.a.n,"ELUvZ8aJEHAQE-0nsevyYTP98rBbGJUrTj5an-pCmwrK") - assert.equal(lastBody.exn.a.s,schema) - assert.equal(lastBody.sig.length,144) - assert.equal(lastBody.recipient,"EP10ooRj0DJF0HWZePEYMLPl-arMV-MAoTKK-o3DXbgX") - assert.equal(lastBody.include, false) - - await credentials.request('aid1', "EP10ooRj0DJF0HWZePEYMLPl-arMV-MAoTKK-o3DXbgX", credential,"EP10ooRj0DJF0HWZePEYMLPl-arMV-MAoTKK-o3DXbgX") - lastCall = fetchMock.mock.calls[fetchMock.mock.calls.length-1]! - lastBody = JSON.parse(lastCall[1]!.body!.toString()) - assert.equal(lastCall[0]!,url+'/identifiers/aid1/requests') - assert.equal(lastCall[1]!.method,'POST') - assert.equal(lastBody.exn.t,"exn") - assert.equal(lastBody.exn.r,"/presentation/request") - assert.equal(lastBody.exn.a.i,registry) - assert.equal(lastBody.exn.a.s,"ELUvZ8aJEHAQE-0nsevyYTP98rBbGJUrTj5an-pCmwrK") - assert.equal(lastBody.sig.length,144) - assert.equal(lastBody.recipient,"EP10ooRj0DJF0HWZePEYMLPl-arMV-MAoTKK-o3DXbgX") - })