Skip to content

Commit

Permalink
fix: issues with interoperability with other sdks
Browse files Browse the repository at this point in the history
Signed-off-by: goncalo-frade-iohk <[email protected]>
  • Loading branch information
goncalo-frade-iohk committed Jun 11, 2024
1 parent afca01b commit dea00b2
Show file tree
Hide file tree
Showing 8 changed files with 312 additions and 29 deletions.
1 change: 0 additions & 1 deletion EdgeAgentSDK/Apollo/Sources/Model/Secp256k1Key.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ struct Secp256k1PublicKey: PublicKey {
self.keySpecifications = specs
self.size = internalKey.raw.toData().count
self.raw = internalKey.raw.toData()

}

init(x: Data, y: Data) {
Expand Down
203 changes: 203 additions & 0 deletions EdgeAgentSDK/Domain/Sources/AnyCodable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
import Foundation

struct AnyCodable {
let value: Any

init<T: Codable>(_ value: T) {
self.value = value
}

init(_ value: Any) {
self.value = value
}

func get<T>() -> T? {
value as? T
}

func get() -> Any {
value
}
}

extension AnyCodable: Codable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()

if container.decodeNil() {
self.init(())
} else if let bool = try? container.decode(Bool.self) {
self.init(bool)
} else if let int = try? container.decode(Int.self) {
self.init(int)
} else if let uint = try? container.decode(UInt.self) {
self.init(uint)
} else if let double = try? container.decode(Double.self) {
self.init(double)
} else if let string = try? container.decode(String.self) {
self.init(string)
} else if let array = try? container.decode([AnyCodable].self) {
self.init(array.map { $0.value })
} else if let dictionary = try? container.decode([String: AnyCodable].self) {
self.init(dictionary.mapValues { $0.value })
} else {
throw DecodingError.dataCorruptedError(
in: container,
debugDescription: "Not a known JSON Primitive"
)
}
}

func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()

switch self.value {
case is Void:
try container.encodeNil()
case let bool as Bool:
try container.encode(bool)
case let int as Int:
try container.encode(int)
case let int8 as Int8:
try container.encode(int8)
case let int16 as Int16:
try container.encode(int16)
case let int32 as Int32:
try container.encode(int32)
case let int64 as Int64:
try container.encode(int64)
case let uint as UInt:
try container.encode(uint)
case let uint8 as UInt8:
try container.encode(uint8)
case let uint16 as UInt16:
try container.encode(uint16)
case let uint32 as UInt32:
try container.encode(uint32)
case let uint64 as UInt64:
try container.encode(uint64)
case let float as Float:
try container.encode(float)
case let double as Double:
try container.encode(double)
case let string as String:
try container.encode(string)
case let date as Date:
try container.encode(date)
case let url as URL:
try container.encode(url)
case let array as [Any]:
try container.encode(array.map { AnyCodable($0) })
case let dictionary as [String: Any]:
try container.encode(dictionary.mapValues { AnyCodable($0) })
default:
let context = EncodingError.Context(
codingPath: container.codingPath,
debugDescription: "Value is not codable"
)
throw EncodingError.invalidValue(self.value, context)
}
}
}

extension AnyCodable: Equatable {
static func ==(lhs: AnyCodable, rhs: AnyCodable) -> Bool {
switch (lhs.value, rhs.value) {
case is (Void, Void):
return true
case let (lhs as Bool, rhs as Bool):
return lhs == rhs
case let (lhs as Int, rhs as Int):
return lhs == rhs
case let (lhs as Int8, rhs as Int8):
return lhs == rhs
case let (lhs as Int16, rhs as Int16):
return lhs == rhs
case let (lhs as Int32, rhs as Int32):
return lhs == rhs
case let (lhs as Int64, rhs as Int64):
return lhs == rhs
case let (lhs as UInt, rhs as UInt):
return lhs == rhs
case let (lhs as UInt8, rhs as UInt8):
return lhs == rhs
case let (lhs as UInt16, rhs as UInt16):
return lhs == rhs
case let (lhs as UInt32, rhs as UInt32):
return lhs == rhs
case let (lhs as UInt64, rhs as UInt64):
return lhs == rhs
case let (lhs as Float, rhs as Float):
return lhs == rhs
case let (lhs as Double, rhs as Double):
return lhs == rhs
case let (lhs as String, rhs as String):
return lhs == rhs
case (let lhs as [String: AnyCodable], let rhs as [String: AnyCodable]):
return lhs == rhs
case (let lhs as [AnyCodable], let rhs as [AnyCodable]):
return lhs == rhs
default:
return false
}
}
}

