UNPKG

@credo-ts/core

Version:

<p align="center"> <br /> <img alt="Credo Logo" src="https://github.com/openwallet-foundation/credo-ts/blob/c7886cb8377ceb8ee4efe8d264211e561a75072d/images/credo-logo.png" height="250px" /> </p> <h1 align="center"><b>Credo - Core</b></h1

1 lines • 7.73 kB
{"version":3,"file":"SdJwtVcRecord.mjs","names":[],"sources":["../../../../src/modules/sd-jwt-vc/repository/SdJwtVcRecord.ts"],"sourcesContent":["import { decodeSdJwtSync } from '@sd-jwt/decode'\nimport { Hasher } from '../../../crypto'\nimport type { TagsBase } from '../../../storage/BaseRecord'\nimport { BaseRecord } from '../../../storage/BaseRecord'\nimport type { NonEmptyArray } from '../../../types'\nimport { JsonTransformer } from '../../../utils'\nimport { CredentialMultiInstanceState } from '../../../utils/credentialUseTypes'\nimport type { Constructable } from '../../../utils/mixins'\nimport { uuid } from '../../../utils/uuid'\nimport type { KnownJwaSignatureAlgorithm } from '../../kms'\nimport { decodeSdJwtVc } from '../decodeSdJwtVc'\nimport type { SdJwtVc } from '../SdJwtVcService'\nimport type { SdJwtVcTypeMetadata } from '../typeMetadata'\n\nexport type DefaultSdJwtVcRecordTags = {\n vct: string\n\n /**\n * The sdAlg is the alg used for creating digests for selective disclosures\n */\n sdAlg: string\n\n /**\n * The alg is the alg used to sign the SD-JWT\n */\n alg: KnownJwaSignatureAlgorithm\n\n /**\n * @since 0.6 - tag was not defined before 0.6\n */\n multiInstanceState?: CredentialMultiInstanceState\n}\n\nexport type SdJwtVcRecordStorageProps = {\n id?: string\n createdAt?: Date\n tags?: TagsBase\n\n /**\n * The SD-JWT VC instances to store on the record.\n *\n * NOTE that all instances should contain roughly the same data (e.g. exp can differ slighty), as they should be usable\n * interchangeably for presentations (allowing single-use credentials and batch issuance).\n */\n credentialInstances: SdJwtVcRecordInstances\n\n /**\n * Optional VCT type metadata associated with the SD JWT VC instances, this type metadata is used for\n * all SD JWT VC instances on this record.\n *\n * The type metadata is the result of resolving and merging the vct value and all `extends` values.\n *\n * NOTE: This may only include the latest VCT document, if the credential was stored before resolving\n * `extends` claims was supported.\n */\n typeMetadata?: SdJwtVcTypeMetadata\n\n /**\n * The original chain of SD-JWT VC Type Metadata documents, ordered from the extending type to the last extended type.\n * This is stored on the record to allow extensions to the type metadata (e.g. EUDI ARF TS12 for payments) to apply a\n * custom merging strategy.\n */\n typeMetadataChain?: NonEmptyArray<SdJwtVcTypeMetadata>\n}\n\nexport type SdJwtVcRecordInstances = NonEmptyArray<{\n compactSdJwtVc: string\n\n /**\n * The kms key id to which the credential is bound. If not defined it either:\n * - uses a legacy key id (which can be calculated based on the key)\n * - is bound to a did (which stores the kms key id on the did record)\n */\n kmsKeyId?: string\n}>\n\nexport class SdJwtVcRecord extends BaseRecord<DefaultSdJwtVcRecordTags> {\n public static readonly type = 'SdJwtVcRecord'\n public readonly type = SdJwtVcRecord.type\n\n public credentialInstances!: SdJwtVcRecordInstances\n\n /**\n * Tracks the state of credential instances on this record.\n *\n * NOTE: This defaults to `CredentialMultiInstanceState.SingleInstanceUsed` for records that\n * don't have a value set from before 0.6. We assume the credential has already been used.\n */\n public multiInstanceState = CredentialMultiInstanceState.SingleInstanceUsed\n\n /**\n * Only here for class transformation. If compactSdJwtVc is set we transform\n * it to the new sdJwtVcs array format\n */\n private set compactSdJwtVc(compactSdJwtVc: string) {\n this.credentialInstances = [\n {\n compactSdJwtVc,\n },\n ]\n }\n\n public typeMetadata?: SdJwtVcTypeMetadata\n\n /**\n * The original chain of SD-JWT VC Type Metadata documents, ordered from the extending type to the last extended type.\n * This is stored on the record to allow extensions to the type metadata (e.g. EUDI ARF TS12 for payments) to apply a\n * custom merging strategy.\n */\n public typeMetadataChain?: NonEmptyArray<SdJwtVcTypeMetadata>\n\n public constructor(props: SdJwtVcRecordStorageProps) {\n super()\n\n if (props) {\n this.id = props.id ?? uuid()\n this.createdAt = props.createdAt ?? new Date()\n\n this.credentialInstances = props.credentialInstances\n\n // Set multiInstanceState based on the number of initial instances. We\n // assume the instance is unused when the record is created.\n this.multiInstanceState =\n this.credentialInstances.length === 1\n ? CredentialMultiInstanceState.SingleInstanceUnused\n : CredentialMultiInstanceState.MultiInstanceFirstUnused\n\n this.typeMetadata = props.typeMetadata\n this.typeMetadataChain = props.typeMetadataChain\n this._tags = props.tags ?? {}\n }\n }\n\n public get firstCredential(): SdJwtVc {\n return {\n ...decodeSdJwtVc(this.credentialInstances[0].compactSdJwtVc, this.typeMetadata),\n kmsKeyId: this.credentialInstances[0].kmsKeyId,\n }\n }\n\n public static fromSdJwtVc(sdJwtVc: SdJwtVc) {\n return new SdJwtVcRecord({\n credentialInstances: [\n {\n compactSdJwtVc: sdJwtVc.compact,\n kmsKeyId: sdJwtVc.kmsKeyId,\n },\n ],\n typeMetadata: sdJwtVc.typeMetadata,\n })\n }\n\n public get extendedVctValues() {\n return this.typeMetadataChain\n ? // Remove the first one, as that's not extended\n this.typeMetadataChain.slice(1).map(({ vct }) => vct)\n : this.typeMetadata?.extends\n ? [this.typeMetadata.extends]\n : []\n }\n\n public getTags() {\n const sdjwt = decodeSdJwtSync(this.credentialInstances[0].compactSdJwtVc, Hasher.hash)\n const vct = sdjwt.jwt.payload.vct as string\n const sdAlg = sdjwt.jwt.payload._sd_alg as string | undefined\n const alg = sdjwt.jwt.header.alg as KnownJwaSignatureAlgorithm\n\n return {\n ...this._tags,\n vct,\n extendedVctValues: this.extendedVctValues,\n sdAlg: sdAlg ?? 'sha-256',\n alg,\n multiInstanceState: this.multiInstanceState,\n }\n }\n\n public clone(): this {\n return JsonTransformer.fromJSON(JsonTransformer.toJSON(this), this.constructor as Constructable<this>)\n }\n\n /**\n * encoded is convenience method added to all credential records\n */\n public get encoded(): string {\n return this.credentialInstances[0].compactSdJwtVc\n }\n}\n"],"mappings":";;;;;;;;;;;;;AA4EA,IAAa,gBAAb,MAAa,sBAAsB,WAAqC;;;;;CAkBtE,IAAY,eAAe,gBAAwB;AACjD,OAAK,sBAAsB,CACzB,EACE,gBACD,CACF;;CAYH,AAAO,YAAY,OAAkC;AACnD,SAAO;OAlCO,OAAO,cAAc;OAU9B,qBAAqB,6BAA6B;AA0BvD,MAAI,OAAO;AACT,QAAK,KAAK,MAAM,MAAM,MAAM;AAC5B,QAAK,YAAY,MAAM,6BAAa,IAAI,MAAM;AAE9C,QAAK,sBAAsB,MAAM;AAIjC,QAAK,qBACH,KAAK,oBAAoB,WAAW,IAChC,6BAA6B,uBAC7B,6BAA6B;AAEnC,QAAK,eAAe,MAAM;AAC1B,QAAK,oBAAoB,MAAM;AAC/B,QAAK,QAAQ,MAAM,QAAQ,EAAE;;;CAIjC,IAAW,kBAA2B;AACpC,SAAO;GACL,GAAG,cAAc,KAAK,oBAAoB,GAAG,gBAAgB,KAAK,aAAa;GAC/E,UAAU,KAAK,oBAAoB,GAAG;GACvC;;CAGH,OAAc,YAAY,SAAkB;AAC1C,SAAO,IAAI,cAAc;GACvB,qBAAqB,CACnB;IACE,gBAAgB,QAAQ;IACxB,UAAU,QAAQ;IACnB,CACF;GACD,cAAc,QAAQ;GACvB,CAAC;;CAGJ,IAAW,oBAAoB;AAC7B,SAAO,KAAK,oBAER,KAAK,kBAAkB,MAAM,EAAE,CAAC,KAAK,EAAE,UAAU,IAAI,GACrD,KAAK,cAAc,UACjB,CAAC,KAAK,aAAa,QAAQ,GAC3B,EAAE;;CAGV,AAAO,UAAU;EACf,MAAM,QAAQ,gBAAgB,KAAK,oBAAoB,GAAG,gBAAgB,OAAO,KAAK;EACtF,MAAM,MAAM,MAAM,IAAI,QAAQ;EAC9B,MAAM,QAAQ,MAAM,IAAI,QAAQ;EAChC,MAAM,MAAM,MAAM,IAAI,OAAO;AAE7B,SAAO;GACL,GAAG,KAAK;GACR;GACA,mBAAmB,KAAK;GACxB,OAAO,SAAS;GAChB;GACA,oBAAoB,KAAK;GAC1B;;CAGH,AAAO,QAAc;AACnB,SAAO,gBAAgB,SAAS,gBAAgB,OAAO,KAAK,EAAE,KAAK,YAAmC;;;;;CAMxG,IAAW,UAAkB;AAC3B,SAAO,KAAK,oBAAoB,GAAG;;;cA5Gd,OAAO"}