wrap Token in TokenScript.Token #4645

pull/4650/head
Krypto Pank 2 years ago
parent 9b271fc649
commit 3764386987
  1. 2
      AlphaWallet/Activities/ActivitiesService.swift
  2. 4
      AlphaWallet/Market/Coordinators/ImportMagicLinkCoordinator.swift
  3. 10
      AlphaWallet/TokenScriptClient/Models/XMLHandler.swift
  4. 2
      AlphaWallet/Tokens/Collectibles/ViewModels/SelectableNFTAssetContainerViewModel.swift
  5. 30
      AlphaWallet/Tokens/Helpers/TokenAdaptor.swift
  6. 108
      AlphaWallet/Tokens/Types/Token.swift
  7. 10
      AlphaWallet/Tokens/Types/TokenHolder.swift
  8. 14
      AlphaWalletTests/Tokens/Helpers/TokenAdaptorTest.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 {

@ -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..<bytes32Tokens.count {
let token = bytes32Tokens[i]

@ -408,7 +408,7 @@ private class PrivateXMLHandler {
inWallet account: Wallet,
server: RPCServer,
tokenType: TokenType
) -> 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,

@ -8,7 +8,7 @@
import UIKit
struct SelectableNFTAssetContainerViewModel {
private let token: Token?
private let token: TokenScript.Token?
private let tokenHolder: TokenHolder
var availableAmount: Int {

@ -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<String, [Token]>.Values {
var dictionary = [String: [Token]]()
private func groupTokensByFields(tokens: [TokenScript.Token]) -> Dictionary<String, [TokenScript.Token]>.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

@ -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
}
}
}

@ -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 }
}

@ -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),

Loading…
Cancel
Save