extension AnyCodable: CustomStringConvertible {
var description: String {
switch value {
case is Void:
return String(describing: nil as Any?)
case let value as CustomStringConvertible:
return value.description
default:
return String(describing: value)
}
}
}

extension AnyCodable: CustomDebugStringConvertible {
var debugDescription: String {
switch value {
case let value as CustomDebugStringConvertible:
return "AnyCodable(\(value.debugDescription))"
default:
return "AnyCodable(\(self.description))"
}
}
}

extension AnyCodable: ExpressibleByNilLiteral, ExpressibleByBooleanLiteral, ExpressibleByIntegerLiteral, ExpressibleByFloatLiteral, ExpressibleByStringLiteral, ExpressibleByArrayLiteral, ExpressibleByDictionaryLiteral {

init(nilLiteral: ()) {
self.init(nil ?? ())
}

init(booleanLiteral value: Bool) {
self.init(value)
}

init(integerLiteral value: Int) {
self.init(value)
}

init(floatLiteral value: Double) {
self.init(value)
}

init(extendedGraphemeClusterLiteral value: String) {
self.init(value)
}

init(stringLiteral value: String) {
self.init(value)
}

init(arrayLiteral elements: Any...) {
self.init(elements)
}

init(dictionaryLiteral elements: (AnyHashable, Any)...) {
self.init(Dictionary<AnyHashable, Any>(elements, uniquingKeysWith: { (first, _) in first }))
}
}
19 changes: 17 additions & 2 deletions EdgeAgentSDK/Domain/Sources/Models/Message+Codable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ extension Message: Codable {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(piuri, forKey: .piuri)
try container.encode(body, forKey: .body)
if let dic = try? JSONSerialization.jsonObject(with: body) as? [String: Any] {
try container.encode(AnyCodable(dic), forKey: .body)
} else {
try container.encode(body, forKey: .body)
}
try container.encode(extraHeaders, forKey: .extraHeaders)
try container.encode(createdTime, forKey: .createdTime)
try container.encode(expiresTimePlus, forKey: .expiresTimePlus)
Expand All @@ -40,7 +44,18 @@ extension Message: Codable {
let container = try decoder.container(keyedBy: CodingKeys.self)
let id = try container.decode(String.self, forKey: .id)
let piuri = try container.decode(String.self, forKey: .piuri)
let body = try container.decodeIfPresent(Data.self, forKey: .body)
let body: Data?
if
let bodyCodable = try? container.decodeIfPresent(AnyCodable.self, forKey: .body),
(bodyCodable.value is [String: Any] || bodyCodable.value is [String]),
let bodyData = try? JSONSerialization.data(withJSONObject: bodyCodable.value)
{
body = bodyData
} else if let bodyData = try? container.decodeIfPresent(Data.self, forKey: .body) {
body = bodyData
} else {
body = nil
}
let extraHeaders = try container.decodeIfPresent([String: String].self, forKey: .extraHeaders)
let createdTime = try container.decodeIfPresent(Date.self, forKey: .createdTime)
let expiresTimePlus = try container.decodeIfPresent(Date.self, forKey: .expiresTimePlus)
Expand Down
38 changes: 22 additions & 16 deletions EdgeAgentSDK/EdgeAgent/Sources/EdgeAgent+Backup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ extension EdgeAgent {
struct Key: Codable {
let key: String
let did: String?
let recoveryType: String
let index: Int?
let recoveryId: String?
}

struct Credential: Codable {
Expand All @@ -19,7 +20,7 @@ extension EdgeAgent {

struct Pair: Codable {
let holder: String
let receiver: String
let recipient: String
let alias: String?
}

Expand Down Expand Up @@ -144,7 +145,8 @@ extension EdgeAgent {
return Backup.Key(
key: keyStr,
did: did.did.string,
recoveryType: key.restorationIdentifier
index: key.index,
recoveryId: key.restorationIdentifier
)
}
}.flatMap { $0 }
Expand All @@ -159,7 +161,8 @@ extension EdgeAgent {
return Backup.Key(
key: keyStr,
did: nil,
recoveryType: key.restorationIdentifier
index: key.index,
recoveryId: key.restorationIdentifier
)
}
return backupKeys + backupDIDKeys
Expand All @@ -168,15 +171,18 @@ extension EdgeAgent {
func recoverDidsWithKeys(dids: [Backup.DIDs], keys: [Backup.Key]) async throws {
try await dids.asyncForEach { [weak self] did in
let storableKeys = try await keys
.filter { $0.did == did.did }
.compactMap {
return Data(base64URLEncoded: $0.key)
.filter {
let didurl = $0.did.flatMap { try? DIDUrl(string: $0) }?.did.string
return didurl == did.did
}
.compactMap { key in
return Data(base64URLEncoded: key.key).map { ($0, key.index) }
}
.asyncCompactMap {
guard let self else {
throw UnknownError.somethingWentWrongError(customMessage: nil, underlyingErrors: nil)
}
return try await jwkToKey(key: $0, restoration: self.apollo)
return try await jwkToKey(key: $0, restoration: self.apollo, index: $1)
}

try await self?.pluto.storeDID(
Expand All @@ -193,7 +199,7 @@ extension EdgeAgent {
try await pairs.asyncForEach { [weak self] in
try await self?.pluto.storeDIDPair(pair: .init(
holder: DID(string: $0.holder),
other: DID(string: $0.receiver),
other: DID(string: $0.recipient),
name: $0.alias
))
.first()
Expand All @@ -202,13 +208,13 @@ extension EdgeAgent {
}

func recoverMessages(messages: [String]) async throws {
let messages = messages.compactMap { messageStr -> (Message, Message.Direction)? in
let messages = try messages.compactMap { messageStr -> (Message, Message.Direction)? in
guard
let messageData = Data(base64URLEncoded: messageStr),
let message = try? JSONDecoder.didComm().decode(Message.self, from: messageData)
let messageData = Data(base64URLEncoded: messageStr)
else {
return nil
}
let message = try JSONDecoder.didComm().decode(Message.self, from: messageData)

return (message, message.direction)
}
Expand All @@ -228,7 +234,7 @@ extension EdgeAgent {
else {
return nil
}
return try? await pollux.importCredential(
return try await pollux.importCredential(
credentialData: data,
restorationType: bakCredential.recoveryId,
options: [
Expand Down Expand Up @@ -285,7 +291,7 @@ extension EdgeAgent {
.first()
.await()
.map {
Backup.Pair(holder: $0.holder.string, receiver: $0.other.string, alias: $0.name)
Backup.Pair(holder: $0.holder.string, recipient: $0.other.string, alias: $0.name)
}
}

Expand Down Expand Up @@ -350,8 +356,8 @@ private func keyToJWK(key: StorableKey, restoration: KeyRestoration) async throw
return try JSONEncoder().encode(exportable.jwk).base64UrlEncodedString()
}

private func jwkToKey(key: Data, restoration: KeyRestoration) async throws -> StorableKey? {
private func jwkToKey(key: Data, restoration: KeyRestoration, index: Int?) async throws -> StorableKey? {
let jwk = try JSONDecoder().decode(Domain.JWK.self, from: key)
let key = try await restoration.restoreKey(jwk, index: nil)
let key = try await restoration.restoreKey(jwk, index: index)
return key.storable
}
Loading

0 comments on commit dea00b2

Please sign in to comment.