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

input-output-hk / atala-prism-wallet-sdk-swift / 9466819027

11 Jun 2024 01:48PM UTC coverage: 40.328% (-0.5%) from 40.822%
9466819027

Pull #145

github

web-flow
Merge 1399bca59 into 8e68386ce
Pull Request #145: feat(pollux): add support for sd-jwt

76 of 394 new or added lines in 20 files covered. (19.29%)

2 existing lines in 2 files now uncovered.

4518 of 11203 relevant lines covered (40.33%)

16.34 hits per line

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

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

8
// MARK: Verifiable credentials functionalities
9
public extension EdgeAgent {
10
    /// This function returns the verifiable credentials stored in pluto database
11
    ///
12
    /// - Returns:  A publisher that emits an array of `VerifiableCredential` and completes when all the
13
    ///              credentials are emitted or terminates with an error if any occurs
14
    func verifiableCredentials() -> AnyPublisher<[Credential], Error> {
×
15
        let pollux = self.pollux
×
16
        return pluto.getAllCredentials().tryMap {
×
17
            $0.compactMap {
×
18
                try? pollux.restoreCredential(
×
19
                    restorationIdentifier: $0.recoveryId,
×
20
                    credentialData: $0.credentialData
×
21
                )
×
22
            }
×
23
        }
×
24
        .eraseToAnyPublisher()
×
25
    }
×
26

27
    /// 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.
28
    ///
29
    /// - Parameters:
30
    ///   - type: The type of the credential for which the presentation is requested.
31
    ///   - fromDID: The decentralized identifier (DID) of the entity initiating the request.
32
    ///   - toDID: The decentralized identifier (DID) of the entity to which the request is being sent.
33
    ///   - claimFilters: A collection of filters specifying the claims required in the credential.
34
    /// - Returns: The initiated request for presentation.
35
    /// - Throws: EdgeAgentError, if there is a problem initiating the presentation request.
36
    func initiatePresentationRequest(
37
        type: CredentialType,
38
        fromDID: DID,
39
        toDID: DID,
40
        claimFilters: [ClaimFilter]
41
    ) async throws -> RequestPresentation {
6✔
42
        let request = try self.pollux.createPresentationRequest(
6✔
43
            type: type,
6✔
44
            toDID: toDID,
6✔
45
            name: UUID().uuidString,
6✔
46
            version: "1.0",
6✔
47
            claimFilters: claimFilters
6✔
48
        )
6✔
49

6✔
50
        let rqstStr = try request.tryToString()
6✔
51
        logger.debug(message: "Request: \(rqstStr)")
6✔
52
        let attachment: AttachmentDescriptor
6✔
53
        switch type {
6✔
54
        case .jwt:
6✔
55
            let data = AttachmentBase64(base64: request.base64URLEncoded())
4✔
56
            attachment = AttachmentDescriptor(
4✔
57
                mediaType: "application/json",
4✔
58
                data: data,
4✔
59
                format: "dif/presentation-exchange/definitions@v1.0"
4✔
60
            )
4✔
61
        case .anoncred:
6✔
62
            let data = AttachmentBase64(base64: request.base64URLEncoded())
2✔
63
            attachment = AttachmentDescriptor(
2✔
64
                mediaType: "application/json",
2✔
65
                data: data,
2✔
66
                format: "anoncreds/proof-request@v1.0"
2✔
67
            )
2✔
68
        }
6✔
69

6✔
70
        return RequestPresentation(
6✔
71
            body: .init(
6✔
72
                proofTypes: [ProofTypes(
6✔
73
                    schema: "",
6✔
74
                    requiredFields: claimFilters.flatMap(\.paths),
8✔
75
                    trustIssuers: nil
6✔
76
                )]
6✔
77
            ),
6✔
78
            attachments: [attachment],
6✔
79
            thid: nil,
6✔
80
            from: fromDID,
6✔
81
            to: toDID
6✔
82
        )
6✔
83
    }
6✔
84

85
    /// This function verifies the presentation contained within a message.
86
    ///
87
    /// - Parameters:
88
    ///   - message: The message containing the presentation to be verified.
89
    /// - Returns: A Boolean value indicating whether the presentation is valid (`true`) or not (`false`).
90
    /// - Throws: EdgeAgentError, if there is a problem verifying the presentation.
91

92
    func verifyPresentation(message: Message) async throws -> Bool {
×
93
        do {
×
94
            let downloader = DownloadDataWithResolver(castor: castor)
×
95
            return try await pollux.verifyPresentation(message: message, options: [
×
96
                .credentialDefinitionDownloader(downloader: downloader),
×
97
                .schemaDownloader(downloader: downloader)
×
98
            ])
×
99
        } catch {
×
100
            logger.error(error: error)
×
101
            throw error
×
102
        }
×
103
    }
×
104

105
    /// This function parses an issued credential message, stores and returns the verifiable credential.
106
    ///
107
    /// - Parameters:
108
    ///   - message: Issue credential Message.
109
    /// - Returns: The parsed verifiable credential.
110
    /// - Throws: EdgeAgentError, if there is a problem parsing the credential.
111
    func processIssuedCredentialMessage(message: IssueCredential3_0) async throws -> Credential {
×
112
        guard
×
113
            let linkSecret = try await pluto.getLinkSecret().first().await()
×
114
        else { throw EdgeAgentError.cannotFindDIDKeyPairIndex }
×
115

×
116
        let restored = try await self.apollo.restoreKey(linkSecret)
×
117
        guard
×
118
            let linkSecretString = String(data: restored.raw, encoding: .utf8)
×
119
        else { throw EdgeAgentError.cannotFindDIDKeyPairIndex }
×
120

×
121
        let downloader = DownloadDataWithResolver(castor: castor)
×
122
        let credential = try await pollux.parseCredential(
×
123
            issuedCredential: message.makeMessage(),
×
124
            options: [
×
125
                .linkSecret(id: "", secret: linkSecretString),
×
126
                .credentialDefinitionDownloader(downloader: downloader),
×
127
                .schemaDownloader(downloader: downloader)
×
128
            ]
×
129
        )
×
130
        
×
131
        guard let storableCredential = credential.storable else {
×
132
            return credential
×
133
        }
×
134
        try await pluto
×
135
            .storeCredential(credential: storableCredential)
×
136
            .first()
×
137
            .await()
×
138
        return credential
×
139
    }
×
140

141
    /// This function prepares a request credential from an offer given the subject DID.
142
    ///
143
    /// - Parameters:
144
    ///   - did: Subject DID.
145
    ///   - did: Received offer credential.
146
    /// - Returns: Created request credential
147
    /// - Throws: EdgeAgentError, if there is a problem creating the request credential.
148
    func prepareRequestCredentialWithIssuer(did: DID, offer: OfferCredential3_0) async throws -> RequestCredential3_0? {
×
149
        guard did.method == "prism" else { throw PolluxError.invalidPrismDID }
×
150
        let didInfo = try await pluto
×
151
            .getDIDInfo(did: did)
×
152
            .first()
×
153
            .await()
×
154

×
155
        guard let storedPrivateKey = didInfo?.privateKeys.first else { throw EdgeAgentError.cannotFindDIDKeyPairIndex }
×
156

×
157
        let privateKey = try await apollo.restorePrivateKey(storedPrivateKey)
×
158

×
159
        guard
×
160
            let exporting = privateKey.exporting,
×
161
            let linkSecret = try await pluto.getLinkSecret().first().await()
×
162
        else { throw EdgeAgentError.cannotFindDIDKeyPairIndex }
×
163

×
164
        let restored = try await self.apollo.restoreKey(linkSecret)
×
165
        guard
×
166
            let linkSecretString = String(data: restored.raw, encoding: .utf8)
×
167
        else { throw EdgeAgentError.cannotFindDIDKeyPairIndex }
×
168

×
169
        let downloader = DownloadDataWithResolver(castor: castor)
×
170
        let requestString = try await pollux.processCredentialRequest(
×
171
            offerMessage: offer.makeMessage(),
×
172
            options: [
×
173
                .exportableKey(exporting),
×
174
                .subjectDID(did),
×
175
                .linkSecret(id: did.string, secret: linkSecretString),
×
176
                .credentialDefinitionDownloader(downloader: downloader),
×
177
                .schemaDownloader(downloader: downloader)
×
178
            ]
×
179
        )
×
180

×
181
        guard
×
182
            let offerFormat = offer.attachments.first?.format,
×
183
            let base64String = requestString.data(using: .utf8)?.base64EncodedString()
×
184
        else {
×
185
            throw CommonError.invalidCoding(message: "Could not encode to base64")
×
186
        }
×
187
        guard
×
188
            let offerPiuri = ProtocolTypes(rawValue: offer.type)
×
189
        else {
×
190
            throw EdgeAgentError.invalidMessageType(
×
191
                type: offer.type,
×
192
                shouldBe: [
×
193
                    ProtocolTypes.didcommOfferCredential3_0.rawValue
×
194
                ]
×
195
            )
×
196
        }
×
197
        let format: String
×
198
        switch offerFormat {
×
199
        case "prism/jwt":
×
200
            format = "prism/jwt"
×
NEW
201
        case "vc+sd-jwt":
×
NEW
202
            format = "vc+sd-jwt"
×
203
        case "anoncreds/credential-offer@v1.0":
×
204
            format = "anoncreds/credential-request@v1.0"
×
205
        default:
×
206
            throw EdgeAgentError.invalidMessageType(
×
207
                type: offerFormat,
×
208
                shouldBe: [
×
209
                    "prism/jwt",
×
210
                    "anoncreds/credential-offer@v1.0"
×
211
                ]
×
212
            )
×
213
        }
×
214
        
×
215
        let type = offerPiuri == .didcommOfferCredential ?
×
216
            ProtocolTypes.didcommRequestCredential :
×
217
            ProtocolTypes.didcommRequestCredential3_0
×
218
        
×
219
        let requestCredential = RequestCredential3_0(
×
220
            body: .init(
×
221
                goalCode: offer.body.goalCode,
×
222
                comment: offer.body.comment
×
223
            ),
×
224
            type: type.rawValue,
×
225
            attachments: [.init(
×
226
                data: AttachmentBase64(base64: base64String),
×
227
                format: format
×
228
            )],
×
229
            thid: offer.thid,
×
230
            from: offer.to,
×
231
            to: offer.from
×
232
        )
×
233
        return requestCredential
×
234
    }
×
235
}
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

© 2025 Coveralls, Inc