-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(agent): add didcomm connection protocol and invitation protocol
- Loading branch information
1 parent
40ce0e3
commit c112c8b
Showing
7 changed files
with
254 additions
and
0 deletions.
There are no files selected for viewing
33 changes: 33 additions & 0 deletions
33
PrismAgent/Sources/Protocols/Connection/DIDCommConnectionRunner.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import Domain | ||
import Foundation | ||
|
||
class DIDCommConnectionRunner { | ||
private let mercury: Mercury | ||
private let invitationMessage: Message | ||
private let ownDID: DID | ||
private let connectionMaker: (DID, DID, Mercury) -> DIDCommConnection | ||
private var request: HandshakeRequest? | ||
|
||
init( | ||
mercury: Mercury, | ||
invitationMessage: Message, | ||
ownDID: DID, | ||
connectionMaker: @escaping (DID, DID, Mercury) -> DIDCommConnection | ||
) { | ||
self.mercury = mercury | ||
self.invitationMessage = invitationMessage | ||
self.ownDID = ownDID | ||
self.connectionMaker = connectionMaker | ||
} | ||
|
||
func run() async throws -> DIDCommConnection { | ||
let request = try HandshakeRequest(inviteMessage: invitationMessage, from: ownDID) | ||
try await mercury.sendMessage(msg: try request.makeMessage()) | ||
let connection = connectionMaker(ownDID, request.to, mercury) | ||
guard | ||
let message = try await connection.awaitMessageResponse(id: request.id), | ||
message.piuri == ProtocolTypes.didcommconnectionResponse.rawValue | ||
else { throw PrismAgentError.noHandshakeResponseError } | ||
return connection | ||
} | ||
} |
62 changes: 62 additions & 0 deletions
62
PrismAgent/Sources/Protocols/Connection/HandshakeRequest.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import Domain | ||
import Foundation | ||
|
||
struct HandshakeRequest { | ||
// Connection Body is the same as Invitation body message | ||
struct Body: Codable { | ||
let goalCode: String? | ||
let goal: String? | ||
let accept: [String] | ||
|
||
init( | ||
goalCode: String? = nil, | ||
goal: String? = nil, | ||
accept: [String] = [] | ||
) { | ||
self.goalCode = goalCode | ||
self.goal = goal | ||
self.accept = accept | ||
} | ||
} | ||
let type: String = ProtocolTypes.didcommconnectionRequest.rawValue | ||
let id: String | ||
let from: DID | ||
// swiftlint:disable identifier_name | ||
let to: DID | ||
// swiftlint:enable identifier_name | ||
let thid: String? | ||
let body: Body | ||
|
||
init(inviteMessage: Message, from: DID) throws { | ||
guard let toDID = inviteMessage.from else { throw PrismAgentError.invitationIsInvalidError } | ||
let body = try JSONDecoder().decode(Body.self, from: inviteMessage.body) | ||
self.init(from: from, to: toDID, thid: inviteMessage.id, body: body) | ||
} | ||
|
||
init( | ||
id: String = UUID().uuidString, | ||
from: DID, | ||
// swiftlint:disable identifier_name | ||
to: DID, | ||
// swiftlint:enable identifier_name | ||
thid: String?, | ||
body: Body | ||
) { | ||
self.id = id | ||
self.from = from | ||
self.to = to | ||
self.thid = thid | ||
self.body = body | ||
} | ||
|
||
func makeMessage() throws -> Message { | ||
Message( | ||
id: id, | ||
piuri: type, | ||
from: from, | ||
to: to, | ||
body: try JSONEncoder().encode(self.body), | ||
thid: thid | ||
) | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
PrismAgent/Sources/Protocols/Invitation/V2/DIDCommInvitationRunner.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import Domain | ||
import Foundation | ||
|
||
class DIDCommInvitationRunner { | ||
private let mercury: Mercury | ||
private let url: URL | ||
|
||
init(mercury: Mercury, url: URL) { | ||
self.mercury = mercury | ||
self.url = url | ||
} | ||
|
||
func run() throws -> Message { | ||
let messageString = try OutOfBandParser().parseMessage(url: url) | ||
let message = try mercury.unpackMessage(msg: messageString, options: .expectDecryptByAllKeys).result | ||
guard message.piuri == ProtocolTypes.didcomminvitation.rawValue else { | ||
throw PrismAgentError.unknownInvitationTypeError | ||
} | ||
return message | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
PrismAgent/Sources/Protocols/Invitation/V2/InvitationRunner.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import Domain | ||
import Foundation | ||
|
||
class InvitationRunner { | ||
private let mercury: Mercury | ||
private let url: URL | ||
|
||
init(mercury: Mercury, url: URL) { | ||
self.mercury = mercury | ||
self.url = url | ||
} | ||
|
||
func run() async throws -> Message { | ||
let messageString = try OutOfBandParser().parseMessage(url: url) | ||
return try await mercury.unpackMessage(msg: messageString, options: .expectDecryptByAllKeys).result | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import Domain | ||
@testable import PrismAgent | ||
import XCTest | ||
|
||
final class ConnectionRunnerTests: XCTestCase { | ||
private let mercury = MercuryStub() | ||
|
||
func testWhenInvitationMessageThenTryConnectingWith() async throws { | ||
let body = HandshakeRequest.Body( | ||
goalCode: "123", | ||
goal: "Test", | ||
accept: ["Test1"] | ||
) | ||
|
||
let exampleMessage = Message( | ||
piuri: ProtocolTypes.didcomminvitation.rawValue, | ||
from: DID(index: 1), | ||
to: DID(index: 2), | ||
body: try JSONEncoder().encode(body) | ||
) | ||
|
||
let exampleMessageResponse = Message( | ||
piuri: ProtocolTypes.didcommconnectionResponse.rawValue, | ||
from: DID(index: 2), | ||
to: DID(index: 1), | ||
body: try JSONEncoder().encode(body) | ||
) | ||
|
||
let selfDID = DID(index: 3) | ||
let connection = ConnectionStub() | ||
connection.awaitMessageResponse = exampleMessageResponse | ||
|
||
_ = try await DIDCommConnectionRunner( | ||
mercury: mercury, | ||
invitationMessage: exampleMessage, | ||
ownDID: selfDID | ||
) { holderDID, otherDID, _ in | ||
connection.holderDID = holderDID | ||
connection.otherDID = otherDID | ||
return connection | ||
}.run() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import Domain | ||
@testable import PrismAgent | ||
import XCTest | ||
|
||
final class DIDCommInvitationRunnerTests: XCTestCase { | ||
private let mercury = MercuryStub() | ||
|
||
func testWhenReceivedOOBUrlThenParseMessage() throws { | ||
let exampleMessage = Message(piuri: ProtocolTypes.didcomminvitation.rawValue, body: Data()) | ||
let queryString = try mercury.packMessage(msg: exampleMessage).result | ||
let exampleURL = URL(string: "localhost:8080?_oob=\(queryString)")! | ||
|
||
let parsedMessage = try DIDCommInvitationRunner(mercury: mercury, url: exampleURL).run() | ||
XCTAssertEqual(exampleMessage, parsedMessage) | ||
} | ||
|
||
func testWhenInvalidInvitationTypeThenThrowError() throws { | ||
let exampleMessage = Message(piuri: "Something wrong", body: Data()) | ||
let queryString = try mercury.packMessage(msg: exampleMessage).result | ||
let exampleURL = URL(string: "localhost:8080?_oob=\(queryString)")! | ||
|
||
XCTAssertThrowsError(try DIDCommInvitationRunner(mercury: mercury, url: exampleURL).run()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import Domain | ||
@testable import PrismAgent | ||
import XCTest | ||
|
||
final class HandshakeRequestTests: XCTestCase { | ||
func testHandshakeRequestMakeMessage() throws { | ||
let request = HandshakeRequest( | ||
from: DID(index: 1), | ||
to: DID(index: 2), | ||
thid: "0", | ||
body: .init(goalCode: "1", goal: "Test", accept: ["Test1"]) | ||
) | ||
|
||
let message = try request.makeMessage() | ||
XCTAssertEqual(message.id, request.id) | ||
XCTAssertEqual(message.piuri, request.type) | ||
XCTAssertEqual(message.from, request.from) | ||
XCTAssertEqual(message.to, request.to) | ||
XCTAssertEqual(message.thid, request.thid) | ||
let decodedBody = try JSONDecoder().decode(HandshakeRequest.Body.self, from: message.body) | ||
XCTAssertEqual(decodedBody, request.body) | ||
} | ||
|
||
func testHandshakeRequestInitFromInvitationMessage() throws { | ||
let body = HandshakeRequest.Body( | ||
goalCode: "123", | ||
goal: "Test", | ||
accept: ["Test1"] | ||
) | ||
|
||
let exampleMessage = Message( | ||
piuri: ProtocolTypes.didcomminvitation.rawValue, | ||
from: DID(index: 1), | ||
to: DID(index: 2), | ||
body: try JSONEncoder().encode(body) | ||
) | ||
|
||
let selfDID = DID(index: 3) | ||
|
||
let request = try HandshakeRequest(inviteMessage: exampleMessage, from: selfDID) | ||
XCTAssertNotEqual(exampleMessage.id, request.id) | ||
XCTAssertEqual(request.type, ProtocolTypes.didcommconnectionRequest.rawValue) | ||
XCTAssertEqual(selfDID, request.from) | ||
XCTAssertEqual(exampleMessage.from, request.to) | ||
XCTAssertEqual(exampleMessage.id, request.thid) | ||
XCTAssertEqual(body, request.body) | ||
} | ||
} | ||
|
||
extension HandshakeRequest.Body: Equatable { | ||
public static func == (lhs: HandshakeRequest.Body, rhs: HandshakeRequest.Body) -> Bool { | ||
lhs.goalCode == rhs.goalCode && lhs.goal == rhs.goal && lhs.accept == rhs.accept | ||
} | ||
} |