@verii/verii-issuing 1.0.0-pre.1754543687
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +62 -0
- package/LICENSE +202 -0
- package/NOTICE +1 -0
- package/README.md +183 -0
- package/jsconfig.json +10 -0
- package/package.json +58 -0
- package/src/adapters/build-issuer-vc-url.js +44 -0
- package/src/adapters/build-revocation-url.js +47 -0
- package/src/adapters/create-revocation-list.js +39 -0
- package/src/adapters/get-revocation-registry.js +48 -0
- package/src/adapters/init-credential-metadata-contract.js +102 -0
- package/src/adapters/mongo-allocation-list-queries.js +123 -0
- package/src/allocate-list-entries.js +76 -0
- package/src/domain/build-verifiable-credentials.js +116 -0
- package/src/domain/hash-offer.js +35 -0
- package/src/domain/prepare-jsonld-credential.js +219 -0
- package/src/index.js +22 -0
- package/src/issue-verii-credentials.js +104 -0
- package/src/utils/allocate-array.js +28 -0
- package/src/utils/constants.js +29 -0
- package/src/utils/generate-list-index.js +26 -0
- package/types/types.d.ts +251 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 Velocity Team
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** @import { Issuer, Context } from "../../types/types" */
|
|
19
|
+
|
|
20
|
+
const { hexFromJwk } = require('@verii/jwt');
|
|
21
|
+
const { initRevocationRegistry } = require('@verii/metadata-registration');
|
|
22
|
+
const { initCallWithKmsKey } = require('@verii/crypto');
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get revocation registry
|
|
26
|
+
* @param {Issuer} issuer the issuer's dlt account
|
|
27
|
+
* @param {Context} context the context
|
|
28
|
+
* @returns {Promise<unknown>} the revocation registry contract
|
|
29
|
+
*/
|
|
30
|
+
const getRevocationRegistry = (issuer, context) => {
|
|
31
|
+
const {
|
|
32
|
+
config: { revocationContractAddress },
|
|
33
|
+
rpcProvider,
|
|
34
|
+
} = context;
|
|
35
|
+
|
|
36
|
+
return initCallWithKmsKey(context)(issuer.dltOperatorKMSKeyId, (key) =>
|
|
37
|
+
initRevocationRegistry(
|
|
38
|
+
{
|
|
39
|
+
contractAddress: revocationContractAddress,
|
|
40
|
+
rpcProvider,
|
|
41
|
+
privateKey: hexFromJwk(key.privateJwk),
|
|
42
|
+
},
|
|
43
|
+
context
|
|
44
|
+
)
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
module.exports = { getRevocationRegistry };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 Velocity Team
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const {
|
|
19
|
+
initMetadataRegistry,
|
|
20
|
+
ALG_TYPE,
|
|
21
|
+
} = require('@verii/metadata-registration');
|
|
22
|
+
const { jsonLdToUnsignedVcJwtContent, hexFromJwk } = require('@verii/jwt');
|
|
23
|
+
const { initCallWithKmsKey } = require('@verii/crypto');
|
|
24
|
+
const { KeyAlgorithms } = require('@verii/crypto/src/constants');
|
|
25
|
+
const { buildIssuerVcUrl } = require('./build-issuer-vc-url');
|
|
26
|
+
|
|
27
|
+
/** @import { Issuer, CredentialMetadata, Context } from "../../types/types" */
|
|
28
|
+
/**
|
|
29
|
+
* Creates a createCredentialMetadataEntry function
|
|
30
|
+
* @param {Issuer} issuer the issuer
|
|
31
|
+
* @param {Context} context the context
|
|
32
|
+
* @returns {Promise<{
|
|
33
|
+
* addEntry: function(CredentialMetadata): Promise<void>,
|
|
34
|
+
* createList: function(number): Promise<boolean>
|
|
35
|
+
* }>} the contract interface to create metadata
|
|
36
|
+
*/
|
|
37
|
+
const initCredentialMetadataContract = async (issuer, context) => {
|
|
38
|
+
const { config, rpcProvider, caoDid } = context;
|
|
39
|
+
|
|
40
|
+
const credentialMetadataRegistry = await initCallWithKmsKey(context)(
|
|
41
|
+
issuer.dltOperatorKMSKeyId,
|
|
42
|
+
({ privateJwk: dltJwk }) =>
|
|
43
|
+
initMetadataRegistry(
|
|
44
|
+
{
|
|
45
|
+
privateKey: hexFromJwk(dltJwk),
|
|
46
|
+
contractAddress: config.metadataRegistryContractAddress,
|
|
47
|
+
rpcProvider,
|
|
48
|
+
},
|
|
49
|
+
context
|
|
50
|
+
)
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
/**
|
|
55
|
+
* Anchor credential metadata to the dlt
|
|
56
|
+
* @param {CredentialMetadata} metadata the credential metadata
|
|
57
|
+
* @returns {Promise<boolean>} true if entry is set
|
|
58
|
+
*/
|
|
59
|
+
addEntry: (metadata) =>
|
|
60
|
+
credentialMetadataRegistry.addCredentialMetadataEntry(
|
|
61
|
+
metadata,
|
|
62
|
+
metadata.contentHash,
|
|
63
|
+
caoDid,
|
|
64
|
+
ALG_TYPE.COSEKEY_AES_256
|
|
65
|
+
),
|
|
66
|
+
/**
|
|
67
|
+
* List to create on the dlt
|
|
68
|
+
* @param {number} listId list id to create
|
|
69
|
+
* @returns {Promise<boolean>} true if a list was created, false if it already existed
|
|
70
|
+
*/
|
|
71
|
+
createList: async (listId) => {
|
|
72
|
+
const accountId = issuer.dltPrimaryAddress;
|
|
73
|
+
const { payload, header } = jsonLdToUnsignedVcJwtContent(
|
|
74
|
+
{
|
|
75
|
+
id: buildIssuerVcUrl(listId, issuer, context),
|
|
76
|
+
type: ['CredentialMetadataListHeader'],
|
|
77
|
+
issuer: issuer.did,
|
|
78
|
+
issuanceDate: new Date().toISOString(),
|
|
79
|
+
credentialSubject: { listId, accountId },
|
|
80
|
+
},
|
|
81
|
+
KeyAlgorithms.SECP256K1,
|
|
82
|
+
issuer.issuingServiceDIDKeyId
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const issuerVC = await context.kms.signJwt(
|
|
86
|
+
payload,
|
|
87
|
+
issuer.issuingServiceKMSKeyId,
|
|
88
|
+
header
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
return credentialMetadataRegistry.createCredentialMetadataList(
|
|
92
|
+
accountId,
|
|
93
|
+
listId,
|
|
94
|
+
issuerVC,
|
|
95
|
+
caoDid,
|
|
96
|
+
ALG_TYPE.COSEKEY_AES_256
|
|
97
|
+
);
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
module.exports = { initCredentialMetadataContract };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 Velocity Team
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
/** @import { Issuer, AllocationListEntry, AllocationListQueries, Context } from "../../types/types" */
|
|
18
|
+
|
|
19
|
+
const { toEthereumAddress } = require('@verii/blockchain-functions');
|
|
20
|
+
const { hexFromJwk } = require('@verii/jwt');
|
|
21
|
+
/**
|
|
22
|
+
* Returns the queries needed for allocating to DLT Lists
|
|
23
|
+
* @param {unknown} db the db connection
|
|
24
|
+
* @param {string} collectionName the collection name
|
|
25
|
+
* @returns {AllocationListQueries} queries to allocate to lists on a db
|
|
26
|
+
*/
|
|
27
|
+
const mongoAllocationListQueries = (db, collectionName) => {
|
|
28
|
+
/**
|
|
29
|
+
* Gets the next entry out of the list
|
|
30
|
+
* @param {string} entityName the name of the collection or table for the list
|
|
31
|
+
* @param {Issuer} issuer the issuer
|
|
32
|
+
* @param {Context} context the context
|
|
33
|
+
* @returns {AllocationListEntry} the next entry of the list
|
|
34
|
+
*/
|
|
35
|
+
const allocateNextEntry = async (entityName, issuer, context) => {
|
|
36
|
+
const operatorAddress = await getOperatorAddress(issuer, context);
|
|
37
|
+
const result = await db.collection(collectionName).findOneAndUpdate(
|
|
38
|
+
{
|
|
39
|
+
tenantId: issuer.id,
|
|
40
|
+
operatorAddress,
|
|
41
|
+
entityName,
|
|
42
|
+
$and: [
|
|
43
|
+
{ freeIndexes: { $exists: true } },
|
|
44
|
+
{ freeIndexes: { $not: { $size: 0 } } },
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
$pop: { freeIndexes: -1 },
|
|
49
|
+
$set: {
|
|
50
|
+
updatedAt: new Date(),
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
upsert: false,
|
|
55
|
+
returnNewDocument: false,
|
|
56
|
+
includeResultMetadata: true,
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
return {
|
|
60
|
+
listId: result.value.currentListId,
|
|
61
|
+
index: result.value.freeIndexes?.[0],
|
|
62
|
+
isNewList: false,
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Create a new allocation list on ledger
|
|
68
|
+
* @param {string} entityName the name of the collection or table for the list
|
|
69
|
+
* @param {Issuer} issuer the issuer
|
|
70
|
+
* @param {number} newListId the new allocation list id
|
|
71
|
+
* @param {number[]} allocations the new allocations to use
|
|
72
|
+
* @param {Context} context the context
|
|
73
|
+
* @returns {AllocationListEntry} the first entry of the list
|
|
74
|
+
*/
|
|
75
|
+
const createNewAllocationList = async (
|
|
76
|
+
entityName,
|
|
77
|
+
issuer,
|
|
78
|
+
newListId,
|
|
79
|
+
allocations,
|
|
80
|
+
context
|
|
81
|
+
) => {
|
|
82
|
+
const operatorAddress = await getOperatorAddress(issuer, context);
|
|
83
|
+
await db.collection(collectionName).insertOne({
|
|
84
|
+
tenantId: issuer.id,
|
|
85
|
+
entityName,
|
|
86
|
+
freeIndexes: allocations.slice(1),
|
|
87
|
+
currentListId: newListId,
|
|
88
|
+
operatorAddress,
|
|
89
|
+
createdAt: new Date(),
|
|
90
|
+
updatedAt: new Date(),
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
listId: newListId,
|
|
95
|
+
index: allocations[0],
|
|
96
|
+
isNewList: true,
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
createNewAllocationList,
|
|
102
|
+
allocateNextEntry,
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Gets the operator address
|
|
108
|
+
* @param {Issuer} issuer the issuer
|
|
109
|
+
* @param {Context} context the context
|
|
110
|
+
* @returns {string} the operator address
|
|
111
|
+
*/
|
|
112
|
+
const getOperatorAddress = async (issuer, { kms }) => {
|
|
113
|
+
if (issuer.dltOperatorAddress != null) {
|
|
114
|
+
return issuer.dltOperatorAddress;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const key = await kms.exportKeyOrSecret(issuer.dltOperatorKMSKeyId);
|
|
118
|
+
return toEthereumAddress(hexFromJwk(key.privateJwk));
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
module.exports = {
|
|
122
|
+
mongoAllocationListQueries,
|
|
123
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 Velocity Team
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** @import { Context, Issuer, AllocationListEntry, AllocationListQueries } from "../../types/types" */
|
|
19
|
+
|
|
20
|
+
const { allocateArray } = require('./utils/allocate-array');
|
|
21
|
+
const { generateListIndex } = require('./utils/generate-list-index');
|
|
22
|
+
/**
|
|
23
|
+
* Allocates list entries
|
|
24
|
+
* @param {number} total the number of entries required (typically the number of offers)
|
|
25
|
+
* @param {Issuer} issuer the issuer
|
|
26
|
+
* @param {string} entityName the entity name
|
|
27
|
+
* @param {number} listSize the list size
|
|
28
|
+
* @param {Context} context the context
|
|
29
|
+
* @returns {Promise<AllocationListEntry[]>} the allocated entries
|
|
30
|
+
*/
|
|
31
|
+
const allocateListEntries = async (
|
|
32
|
+
total,
|
|
33
|
+
issuer,
|
|
34
|
+
entityName,
|
|
35
|
+
listSize,
|
|
36
|
+
context
|
|
37
|
+
) => {
|
|
38
|
+
const entries = [];
|
|
39
|
+
for (let i = 0; i < total; i += 1) {
|
|
40
|
+
entries.push(
|
|
41
|
+
// eslint-disable-next-line no-await-in-loop
|
|
42
|
+
await allocateListEntry(issuer, entityName, listSize, context)
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
return entries;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Gets the next list entry
|
|
50
|
+
* @param {Issuer} issuer the issuer
|
|
51
|
+
* @param {string} entityName the entity name
|
|
52
|
+
* @param {number} listSize the list size
|
|
53
|
+
* @param {Context} context the context
|
|
54
|
+
* @returns {Promise<AllocationListEntry>} the entry
|
|
55
|
+
*/
|
|
56
|
+
const allocateListEntry = async (issuer, entityName, listSize, context) => {
|
|
57
|
+
const { allocationListQueries: queries } = context;
|
|
58
|
+
try {
|
|
59
|
+
return await queries.allocateNextEntry(entityName, issuer, context);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
const allocations = allocateArray(listSize);
|
|
62
|
+
const newListId = generateListIndex();
|
|
63
|
+
return queries.createNewAllocationList(
|
|
64
|
+
entityName,
|
|
65
|
+
issuer,
|
|
66
|
+
newListId,
|
|
67
|
+
allocations,
|
|
68
|
+
context
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
module.exports = {
|
|
74
|
+
allocateListEntries,
|
|
75
|
+
allocateListEntry,
|
|
76
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 Velocity Team
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const { toLower } = require('lodash/fp');
|
|
19
|
+
const { mapWithIndex } = require('@verii/common-functions');
|
|
20
|
+
const {
|
|
21
|
+
generateJWAKeyPair,
|
|
22
|
+
get2BytesHash,
|
|
23
|
+
KeyAlgorithms,
|
|
24
|
+
} = require('@verii/crypto');
|
|
25
|
+
const { jsonLdToUnsignedVcJwtContent, jwtSign } = require('@verii/jwt');
|
|
26
|
+
const { extractCredentialType } = require('@verii/vc-checks');
|
|
27
|
+
const { hashOffer } = require('./hash-offer');
|
|
28
|
+
const { buildRevocationUrl } = require('../adapters/build-revocation-url');
|
|
29
|
+
const { prepareJsonLdCredential } = require('./prepare-jsonld-credential');
|
|
30
|
+
|
|
31
|
+
/** @import { Issuer, AllocationListEntry, CredentialOffer, CredentialMetadata, CredentialTypeMetadata, Context } from "../types/types" */
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Builds the VCs
|
|
35
|
+
* @param {CredentialOffer[]} offers array of offers
|
|
36
|
+
* @param {string} credentialSubjectId optional field if credential subject needs to be bound into the offer
|
|
37
|
+
* @param {Issuer} issuer the issuer
|
|
38
|
+
* @param {AllocationListEntry[]} metadataEntries metadata entries
|
|
39
|
+
* @param {AllocationListEntry[]} revocationListEntries revocation list entries
|
|
40
|
+
* @param {{[Name: string]: CredentialTypeMetadata}} credentialTypesMap the credential types
|
|
41
|
+
* @param {Context} context the context
|
|
42
|
+
* @returns {Promise<{metadata: CredentialMetadata, vcJwt: string}[]>} the vc and its metadata
|
|
43
|
+
*/
|
|
44
|
+
const buildVerifiableCredentials = async (
|
|
45
|
+
offers,
|
|
46
|
+
credentialSubjectId,
|
|
47
|
+
issuer,
|
|
48
|
+
metadataEntries,
|
|
49
|
+
revocationListEntries,
|
|
50
|
+
credentialTypesMap,
|
|
51
|
+
context
|
|
52
|
+
) => {
|
|
53
|
+
return Promise.all(
|
|
54
|
+
mapWithIndex(async (offer, i) => {
|
|
55
|
+
const metadataEntry = metadataEntries[i];
|
|
56
|
+
const credentialType = extractCredentialType(offer);
|
|
57
|
+
const digitalSignatureAlgorithm =
|
|
58
|
+
credentialTypesMap[credentialType].defaultSignatureAlgorithm ??
|
|
59
|
+
KeyAlgorithms.SECP256K1;
|
|
60
|
+
|
|
61
|
+
const keyPair = generateJWAKeyPair(digitalSignatureAlgorithm);
|
|
62
|
+
|
|
63
|
+
const metadata = {
|
|
64
|
+
...metadataEntry,
|
|
65
|
+
credentialType,
|
|
66
|
+
credentialTypeEncoded: get2BytesHash(credentialType), // TODO replace with bytes encoding from credentialMetadata
|
|
67
|
+
contentHash: hashOffer(offer),
|
|
68
|
+
publicKey: keyPair.publicKey,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const credentialId = buildVelocityCredentialMetadataDID(
|
|
72
|
+
metadataEntry,
|
|
73
|
+
issuer,
|
|
74
|
+
metadata.contentHash
|
|
75
|
+
);
|
|
76
|
+
const revocationUrl = buildRevocationUrl(
|
|
77
|
+
revocationListEntries[i],
|
|
78
|
+
issuer,
|
|
79
|
+
context
|
|
80
|
+
);
|
|
81
|
+
const jsonLdCredential = prepareJsonLdCredential(
|
|
82
|
+
issuer,
|
|
83
|
+
credentialSubjectId,
|
|
84
|
+
offer,
|
|
85
|
+
credentialId,
|
|
86
|
+
metadata.contentHash, // TODO remove June 2026
|
|
87
|
+
credentialTypesMap[metadata.credentialType],
|
|
88
|
+
revocationUrl,
|
|
89
|
+
context
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const { header, payload } = jsonLdToUnsignedVcJwtContent(
|
|
93
|
+
jsonLdCredential,
|
|
94
|
+
digitalSignatureAlgorithm,
|
|
95
|
+
`${credentialId}#key-1`
|
|
96
|
+
);
|
|
97
|
+
const vcJwt = await jwtSign(payload, keyPair.privateKey, header);
|
|
98
|
+
|
|
99
|
+
return { metadata, jsonLdCredential, vcJwt };
|
|
100
|
+
}, offers)
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Builds a credential metadata DID URI
|
|
106
|
+
* @param {AllocationListEntry} entry the list entry
|
|
107
|
+
* @param {Issuer} issuer the issuer
|
|
108
|
+
* @param {string} contentHash the content hash of the credential
|
|
109
|
+
* @returns {string} the DID URI for the location on the credential metadata list
|
|
110
|
+
*/
|
|
111
|
+
const buildVelocityCredentialMetadataDID = (entry, issuer, contentHash) =>
|
|
112
|
+
`did:velocity:v2:${toLower(issuer.dltPrimaryAddress)}:${entry.listId}:${
|
|
113
|
+
entry.index
|
|
114
|
+
}:${contentHash}`;
|
|
115
|
+
|
|
116
|
+
module.exports = { buildVerifiableCredentials };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 Velocity Team
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const { flow, pick } = require('lodash/fp');
|
|
19
|
+
const canonicalize = require('canonicalize');
|
|
20
|
+
const { hashAndEncodeHex } = require('@verii/crypto');
|
|
21
|
+
/** @import { CredentialOffer } from "../types/types" */
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The hex encoded hash of the CredentialOffer
|
|
25
|
+
* @param {CredentialOffer} offer the offer to hash
|
|
26
|
+
* @returns {string} the hash of the offer encoded in hex
|
|
27
|
+
*/
|
|
28
|
+
const hashOffer = (offer) =>
|
|
29
|
+
flow(
|
|
30
|
+
pick(['credentialSubject', 'validFrom', 'expirationDate', 'validUntil']),
|
|
31
|
+
canonicalize,
|
|
32
|
+
hashAndEncodeHex
|
|
33
|
+
)(offer);
|
|
34
|
+
|
|
35
|
+
module.exports = { hashOffer };
|