LibertyDSNP / dsnp-wallet-swift

0 stars 0 forks source link

iOS > Implement solution for temporary metadata pod issue #99

Closed ryansheh closed 1 year ago

ryansheh commented 1 year ago

Updated 7/19/23

This needs to be fixed sooner rather than later in order to enable CircleCI/automation to pod install in their builds. Because of these temporary type and versioning fixes, pod installing will break extrinsic logic.

End Update

The file below TypeRegistryCatalog is a file in one of Nova's pod that will be updated when we update pods in the project.

I've implemented a temporary "localized" fix for our project return versionedRegistries[versions.first ?? 0] ?? baseRegistry //MARK: RYAN IF WE HIT THIS, ITS GOOD

We need to implement a permanent fix that manages this dependency file to our needs, rather than having to add that line above each time we update our pods.

`import Foundation

enum TypeRegistryCatalogError: Error { case missingVersioning case missingCurrentVersion case missingNetworkTypes case duplicatedVersioning }

public protocol TypeRegistryCatalogProtocol { func node(for typeName: String, version: UInt64) -> Node? }

/**

public class TypeRegistryCatalog: TypeRegistryCatalogProtocol { public let runtimeMetadataRegistry: TypeRegistryProtocol? public let baseRegistry: TypeRegistryProtocol public let versionedRegistries: [UInt64: TypeRegistryProtocol] public let versionedTypes: [String: [UInt64]] public let typeResolver: TypeResolving?

public let allTypes: Set<String>
public let mutex = NSLock()
public var registryCache: [String: TypeRegistryProtocol] = [:]

public init(baseRegistry: TypeRegistryProtocol,
            versionedRegistries: [UInt64: TypeRegistryProtocol],
            runtimeMetadataRegistry: TypeRegistryProtocol?,
            typeResolver: TypeResolving?) {
    self.baseRegistry = baseRegistry
    self.versionedRegistries = versionedRegistries
    self.runtimeMetadataRegistry = runtimeMetadataRegistry
    self.typeResolver = typeResolver

    let allVersions = versionedRegistries.keys.sorted()

    versionedTypes = allVersions.reduce(into: [String: [UInt64]]()) { (result, item) in
        guard let typeRegistry = versionedRegistries[item] else {
            return
        }

        let typeNames = typeRegistry.registeredTypeNames.filter { !(typeRegistry.node(for: $0) is GenericNode) }

        for typeName in typeNames {
            let versions: [UInt64] = result[typeName] ?? []

            if versions.last != item {
                result[typeName] = versions + [item]
            }
        }
    }

    allTypes = Set(versionedTypes.keys)
}

public func node(for typeName: String, version: UInt64) -> Node? {
    mutex.lock()

    defer {
        mutex.unlock()
    }

    let cacheKey = "\(typeName)_\(version)"

    if let registry = registryCache[cacheKey] {
        return registry.node(for: typeName)
    }

    let registry = getRegistry(for: typeName, version: version)
    return fallbackToRuntimeMetadataIfNeeded(from: registry, typeName: typeName, cacheKey: cacheKey)
}

public func replacingRuntimeMetadata(_ newMetadata: RuntimeMetadata) throws
-> TypeRegistryCatalogProtocol {
    mutex.lock()

    defer {
        mutex.unlock()
    }

    registryCache = [:]

    let newRuntimeRegistry = try TypeRegistry.createFromRuntimeMetadata(newMetadata)

    return TypeRegistryCatalog(baseRegistry: baseRegistry,
                               versionedRegistries: versionedRegistries,
                               runtimeMetadataRegistry: newRuntimeRegistry,
                               typeResolver: typeResolver)
}

// MARK: Private

private func getRegistry(for typeName: String, version: UInt64) -> TypeRegistryProtocol {

    let versions: [UInt64]

    if let typeVersions = versionedTypes[typeName] {
        versions = typeVersions
    } else if let resolvedName = typeResolver?.resolve(typeName: typeName, using: allTypes) {
        versions = versionedTypes[resolvedName] ?? []
    } else {
        versions = []
    }

// guard let minVersion = versions.reversed().first(where: { $0 <= version }) else { // return baseRegistry // }

// return versionedRegistries[minVersion] ?? baseRegistry return versionedRegistries[versions.first ?? 0] ?? baseRegistry //MARK: RYAN IF WE HIT THIS, ITS GOOD }

private func fallbackToRuntimeMetadataIfNeeded(from registry: TypeRegistryProtocol,
                                               typeName: String,
                                               cacheKey: String) -> Node? {
    if let node = registry.node(for: typeName) {
        registryCache[cacheKey] = registry
        return node
    }

    registryCache[cacheKey] = runtimeMetadataRegistry
    return runtimeMetadataRegistry?.node(for: typeName)
}

}`

