Skip to content

Commit

Permalink
- update dependencies
Browse files Browse the repository at this point in the history
- update some code comments
  • Loading branch information
simonmcl committed Sep 20, 2023
1 parent ac7215f commit 788438b
Show file tree
Hide file tree
Showing 18 changed files with 69 additions and 7 deletions.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ let package = Package(
.library(name: "KukaiCoreSwift", targets: ["KukaiCoreSwift"]),
],
dependencies: [
.package(name: "KukaiCryptoSwift", url: "https://github.com/kukai-wallet/kukai-crypto-swift", from: "1.0.7"),
.package(name: "KukaiCryptoSwift", url: "https://github.com/kukai-wallet/kukai-crypto-swift", from: "1.0.10"),
//.package(url: "https://github.com/onevcat/Kingfisher.git", from: "7.6.2"),
.package(url: "https://github.com/simonmcl/Kingfisher.git", from: "1.0.0"),
.package(name: "CustomAuth", url: "https://github.com/torusresearch/customauth-swift-sdk", from: "6.0.0"),
Expand Down
4 changes: 2 additions & 2 deletions Sources/KukaiCoreSwift/Clients/BetterCallDevClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import Foundation
import Kingfisher
import os.log

/// BetterCallDev (BCD) is an indexing/smart contract debugging tool, used for the Tezos blockchain.
/// This class allows developers to interact with their API, to fetch data that would otherwise be impossible for a mobile app
/// BetterCallDev (BCD) is an indexer/smart contract debugging tool, used for the Tezos blockchain.
/// This class allows developers to interact with their API, to fetch data that would otherwise be impossible for a mobile app to fetch from the Tezos RPC
public class BetterCallDevClient {

/// Dedicated BCD errors
Expand Down
4 changes: 2 additions & 2 deletions Sources/KukaiCoreSwift/Clients/DipDupClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import Foundation

/**
Class exposes functions to allow communication to the dedicated indexer platform DipDup ( https://dipdup.net/ ).
DipDup is composed on many small, dedicated indexers, powered by GraphQL. This class tries to exposes userflow functions, allowing users to accomplish tasks without having to worry about the underlying complexities
This client exposes functions to allow communication to the indexer platform DipDup ( https://dipdup.net/ ).
DipDup is composed of many small, dedicated indexers, powered by GraphQL. This client tries to exposes userflow functions, allowing users to accomplish tasks without having to worry about the underlying complexities
*/
public class DipDupClient {

Expand Down
23 changes: 23 additions & 0 deletions Sources/KukaiCoreSwift/Clients/ObjktClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import Foundation

/// Client for interacting with the API of the popular NFT marketplace, OBJKT.com
/// Client exposes functions for fetching metadata, pricing, purchase offers, listing etc
public class ObjktClient {

/// The networking service used to fire requests
Expand All @@ -21,7 +23,10 @@ public class ObjktClient {
private static let collectionCacheKey = "objkt-collection-cache-key"
private static let tokenCacheKey = "objkt-token-cache-key"

/// Cached metadata of NFT collections, e.g. name, thumbnailURL etc
public var collections: [String: ObjktCollection]

/// Cached metadata of specific tokens, e.g. prices, offers etc
public var tokens: [String: ObjktTokenReponse]


Expand All @@ -46,6 +51,9 @@ public class ObjktClient {

// MARK: - Public single functions

/**
Take in an array of contract addresses, and return a list of the ones that we currently have no metadata for
*/
public func unresolvedCollections(addresses: [String]) -> [String] {

// OBJKT doesn't currently support testnet, easy solution to prevent unwanted requests / processing until a solution is found
Expand All @@ -64,6 +72,9 @@ public class ObjktClient {
return unresolved
}

/**
Search OBJKT to find metadata on the list of addresses provided
*/
public func resolveCollectionsAll(addresses: [String], completion: @escaping ((Result<Bool, KukaiError>) -> Void)) {
if addresses.count == 0 {
completion(Result.success(true))
Expand Down Expand Up @@ -114,6 +125,9 @@ public class ObjktClient {

// MARK: - Public single functions

/**
Find the metadata of a list of contracts, used recurrisvely to find all collections while limited to request query size
*/
public func resolveCollectionsPage(addresses: ArraySlice<String>, completion: @escaping ((Result<GraphQLResponse<ObjktCollections>, KukaiError>) -> Void)) {
var addressArray = ""
for add in addresses {
Expand All @@ -126,6 +140,9 @@ public class ObjktClient {
self.networkService.request(url: self.config.objktApiURL, isPOST: true, withBody: data, forReturnType: GraphQLResponse<ObjktCollections>.self, completion: completion)
}

/**
Find the meatdata of a specific token
*/
public func resolveToken(address: String, tokenId: Decimal, forOwnerWalletAddress walletAddress: String, completion: @escaping ((Result<GraphQLResponse<ObjktTokenReponse>, KukaiError>) -> Void)) {
var query = """
query {
Expand Down Expand Up @@ -184,10 +201,16 @@ public class ObjktClient {
}
}

/**
Helper to fetch a specific token metadata from the cache
*/
public func tokenResponse(forAddress: String, tokenId: Int) -> ObjktTokenReponse? {
return tokens["\(forAddress):\(tokenId)"]
}

/**
Clear all the cached data
*/
public func deleteCache() {
self.collections = [:]
self.tokens = [:]
Expand Down
6 changes: 6 additions & 0 deletions Sources/KukaiCoreSwift/Clients/TezosDomainsClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,15 @@ public class TezosDomainsClient {

// MARK: - Public single functions

/// Get Tezos domain response for a given address
public func getDomainFor(address: String, url: URL? = nil, completion: @escaping ((Result<GraphQLResponse<TezosDomainsDomainResponse>, KukaiError>) -> Void)) {
let queryDict = ["query": "query {reverseRecord(address: \"\(address)\") {id, address, owner, expiresAtUtc, domain { name, address}}}"]
let data = try? JSONEncoder().encode(queryDict)

self.networkService.request(url: url ?? self.config.tezosDomainsURL, isPOST: true, withBody: data, forReturnType: GraphQLResponse<TezosDomainsDomainResponse>.self, completion: completion)
}

/// Query both mainnet and ghostnet versions of Tezos domains to find all records for the given address
public func getMainAndGhostDomainFor(address: String, completion: @escaping (( Result<BothNetworkReverseRecord, KukaiError> ) -> Void)) {
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
Expand Down Expand Up @@ -99,6 +101,7 @@ public class TezosDomainsClient {
}
}

/// Find the tz address of a given domain
public func getAddressFor(domain: String, completion: @escaping ((Result<GraphQLResponse<TezosDomainsAddressResponse>, KukaiError>) -> Void)) {
let queryDict = ["query": "query {domain(name: \"\(domain)\") { name, address }}"]
let data = try? JSONEncoder().encode(queryDict)
Expand All @@ -110,6 +113,7 @@ public class TezosDomainsClient {

// MARK: - Public bulk functions

/// Bulk function for fetching domains for an array of addresses
public func getDomainsFor(addresses: [String], url: URL? = nil, completion: @escaping ((Result<GraphQLResponse<TezosDomainsDomainBulkResponse>, KukaiError>) -> Void)) {
var addressArray = ""
for add in addresses {
Expand All @@ -122,6 +126,7 @@ public class TezosDomainsClient {
self.networkService.request(url: url ?? self.config.tezosDomainsURL, isPOST: true, withBody: data, forReturnType: GraphQLResponse<TezosDomainsDomainBulkResponse>.self, completion: completion)
}

/// Bulk function for fetching domains for an array of addresses, check ghostnet and mainnet for each
public func getMainAndGhostDomainsFor(addresses: [String], completion: @escaping (( Result<[String: BothNetworkReverseRecord], KukaiError> ) -> Void)) {
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
Expand Down Expand Up @@ -183,6 +188,7 @@ public class TezosDomainsClient {
}
}

/// Bulk function to find all domains for a list of addresses
public func getAddressesFor(domains: [String], completion: @escaping ((Result<GraphQLResponse<TezosDomainsAddressBulkResponse>, KukaiError>) -> Void)) {
var domainsArray = ""
for dom in domains {
Expand Down
8 changes: 7 additions & 1 deletion Sources/KukaiCoreSwift/Clients/TzKTClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Kingfisher
import os.log


/// TzKT is an indexer for Tezos, who's API allows developers to query details about wallets, and transactions
/// TzKT is an indexer for Tezos, who's API allows developers to query details about wallets, transactions, bakers, account status etc
public class TzKTClient {

/// Unique Errors that TzKTClient can throw
Expand All @@ -22,6 +22,7 @@ public class TzKTClient {
case parseError(String)
}

/// Constants needed for interacting with the API
public struct Constants {
public static let tokenBalanceQuerySize = 10000
}
Expand All @@ -41,8 +42,10 @@ public class TzKTClient {
private var addressesToWatch: [String] = []
private var newAddressesToWatch: [String] = []

/// Is currently monitoring an address for update notifications
public var isListening = false

/// Notifications of monitored addresses that have changed
@Published public var accountDidChange: [String] = []


Expand Down Expand Up @@ -923,6 +926,7 @@ public class TzKTClient {

// MARK: - Transaction History

/// Fetch all transactions, both account operations, and token transfers, and combine them into 1 response
public func fetchTransactions(forAddress address: String, limit: Int = 50, completion: @escaping (([TzKTTransaction]) -> Void)) {
let dispatchGroupTransactions = DispatchGroup()
dispatchGroupTransactions.enter()
Expand Down Expand Up @@ -1018,6 +1022,7 @@ public class TzKTClient {
self.tempTokenTransfers = []
}

/// Group transactions into logical groups, so user doesn't see N enteries for 1 contract call resulting in many internal operations
public func groupTransactions(transactions: [TzKTTransaction], currentWalletAddress: String) -> [TzKTTransactionGroup] {
var tempTrans: [TzKTTransaction] = []
var groups: [TzKTTransactionGroup] = []
Expand Down Expand Up @@ -1081,6 +1086,7 @@ public class TzKTClient {
}
}

/// SingnalR implementation to support account monitoring webscokets
extension TzKTClient: HubConnectionDelegate {

public func connectionDidOpen(hubConnection: HubConnection) {
Expand Down
7 changes: 7 additions & 0 deletions Sources/KukaiCoreSwift/Extensions/Codable+extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

import Foundation

/// Allowing the encoding/decoing of types containing `Any`, e.g. `[String: Any]`, `[Any]` etc. Necessary for third party APIs that have flexible responses
private struct DummyCodable: Codable {}

/// Allowing the encoding/decoing of types containing `Any`, e.g. `[String: Any]`, `[Any]` etc. Necessary for third party APIs that have flexible responses
struct JSONCodingKeys: CodingKey {
var stringValue: String
var intValue: Int?
Expand All @@ -24,6 +26,7 @@ struct JSONCodingKeys: CodingKey {
}
}

/// Allowing the encoding/decoing of types containing `Any`, e.g. `[String: Any]`, `[Any]` etc. Necessary for third party APIs that have flexible responses
extension KeyedDecodingContainer {

func decode(_ type: [String: Any].Type, forKey key: K) throws -> [String: Any] {
Expand Down Expand Up @@ -108,6 +111,7 @@ extension KeyedDecodingContainer {
}
}

/// Allowing the encoding/decoing of types containing `Any`, e.g. `[String: Any]`, `[Any]` etc. Necessary for third party APIs that have flexible responses
extension UnkeyedDecodingContainer {

mutating func decode(_ type: [[String: Any]].Type) throws -> [[String: Any]] {
Expand Down Expand Up @@ -180,6 +184,7 @@ extension UnkeyedDecodingContainer {
}
}

/// Allowing the encoding/decoing of types containing `Any`, e.g. `[String: Any]`, `[Any]` etc. Necessary for third party APIs that have flexible responses
extension KeyedEncodingContainerProtocol where Key == JSONCodingKeys {

mutating func encode(_ value: [String: Any]) throws {
Expand Down Expand Up @@ -229,6 +234,7 @@ extension KeyedEncodingContainerProtocol where Key == JSONCodingKeys {
}
}

/// Allowing the encoding/decoing of types containing `Any`, e.g. `[String: Any]`, `[Any]` etc. Necessary for third party APIs that have flexible responses
extension KeyedEncodingContainerProtocol {
mutating func encode(_ value: [String: Any]?, forKey key: Key) throws {
guard let value = value else { return }
Expand All @@ -245,6 +251,7 @@ extension KeyedEncodingContainerProtocol {
}
}

/// Allowing the encoding/decoing of types containing `Any`, e.g. `[String: Any]`, `[Any]` etc. Necessary for third party APIs that have flexible responses
extension UnkeyedEncodingContainer {

mutating func encode(_ value: [Any]) throws {
Expand Down
1 change: 1 addition & 0 deletions Sources/KukaiCoreSwift/Extensions/Date+extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Foundation

public extension Date {

/// Helper to return strings like "15 seconds ago", "1 minute ago" etc, from a Date
func timeAgoDisplay() -> String {
let formatter = RelativeDateTimeFormatter()
formatter.unitsStyle = .full
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Foundation

public extension DateFormatter {

/// Helper to create a DateFormatter with a format in 1 call
convenience init(withFormat: String) {
self.init()
self.dateFormat = withFormat
Expand Down
9 changes: 8 additions & 1 deletion Sources/KukaiCoreSwift/Extensions/URL+extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
//

import Foundation
import OSLog

/// Extensions to make adding query items easier
extension URL {

/// Helper to append a String as a query param to a URL
mutating func appendQueryItem(name: String, value: String?) {

guard var urlComponents = URLComponents(string: absoluteString) else { return }
Expand All @@ -28,9 +30,14 @@ extension URL {
urlComponents.queryItems = queryItems

// Returns the url from new url components
self = urlComponents.url!
if let u = urlComponents.url {
self = u
} else {
os_log("Unable to appendQueryItem %@ to URL", log: .kukaiCoreSwift, type: .error, name)
}
}

/// Helper to append a Int as a query param to a URL
mutating func appendQueryItem(name: String, value: Int) {
self.appendQueryItem(name: name, value: value.description)
}
Expand Down
1 change: 1 addition & 0 deletions Sources/KukaiCoreSwift/Factories/OperationFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ public class OperationFactory {

// MARK: - Extractors

/// Internal Struct to encapsulate helpers methods needed to extract critical information from an array of operations, needed for processing decisions like "do i display a send token screen, or a send NFt screen", fetching total XTZ sent in 1 action etc
public struct Extractor {

/**
Expand Down
3 changes: 3 additions & 0 deletions Sources/KukaiCoreSwift/Models/BakingBad/TzKTBaker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ public struct TzKTBaker: Codable, Hashable {
self.config = config
}

/// Ghostnet has a different setup for bakers, but we need to display and interact with them the same way.
/// So this helper extract what it can from the API and creates semi-real baker objects to help users deal with Ghostnet
public static func fromTestnetArray(_ data: [Any]) -> TzKTBaker? {
guard data.count == 4, let address = data[0] as? String, let balance = (data[2] as? NSNumber)?.decimalValue, let stakingBalance = (data[3] as? NSNumber)?.decimalValue else {
return nil
Expand All @@ -108,6 +110,7 @@ public struct TzKTBaker: Codable, Hashable {
return TzKTBaker(address: address, name: name, logo: nil, balance: normalisedBalance, stakingBalance: normalisedStakingBal, stakingCapacity: normalisedStakingBal, maxStakingBalance: normalisedStakingBal, freeSpace: normalisedStakingBal, fee: 0.05, minDelegation: 0, payoutDelay: 6, payoutPeriod: 1, openForDelegation: true, estimatedRoi: 0.05, serviceHealth: .active, payoutTiming: .no_data, payoutAccuracy: .no_data, config: nil)
}

/// Convert con-chain data into a meaningful, readable object
public func rewardStruct() -> TzKTBakerConfigRewardStruct? {
guard let config = config, let rewardStructInt = config.latestRewardStruct() else {
return nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import Foundation

/// An object containing info on the reward a delegator should receive from a baker
public struct TzKTDelegatorReward: Codable {

public let cycle: Int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import Foundation

/// FA1.2 / FA2 token transafers are treated differently from transactions. This object is used when fetching data form the API, as a temporary placeholder, ultimately to be merged into the transactions
public struct TzKTTokenTransfer: Codable {
public let id: Decimal
public var hash: String? // Doesn't come from API, but needed later, added during grouping / conversion phase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import Foundation

/// Artifical object used to group related transactions into a more user friendly display
/// For example, 1 contract call can reuslt in many transactions being returned. To avoid the users UI being clogged, we group all them into 1 group, so the user only needs to see 1 item for 1 action they performed
public struct TzKTTransactionGroup: Codable, Hashable, Identifiable, CustomStringConvertible {

// MARK: - Properties
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import Foundation

/// Dedicated "FailWith" parser for the codes received from Liquidity Baking contract
public struct FailWithParserLiquidityBaking: FailWithParser {

public func parse(failWith: FailWith?) -> String? {
Expand Down
1 change: 1 addition & 0 deletions Sources/KukaiCoreSwift/Models/NilOnDecodingError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import Foundation

/// property wrapper to easily handle a situation where we don't want decoding to fail for 1 property which may be problematic. Instead just default it to nil
@propertyWrapper
public struct NilOnDecodingError<Wrapped> {

Expand Down
1 change: 1 addition & 0 deletions Sources/KukaiCoreSwift/Models/SVGImageProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import UIKit
import Kingfisher
import SVGKit

/// SVG image processor for Kingfisher library
public struct SVGImgProcessor: ImageProcessor {

public var identifier: String = "app.kukai.mobile.webpprocessor"
Expand Down

0 comments on commit 788438b

Please sign in to comment.