Skip to content

Commit

Permalink
add predefined types
Browse files Browse the repository at this point in the history
  • Loading branch information
ERussel committed Dec 15, 2023
1 parent b48942e commit 124f4b8
Show file tree
Hide file tree
Showing 10 changed files with 384 additions and 2 deletions.
4 changes: 4 additions & 0 deletions Example/SubstrateSdk.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
0CE92A6F2B2C5906009A21E9 /* kusama-v14-metadata-latest in Resources */ = {isa = PBXBuildFile; fileRef = 0CE92A6E2B2C5906009A21E9 /* kusama-v14-metadata-latest */; };
6976AE87036D532DDD11B3D9 /* Pods_SubstrateSdkExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00060C8DD6432907D485E325 /* Pods_SubstrateSdkExample.framework */; };
841D528A25C4A11900DFA15B /* RegexParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841D528925C4A11900DFA15B /* RegexParserTests.swift */; };
841D52B425C6BAE600DFA15B /* ComponentsParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841D52B325C6BAE600DFA15B /* ComponentsParserTests.swift */; };
Expand Down Expand Up @@ -136,6 +137,7 @@

/* Begin PBXFileReference section */
00060C8DD6432907D485E325 /* Pods_SubstrateSdkExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SubstrateSdkExample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0CE92A6E2B2C5906009A21E9 /* kusama-v14-metadata-latest */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "kusama-v14-metadata-latest"; sourceTree = "<group>"; };
27A1BEB05AA8335CF4053A81 /* Pods_SubstrateSdkTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SubstrateSdkTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
2E305CB3E5589CF7DC3BD962 /* Pods-SubstrateSdkTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SubstrateSdkTests.debug.xcconfig"; path = "Target Support Files/Pods-SubstrateSdkTests/Pods-SubstrateSdkTests.debug.xcconfig"; sourceTree = "<group>"; };
3DC3C61E2550AB6A7358DB29 /* Pods-SubstrateSdkTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SubstrateSdkTests.release.xcconfig"; path = "Target Support Files/Pods-SubstrateSdkTests/Pods-SubstrateSdkTests.release.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -367,6 +369,7 @@
8429C7FB25C432DA0086D7F6 /* Runtime */ = {
isa = PBXGroup;
children = (
0CE92A6E2B2C5906009A21E9 /* kusama-v14-metadata-latest */,
84AF3766271A3A8D007408D6 /* kusama-v14-metadata */,
84AF3767271A3A8D007408D6 /* polkadot-v14-metadata */,
84AF3768271A3A8D007408D6 /* westend-v14-metadata */,
Expand Down Expand Up @@ -749,6 +752,7 @@
8429C81825C434E40086D7F6 /* default.json in Resources */,
8467FD1524E677C6005D486C /* ecdsaHDKD.json in Resources */,
84452C0F25D2D5C300F47EC5 /* polkadot-metadata in Resources */,
0CE92A6F2B2C5906009A21E9 /* kusama-v14-metadata-latest in Resources */,
8429C82725C434ED0086D7F6 /* westend.json in Resources */,
84A0DE3124DBF49400F436A8 /* keystore-ed25519.json in Resources */,
849CFADE27394E5D0096D201 /* keystore-ethereum-int-version.json in Resources */,
Expand Down
2 changes: 2 additions & 0 deletions SubstrateSdk/Classes/Runtime/KnownType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ public enum KnownType: String, CaseIterable {
case index = "Index"
case phase = "Phase"
case call = "GenericCall"
case event = "GenericEvent"
case address = "Address"
case signature = "ExtrinsicSignature"
case runtimeDispatchInfo = "RuntimeDispatchInfo"

public var name: String { rawValue }
}
8 changes: 6 additions & 2 deletions SubstrateSdk/Classes/Runtime/Metadata/V14/RuntimeType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,14 @@ public struct RuntimeType {
}
}

extension RuntimeType {
var pathBasedName: String? {
public extension RuntimeType {
public var pathBasedName: String? {
!path.isEmpty ? path.joined(separator: ".") : nil
}

public static func pathFromName(_ name: String) -> [String] {
name.components(separatedBy: ".")
}
}

extension RuntimeType: ScaleCodable {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
import Foundation

public protocol RuntimeAugmentationFactoryProtocol: AnyObject {
func createSubstrateAugmentation(for runtime: RuntimeMetadataV14) -> RuntimeAugmentationResult
func createEthereumBasedAugmentation(for runtime: RuntimeMetadataV14) -> RuntimeAugmentationResult
}

public final class RuntimeAugmentationFactory: RuntimeAugmentationFactoryProtocol {
static let uncheckedExtrinsicModuleName = "sp_runtime.UncheckedExtrinsic"

public init() {}

private func addingAdditionalOneOfTo(
types: [String],
fromType: String,
additionalNodes: RuntimeAugmentationResult.AdditionalNodes,
runtime: RuntimeMetadataV14,
mode: RuntimeTypeMatchingMode
) -> RuntimeAugmentationResult.AdditionalNodes {
for type in types {
if let metadataType = RuntimeMetadataSearchEngine.find(type: type, in: runtime, mode: mode) {
let node = AliasNode(typeName: fromType, underlyingTypeName: metadataType)
return additionalNodes.adding(node: node)
}
}

return additionalNodes.adding(notMatchedType: fromType)
}

private func addingAdditionalOneOfFrom(
types: [String],
toType: String,
additionalNodes: RuntimeAugmentationResult.AdditionalNodes,
runtime: RuntimeMetadataV14,
mode: RuntimeTypeMatchingMode
) -> RuntimeAugmentationResult.AdditionalNodes {
for type in types {
if let metadataType = RuntimeMetadataSearchEngine.find(type: type, in: runtime, mode: mode) {
let node = AliasNode(typeName: metadataType, underlyingTypeName: toType)
return additionalNodes.adding(node: node)
}
}

return additionalNodes.adding(notMatchedType: toType)
}

private func addingEventPhaseNode(
to additionalNodes: RuntimeAugmentationResult.AdditionalNodes,
runtime: RuntimeMetadataV14
) -> RuntimeAugmentationResult.AdditionalNodes {
addingAdditionalOneOfTo(
types: ["frame_system.Phase"],
fromType: KnownType.phase.name,
additionalNodes: additionalNodes,
runtime: runtime,
mode: .firstLastComponents
)
}

private func addingSubstrateAddressNode(
to additionalNodes: RuntimeAugmentationResult.AdditionalNodes,
runtime: RuntimeMetadataV14
) -> RuntimeAugmentationResult.AdditionalNodes {
if let addressType = RuntimeMetadataSearchEngine.findParameterType(
for: Self.uncheckedExtrinsicModuleName,
parameterName: "Address",
in: runtime,
mode: .firstLastComponents
) {
let node = AliasNode(typeName: KnownType.address.name, underlyingTypeName: addressType)
return additionalNodes.adding(node: node)
} else {
return additionalNodes.adding(notMatchedType: KnownType.address.name)
}
}

private func addingEthereumBasedAddressNode(
to additionalNodes: RuntimeAugmentationResult.AdditionalNodes,
runtime: RuntimeMetadataV14
) -> RuntimeAugmentationResult.AdditionalNodes {
addingAdditionalOneOfTo(
types: ["AccountId20"],
fromType: KnownType.address.name,
additionalNodes: additionalNodes,
runtime: runtime,
mode: .lastComponent
)
}

private func addingSubstrateSignatureNode(
to additionalNodes: RuntimeAugmentationResult.AdditionalNodes,
runtime: RuntimeMetadataV14
) -> RuntimeAugmentationResult.AdditionalNodes {
if let signatureType = RuntimeMetadataSearchEngine.findParameterType(
for: Self.uncheckedExtrinsicModuleName,
parameterName: "Signature",
in: runtime,
mode: .firstLastComponents
) {
let node = AliasNode(typeName: KnownType.signature.name, underlyingTypeName: signatureType)
return additionalNodes.adding(node: node)
} else {
return additionalNodes.adding(notMatchedType: KnownType.signature.name)
}
}

private func addingEthereumBasedSignatureNode(
to additionalNodes: RuntimeAugmentationResult.AdditionalNodes,
runtime _: RuntimeMetadataV14
) -> RuntimeAugmentationResult.AdditionalNodes {
let node = StructNode(
typeName: KnownType.signature.name,
typeMapping: [
NameNode(name: "r", node: ProxyNode(typeName: GenericType.h256.name)),
NameNode(name: "s", node: ProxyNode(typeName: GenericType.h256.name)),
NameNode(name: "v", node: ProxyNode(typeName: PrimitiveType.u8.name))
]
)

return additionalNodes.adding(node: node)
}

private func addingSubstrateAccountIdNode(
to additionalNodes: RuntimeAugmentationResult.AdditionalNodes,
runtime: RuntimeMetadataV14
) -> RuntimeAugmentationResult.AdditionalNodes {
addingAdditionalOneOfFrom(
types: ["AccountId32"],
toType: GenericType.accountId.name,
additionalNodes: additionalNodes,
runtime: runtime,
mode: .lastComponent
)
}

private func addingPalletIdentityDataNode(
to additionalNodes: RuntimeAugmentationResult.AdditionalNodes,
runtime: RuntimeMetadataV14
) -> RuntimeAugmentationResult.AdditionalNodes {
addingAdditionalOneOfFrom(
types: ["pallet_identity.Data"],
toType: GenericType.data.name,
additionalNodes: additionalNodes,
runtime: runtime,
mode: .firstLastComponents
)
}

private func addingRuntimeEventNode(
to additionalNodes: RuntimeAugmentationResult.AdditionalNodes,
runtime: RuntimeMetadataV14
) -> RuntimeAugmentationResult.AdditionalNodes {
addingAdditionalOneOfFrom(
types: ["RuntimeEvent", "Event"],
toType: GenericType.event.name,
additionalNodes: additionalNodes,
runtime: runtime,
mode: .lastComponent
)
}

private func addingRuntimeCallNode(
to additionalNodes: RuntimeAugmentationResult.AdditionalNodes,
runtime: RuntimeMetadataV14
) -> RuntimeAugmentationResult.AdditionalNodes {
addingAdditionalOneOfFrom(
types: ["RuntimeCall", "Call"],
toType: GenericType.call.name,
additionalNodes: additionalNodes,
runtime: runtime,
mode: .lastComponent
)
}

private func addingRuntimeDispatchNode(
to additionalNodes: RuntimeAugmentationResult.AdditionalNodes,
runtime: RuntimeMetadataV14
) -> RuntimeAugmentationResult.AdditionalNodes {
let feeType = KnownType.runtimeDispatchInfo.name
let runtimeType = "frame_support.dispatch.DispatchInfo"

guard
let portableType = RuntimeMetadataSearchEngine.findPortableType(
for: runtimeType,
in: runtime,
mode: .firstLastComponents
),
case let .composite(compositeType) = portableType.type.typeDefinition else {
return additionalNodes.adding(notMatchedType: feeType)
}

guard
let weightLookupId = compositeType.fields.first(where: { $0.name == "weight" })?.type,
let weightType = runtime.types.types.first(
where: { $0.identifier == weightLookupId }
)?.type.pathBasedName,
let dispatchClassLookupId = compositeType.fields.first(where: { $0.name == "class" })?.type,
let dispatchClassType = runtime.types.types.first(
where: { $0.identifier == dispatchClassLookupId }
)?.type.pathBasedName else {
return additionalNodes.adding(notMatchedType: feeType)
}

let node = StructNode(
typeName: feeType,
typeMapping: [
NameNode(name: "weight", node: ProxyNode(typeName: weightType)),
NameNode(name: "class", node: ProxyNode(typeName: dispatchClassType)),
NameNode(name: "partialFee", node: ProxyNode(typeName: PrimitiveType.u128.name))
]
)

return additionalNodes.adding(node: node)
}

private func getCommonAdditionalNodes(
for runtime: RuntimeMetadataV14
) -> RuntimeAugmentationResult.AdditionalNodes {
var additionalNodes = RuntimeAugmentationResult.AdditionalNodes(
nodes: [
AliasNode(typeName: KnownType.balance.name, underlyingTypeName: PrimitiveType.u128.name),
AliasNode(typeName: KnownType.index.name, underlyingTypeName: PrimitiveType.u32.name)
],
notMatch: []
)

additionalNodes = addingEventPhaseNode(to: additionalNodes, runtime: runtime)
additionalNodes = addingRuntimeEventNode(to: additionalNodes, runtime: runtime)
additionalNodes = addingRuntimeCallNode(to: additionalNodes, runtime: runtime)
additionalNodes = addingSubstrateAccountIdNode(to: additionalNodes, runtime: runtime)
additionalNodes = addingPalletIdentityDataNode(to: additionalNodes, runtime: runtime)
additionalNodes = addingRuntimeDispatchNode(to: additionalNodes, runtime: runtime)

return additionalNodes
}

private func addingSubstrateSpecificNodes(
to additionalNodes: RuntimeAugmentationResult.AdditionalNodes,
runtime: RuntimeMetadataV14
) -> RuntimeAugmentationResult.AdditionalNodes {
var updatedNodes = additionalNodes
updatedNodes = addingSubstrateAddressNode(to: updatedNodes, runtime: runtime)
updatedNodes = addingSubstrateSignatureNode(to: updatedNodes, runtime: runtime)

return updatedNodes
}

private func addingEthereumBasedSpecificNodes(
to additionalNodes: RuntimeAugmentationResult.AdditionalNodes,
runtime: RuntimeMetadataV14
) -> RuntimeAugmentationResult.AdditionalNodes {
var updatedNodes = additionalNodes
updatedNodes = addingEthereumBasedAddressNode(to: updatedNodes, runtime: runtime)
updatedNodes = addingEthereumBasedSignatureNode(to: updatedNodes, runtime: runtime)

return updatedNodes
}
}

extension RuntimeAugmentationFactory {
public func createSubstrateAugmentation(for runtime: RuntimeMetadataV14) -> RuntimeAugmentationResult {
var additionalNodes = getCommonAdditionalNodes(for: runtime)
additionalNodes = addingSubstrateSpecificNodes(to: additionalNodes, runtime: runtime)

return RuntimeAugmentationResult(additionalNodes: additionalNodes)
}

public func createEthereumBasedAugmentation(for runtime: RuntimeMetadataV14) -> RuntimeAugmentationResult {
var additionalNodes = getCommonAdditionalNodes(for: runtime)
additionalNodes = addingEthereumBasedSpecificNodes(to: additionalNodes, runtime: runtime)

return RuntimeAugmentationResult(additionalNodes: additionalNodes)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Foundation

public struct RuntimeAugmentationResult {
public struct AdditionalNodes {
public let nodes: [Node]
public let notMatch: Set<String>

public init(nodes: [Node], notMatch: Set<String>) {
self.nodes = nodes
self.notMatch = notMatch
}

public func adding(node: Node) -> AdditionalNodes {
.init(nodes: nodes + [node], notMatch: notMatch)
}

public func adding(notMatchedType: String) -> AdditionalNodes {
.init(nodes: nodes, notMatch: notMatch.union([notMatchedType]))
}
}

public let additionalNodes: AdditionalNodes
}
Loading

0 comments on commit 124f4b8

Please sign in to comment.