Skip to content
This repository has been archived by the owner on Feb 15, 2024. It is now read-only.

Commit

Permalink
feat: expose collections api
Browse files Browse the repository at this point in the history
- Get details of a collection at the given address
- Get a list of collection filters
- Get a list of collections
  • Loading branch information
CassiusPacheco committed Nov 11, 2022
1 parent abe389f commit 502ad16
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 2 deletions.
1 change: 1 addition & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
disabled_rules:
- trailing_comma
- identifier_name # Lots of math operations are written with short variable names as a standard
- inclusive_language
included:
- Sources
excluded:
Expand Down
73 changes: 72 additions & 1 deletion Sources/ImmutableXCore/ImmutableX.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Foundation

// swiftlint:disable file_length
public struct ImmutableX {
/// A shared instance of ``ImmutableX`` that holds configuration for ``base``, ``logLevel`` and
/// a set o utility methods for the most common workflows for the core SDK.
Expand Down Expand Up @@ -37,6 +38,7 @@ public struct ImmutableX {
private let usersAPI: UsersAPI.Type
private let depositAPI: DepositsAPI.Type
private let assetsAPI: AssetsAPI.Type
private let collectionsAPI: CollectionsAPI.Type

/// Internal init method that includes dependencies. For the public facing API use ``initialize(base:logLevel:)``
/// instead.
Expand All @@ -51,7 +53,8 @@ public struct ImmutableX {
buyCryptoWorkflow: BuyCryptoWorkflow.Type = BuyCryptoWorkflow.self,
usersAPI: UsersAPI.Type = UsersAPI.self,
depositAPI: DepositsAPI.Type = DepositsAPI.self,
assetsAPI: AssetsAPI.Type = AssetsAPI.self
assetsAPI: AssetsAPI.Type = AssetsAPI.self,
collectionsAPI: CollectionsAPI.Type = CollectionsAPI.self
) {
self.base = base
self.logLevel = logLevel
Expand All @@ -64,6 +67,7 @@ public struct ImmutableX {
self.usersAPI = usersAPI
self.depositAPI = depositAPI
self.assetsAPI = assetsAPI
self.collectionsAPI = collectionsAPI
}

/// Initializes the SDK with the given ``base`` and ``logLevel`` by assigning a shared instance accessible via
Expand Down Expand Up @@ -344,4 +348,71 @@ public struct ImmutableX {
)
}
}

/// Get details of a collection at the given address
///
/// - Parameter address: Collection contract address
/// - Returns: ``Collection``
/// - Throws: A variation of ``ImmutableXError``
public func getCollection(address: String) async throws -> Collection {
try await APIErrorMapper.map(caller: "Get Collection") {
try await self.collectionsAPI.getCollection(address: address)
}
}

/// Get a list of collection filters
///
/// - Parameters:
/// - address: Collection contract address
/// - pageSize: Page size of the result (optional)
/// - nextPageToken: Next page token (optional)
/// - Returns: ``CollectionFilter``
/// - Throws: A variation of ``ImmutableXError``
public func listCollectionFilters(
address: String,
pageSize: Int? = nil,
nextPageToken: String? = nil
) async throws -> CollectionFilter {
try await APIErrorMapper.map(caller: "List Collection Filters") {
try await self.collectionsAPI.listCollectionFilters(
address: address,
pageSize: pageSize,
nextPageToken: nextPageToken
)
}
}

/// Get a list of collections
///
/// - Parameters:
/// - pageSize: Page size of the result (optional)
/// - cursor: Cursor (optional)
/// - orderBy: Property to sort by (optional)
/// - direction: Direction to sort (asc/desc) (optional)
/// - blacklist: List of collections not to be included, separated by commas (optional)
/// - whitelist: List of collections to be included, separated by commas (optional)
/// - keyword: Keyword to search in collection name and description (optional)
/// - Returns: ``ListCollectionsResponse``
/// - Throws: A variation of ``ImmutableXError``
public func listCollections(
pageSize: Int? = nil,
cursor: String? = nil,
orderBy: ListCollectionsOrderBy? = nil,
direction: String? = nil,
blacklist: String? = nil,
whitelist: String? = nil,
keyword: String? = nil
) async throws -> ListCollectionsResponse {
try await APIErrorMapper.map(caller: "List Collections") {
try await self.collectionsAPI.listCollections(
pageSize: pageSize,
cursor: cursor,
orderBy: orderBy?.asApiArgument,
direction: direction,
blacklist: blacklist,
whitelist: whitelist,
keyword: keyword
)
}
}
}
27 changes: 27 additions & 0 deletions Sources/ImmutableXCore/Model/ListCollectionsOrderBy.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Foundation

