Skip to content

Commit 7d675ee

Browse files
author
Fernando Fernandes
committed
Refactor, moving things around
- Making room for new exchanges.
1 parent fb48637 commit 7d675ee

File tree

5 files changed

+248
-214
lines changed

5 files changed

+248
-214
lines changed

Sources/SwiftTrader/Model/Error/SwiftTraderError+Kucoin.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ public extension SwiftTraderError {
1212

1313
static func error(for statusCode: Int, localizedErrorMessage: String, data: Data) -> SwiftTraderError {
1414
guard let kucoinError = try? JSONDecoder().decode(KucoinSystemError.self, from: data) else {
15-
return .statusCodeNotOK(statusCode: statusCode, localizedErrorMessage: localizedErrorMessage)
15+
return .kucoinStatusCodeNotOK(statusCode: statusCode, localizedErrorMessage: localizedErrorMessage)
1616
}
17-
return .statusCodeNotOK(
17+
return .kucoinStatusCodeNotOK(
1818
statusCode: statusCode,
1919
localizedErrorMessage: localizedErrorMessage,
2020
kucoinErrorCode: kucoinError.code,

Sources/SwiftTrader/Model/Error/SwiftTraderError.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@ public enum SwiftTraderError: Error {
2020

2121
// MARK: - Kucoin Related
2222

23+
/// No `KucoinAuth` instance was given; it will be impossible to authenticate with Kucoin.
24+
case kucoinMissingAuthentication
25+
2326
/// The response status code is something other than `200`.
2427
///
2528
/// The underlying Kucoin system error may be verified by reading the returned extra arguments, if present.
26-
case statusCodeNotOK(
29+
case kucoinStatusCodeNotOK(
2730
statusCode: Int,
2831
localizedErrorMessage: String,
2932
kucoinErrorCode: String? = nil,
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// SwiftTrader+Error.swift
3+
//
4+
//
5+
// Created by Fernando Fernandes on 07.03.22.
6+
//
7+
8+
import Foundation
9+
10+
public extension SwiftTrader {
11+
12+
/// Translates a `NetworkRequestError` to a `SwiftTraderError`.
13+
func handle(networkRequestError: NetworkRequestError, operation: SwiftTraderOperation) -> SwiftTraderError {
14+
switch networkRequestError {
15+
16+
case .statusCodeNotOK(let statusCode, let errorMessage, let data):
17+
let error = SwiftTraderError.error(for: statusCode, localizedErrorMessage: errorMessage, data: data)
18+
return error
19+
20+
default:
21+
switch operation {
22+
case .kucoinFuturesAccountOverview:
23+
return .kucoinFuturesAccountOverview(error: networkRequestError)
24+
case .kucoinFuturesCancelStopOrders:
25+
return .kucoinFuturesCancelStopOrders(error: networkRequestError)
26+
case .kucoinFuturesStopOrderList:
27+
return .kucoinFuturesStopOrderList(error: networkRequestError)
28+
case .kucoinFuturesOrderList:
29+
return .kucoinFuturesOrderList(error: networkRequestError)
30+
case .kucoinFuturesPlaceStopLimitOrder:
31+
return .kucoinFuturesPlaceStopLimitOrder(error: networkRequestError)
32+
case .kucoinFuturesPositionList:
33+
return .kucoinFuturesPositionList(error: networkRequestError)
34+
}
35+
}
36+
}
37+
}
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
//
2+
// SwiftTrader+Kucoin.swift
3+
//
4+
//
5+
// Created by Fernando Fernandes on 07.03.22.
6+
//
7+
8+
import Foundation
9+
10+
/// Interface to Kucoin APIs.
11+
public extension SwiftTrader {
12+
13+
// MARK: Account Overview
14+
15+
/// Retrieves the overview of a Kucoin Futures account.
16+
///
17+
/// https://docs.kucoin.com/futures/#account
18+
///
19+
/// - Parameter currencySymbol: The `CurrencySymbol` of the account balance. The default is `.USDT`.
20+
/// - Returns: An instance of `KucoinFuturesAccountOverview` or `SwiftTraderError`.
21+
func kucoinFuturesAccountOverview(currencySymbol: CurrencySymbol = .USDT) async throws -> Result<KucoinFuturesAccountOverview, SwiftTraderError> {
22+
guard let auth = kucoinAuth else {
23+
return .failure(.kucoinMissingAuthentication)
24+
}
25+
let request = KucoinFuturesAccountOverviewRequest(
26+
currencySymbol: currencySymbol,
27+
kucoinAuth: auth,
28+
settings: settings.networkRequestSettings
29+
)
30+
switch await request.execute() {
31+
case .success(let model):
32+
guard let accountOverview = model as? KucoinFuturesAccountOverview else {
33+
return .failure(.unexpectedResponse(modelString: "\(model)"))
34+
}
35+
return .success(accountOverview)
36+
case .failure(let error):
37+
let swiftTraderError = handle(networkRequestError: error, operation: .kucoinFuturesAccountOverview)
38+
return .failure(swiftTraderError)
39+
}
40+
}
41+
42+
// MARK: List Orders
43+
44+
/// Retrieves the list of un-triggered stop orders.
45+
///
46+
/// https://docs.kucoin.com/futures/#get-untriggered-stop-order-list
47+
///
48+
/// - Parameter orderStatus: `KucoinFuturesOrderStatus`, default is `.active`.
49+
/// - Returns: An instance of `KucoinFuturesOrderList` or `SwiftTraderError`.
50+
func kucoinFuturesStopOrderList(symbol: String) async throws -> Result<KucoinFuturesOrderList, SwiftTraderError> {
51+
guard let auth = kucoinAuth else {
52+
return .failure(.kucoinMissingAuthentication)
53+
}
54+
let request = KucoinFuturesListStopOrdersRequest(
55+
symbol: symbol,
56+
kucoinAuth: auth,
57+
settings: settings.networkRequestSettings
58+
)
59+
switch await request.execute() {
60+
case .success(let model):
61+
guard let stopOrders = model as? KucoinFuturesOrderList else {
62+
return .failure(.unexpectedResponse(modelString: "\(model)"))
63+
}
64+
return .success(stopOrders)
65+
case .failure(let error):
66+
let swiftTraderError = handle(networkRequestError: error, operation: .kucoinFuturesStopOrderList)
67+
return .failure(swiftTraderError)
68+
}
69+
}
70+
71+
/// Retrieves the list of active Futures orders.
72+
///
73+
/// Notice: this does **not** include the list of stop orders
74+
/// https://docs.kucoin.com/futures/#get-order-list
75+
///
76+
/// - Parameter orderStatus: `KucoinFuturesOrderStatus`, default is `.active`.
77+
/// - Returns: An instance of `KucoinFuturesOrderList` or `SwiftTraderError`.
78+
func kucoinFuturesOrderList(orderStatus: KucoinOrderStatus = .active) async throws -> Result<KucoinFuturesOrderList, SwiftTraderError> {
79+
guard let auth = kucoinAuth else {
80+
return .failure(.kucoinMissingAuthentication)
81+
}
82+
let request = KucoinFuturesOrdersListRequest(
83+
orderStatus: orderStatus,
84+
kucoinAuth: auth,
85+
settings: settings.networkRequestSettings
86+
)
87+
switch await request.execute() {
88+
case .success(let model):
89+
guard let orderList = model as? KucoinFuturesOrderList else {
90+
return .failure(.unexpectedResponse(modelString: "\(model)"))
91+
}
92+
return .success(orderList)
93+
case .failure(let error):
94+
let swiftTraderError = handle(networkRequestError: error, operation: .kucoinFuturesOrderList)
95+
return .failure(swiftTraderError)
96+
}
97+
}
98+
99+
// MARK: Place Orders
100+
101+
/// Places a Futures stop limit order.
102+
///
103+
/// https://docs.kucoin.com/futures/#place-an-order
104+
///
105+
/// - Parameter orderInput: `SwiftTraderStopLimitOrderInput` instance that encapsulates
106+
/// all the arguments required for submiting the stop limit order.
107+
/// - Returns: An instance of `KucoinFuturesPlaceOrder` or `SwiftTraderError`.
108+
func kucoinFuturesPlaceStopLimitOrder(_ orderInput: SwiftTraderStopLimitOrderInput) async throws -> Result<KucoinFuturesPlaceOrder, SwiftTraderError> {
109+
guard let auth = kucoinAuth else {
110+
return .failure(.kucoinMissingAuthentication)
111+
}
112+
do {
113+
let orderParameters = try createStopLimitOrderParameters(for: orderInput)
114+
115+
if orderInput.cancelStopOrders {
116+
do {
117+
try await kucoinFuturesCancelStopOrders(symbol: orderInput.contractSymbol)
118+
} catch {
119+
logger.log("Could not cancel untriggered stop orders: \(error)")
120+
}
121+
}
122+
123+
let request = KucoinFuturesPlaceOrdersRequest(
124+
orderParameters: orderParameters,
125+
kucoinAuth: auth,
126+
settings: settings.networkRequestSettings
127+
)
128+
switch await request.execute() {
129+
case .success(let model):
130+
guard let placeOrder = model as? KucoinFuturesPlaceOrder else {
131+
return .failure(.unexpectedResponse(modelString: "\(model)"))
132+
}
133+
return .success(placeOrder)
134+
case .failure(let error):
135+
let swiftTraderError = handle(networkRequestError: error, operation: .kucoinFuturesPlaceStopLimitOrder)
136+
return .failure(swiftTraderError)
137+
}
138+
} catch {
139+
if let swiftTraderError = error as? SwiftTraderError {
140+
return .failure(swiftTraderError)
141+
} else {
142+
return .failure(.unexpected(error))
143+
}
144+
}
145+
}
146+
147+
// MARK: Cancel Orders
148+
149+
/// Cancels all untriggered Futures stop orders of a given symbol (contract).
150+
///
151+
/// https://docs.kucoin.com/futures/#stop-order-mass-cancelation
152+
///
153+
/// - Parameter symbol: `String`, represents the specific contract for which all the untriggered stop orders will be cancelled.
154+
/// - Returns: An instance of `KucoinFuturesCancelStopOrders` or `SwiftTraderError`.
155+
@discardableResult func kucoinFuturesCancelStopOrders(symbol: String) async throws -> Result<KucoinFuturesCancelStopOrders, SwiftTraderError> {
156+
guard let auth = kucoinAuth else {
157+
return .failure(.kucoinMissingAuthentication)
158+
}
159+
let request = KucoinFuturesCancelOrdersRequest(
160+
symbol: symbol,
161+
kucoinAuth: auth,
162+
settings: settings.networkRequestSettings
163+
)
164+
switch await request.execute() {
165+
case .success(let model):
166+
guard let cancelledOrders = model as? KucoinFuturesCancelStopOrders else {
167+
return .failure(.unexpectedResponse(modelString: "\(model)"))
168+
}
169+
return .success(cancelledOrders)
170+
case .failure(let error):
171+
let swiftTraderError = handle(networkRequestError: error, operation: .kucoinFuturesCancelStopOrders)
172+
return .failure(swiftTraderError)
173+
}
174+
}
175+
176+
// MARK: Positions
177+
178+
/// Lists open Futures positions.
179+
///
180+
/// https://docs.kucoin.com/futures/#get-position-list
181+
///
182+
/// - Returns: An instance of `KucoinFuturesPositionList` or `SwiftTraderError`.
183+
func kucoinFuturesPositionList() async throws -> Result<KucoinFuturesPositionList, SwiftTraderError> {
184+
guard let auth = kucoinAuth else {
185+
return .failure(.kucoinMissingAuthentication)
186+
}
187+
let request = KucoinFuturesPositionListRequest(
188+
kucoinAuth: auth,
189+
settings: settings.networkRequestSettings
190+
)
191+
switch await request.execute() {
192+
case .success(let model):
193+
guard let positionList = model as? KucoinFuturesPositionList else {
194+
return .failure(.unexpectedResponse(modelString: "\(model)"))
195+
}
196+
return .success(positionList)
197+
case .failure(let error):
198+
let swiftTraderError = handle(networkRequestError: error, operation: .kucoinFuturesPositionList)
199+
return .failure(swiftTraderError)
200+
}
201+
}
202+
}

0 commit comments

Comments
 (0)