@bifold/verifier 1.0.0
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/README.md +1 -0
- package/build/commonjs/README.md +4 -0
- package/build/commonjs/constants.js +9 -0
- package/build/commonjs/constants.js.map +1 -0
- package/build/commonjs/hooks/proofs.js +22 -0
- package/build/commonjs/hooks/proofs.js.map +1 -0
- package/build/commonjs/index.js +120 -0
- package/build/commonjs/index.js.map +1 -0
- package/build/commonjs/request-templates.js +59 -0
- package/build/commonjs/request-templates.js.map +1 -0
- package/build/commonjs/types/agent.js +9 -0
- package/build/commonjs/types/agent.js.map +1 -0
- package/build/commonjs/types/metadata.js +11 -0
- package/build/commonjs/types/metadata.js.map +1 -0
- package/build/commonjs/types/proof-reqeust-template.js +12 -0
- package/build/commonjs/types/proof-reqeust-template.js.map +1 -0
- package/build/commonjs/types/proof.js +26 -0
- package/build/commonjs/types/proof.js.map +1 -0
- package/build/commonjs/utils/proof-request.js +163 -0
- package/build/commonjs/utils/proof-request.js.map +1 -0
- package/build/commonjs/utils/proof.js +184 -0
- package/build/commonjs/utils/proof.js.map +1 -0
- package/build/module/README.md +4 -0
- package/build/module/constants.js +3 -0
- package/build/module/constants.js.map +1 -0
- package/build/module/hooks/proofs.js +15 -0
- package/build/module/hooks/proofs.js.map +1 -0
- package/build/module/index.js +7 -0
- package/build/module/index.js.map +1 -0
- package/build/module/request-templates.js +52 -0
- package/build/module/request-templates.js.map +1 -0
- package/build/module/types/agent.js +5 -0
- package/build/module/types/agent.js.map +1 -0
- package/build/module/types/metadata.js +5 -0
- package/build/module/types/metadata.js.map +1 -0
- package/build/module/types/proof-reqeust-template.js +8 -0
- package/build/module/types/proof-reqeust-template.js.map +1 -0
- package/build/module/types/proof.js +18 -0
- package/build/module/types/proof.js.map +1 -0
- package/build/module/utils/proof-request.js +151 -0
- package/build/module/utils/proof-request.js.map +1 -0
- package/build/module/utils/proof.js +171 -0
- package/build/module/utils/proof.js.map +1 -0
- package/build/typescript/__tests__/verifier/proof-request.test.d.ts +2 -0
- package/build/typescript/__tests__/verifier/proof-request.test.d.ts.map +1 -0
- package/build/typescript/__tests__/verifier/proof.test.d.ts +2 -0
- package/build/typescript/__tests__/verifier/proof.test.d.ts.map +1 -0
- package/build/typescript/constants.d.ts +3 -0
- package/build/typescript/constants.d.ts.map +1 -0
- package/build/typescript/hooks/proofs.d.ts +3 -0
- package/build/typescript/hooks/proofs.d.ts.map +1 -0
- package/build/typescript/index.d.ts +11 -0
- package/build/typescript/index.d.ts.map +1 -0
- package/build/typescript/request-templates.d.ts +3 -0
- package/build/typescript/request-templates.d.ts.map +1 -0
- package/build/typescript/types/agent.d.ts +12 -0
- package/build/typescript/types/agent.d.ts.map +1 -0
- package/build/typescript/types/metadata.d.ts +9 -0
- package/build/typescript/types/metadata.d.ts.map +1 -0
- package/build/typescript/types/proof-reqeust-template.d.ts +48 -0
- package/build/typescript/types/proof-reqeust-template.d.ts.map +1 -0
- package/build/typescript/types/proof.d.ts +51 -0
- package/build/typescript/types/proof.d.ts.map +1 -0
- package/build/typescript/utils/proof-request.d.ts +30 -0
- package/build/typescript/utils/proof-request.d.ts.map +1 -0
- package/build/typescript/utils/proof.d.ts +18 -0
- package/build/typescript/utils/proof.d.ts.map +1 -0
- package/package.json +59 -0
- package/src/README.md +4 -0
- package/src/__tests__/verifier/__snapshots__/proof-request.test.ts.snap +72 -0
- package/src/__tests__/verifier/__snapshots__/proof.test.ts.snap +135 -0
- package/src/__tests__/verifier/proof-request.test.ts +34 -0
- package/src/__tests__/verifier/proof.test.ts +99 -0
- package/src/constants.ts +2 -0
- package/src/hooks/proofs.ts +20 -0
- package/src/index.ts +45 -0
- package/src/request-templates.ts +62 -0
- package/src/types/agent.ts +53 -0
- package/src/types/metadata.ts +9 -0
- package/src/types/proof-reqeust-template.ts +59 -0
- package/src/types/proof.ts +68 -0
- package/src/utils/proof-request.ts +177 -0
- package/src/utils/proof.ts +173 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AnonCredsRequestedAttribute,
|
|
3
|
+
AnonCredsRequestedPredicate,
|
|
4
|
+
LegacyIndyProofRequest,
|
|
5
|
+
V1RequestPresentationMessage,
|
|
6
|
+
} from '@credo-ts/anoncreds'
|
|
7
|
+
import { Agent, AgentMessage, AutoAcceptProof, ProofExchangeRecord } from '@credo-ts/core'
|
|
8
|
+
|
|
9
|
+
import { BifoldAgent } from '../types/agent'
|
|
10
|
+
import { ProofRequestTemplate, ProofRequestType } from '../types/proof-reqeust-template'
|
|
11
|
+
|
|
12
|
+
const protocolVersion = 'v2'
|
|
13
|
+
const domain = 'http://aries-mobile-agent.com'
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
* Find Proof Request message in the storage by the given id
|
|
17
|
+
* */
|
|
18
|
+
export const findProofRequestMessage = async (
|
|
19
|
+
agent: Agent,
|
|
20
|
+
id: string
|
|
21
|
+
): Promise<LegacyIndyProofRequest | undefined> => {
|
|
22
|
+
const message = await agent.proofs.findRequestMessage(id)
|
|
23
|
+
if (message && message instanceof V1RequestPresentationMessage && message.indyProofRequest) {
|
|
24
|
+
return message.indyProofRequest
|
|
25
|
+
} else {
|
|
26
|
+
return undefined
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
* Build Proof Request data from for provided template
|
|
32
|
+
* */
|
|
33
|
+
/*
|
|
34
|
+
* Build Proof Request data for provided template
|
|
35
|
+
* */
|
|
36
|
+
export const buildProofRequestDataForTemplate = (
|
|
37
|
+
template: ProofRequestTemplate,
|
|
38
|
+
customValues?: Record<string, Record<string, number>>
|
|
39
|
+
) => {
|
|
40
|
+
if (template.payload.type === ProofRequestType.AnonCreds) {
|
|
41
|
+
const requestedAttributes: Record<string, AnonCredsRequestedAttribute> = {}
|
|
42
|
+
const requestedPredicates: Record<string, AnonCredsRequestedPredicate> = {}
|
|
43
|
+
let index = 0
|
|
44
|
+
|
|
45
|
+
template.payload.data.forEach((data) => {
|
|
46
|
+
if (data.requestedAttributes?.length) {
|
|
47
|
+
data.requestedAttributes.forEach((requestedAttribute) => {
|
|
48
|
+
requestedAttributes[`referent_${index}`] = {
|
|
49
|
+
name: requestedAttribute.name,
|
|
50
|
+
names: requestedAttribute.names,
|
|
51
|
+
non_revoked: requestedAttribute.nonRevoked,
|
|
52
|
+
restrictions: requestedAttribute.restrictions,
|
|
53
|
+
}
|
|
54
|
+
index++
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
if (data.requestedPredicates?.length) {
|
|
58
|
+
data.requestedPredicates.forEach((requestedPredicate) => {
|
|
59
|
+
const customValue =
|
|
60
|
+
customValues && customValues[data.schema] ? customValues[data.schema][requestedPredicate.name] : undefined
|
|
61
|
+
|
|
62
|
+
requestedPredicates[`referent_${index}`] = {
|
|
63
|
+
name: requestedPredicate.name,
|
|
64
|
+
p_value:
|
|
65
|
+
requestedPredicate.parameterizable && customValue ? customValue : requestedPredicate.predicateValue,
|
|
66
|
+
p_type: requestedPredicate.predicateType,
|
|
67
|
+
non_revoked: requestedPredicate.nonRevoked,
|
|
68
|
+
restrictions: requestedPredicate.restrictions,
|
|
69
|
+
}
|
|
70
|
+
index++
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
return {
|
|
75
|
+
anoncreds: {
|
|
76
|
+
name: template.name,
|
|
77
|
+
version: template.version,
|
|
78
|
+
nonce: Date.now().toString(),
|
|
79
|
+
requested_attributes: requestedAttributes,
|
|
80
|
+
requested_predicates: requestedPredicates,
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (template.payload.type === ProofRequestType.DIF) {
|
|
85
|
+
return {}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface CreateProofRequestInvitationResult {
|
|
90
|
+
request: AgentMessage
|
|
91
|
+
proofRecord: ProofExchangeRecord
|
|
92
|
+
invitation: AgentMessage
|
|
93
|
+
invitationUrl: string
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/*
|
|
97
|
+
* Create connectionless proof request invitation for provided template
|
|
98
|
+
* */
|
|
99
|
+
export const createConnectionlessProofRequestInvitation = async (
|
|
100
|
+
agent: BifoldAgent,
|
|
101
|
+
template: ProofRequestTemplate,
|
|
102
|
+
customPredicateValues?: Record<string, Record<string, number>>
|
|
103
|
+
): Promise<CreateProofRequestInvitationResult | undefined> => {
|
|
104
|
+
const proofFormats = buildProofRequestDataForTemplate(template, customPredicateValues)
|
|
105
|
+
if (!proofFormats) {
|
|
106
|
+
return undefined
|
|
107
|
+
}
|
|
108
|
+
const { message: request, proofRecord } = await agent.proofs.createRequest({
|
|
109
|
+
protocolVersion,
|
|
110
|
+
autoAcceptProof: AutoAcceptProof.Always,
|
|
111
|
+
proofFormats,
|
|
112
|
+
})
|
|
113
|
+
const { message: invitation, invitationUrl } = await agent.oob.createLegacyConnectionlessInvitation({
|
|
114
|
+
recordId: proofRecord.id,
|
|
115
|
+
message: request,
|
|
116
|
+
domain,
|
|
117
|
+
})
|
|
118
|
+
return {
|
|
119
|
+
request,
|
|
120
|
+
proofRecord,
|
|
121
|
+
invitation,
|
|
122
|
+
invitationUrl,
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface SendProofRequestResult {
|
|
127
|
+
proofRecord: ProofExchangeRecord
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/*
|
|
131
|
+
* Build Proof Request for provided template and send it to provided connection
|
|
132
|
+
* */
|
|
133
|
+
export const sendProofRequest = async (
|
|
134
|
+
agent: BifoldAgent,
|
|
135
|
+
template: ProofRequestTemplate,
|
|
136
|
+
connectionId: string,
|
|
137
|
+
customPredicateValues?: Record<string, Record<string, number>>
|
|
138
|
+
): Promise<SendProofRequestResult | undefined> => {
|
|
139
|
+
const proofFormats = buildProofRequestDataForTemplate(template, customPredicateValues)
|
|
140
|
+
if (!proofFormats) {
|
|
141
|
+
return undefined
|
|
142
|
+
}
|
|
143
|
+
const proofRecord = await agent.proofs.requestProof({
|
|
144
|
+
protocolVersion,
|
|
145
|
+
connectionId,
|
|
146
|
+
proofFormats,
|
|
147
|
+
})
|
|
148
|
+
return {
|
|
149
|
+
proofRecord,
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/*
|
|
154
|
+
* Check if the Proof Request template contains at least one predicate
|
|
155
|
+
* */
|
|
156
|
+
export const hasPredicates = (record: ProofRequestTemplate): boolean => {
|
|
157
|
+
if (record.payload.type === ProofRequestType.AnonCreds) {
|
|
158
|
+
return record.payload.data.some((d) => d.requestedPredicates && d.requestedPredicates?.length > 0)
|
|
159
|
+
}
|
|
160
|
+
if (record.payload.type === ProofRequestType.DIF) {
|
|
161
|
+
return false
|
|
162
|
+
}
|
|
163
|
+
return false
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/*
|
|
167
|
+
* Check if the Proof Request template contains parameterizable predicates
|
|
168
|
+
* */
|
|
169
|
+
export const isParameterizable = (record: ProofRequestTemplate): boolean => {
|
|
170
|
+
if (record.payload.type === ProofRequestType.AnonCreds) {
|
|
171
|
+
return record.payload.data.some((d) => d.requestedPredicates?.some((predicate) => predicate.parameterizable))
|
|
172
|
+
}
|
|
173
|
+
if (record.payload.type === ProofRequestType.DIF) {
|
|
174
|
+
return false
|
|
175
|
+
}
|
|
176
|
+
return false
|
|
177
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { AnonCredsProof, AnonCredsProofRequest } from '@credo-ts/anoncreds'
|
|
2
|
+
import { Agent, ProofExchangeRecord, ProofState } from '@credo-ts/core'
|
|
3
|
+
|
|
4
|
+
import { BifoldAgent } from '../types/agent'
|
|
5
|
+
import { ProofMetadata } from '../types/metadata'
|
|
6
|
+
import {
|
|
7
|
+
CredentialSharedProofData,
|
|
8
|
+
GroupedSharedProofData,
|
|
9
|
+
GroupedSharedProofDataItem,
|
|
10
|
+
ParsedAnonCredsProof,
|
|
11
|
+
} from '../types/proof'
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* Extract identifiers from indy proof
|
|
15
|
+
* */
|
|
16
|
+
export const getProofIdentifiers = (proof: AnonCredsProof, proofIndex: number) => {
|
|
17
|
+
const identifiers = proof.identifiers[proofIndex]
|
|
18
|
+
if (!identifiers) {
|
|
19
|
+
throw new Error('Invalid indy proof data')
|
|
20
|
+
}
|
|
21
|
+
return identifiers
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* Process anoncreds proof and return
|
|
26
|
+
* - shared attributes
|
|
27
|
+
* - shared attribute groups
|
|
28
|
+
* - resolved predicates
|
|
29
|
+
* - missing attributes
|
|
30
|
+
* - missing attribute groups
|
|
31
|
+
* - unresolved predicates
|
|
32
|
+
* */
|
|
33
|
+
export const parseAnonCredsProof = (request: AnonCredsProofRequest, proof: AnonCredsProof): ParsedAnonCredsProof => {
|
|
34
|
+
const result = new ParsedAnonCredsProof()
|
|
35
|
+
|
|
36
|
+
for (const [referent, requested_attribute] of Object.entries(request.requested_attributes)) {
|
|
37
|
+
if (requested_attribute.name) {
|
|
38
|
+
const shared = proof.requested_proof.revealed_attrs[referent]
|
|
39
|
+
if (shared) {
|
|
40
|
+
const identifiers = getProofIdentifiers(proof, shared.sub_proof_index)
|
|
41
|
+
result.sharedAttributes.push({
|
|
42
|
+
name: requested_attribute.name,
|
|
43
|
+
value: shared.raw,
|
|
44
|
+
identifiers,
|
|
45
|
+
})
|
|
46
|
+
} else {
|
|
47
|
+
result.unresolvedAttributes.push({
|
|
48
|
+
name: requested_attribute.name,
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (requested_attribute.names) {
|
|
54
|
+
const shared = proof.requested_proof.revealed_attr_groups?.[referent]
|
|
55
|
+
if (shared) {
|
|
56
|
+
const attributes = Object.entries(shared.values).map(([name, value]) => ({
|
|
57
|
+
name,
|
|
58
|
+
value: value.raw,
|
|
59
|
+
}))
|
|
60
|
+
const identifiers = getProofIdentifiers(proof, shared.sub_proof_index)
|
|
61
|
+
result.sharedAttributeGroups.push({
|
|
62
|
+
attributes,
|
|
63
|
+
identifiers,
|
|
64
|
+
})
|
|
65
|
+
} else {
|
|
66
|
+
result.unresolvedAttributeGroups.push(requested_attribute.names.map((name) => ({ name })))
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
for (const [referent, requestedPredicate] of Object.entries(request.requested_predicates)) {
|
|
72
|
+
const shared = proof.requested_proof.predicates[referent]
|
|
73
|
+
if (shared) {
|
|
74
|
+
const identifiers = getProofIdentifiers(proof, shared.sub_proof_index)
|
|
75
|
+
result.resolvedPredicates.push({
|
|
76
|
+
name: requestedPredicate.name,
|
|
77
|
+
predicateType: requestedPredicate.p_type,
|
|
78
|
+
predicateValue: requestedPredicate.p_value,
|
|
79
|
+
identifiers,
|
|
80
|
+
})
|
|
81
|
+
} else {
|
|
82
|
+
result.unresolvedPredicates.push({
|
|
83
|
+
name: requestedPredicate.name,
|
|
84
|
+
predicateType: requestedPredicate.p_type,
|
|
85
|
+
predicateValue: requestedPredicate.p_value,
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return result
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
* Group parsed indy proof data ( returned from `parseIndyProof`) by credential definition id
|
|
95
|
+
* */
|
|
96
|
+
export const groupSharedProofDataByCredential = (data: ParsedAnonCredsProof): GroupedSharedProofData => {
|
|
97
|
+
const result: GroupedSharedProofData = new Map<string, GroupedSharedProofDataItem>()
|
|
98
|
+
for (const item of data.sharedAttributes) {
|
|
99
|
+
if (!result.has(item.identifiers.cred_def_id)) {
|
|
100
|
+
result.set(item.identifiers.cred_def_id, {
|
|
101
|
+
data: new CredentialSharedProofData(),
|
|
102
|
+
identifiers: item.identifiers,
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
result.get(item.identifiers.cred_def_id)?.data.sharedAttributes.push(item)
|
|
106
|
+
}
|
|
107
|
+
for (const item of data.sharedAttributeGroups) {
|
|
108
|
+
if (!result.has(item.identifiers.cred_def_id)) {
|
|
109
|
+
result.set(item.identifiers.cred_def_id, {
|
|
110
|
+
data: new CredentialSharedProofData(),
|
|
111
|
+
identifiers: item.identifiers,
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
result.get(item.identifiers.cred_def_id)?.data.sharedAttributeGroups.push(item)
|
|
115
|
+
}
|
|
116
|
+
for (const item of data.resolvedPredicates) {
|
|
117
|
+
if (!result.has(item.identifiers.cred_def_id)) {
|
|
118
|
+
result.set(item.identifiers.cred_def_id, {
|
|
119
|
+
data: new CredentialSharedProofData(),
|
|
120
|
+
identifiers: item.identifiers,
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
result.get(item.identifiers.cred_def_id)?.data.resolvedPredicates.push(item)
|
|
124
|
+
}
|
|
125
|
+
return result
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/*
|
|
129
|
+
* Retrieve proof details from Credo record
|
|
130
|
+
* */
|
|
131
|
+
export const getProofData = async (agent: BifoldAgent, recordId: string): Promise<ParsedAnonCredsProof | undefined> => {
|
|
132
|
+
const data = await agent.proofs.getFormatData(recordId)
|
|
133
|
+
if (data.request?.anoncreds && data.presentation?.anoncreds) {
|
|
134
|
+
return parseAnonCredsProof(data.request.anoncreds, data.presentation.anoncreds)
|
|
135
|
+
} else if (data.request?.indy && data.presentation?.indy) {
|
|
136
|
+
return parseAnonCredsProof(data.request.indy, data.presentation.indy)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return undefined
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/*
|
|
143
|
+
* Check if a presentation received
|
|
144
|
+
* */
|
|
145
|
+
export const isPresentationReceived = (record: ProofExchangeRecord) => {
|
|
146
|
+
return record.state === ProofState.PresentationReceived || record.state === ProofState.Done
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/*
|
|
150
|
+
* Check if a presentation failed
|
|
151
|
+
* */
|
|
152
|
+
export const isPresentationFailed = (record: ProofExchangeRecord) => {
|
|
153
|
+
return record.state === ProofState.Abandoned
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/*
|
|
157
|
+
* Mark Proof record as viewed
|
|
158
|
+
* */
|
|
159
|
+
export const markProofAsViewed = async (agent: Agent, record: ProofExchangeRecord) => {
|
|
160
|
+
record.metadata.set(ProofMetadata.customMetadata, { ...record.metadata.data.customMetadata, details_seen: true })
|
|
161
|
+
return agent.proofs.update(record)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/*
|
|
165
|
+
* Add template reference to Proof Exchange record
|
|
166
|
+
* */
|
|
167
|
+
export const linkProofWithTemplate = async (agent: Agent, record: ProofExchangeRecord, templateId: string) => {
|
|
168
|
+
record.metadata.set(ProofMetadata.customMetadata, {
|
|
169
|
+
...record.metadata.data.customMetadata,
|
|
170
|
+
proof_request_template_id: templateId,
|
|
171
|
+
})
|
|
172
|
+
return agent.proofs.update(record)
|
|
173
|
+
}
|