• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hyperledger / identus-edge-agent-sdk-swift / 11035384347

25 Sep 2024 02:40PM UTC coverage: 40.842% (-3.1%) from 43.981%
11035384347

Pull #159

github

web-flow
Merge 65ff99d66 into d3597e19d
Pull Request #159: feat(agent): agent separation of concerns

232 of 1063 new or added lines in 19 files covered. (21.83%)

187 existing lines in 14 files now uncovered.

5202 of 12737 relevant lines covered (40.84%)

97.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

16.6
/EdgeAgentSDK/EdgeAgent/Sources/DIDCommAgent/DIDCommAgent+Credentials.swift
1
import Core
2
import Combine
3
import Domain
4
import Foundation
5
import Logging
6
import JSONWebToken
7

8
public extension DIDCommAgent {
9

10
    /// This function initiates a presentation request for a specific type of credential, specifying the sender's and receiver's DIDs, and any claim filters applicable.
11
    ///
12
    /// - Parameters:
13
    ///   - type: The type of the credential for which the presentation is requested.
14
    ///   - fromDID: The decentralized identifier (DID) of the entity initiating the request.
15
    ///   - toDID: The decentralized identifier (DID) of the entity to which the request is being sent.
16
    ///   - claimFilters: A collection of filters specifying the claims required in the credential.
17
    /// - Returns: The initiated request for presentation.
18
    /// - Throws: EdgeAgentError, if there is a problem initiating the presentation request.
19
    func initiatePresentationRequest(
20
        type: CredentialType,
21
        fromDID: DID,
22
        toDID: DID,
23
        claimFilters: [ClaimFilter]
24
    ) async throws -> RequestPresentation {
8✔
25
        let rqstStr = try await edgeAgent.initiatePresentationRequest(
8✔
26
            type: type,
8✔
27
            fromDID: fromDID,
8✔
28
            toDID: toDID,
8✔
29
            claimFilters: claimFilters
8✔
30
        )
8✔
31
        let attachment: AttachmentDescriptor
8✔
32
        switch type {
8✔
33
        case .jwt:
8✔
34
            let data = try AttachmentBase64(base64: rqstStr.tryToData().base64URLEncoded())
6✔
35
            attachment = AttachmentDescriptor(
6✔
36
                mediaType: "application/json",
6✔
37
                data: data,
6✔
38
                format: "dif/presentation-exchange/definitions@v1.0"
6✔
39
            )
6✔
40
        case .anoncred:
8✔
41
            let data = try AttachmentBase64(base64: rqstStr.tryToData().base64URLEncoded())
2✔
42
            attachment = AttachmentDescriptor(
2✔
43
                mediaType: "application/json",
2✔
44
                data: data,
2✔
45
                format: "anoncreds/proof-request@v1.0"
2✔
46
            )
2✔
47
        }
8✔
48

8✔
49
        return RequestPresentation(
8✔
50
            body: .init(
8✔
51
                proofTypes: [ProofTypes(
8✔
52
                    schema: "",
8✔
53
                    requiredFields: claimFilters.flatMap(\.paths),
10✔
54
                    trustIssuers: nil
8✔
55
                )]
8✔
56
            ),
8✔
57
            attachments: [attachment],
8✔
58
            thid: nil,
8✔
59
            from: fromDID,
8✔
60
            to: toDID
8✔
61
        )
8✔
62
    }
8✔
63

64
    /// This function verifies the presentation contained within a message.
65
    ///
66
    /// - Parameters:
67
    ///   - message: The message containing the presentation to be verified.
68
    /// - Returns: A Boolean value indicating whether the presentation is valid (`true`) or not (`false`).
69
    /// - Throws: EdgeAgentError, if there is a problem verifying the presentation.
70

NEW
71
    func verifyPresentation(message: Message) async throws -> Bool {
×
NEW
72
        do {
×
NEW
73
            let downloader = DownloadDataWithResolver(castor: castor)
×
NEW
74
            guard
×
NEW
75
                let attachment = message.attachments.first,
×
NEW
76
                let requestId = message.thid
×
NEW
77
            else {
×
NEW
78
                throw PolluxError.couldNotFindPresentationInAttachments
×
NEW
79
            }
×
NEW
80

×
NEW
81
            let jsonData: Data
×
NEW
82
            switch attachment.data {
×
NEW
83
            case let attchedData as AttachmentBase64:
×
NEW
84
                guard let decoded = Data(fromBase64URL: attchedData.base64) else {
×
NEW
85
                    throw CommonError.invalidCoding(message: "Invalid base64 url attachment")
×
NEW
86
                }
×
NEW
87
                jsonData = decoded
×
NEW
88
            case let attchedData as AttachmentJsonData:
×
NEW
89
                jsonData = attchedData.data
×
NEW
90
            default:
×
NEW
91
                throw EdgeAgentError.invalidAttachmentFormat(nil)
×
NEW
92
            }
×
NEW
93

×
NEW
94
            guard let format = attachment.format else {
×
NEW
95
                throw EdgeAgentError.invalidAttachmentFormat(nil)
×
NEW
96
            }
×
NEW
97

×
NEW
98
            return try await pollux.verifyPresentation(
×
NEW
99
                type: format,
×
NEW
100
                presentationPayload: jsonData,
×
NEW
101
                options: [
×
NEW
102
                    .presentationRequestId(requestId),
×
NEW
103
                    .credentialDefinitionDownloader(downloader: downloader),
×
NEW
104
                    .schemaDownloader(downloader: downloader)
×
NEW
105
            ])
×
NEW
106
        } catch {
×
NEW
107
            logger.error(error: error)
×
NEW
108
            throw error
×
NEW
109
        }
×
NEW
110
    }
×
111

112
    /// This function parses an issued credential message, stores and returns the verifiable credential.
113
    ///
114
    /// - Parameters:
115
    ///   - message: Issue credential Message.
116
    /// - Returns: The parsed verifiable credential.
117
    /// - Throws: EdgeAgentError, if there is a problem parsing the credential.
NEW
118
    func processIssuedCredentialMessage(message: IssueCredential3_0) async throws -> Credential {
×
NEW
119
        guard
×
NEW
120
            let linkSecret = try await pluto.getLinkSecret().first().await()
×
NEW
121
        else { throw EdgeAgentError.cannotFindDIDKeyPairIndex }
×
NEW
122

×
NEW
123
        let restored = try await self.apollo.restoreKey(linkSecret)
×
NEW
124
        guard
×
NEW
125
            let linkSecretString = String(data: restored.raw, encoding: .utf8)
×
NEW
126
        else { throw EdgeAgentError.cannotFindDIDKeyPairIndex }
×
NEW
127

×
NEW
128
        let downloader = DownloadDataWithResolver(castor: castor)
×
NEW
129
        guard 
×
NEW
130
            let attachment = message.attachments.first,
×
NEW
131
            let format = attachment.format
×
NEW
132
        else {
×
NEW
133
            throw PolluxError.unsupportedIssuedMessage
×
NEW
134
        }
×
NEW
135

×
NEW
136
        let jsonData: Data
×
NEW
137
        switch attachment.data {
×
NEW
138
        case let attchedData as AttachmentBase64:
×
NEW
139
            guard let decoded = Data(fromBase64URL: attchedData.base64) else {
×
NEW
140
                throw CommonError.invalidCoding(message: "Invalid base64 url attachment")
×
NEW
141
            }
×
NEW
142
            jsonData = decoded
×
NEW
143
        case let attchedData as AttachmentJsonData:
×
NEW
144
            jsonData = attchedData.data
×
NEW
145
        default:
×
NEW
146
            throw EdgeAgentError.invalidAttachmentFormat(nil)
×
NEW
147
        }
×
NEW
148

×
NEW
149
        let credential = try await pollux.parseCredential(
×
NEW
150
            type: format,
×
NEW
151
            credentialPayload: jsonData,
×
NEW
152
            options: [
×
NEW
153
                .linkSecret(id: "", secret: linkSecretString),
×
NEW
154
                .credentialDefinitionDownloader(downloader: downloader),
×
NEW
155
                .schemaDownloader(downloader: downloader)
×
NEW
156
            ]
×
NEW
157
        )
×
NEW
158

×
NEW
159
        guard let storableCredential = credential.storable else {
×
NEW
160
            return credential
×
NEW
161
        }
×
NEW
162
        try await pluto
×
NEW
163
            .storeCredential(credential: storableCredential)
×
NEW
164
            .first()
×
NEW
165
            .await()
×
NEW
166
        return credential
×
NEW
167
    }
×
168

169
    /// This function prepares a request credential from an offer given the subject DID.
170
    ///
171
    /// - Parameters:
172
    ///   - did: Subject DID.
173
    ///   - did: Received offer credential.
174
    /// - Returns: Created request credential
175
    /// - Throws: EdgeAgentError, if there is a problem creating the request credential.
NEW
176
    func prepareRequestCredentialWithIssuer(did: DID, offer: OfferCredential3_0) async throws -> RequestCredential3_0? {
×
NEW
177
        guard did.method == "prism" else { throw PolluxError.invalidPrismDID }
×
NEW
178
        let didInfo = try await pluto
×
NEW
179
            .getDIDInfo(did: did)
×
NEW
180
            .first()
×
NEW
181
            .await()
×
NEW
182

×
NEW
183
        guard let storedPrivateKey = didInfo?.privateKeys.first else { throw EdgeAgentError.cannotFindDIDKeyPairIndex }
×
NEW
184

×
NEW
185
        let privateKey = try await apollo.restorePrivateKey(storedPrivateKey)
×
NEW
186

×
NEW
187
        guard
×
NEW
188
            let exporting = privateKey.exporting,
×
NEW
189
            let linkSecret = try await pluto.getLinkSecret().first().await()
×
NEW
190
        else { throw EdgeAgentError.cannotFindDIDKeyPairIndex }
×
NEW
191

×
NEW
192
        let restored = try await self.apollo.restoreKey(linkSecret)
×
NEW
193
        guard
×
NEW
194
            let linkSecretString = String(data: restored.raw, encoding: .utf8)
×
NEW
195
        else { throw EdgeAgentError.cannotFindDIDKeyPairIndex }
×
NEW
196

×
NEW
197
        let downloader = DownloadDataWithResolver(castor: castor)
×
NEW
198
        guard
×
NEW
199
            let attachment = offer.attachments.first,
×
NEW
200
            let offerFormat = attachment.format
×
NEW
201
        else {
×
NEW
202
            throw PolluxError.unsupportedIssuedMessage
×
NEW
203
        }
×
NEW
204

×
NEW
205
        let jsonData: Data
×
NEW
206
        switch attachment.data {
×
NEW
207
        case let attchedData as AttachmentBase64:
×
NEW
208
            guard let decoded = Data(fromBase64URL: attchedData.base64) else {
×
NEW
209
                throw CommonError.invalidCoding(message: "Invalid base64 url attachment")
×
NEW
210
            }
×
NEW
211
            jsonData = decoded
×
NEW
212
        case let attchedData as AttachmentJsonData:
×
NEW
213
            jsonData = attchedData.data
×
NEW
214
        default:
×
NEW
215
            throw EdgeAgentError.invalidAttachmentFormat(nil)
×
NEW
216
        }
×
NEW
217
        let requestString = try await pollux.processCredentialRequest(
×
NEW
218
            type: offerFormat,
×
NEW
219
            offerPayload: jsonData,
×
NEW
220
            options: [
×
NEW
221
                .exportableKey(exporting),
×
NEW
222
                .subjectDID(did),
×
NEW
223
                .linkSecret(id: did.string, secret: linkSecretString),
×
NEW
224
                .credentialDefinitionDownloader(downloader: downloader),
×
NEW
225
                .schemaDownloader(downloader: downloader)
×
NEW
226
            ]
×
NEW
227
        )
×
NEW
228

×
NEW
229
        guard
×
NEW
230
            let base64String = requestString.data(using: .utf8)?.base64EncodedString()
×
NEW
231
        else {
×
NEW
232
            throw CommonError.invalidCoding(message: "Could not encode to base64")
×
NEW
233
        }
×
NEW
234
        guard
×
NEW
235
            let offerPiuri = ProtocolTypes(rawValue: offer.type)
×
NEW
236
        else {
×
NEW
237
            throw EdgeAgentError.invalidMessageType(
×
NEW
238
                type: offer.type,
×
NEW
239
                shouldBe: [
×
NEW
240
                    ProtocolTypes.didcommOfferCredential3_0.rawValue
×
NEW
241
                ]
×
NEW
242
            )
×
NEW
243
        }
×
NEW
244
        let format: String
×
NEW
245
        switch offerFormat {
×
NEW
246
        case "prism/jwt":
×
NEW
247
            format = "prism/jwt"
×
NEW
248
        case "vc+sd-jwt":
×
NEW
249
            format = "vc+sd-jwt"
×
NEW
250
        case "anoncreds/credential-offer@v1.0":
×
NEW
251
            format = "anoncreds/credential-request@v1.0"
×
NEW
252
        default:
×
NEW
253
            throw EdgeAgentError.invalidMessageType(
×
NEW
254
                type: offerFormat,
×
NEW
255
                shouldBe: [
×
NEW
256
                    "prism/jwt",
×
NEW
257
                    "anoncreds/credential-offer@v1.0"
×
NEW
258
                ]
×
NEW
259
            )
×
NEW
260
        }
×
NEW
261

×
NEW
262
        let type = offerPiuri == .didcommOfferCredential ?
×
NEW
263
            ProtocolTypes.didcommRequestCredential :
×
NEW
264
            ProtocolTypes.didcommRequestCredential3_0
×
NEW
265

×
NEW
266
        let requestCredential = RequestCredential3_0(
×
NEW
267
            body: .init(
×
NEW
268
                goalCode: offer.body.goalCode,
×
NEW
269
                comment: offer.body.comment
×
NEW
270
            ),
×
NEW
271
            type: type.rawValue,
×
NEW
272
            attachments: [.init(
×
NEW
273
                data: AttachmentBase64(base64: base64String),
×
NEW
274
                format: format
×
NEW
275
            )],
×
NEW
276
            thid: offer.thid,
×
NEW
277
            from: offer.to,
×
NEW
278
            to: offer.from
×
NEW
279
        )
×
NEW
280
        return requestCredential
×
NEW
281
    }
×
282
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc