diff --git a/AlphaWallet/Activities/ActivitiesService.swift b/AlphaWallet/Activities/ActivitiesService.swift index 9f0283c3c..21db4a5b5 100644 --- a/AlphaWallet/Activities/ActivitiesService.swift +++ b/AlphaWallet/Activities/ActivitiesService.swift @@ -247,7 +247,7 @@ class ActivitiesService: NSObject, ActivitiesServiceType { } else { tokenObject = token if tokenObject.contractAddress.sameContract(as: Constants.nativeCryptoAddressInDatabase) { - let token = Token(tokenIdOrEvent: .tokenId(tokenId: .init(1)), tokenType: .nativeCryptocurrency, index: 0, name: "", symbol: "", status: .available, values: .init()) + let token = TokenScript.Token(tokenIdOrEvent: .tokenId(tokenId: .init(1)), tokenType: .nativeCryptocurrency, index: 0, name: "", symbol: "", status: .available, values: .init()) tokenHolders = [TokenHolder(tokens: [token], contractAddress: tokenObject.contractAddress, hasAssetDefinition: true)] } else { diff --git a/AlphaWallet/Market/Coordinators/ImportMagicLinkCoordinator.swift b/AlphaWallet/Market/Coordinators/ImportMagicLinkCoordinator.swift index 18d7c2a27..2e58de9cb 100644 --- a/AlphaWallet/Market/Coordinators/ImportMagicLinkCoordinator.swift +++ b/AlphaWallet/Market/Coordinators/ImportMagicLinkCoordinator.swift @@ -244,7 +244,7 @@ class ImportMagicLinkCoordinator: Coordinator { amt = 0 } count = amt - let token = Token( + let token = TokenScript.Token( tokenIdOrEvent: .tokenId(tokenId: 0), tokenType: TokenType.nativeCryptocurrency, index: 0, @@ -504,7 +504,7 @@ class ImportMagicLinkCoordinator: Coordinator { private func makeTokenHolderImpl(name: String, symbol: String, type: TokenType? = nil, bytes32Tokens: [String], contractAddress: AlphaWallet.Address) { //TODO pass in the wallet instead guard let tokenType = type ?? (tokensDataStore.token(forContract: contractAddress, server: server)?.type) else { return } - var tokens = [Token]() + var tokens = [TokenScript.Token]() let xmlHandler = XMLHandler(contract: contractAddress, tokenType: tokenType, assetDefinitionStore: assetDefinitionStore) for i in 0.. Token { + ) -> TokenScript.Token { guard tokenIdOrEvent.tokenId != 0 else { return .empty } let values: [AttributeId: AssetAttributeSyntaxValue] if fields.isEmpty { @@ -418,7 +418,7 @@ private class PrivateXMLHandler { values = resolveAttributesBypassingCache(withTokenIdOrEvent: tokenIdOrEvent, server: server, account: account) cache(attributeValues: values, forTokenId: tokenIdOrEvent.tokenId) } - return Token( + return TokenScript.Token( tokenIdOrEvent: tokenIdOrEvent, tokenType: tokenType, index: index, @@ -915,16 +915,16 @@ public class XMLHandler { self.privateXMLHandler = privateXMLHandler } - func getToken(name: String, symbol: String, fromTokenIdOrEvent tokenIdOrEvent: TokenIdOrEvent, index: UInt16, inWallet account: Wallet, server: RPCServer, tokenType: TokenType) -> Token { + func getToken(name: String, symbol: String, fromTokenIdOrEvent tokenIdOrEvent: TokenIdOrEvent, index: UInt16, inWallet account: Wallet, server: RPCServer, tokenType: TokenType) -> TokenScript.Token { //TODO get rid of the forced unwrap - var token: Token! + var token: TokenScript.Token! threadSafe.performSync { let overrides = privateXMLHandler.getToken(name: name, symbol: symbol, fromTokenIdOrEvent: tokenIdOrEvent, index: index, inWallet: account, server: server, tokenType: tokenType) if let baseXMLHandler = baseXMLHandler { let base = baseXMLHandler.getToken(name: name, symbol: symbol, fromTokenIdOrEvent: tokenIdOrEvent, index: index, inWallet: account, server: server, tokenType: tokenType) let baseValues = base.values let overriddenValues = overrides.values - token = Token( + token = TokenScript.Token( tokenIdOrEvent: overrides.tokenIdOrEvent, tokenType: overrides.tokenType, index: overrides.index, diff --git a/AlphaWallet/Tokens/Collectibles/ViewModels/SelectableNFTAssetContainerViewModel.swift b/AlphaWallet/Tokens/Collectibles/ViewModels/SelectableNFTAssetContainerViewModel.swift index cf6c9f198..822a116eb 100644 --- a/AlphaWallet/Tokens/Collectibles/ViewModels/SelectableNFTAssetContainerViewModel.swift +++ b/AlphaWallet/Tokens/Collectibles/ViewModels/SelectableNFTAssetContainerViewModel.swift @@ -8,7 +8,7 @@ import UIKit struct SelectableNFTAssetContainerViewModel { - private let token: Token? + private let token: TokenScript.Token? private let tokenHolder: TokenHolder var availableAmount: Int { diff --git a/AlphaWallet/Tokens/Helpers/TokenAdaptor.swift b/AlphaWallet/Tokens/Helpers/TokenAdaptor.swift index fe2392468..be4ce24f0 100644 --- a/AlphaWallet/Tokens/Helpers/TokenAdaptor.swift +++ b/AlphaWallet/Tokens/Helpers/TokenAdaptor.swift @@ -30,7 +30,7 @@ extension TokenObject { let subscribablesForAttributeValues = values.values let allResolved = subscribablesForAttributeValues.allSatisfy { $0.subscribableValue?.value != nil } - let token = Token(tokenIdOrEvent: .tokenId(tokenId: hardcodedTokenIdForFungibles), tokenType: type, index: 0, name: name, symbol: symbol, status: .available, values: values) + let token = TokenScript.Token(tokenIdOrEvent: .tokenId(tokenId: hardcodedTokenIdForFungibles), tokenType: type, index: 0, name: name, symbol: symbol, status: .available, values: values) let tokenHolder = TokenHolder(tokens: [token], contractAddress: contractAddress, hasAssetDefinition: true) if allResolved { @@ -78,7 +78,7 @@ class TokenAdaptor { private func getNotSupportedByNonFungibleJsonTokenHolders(forWallet account: Wallet) -> [TokenHolder] { let balance = token.balance - var tokens = [Token]() + var tokens = [TokenScript.Token]() switch token.type { case .erc875, .erc721ForTickets, .erc721, .erc1155, .nativeCryptocurrency: for (index, item) in balance.enumerated() { @@ -108,7 +108,7 @@ class TokenAdaptor { private func getSupportedByNonFungibleJsonTokenHolders(forWallet account: Wallet, isSourcedFromEvents: Bool) -> [TokenHolder] { let balance = token.balance - var tokens = [Token]() + var tokens = [TokenScript.Token]() for item in balance { if let nonFungibleBalance = item.nonFungibleBalance, let token = getTokenForNonFungible(nonFungible: nonFungibleBalance, inWallet: account, server: self.token.server, isSourcedFromEvents: isSourcedFromEvents, tokenType: self.token.type) { tokens.append(token) @@ -118,11 +118,11 @@ class TokenAdaptor { } //NOTE: internal for testing purposes - func bundleTestsOnly(tokens: [Token]) -> [TokenHolder] { + func bundleTestsOnly(tokens: [TokenScript.Token]) -> [TokenHolder] { bundle(tokens: tokens) } - private func bundle(tokens: [Token]) -> [TokenHolder] { + private func bundle(tokens: [TokenScript.Token]) -> [TokenHolder] { switch token.type { case .nativeCryptocurrency, .erc20, .erc875: if !tokens.isEmpty && tokens[0].isSpawnableMeetupContract { @@ -156,13 +156,13 @@ class TokenAdaptor { //If sequential or have the same seat number, add them together ///e.g 21, 22, 25 is broken up into 2 bundles: 21-22 and 25. ///e.g 21, 21, 22, 25 is broken up into 2 bundles: (21,21-22) and 25. - private func breakBundlesFurtherToHaveContinuousSeatRange(tokens: [Token]) -> [[Token]] { + private func breakBundlesFurtherToHaveContinuousSeatRange(tokens: [TokenScript.Token]) -> [[TokenScript.Token]] { let tokens = tokens.sorted { let s0 = $0.values.numeroIntValue ?? 0 let s1 = $1.values.numeroIntValue ?? 0 return s0 <= s1 } - return tokens.reduce([[Token]]()) { results, token in + return tokens.reduce([[TokenScript.Token]]()) { results, token in var results = results if var previousRange = results.last, let previousToken = previousRange.last, (previousToken.seatId + 1 == token.seatId || previousToken.seatId == token.seatId) { previousRange.append(token) @@ -176,8 +176,8 @@ class TokenAdaptor { } ///Group by the properties used in the hash. We abuse a dictionary to help with grouping - private func groupTokensByFields(tokens: [Token]) -> Dictionary.Values { - var dictionary = [String: [Token]]() + private func groupTokensByFields(tokens: [TokenScript.Token]) -> Dictionary.Values { + var dictionary = [String: [TokenScript.Token]]() for each in tokens { let city = each.values.localityStringValue ?? "N/A" let venue = each.values.venueStringValue ?? "N/A" @@ -196,7 +196,7 @@ class TokenAdaptor { } //TODO pass lang into here - private func getToken(name: String, symbol: String, forTokenIdOrEvent tokenIdOrEvent: TokenIdOrEvent, index: UInt16, inWallet account: Wallet, server: RPCServer) -> Token { + private func getToken(name: String, symbol: String, forTokenIdOrEvent tokenIdOrEvent: TokenIdOrEvent, index: UInt16, inWallet account: Wallet, server: RPCServer) -> TokenScript.Token { xmlHandler.getToken(name: name, symbol: symbol, fromTokenIdOrEvent: tokenIdOrEvent, index: index, inWallet: account, server: server, tokenType: token.type) } @@ -233,7 +233,7 @@ class TokenAdaptor { return tokenIdOrEvent } - private func getTokenForNonFungible(nonFungible: NonFungibleFromJson, inWallet account: Wallet, server: RPCServer, isSourcedFromEvents: Bool, tokenType: TokenType) -> Token? { + private func getTokenForNonFungible(nonFungible: NonFungibleFromJson, inWallet account: Wallet, server: RPCServer, isSourcedFromEvents: Bool, tokenType: TokenType) -> TokenScript.Token? { switch nonFungible.tokenType { case .erc721: break @@ -285,14 +285,14 @@ class TokenAdaptor { values.setSlug(string: nonFungible.slug) values.setCreator(creator: nonFungible.creator) - let status: Token.Status + let status: TokenScript.Token.Status let cryptoKittyGenerationWhenDataNotAvailable = "-1" if let generation = nonFungible.generationTrait, generation.value == cryptoKittyGenerationWhenDataNotAvailable { status = .availableButDataUnavailable } else { status = .available } - return Token( + return TokenScript.Token( tokenIdOrEvent: tokenIdOrEvent, tokenType: nonFungible.tokenType.asTokenType, index: 0, @@ -303,7 +303,7 @@ class TokenAdaptor { ) } - private func getTokenHolder(for tokens: [Token]) -> TokenHolder { + private func getTokenHolder(for tokens: [TokenScript.Token]) -> TokenHolder { return TokenHolder( tokens: tokens, contractAddress: token.contractAddress, @@ -313,7 +313,7 @@ class TokenAdaptor { } -extension Token { +extension TokenScript.Token { //TODO Convenience-only. (Look for references). Should remove once we generalize things further and not hardcode the use of seatId var seatId: Int { return values.numeroIntValue.flatMap { Int($0) } ?? 0 diff --git a/AlphaWallet/Tokens/Types/Token.swift b/AlphaWallet/Tokens/Types/Token.swift index ef31a7e6a..aff034d03 100644 --- a/AlphaWallet/Tokens/Types/Token.swift +++ b/AlphaWallet/Tokens/Types/Token.swift @@ -9,64 +9,66 @@ import Foundation import BigInt -struct Token: Hashable { - static func == (lhs: Token, rhs: Token) -> Bool { - return lhs.id == rhs.id - } +extension TokenScript { + struct Token: Hashable { + static func == (lhs: Token, rhs: Token) -> Bool { + return lhs.id == rhs.id + } - func hash(into hasher: inout Hasher) { - hasher.combine(id) - hasher.combine(tokenIdOrEvent.tokenId) - hasher.combine(tokenType) - hasher.combine(index) - hasher.combine(name) - hasher.combine(symbol) - hasher.combine(status) - hasher.combine(values) - } + func hash(into hasher: inout Hasher) { + hasher.combine(id) + hasher.combine(tokenIdOrEvent.tokenId) + hasher.combine(tokenType) + hasher.combine(index) + hasher.combine(name) + hasher.combine(symbol) + hasher.combine(status) + hasher.combine(values) + } - enum Status { - case available, sold, redeemed, forSale, transferred, pending, availableButDataUnavailable - } + enum Status { + case available, sold, redeemed, forSale, transferred, pending, availableButDataUnavailable + } - var id: TokenId { - tokenIdOrEvent.tokenId - } - let tokenIdOrEvent: TokenIdOrEvent - let tokenType: TokenType - let index: UInt16 - let name: String - let symbol: String - let status: Status - let values: [AttributeId: AssetAttributeSyntaxValue] + var id: TokenId { + tokenIdOrEvent.tokenId + } + let tokenIdOrEvent: TokenIdOrEvent + let tokenType: TokenType + let index: UInt16 + let name: String + let symbol: String + let status: Status + let values: [AttributeId: AssetAttributeSyntaxValue] - var value: Int? { - values.valueIntValue.flatMap { String($0) }.flatMap { Int($0) } - } + var value: Int? { + values.valueIntValue.flatMap { String($0) }.flatMap { Int($0) } + } - static var empty: Token { - return Token( - tokenIdOrEvent: .tokenId(tokenId: Constants.nullTokenIdBigUInt), - tokenType: TokenType.erc875, - index: 0, - name: R.string.localizable.tokensTitlecase(), - symbol: "", - status: .available, - values: [ - "locality": .init(defaultValueWithSyntax: .directoryString), - "venue": .init(defaultValueWithSyntax: .directoryString), - "match": .init(defaultValueWithSyntax: .integer), - "time": .init(defaultValueWithSyntax: .generalisedTime), - "numero": .init(defaultValueWithSyntax: .integer), - "category": .init(defaultValueWithSyntax: .directoryString), - "countryA": .init(defaultValueWithSyntax: .directoryString), - "countryB": .init(defaultValueWithSyntax: .directoryString) - ] - ) - } + static var empty: Token { + return Token( + tokenIdOrEvent: .tokenId(tokenId: Constants.nullTokenIdBigUInt), + tokenType: TokenType.erc875, + index: 0, + name: R.string.localizable.tokensTitlecase(), + symbol: "", + status: .available, + values: [ + "locality": .init(defaultValueWithSyntax: .directoryString), + "venue": .init(defaultValueWithSyntax: .directoryString), + "match": .init(defaultValueWithSyntax: .integer), + "time": .init(defaultValueWithSyntax: .generalisedTime), + "numero": .init(defaultValueWithSyntax: .integer), + "category": .init(defaultValueWithSyntax: .directoryString), + "countryA": .init(defaultValueWithSyntax: .directoryString), + "countryB": .init(defaultValueWithSyntax: .directoryString) + ] + ) + } - //TODO have a better way to test for spawnable meetup contracts - var isSpawnableMeetupContract: Bool { - return values["expired"] != nil && values["locality"] != nil && values["building"] != nil + //TODO have a better way to test for spawnable meetup contracts + var isSpawnableMeetupContract: Bool { + return values["expired"] != nil && values["locality"] != nil && values["building"] != nil + } } } diff --git a/AlphaWallet/Tokens/Types/TokenHolder.swift b/AlphaWallet/Tokens/Types/TokenHolder.swift index d982d07d0..7ffd22788 100644 --- a/AlphaWallet/Tokens/Types/TokenHolder.swift +++ b/AlphaWallet/Tokens/Types/TokenHolder.swift @@ -118,7 +118,7 @@ class TokenHolder: Hashable { hasher.combine(selections) } - let tokens: [Token] + let tokens: [TokenScript.Token] let contractAddress: AlphaWallet.Address let hasAssetDefinition: Bool @@ -126,13 +126,13 @@ class TokenHolder: Hashable { var areDetailsVisible = false var selections: [TokenSelection] = [] - init(tokens: [Token], contractAddress: AlphaWallet.Address, hasAssetDefinition: Bool) { + init(tokens: [TokenScript.Token], contractAddress: AlphaWallet.Address, hasAssetDefinition: Bool) { self.tokens = tokens self.contractAddress = contractAddress self.hasAssetDefinition = hasAssetDefinition } - func token(tokenId: TokenId) -> Token? { + func token(tokenId: TokenId) -> TokenScript.Token? { tokens.first(where: { $0.id == tokenId }) } @@ -181,7 +181,7 @@ class TokenHolder: Hashable { return values.traitsValue } - var status: Token.Status { + var status: TokenScript.Token.Status { return tokens[0].status } @@ -217,7 +217,7 @@ class TokenHolder: Hashable { .flatMap { $0.values } } - func status(tokenId: TokenId) -> Token.Status? { + func status(tokenId: TokenId) -> TokenScript.Token.Status? { token(tokenId: tokenId) .flatMap { $0.status } } diff --git a/AlphaWalletTests/Tokens/Helpers/TokenAdaptorTest.swift b/AlphaWalletTests/Tokens/Helpers/TokenAdaptorTest.swift index 7f583ce45..25ad11b35 100644 --- a/AlphaWalletTests/Tokens/Helpers/TokenAdaptorTest.swift +++ b/AlphaWalletTests/Tokens/Helpers/TokenAdaptorTest.swift @@ -9,7 +9,7 @@ class TokenAdaptorTest: XCTestCase { func testBundlesAreBrokenIntoContinuousSeatRanges() { let date = GeneralisedTime() let tokens = [ - Token(tokenIdOrEvent: .tokenId(tokenId: 1), tokenType: TokenType.erc875, index: UInt16(1), name: "Name", symbol: "SYM", status: .available, values: [ + TokenScript.Token(tokenIdOrEvent: .tokenId(tokenId: 1), tokenType: TokenType.erc875, index: UInt16(1), name: "Name", symbol: "SYM", status: .available, values: [ "city": .init(directoryString: "City"), "venue": .init(directoryString: "Venue"), "match": .init(int: 1), @@ -19,7 +19,7 @@ class TokenAdaptorTest: XCTestCase { "countryA": .init(directoryString: "Team A"), "countryB": .init(directoryString: "Team B") ]), - Token(tokenIdOrEvent: .tokenId(tokenId: 2), tokenType: TokenType.erc875, index: UInt16(2), name: "Name", symbol: "SYM", status: .available, values: [ + TokenScript.Token(tokenIdOrEvent: .tokenId(tokenId: 2), tokenType: TokenType.erc875, index: UInt16(2), name: "Name", symbol: "SYM", status: .available, values: [ "city": .init(directoryString: "City"), "venue": .init(directoryString: "Venue"), "match": .init(int: 1), @@ -29,7 +29,7 @@ class TokenAdaptorTest: XCTestCase { "countryA": .init(directoryString: "Team A"), "countryB": .init(directoryString: "Team B") ]), - Token(tokenIdOrEvent: .tokenId(tokenId: 3), tokenType: TokenType.erc875, index: UInt16(3), name: "Name", symbol: "SYM", status: .available, values: [ + TokenScript.Token(tokenIdOrEvent: .tokenId(tokenId: 3), tokenType: TokenType.erc875, index: UInt16(3), name: "Name", symbol: "SYM", status: .available, values: [ "city": .init(directoryString: "City"), "venue": .init(directoryString: "Venue"), "match": .init(int: 1), @@ -50,7 +50,7 @@ class TokenAdaptorTest: XCTestCase { func testBundlesGroupIdenticalSeatIDsTogether() { let date = GeneralisedTime() let tokens = [ - Token(tokenIdOrEvent: .tokenId(tokenId: 1), tokenType: TokenType.erc875, index: UInt16(1), name: "Name", symbol: "SYM", status: .available, values: [ + TokenScript.Token(tokenIdOrEvent: .tokenId(tokenId: 1), tokenType: TokenType.erc875, index: UInt16(1), name: "Name", symbol: "SYM", status: .available, values: [ "city": .init(directoryString: "City"), "venue": .init(directoryString: "Venue"), "match": .init(int: 1), @@ -60,7 +60,7 @@ class TokenAdaptorTest: XCTestCase { "countryA": .init(directoryString: "Team A"), "countryB": .init(directoryString: "Team B") ]), - Token(tokenIdOrEvent: .tokenId(tokenId: 2), tokenType: TokenType.erc875, index: UInt16(2), name: "Name", symbol: "SYM", status: .available, values: [ + TokenScript.Token(tokenIdOrEvent: .tokenId(tokenId: 2), tokenType: TokenType.erc875, index: UInt16(2), name: "Name", symbol: "SYM", status: .available, values: [ "city": .init(directoryString: "City"), "venue": .init(directoryString: "Venue"), "match": .init(int: 1), @@ -70,7 +70,7 @@ class TokenAdaptorTest: XCTestCase { "countryA": .init(directoryString: "Team A"), "countryB": .init(directoryString: "Team B") ]), - Token(tokenIdOrEvent: .tokenId(tokenId: 3), tokenType: TokenType.erc875, index: UInt16(3), name: "Name", symbol: "SYM", status: .available, values: [ + TokenScript.Token(tokenIdOrEvent: .tokenId(tokenId: 3), tokenType: TokenType.erc875, index: UInt16(3), name: "Name", symbol: "SYM", status: .available, values: [ "city": .init(directoryString: "City"), "venue": .init(directoryString: "Venue"), "match": .init(int: 1), @@ -80,7 +80,7 @@ class TokenAdaptorTest: XCTestCase { "countryA": .init(directoryString: "Team A"), "countryB": .init(directoryString: "Team B") ]), - Token(tokenIdOrEvent: .tokenId(tokenId: 4), tokenType: TokenType.erc875, index: UInt16(4), name: "Name", symbol: "SYM", status: .available, values: [ + TokenScript.Token(tokenIdOrEvent: .tokenId(tokenId: 4), tokenType: TokenType.erc875, index: UInt16(4), name: "Name", symbol: "SYM", status: .available, values: [ "city": .init(directoryString: "City"), "venue": .init(directoryString: "Venue"), "match": .init(int: 1),