Skip to content

Commit

Permalink
Merge pull request #893 from AlphaWallet/update-xml-parsing-for-lates…
Browse files Browse the repository at this point in the history
…t-asset-definition-schema

Update XML parsing to handle latest asset definition schema
  • Loading branch information
bitcoinwarrior1 authored Nov 12, 2018
2 parents 69c8624 + 4d38bfb commit 89d05d4
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 22 deletions.
49 changes: 30 additions & 19 deletions AlphaWallet/AssetDefinition/AssetAttribute.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,27 +83,16 @@ enum AssetAttribute {
let attributeAccessor = XML.Accessor(attribute)
let functionElement = attributeAccessor["\(rootNamespacePrefix)origin"]["\(rootNamespacePrefix)function"]

if let attributeName = attributeAccessor.attributes["id"], case .singleElement(let origin) = attributeAccessor["\(rootNamespacePrefix)origin"], let rawSyntax = attributeAccessor.attributes["syntax"], let syntax = AssetAttributeSyntax(rawValue: rawSyntax), let functionName = functionElement.text?.dropParenthesis, !functionName.isEmpty {
if let attributeName = attributeAccessor.attributes["id"], case .singleElement(let origin) = attributeAccessor["\(rootNamespacePrefix)origin"], let rawSyntax = attributeAccessor.attributes["syntax"], let syntax = AssetAttributeSyntax(rawValue: rawSyntax), let functionName = functionElement.attributes["name"], !functionName.isEmpty {
let inputs: [CallForAssetAttribute.Argument]
let returnType = syntax.solidityReturnType
let output = CallForAssetAttribute.ReturnType(type: returnType)


switch functionElement["\(rootNamespacePrefix)value"] {
case .singleElement(let inputElement):
if let inputTypeString = inputElement.text, !inputTypeString.isEmpty, let inputName = inputElement.attributes["ref"], !inputName.isEmpty, let inputType = CallForAssetAttribute.SolidityType(rawValue: inputTypeString) {
inputs = [.init(name: inputName, type: inputType)]
} else {
inputs = []
}
case .sequence(let inputElements):
inputs = inputElements.compactMap {
if let inputTypeString = $0.text, !inputTypeString.isEmpty, let inputName = $0.attributes["ref"], !inputName.isEmpty, let inputType = CallForAssetAttribute.SolidityType(rawValue: inputTypeString) {
return .init(name: inputName, type: inputType)
} else {
return nil
}
}
switch functionElement["\(rootNamespacePrefix)inputs"] {
case .singleElement(let inputsElement):
inputs = AssetAttribute.extractInputs(fromInputsElements: [inputsElement])
case .sequence(let inputsElements):
inputs = AssetAttribute.extractInputs(fromInputsElements: inputsElements)
case .failure:
inputs = []
}
Expand All @@ -116,7 +105,18 @@ enum AssetAttribute {
}()
}

func extract(from tokenValue: BigUInt, ofContract contract: String, config: Config, callForAssetAttributeCoordinator: CallForAssetAttributeCoordinator?) -> AssetAttributeValue {
private static func extractInputs(fromInputsElements inputsElements: [XML.Element]) -> [CallForAssetAttribute.Argument]{
return inputsElements.flatMap { $0.childElements }.compactMap {
let inputTypeString = $0.name.withoutXMLNamespacePrefix
if !inputTypeString.isEmpty, let inputName = $0.attributes["ref"], !inputName.isEmpty, let inputType = CallForAssetAttribute.SolidityType(rawValue: inputTypeString) {
return .init(name: inputName, type: inputType)
} else {
return nil
}
}
}

func extract(from tokenValue: BigUInt, ofContract contract: String, config: Config, callForAssetAttributeCoordinator: CallForAssetAttributeCoordinator?) -> AssetAttributeValue {
switch self {
case .mapping(_, _, let syntax, _, _, _), .direct(_, _, let syntax, _, _):
switch syntax {
Expand Down Expand Up @@ -155,7 +155,7 @@ enum AssetAttribute {
switch self {
case .mapping(let attribute, let rootNamespacePrefix, let syntax, let lang, _, _):
guard let key = parseValue(tokenValue: tokenValue) else { return nil }
guard let value = attribute["\(rootNamespacePrefix)origin"]["\(rootNamespacePrefix)option"].getElementWithKeyAttribute(equals: String(key))?["\(rootNamespacePrefix)value"].getElementWithLangAttribute(equals: lang)?.text else { return nil }
guard let value = attribute["\(rootNamespacePrefix)origin"]["\(rootNamespacePrefix)mapping"]["\(rootNamespacePrefix)option"].getElementWithKeyAttribute(equals: String(key))?["\(rootNamespacePrefix)value"].getElementWithLangAttribute(equals: lang)?.text else { return nil }
return syntax.extract(from: value, isMapping: true) as? T
case .direct(_, _, let syntax, _, _):
guard let value = parseValue(tokenValue: tokenValue) else { return nil }
Expand Down Expand Up @@ -222,3 +222,14 @@ enum AssetAttribute {
return callForAssetAttributeCoordinator.getValue(forAttributeName: attributeName, tokenId: tokenId, functionCall: functionCall)
}
}

extension String {
fileprivate var withoutXMLNamespacePrefix: String {
let components = split(separator: ":")
if components.count > 1 {
return String(components[1])
} else {
return String(components[0])
}
}
}
2 changes: 1 addition & 1 deletion AlphaWallet/AssetDefinition/XMLHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ private class PrivateXMLHandler {
let lang = getLang()
var fields = [String: AssetAttribute]()
for e in xml["\(rootNamespacePrefix)token"]["\(rootNamespacePrefix)attribute-types"]["\(rootNamespacePrefix)attribute-type"] {
if let id = e.attributes["id"], case let .singleElement(element) = e, XML.Accessor(element)["\(rootNamespacePrefix)origin"].attributes["as"] != nil {
if let id = e.attributes["id"], case let .singleElement(element) = e, XML.Accessor(element)["\(rootNamespacePrefix)origin"].attributes["bitmask"] != nil {
fields[id] = AssetAttribute(attribute: element, rootNamespacePrefix: rootNamespacePrefix, lang: lang)
} else if let id = e.attributes["id"], case let .singleElement(element) = e, XML.Accessor(element)["\(rootNamespacePrefix)origin"].attributes["contract"] == "holding-contract" {
fields[id] = AssetAttribute(attribute: element, rootNamespacePrefix: rootNamespacePrefix)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,24 @@ import Foundation

struct CallForAssetAttribute {
enum SolidityType: String {
//TODO do we need to support the "odd" ones like uint24 in all steps of 8?
//TODO support address, enums, etc?
case bool
case int
case string
case int8
case int16
case int32
case int64
case int128
case int256
case uint
case uint8
case uint16
case uint32
case uint64
case uint128
case uint256
case string
}

struct Argument: Equatable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class CallForAssetAttributeCoordinator {
let result = value as? String ?? ""
seal.fulfill(result)
self.updateDataStore(forContract: functionCall.contract, tokenId: tokenId, attributeName: attributeName, value: result)
case .int, .uint256:
case .int, .int8, .int16, .int32, .int64, .int128, .int256, .uint, .uint8, .uint16, .uint32, .uint64, .uint128, .uint256:
let result = value as? Int ?? 0
seal.fulfill(result)
self.updateDataStore(forContract: functionCall.contract, tokenId: tokenId, attributeName: attributeName, value: result)
Expand Down
11 changes: 11 additions & 0 deletions AlphaWallet/UI/ViewModels/TokenCardRowViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@ struct TokenCardRowViewModel: TokenCardRowViewModelProtocol {
}
}

func subscribeLocality(withBlock block: @escaping (String) -> ()) {
guard isMeetupContract else { return }
if let subscribableAssetAttributeValue = tokenHolder.values["locality"] as? SubscribableAssetAttributeValue {
subscribableAssetAttributeValue.subscribable.subscribe { value in
if let value = value as? String {
block(value)
}
}
}
}

func subscribeBuilding(withBlock block: @escaping (String) -> ()) {
if let subscribableAssetAttributeValue = tokenHolder.values["building"] as? SubscribableAssetAttributeValue {
subscribableAssetAttributeValue.subscribable.subscribe { value in
Expand Down
5 changes: 5 additions & 0 deletions AlphaWallet/UI/Views/TokenCardRowView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ class TokenCardRowView: UIView {
strongSelf.categoryLabel.text = building
}

vm.subscribeLocality { [weak self] locality in
guard let strongSelf = self else { return }
strongSelf.cityLabel.text = ", \(locality)"
}

vm.subscribeExpired { [weak self] expired in
guard let strongSelf = self else { return }
strongSelf.teamsLabel.text = expired
Expand Down

0 comments on commit 89d05d4

Please sign in to comment.