// swiftlint:disable:next line_length
/// Ordering options available for ``ImmutableX/listCollections(pageSize:cursor:orderBy:direction:blacklist:whitelist:keyword:)``
public enum ListCollectionsOrderBy: String, CaseIterable {
case name
case address
case projectId = "project_id"
case createdAt = "created_at"
case updatedAt = "updated_at"

/// Converts this enum to the type expected by the generated API code
internal var asApiArgument: CollectionsAPI.OrderBy_listCollections {
switch self {
case .name:
return .name
case .address:
return .address
case .projectId:
return .projectId
case .createdAt:
return .createdAt
case .updatedAt:
return .updatedAt
}
}
}
64 changes: 63 additions & 1 deletion Tests/ImmutableXCoreTests/ImmutableXTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ final class ImmutableXTests: XCTestCase {
let usersAPIMock = UsersAPIMock.self
let depositAPIMock = DepositAPIMock.self
let assetsAPIMock = AssetsAPIMock.self
let collectionsAPIMock = CollectionsAPIMock.self

lazy var core = ImmutableX(
buyWorkflow: buyWorkflow,
Expand All @@ -21,7 +22,8 @@ final class ImmutableXTests: XCTestCase {
buyCryptoWorkflow: buyCryptoWorkflowMock,
usersAPI: usersAPIMock,
depositAPI: depositAPIMock,
assetsAPI: assetsAPIMock
assetsAPI: assetsAPIMock,
collectionsAPI: collectionsAPIMock
)

override func setUp() {
Expand All @@ -35,6 +37,7 @@ final class ImmutableXTests: XCTestCase {
usersAPIMock.resetMock()
depositAPIMock.resetMock()
assetsAPIMock.resetMock()
collectionsAPIMock.resetMock()

ImmutableX.initialize()

Expand Down Expand Up @@ -81,6 +84,18 @@ final class ImmutableXTests: XCTestCase {
let listAssetsCompanion = AssetsAPIMock.ListAssetsCompanion()
listAssetsCompanion.returnValue = listAssetsResponseStub1
assetsAPIMock.mock(listAssetsCompanion)

let collectionCompanion = CollectionsAPIMock.GetCollectionCompanion()
collectionCompanion.returnValue = collectionStub1
collectionsAPIMock.mock(collectionCompanion)

let listCollectionFiltersCompanion = CollectionsAPIMock.ListCollectionFiltersCompanion()
listCollectionFiltersCompanion.returnValue = collectionFilterStub1
collectionsAPIMock.mock(listCollectionFiltersCompanion)

let listCollectionsCompanion = CollectionsAPIMock.ListCollectionsCompanion()
listCollectionsCompanion.returnValue = listCollectionResponseStub1
collectionsAPIMock.mock(listCollectionsCompanion)
}

func testSdkVersion() {
Expand Down Expand Up @@ -280,4 +295,51 @@ final class ImmutableXTests: XCTestCase {
_ = try await core.listAssets()
}
}

// MARK: - Collections

func testGetCollectionSuccess() async throws {
let response = try await core.getCollection(address: "address")
XCTAssertEqual(response, collectionStub1)
}

func testGetCollectionFailure() async {
let companion = CollectionsAPIMock.GetCollectionCompanion()
companion.throwableError = DummyError.something
collectionsAPIMock.mock(companion)

await XCTAssertThrowsErrorAsync {
_ = try await core.getCollection(address: "address")
}
}

func testListCollectionFiltersSuccess() async throws {
let response = try await core.listCollectionFilters(address: "address")
XCTAssertEqual(response, collectionFilterStub1)
}

func testListCollectionFiltersFailure() async {
let companion = CollectionsAPIMock.ListCollectionFiltersCompanion()
companion.throwableError = DummyError.something
collectionsAPIMock.mock(companion)

await XCTAssertThrowsErrorAsync {
_ = try await core.listCollectionFilters(address: "address")
}
}

func testListCollectionsSuccess() async throws {
let response = try await core.listCollections()
XCTAssertEqual(response, listCollectionResponseStub1)
}

func testListCollectionsFailure() async {
let companion = CollectionsAPIMock.ListCollectionsCompanion()
companion.throwableError = DummyError.something
collectionsAPIMock.mock(companion)

await XCTAssertThrowsErrorAsync {
_ = try await core.listCollections()
}
}
}
77 changes: 77 additions & 0 deletions Tests/ImmutableXCoreTests/Mocks/API/CollectionsAPIMock.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import Foundation
@testable import ImmutableXCore

final class CollectionsAPIMock: CollectionsAPI {
class GetCollectionCompanion {
var throwableError: Error?
var callsCount = 0
var returnValue: Collection!
}

class ListCollectionFiltersCompanion {
var throwableError: Error?
var callsCount = 0
var returnValue: CollectionFilter!
}

class ListCollectionsCompanion {
var throwableError: Error?
var callsCount = 0
var returnValue: ListCollectionsResponse!
}

static var getCollectionCompanion: GetCollectionCompanion?
static var listCollectionFiltersCompanion: ListCollectionFiltersCompanion?
static var listCollectionsCompanion: ListCollectionsCompanion?

static func mock(_ companion: GetCollectionCompanion) {
getCollectionCompanion = companion
}

static func mock(_ companion: ListCollectionFiltersCompanion) {
listCollectionFiltersCompanion = companion
}

static func mock(_ companion: ListCollectionsCompanion) {
listCollectionsCompanion = companion
}

static func resetMock() {
getCollectionCompanion = nil
listCollectionFiltersCompanion = nil
listCollectionsCompanion = nil
}

override class func getCollection(address: String) async throws -> Collection {
let companion = getCollectionCompanion!
companion.callsCount += 1

if let error = companion.throwableError {
throw error
}

return companion.returnValue
}

override class func listCollectionFilters(address: String, pageSize: Int? = nil, nextPageToken: String? = nil) async throws -> CollectionFilter {
let companion = listCollectionFiltersCompanion!
companion.callsCount += 1

if let error = companion.throwableError {
throw error
}

return companion.returnValue
}

override class func listCollections(pageSize: Int? = nil, cursor: String? = nil, orderBy: CollectionsAPI.OrderBy_listCollections? = nil, direction: String? = nil, blacklist: String? = nil, whitelist: String? = nil, keyword: String? = nil) async throws -> ListCollectionsResponse {
let companion = listCollectionsCompanion!
companion.callsCount += 1

if let error = companion.throwableError {
throw error
}

return companion.returnValue
}
}
24 changes: 24 additions & 0 deletions Tests/ImmutableXCoreTests/Mocks/Stubs/Models.swift
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,27 @@ let listAssetsResponseStub1 = ListAssetsResponse(
remaining: 0,
result: [assetWithOrdersStub1]
)

let collectionStub1 = Collection(
address: "address",
collectionImageUrl: nil,
description: nil,
iconUrl: nil,
metadataApiUrl: nil,
name: "name",
projectId: 1,
projectOwnerAddress: "address"
)

let collectionFilterStub1 = CollectionFilter(
key: "key",
range: nil,
type: nil,
value: nil
)

let listCollectionResponseStub1 = ListCollectionsResponse(
cursor: "",
remaining: 0,
result: [collectionStub1]
)
16 changes: 16 additions & 0 deletions Tests/ImmutableXCoreTests/Model/ListCollectionsOrderByTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@testable import ImmutableXCore
import XCTest

final class ListCollectionsOrderByTests: XCTestCase {
func testAsApiArgument() throws {
XCTAssertEqual(ListCollectionsOrderBy.name.asApiArgument, .name)
XCTAssertEqual(ListCollectionsOrderBy.address.asApiArgument, .address)
XCTAssertEqual(ListCollectionsOrderBy.projectId.asApiArgument, .projectId)
XCTAssertEqual(ListCollectionsOrderBy.createdAt.asApiArgument, .createdAt)
XCTAssertEqual(ListCollectionsOrderBy.updatedAt.asApiArgument, .updatedAt)
XCTAssertEqual(
ListCollectionsOrderBy.allCases.map(\.rawValue),
CollectionsAPI.OrderBy_listCollections.allCases.map(\.rawValue)
)
}
}

0 comments on commit 502ad16

Please sign in to comment.