ryansheh commented 1 year ago

There's also a temporary fix in SITypeRegistry that needs to be resolved ```SITYPEREGISTRY POD FIX import Foundation

protocol ScaleInfoRegistring { func register(identifier: String) -> Node }

public class SiTypeRegistry: TypeRegistryProtocol { private var allKeys: Set private let types: [String: RuntimeType] private let nodeFactory: ScaleInfoNodeFactoryProtocol private let baseNodes: [String: Node]

public var registeredTypes: [Node] { [] }
public var registeredTypeNames: Set<String> { allKeys }

public func node(for key: String) -> Node? {
    if let node = baseNodes[key] {
        return node
    }

    guard let type = types[key] else {
        return nil
    }

    let maybePathBasedName = type.pathBasedName

    //MARK: RYAN IMPORTANT
    if maybePathBasedName == "frequency_runtime.RuntimeEvent" {
        return baseNodes["GenericEvent"]
    }

    if let pathBasedName = maybePathBasedName, let node = baseNodes[pathBasedName] {
        return node
    } else if let pathBasedName = maybePathBasedName, key != pathBasedName, types[pathBasedName] != nil {
        return AliasNode(typeName: key, underlyingTypeName: pathBasedName)
    } else {
        return nodeFactory.buildNode(from: type, identifier: key)
    }
}

init(typesLookup: RuntimeTypesLookup, baseNodes: [Node], nodeFactory: ScaleInfoNodeFactoryProtocol) {
    let pathDuplications: [String: Int] = typesLookup.types.reduce(into: [:]) { (result, item) in
        guard let pathBasedName = item.type.pathBasedName else {
            return
        }

        if let counter = result[pathBasedName] {
            result[pathBasedName] = counter + 1
        } else {
            result[pathBasedName] = 1
        }
    }

    types = typesLookup.types.reduce(into: [:]) { (result, item) in
        let key = String(item.identifier)
        result[key] = item.type

        guard let pathBasedName = item.type.pathBasedName else {
            return
        }

        let counter = pathDuplications[pathBasedName] ?? 0

        guard counter <= 1 else {
            return
        }

        result[pathBasedName] = item.type
     }

    let baseKeys = Set(baseNodes.map({ $0.typeName }))

    allKeys = Set(types.keys).union(baseKeys)

    self.nodeFactory = nodeFactory
    self.baseNodes = baseNodes.reduce(into: [:]) { (result, item) in
        result[item.typeName] = item
    }
}

}

public extension SiTypeRegistry { static func createFromTypesLookup( _ metadata: RuntimeMetadataV14, additionalNodes: [Node] = [], customExtensions: [ExtrinsicExtensionCoder] = [], customTypeMapper: SiTypeMapping? = nil, customNameMapper: SiNameMapping? = nil ) -> SiTypeRegistry { var genericTypeMappings = createGenericTypeMappers()

    if let customTypeMapper = customTypeMapper {
        genericTypeMappings.append(customTypeMapper)
    }

    let typeMapping = OneOfSiTypeMapper(innerMappers: genericTypeMappings)

    let nodeFactory = ScaleInfoNodeFactory(typeMapper: typeMapping, nameMapper: customNameMapper)

    let allNodes = BasisNodes.allNodes(for: metadata, customExtensions: customExtensions)
    let baseNodes = allNodes + additionalNodes
    let registry = SiTypeRegistry(typesLookup: metadata.types, baseNodes: baseNodes, nodeFactory: nodeFactory)

    return registry
}

}

extension SiTypeRegistry { static func createGenericTypeMappers() -> [SiTypeMapping] { [ SiOptionTypeMapper(), SiSetTypeMapper(), SiCompositeNoneToAliasMapper() ] } }