diff --git a/Sources/KukaiCoreSwift/Models/Token.swift b/Sources/KukaiCoreSwift/Models/Token.swift index cd4e2421..3d970525 100644 --- a/Sources/KukaiCoreSwift/Models/Token.swift +++ b/Sources/KukaiCoreSwift/Models/Token.swift @@ -49,6 +49,19 @@ public class Token: Codable, CustomStringConvertible { /// Object that holds and formats the balance of the token public var balance: TokenAmount + /// Object that holds and formats the staked balance of the token + public var stakedBalance: TokenAmount + + /// Object that holds and formats the pending unstaked balance of the token + public var unstakedBalance: TokenAmount + + /// helper to return the available spendable balance of the token `(balance - stakedBalance) - unstakedBalance` + public var availableBalance: TokenAmount { + get { + return (balance - stakedBalance) - unstakedBalance + } + } + /// Get the underlying number of decimal places that this token represents public var decimalPlaces: Int { get { @@ -100,12 +113,14 @@ public class Token: Codable, CustomStringConvertible { - parameter tokenId: The token id if the token is an FA2 token, nil otherwise. - parameter nfts:The individual NFT's owned of this token type */ - public init(name: String?, symbol: String, tokenType: TokenType, faVersion: FaVersion?, balance: TokenAmount, thumbnailURL: URL?, tokenContractAddress: String?, tokenId: Decimal?, nfts: [NFT]?, mintingTool: String?) { + public init(name: String?, symbol: String, tokenType: TokenType, faVersion: FaVersion?, balance: TokenAmount, stakedBalance: TokenAmount = .zero(), unstakedBalance: TokenAmount = .zero(), thumbnailURL: URL?, tokenContractAddress: String?, tokenId: Decimal?, nfts: [NFT]?, mintingTool: String?) { self.name = name self.symbol = symbol self.tokenType = tokenType self.faVersion = faVersion self.balance = balance + self.stakedBalance = stakedBalance + self.unstakedBalance = unstakedBalance self.thumbnailURL = thumbnailURL self.tokenContractAddress = tokenContractAddress self.tokenId = tokenId @@ -121,7 +136,7 @@ public class Token: Codable, CustomStringConvertible { /** Init a `Token` from an object returned by the TzKT API */ - public init(from: TzKTBalanceToken, andTokenAmount: TokenAmount) { + public init(from: TzKTBalanceToken, andTokenAmount: TokenAmount, stakedTokenAmount: TokenAmount = .zero(), unstakedTokenAmount: TokenAmount = .zero()) { let decimalsString = from.metadata?.decimals ?? "0" let decimalsInt = Int(decimalsString) ?? 0 let isNFT = (from.metadata?.artifactUri != nil && decimalsInt == 0 && from.standard == .fa2) @@ -131,6 +146,8 @@ public class Token: Codable, CustomStringConvertible { self.tokenType = isNFT ? .nonfungible : .fungible self.faVersion = from.standard self.balance = andTokenAmount + self.stakedBalance = stakedTokenAmount + self.unstakedBalance = unstakedTokenAmount self.thumbnailURL = from.metadata?.thumbnailURL ?? TzKTClient.avatarURL(forToken: from.contract.address) self.tokenContractAddress = from.contract.address self.tokenId = Decimal(string: from.tokenId) ?? 0 @@ -157,6 +174,8 @@ public class Token: Codable, CustomStringConvertible { self.tokenType = isNFT ? .nonfungible : .fungible self.faVersion = from.token.standard self.balance = from.tokenAmount() + self.stakedBalance = .zero() + self.unstakedBalance = .zero() self.thumbnailURL = from.token.metadata?.thumbnailURL ?? TzKTClient.avatarURL(forToken: from.token.contract.address) self.tokenContractAddress = from.token.contract.address self.tokenId = Decimal(string: from.token.tokenId) ?? 0 @@ -175,7 +194,7 @@ public class Token: Codable, CustomStringConvertible { - returns: `Token` */ public static func xtz() -> Token { - return Token(name: "Tezos", symbol: "XTZ", tokenType: .xtz, faVersion: nil, balance: TokenAmount.zeroBalance(decimalPlaces: 6), thumbnailURL: nil, tokenContractAddress: nil, tokenId: nil, nfts: nil, mintingTool: nil) + return Token(name: "Tezos", symbol: "XTZ", tokenType: .xtz, faVersion: nil, balance: TokenAmount.zeroBalance(decimalPlaces: 6), stakedBalance: TokenAmount.zeroBalance(decimalPlaces: 6), unstakedBalance: TokenAmount.zeroBalance(decimalPlaces: 6), thumbnailURL: nil, tokenContractAddress: nil, tokenId: nil, nfts: nil, mintingTool: nil) } /** @@ -184,12 +203,12 @@ public class Token: Codable, CustomStringConvertible { - returns: `Token`. */ public static func xtz(withAmount amount: TokenAmount) -> Token { - return Token(name: "Tezos", symbol: "XTZ", tokenType: .xtz, faVersion: nil, balance: amount, thumbnailURL: nil, tokenContractAddress: nil, tokenId: nil, nfts: nil, mintingTool: nil) + return Token(name: "Tezos", symbol: "XTZ", tokenType: .xtz, faVersion: nil, balance: amount, stakedBalance: .zero(), unstakedBalance: .zero(), thumbnailURL: nil, tokenContractAddress: nil, tokenId: nil, nfts: nil, mintingTool: nil) } /// Useful for creating placeholders for pending activity items public static func placeholder(fromNFT nft: NFT, amount: TokenAmount, thumbnailURL: URL?) -> Token { - return Token(name: nft.name, symbol: nft.parentAlias ?? "", tokenType: .nonfungible, faVersion: .fa2, balance: amount, thumbnailURL: thumbnailURL, tokenContractAddress: nft.parentContract, tokenId: nft.tokenId, nfts: nil, mintingTool: nil) + return Token(name: nft.name, symbol: nft.parentAlias ?? "", tokenType: .nonfungible, faVersion: .fa2, balance: amount, stakedBalance: .zero(), unstakedBalance: .zero(), thumbnailURL: thumbnailURL, tokenContractAddress: nft.parentContract, tokenId: nft.tokenId, nfts: nil, mintingTool: nil) } /// Conforming to `CustomStringConvertible` to print a number, giving the appearence of a numeric type diff --git a/Tests/KukaiCoreSwiftTests/Models/TokenTests.swift b/Tests/KukaiCoreSwiftTests/Models/TokenTests.swift index b50720a3..2d8706cb 100644 --- a/Tests/KukaiCoreSwiftTests/Models/TokenTests.swift +++ b/Tests/KukaiCoreSwiftTests/Models/TokenTests.swift @@ -48,6 +48,7 @@ class TokenTests: XCTestCase { let placeholder = Token.placeholder(fromNFT: nft, amount: .init(fromNormalisedAmount: 1, decimalPlaces: 0), thumbnailURL: nil) XCTAssert(placeholder.name == "Unknown Token", placeholder.name ?? "-") XCTAssert(placeholder.balance.description == "1", placeholder.balance.description) + XCTAssert(placeholder.availableBalance.description == "1", placeholder.availableBalance.description) XCTAssert(token == token) XCTAssert(token != token2) diff --git a/Tests/KukaiCoreSwiftTests/Models/TzKTTransactionTests.swift b/Tests/KukaiCoreSwiftTests/Models/TzKTTransactionTests.swift index 32c2ad0a..ff29eec2 100644 --- a/Tests/KukaiCoreSwiftTests/Models/TzKTTransactionTests.swift +++ b/Tests/KukaiCoreSwiftTests/Models/TzKTTransactionTests.swift @@ -97,7 +97,7 @@ final class TzKTTransactionTests: XCTestCase { transaction.processAdditionalData(withCurrentWalletAddress: "tz1abc") if let json = try? JSONEncoder().encode(transaction), let jsonString = String(data: json, encoding: .utf8) { - XCTAssert(jsonString.count == 850, jsonString.count.description) + XCTAssert(jsonString.count == 952, jsonString.count.description) } else { XCTFail() }