Skip to content

Commit 7cb717a

Browse files
author
Fernando Fernandes
committed
Implement main components
1 parent 19042f3 commit 7cb717a

17 files changed

+491
-1
lines changed

Package.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import PackageDescription
33

44
let package = Package(
55
name: "SwiftTrader",
6+
platforms: [
7+
.macOS(.v12),
8+
.iOS(.v15)
9+
],
610
products: [
711
.library(
812
name: "SwiftTrader",
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// CurrencySymbol.swift
3+
//
4+
//
5+
// Created by Fernando Fernandes on 29.01.22.
6+
//
7+
8+
import Foundation
9+
10+
/// Holds currency symbols according to the API requirements of the supported exchanges.
11+
///
12+
/// The list will grow as needed.
13+
public enum CurrencySymbol: String {
14+
case BTC
15+
case USDT
16+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// Date+Timestamp.swift
3+
//
4+
//
5+
// Created by Fernando Fernandes on 29.01.22.
6+
//
7+
8+
import Foundation
9+
10+
public extension Date {
11+
12+
var timestampMilliseconds: Int64 {
13+
Int64(timeIntervalSince1970 * 1000)
14+
}
15+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// URLRequest+HTTPMethod.swift
3+
//
4+
//
5+
// Created by Fernando Fernandes on 29.01.22.
6+
//
7+
8+
import Foundation
9+
10+
public enum HTTPMethod: String {
11+
case GET
12+
case POST
13+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// KucoinAuthentication.swift
3+
//
4+
//
5+
// Created by Fernando Fernandes on 29.01.22.
6+
//
7+
8+
import Foundation
9+
10+
/// Holds data required to authenticate the requests against Kucoin APIs.
11+
public struct KucoinAuth {
12+
public let apiKey: String
13+
public let apiSecret: String
14+
public let apiPassphrase: String
15+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// KucoinError.swift
3+
//
4+
//
5+
// Created by Fernando Fernandes on 28.01.22.
6+
//
7+
8+
import Foundation
9+
10+
/// Represents errors that may occur while interacting with Kucoin REST APIs.
11+
///
12+
/// https://docs.kucoin.com/futures/#requests
13+
public struct KucoinSystemError: Codable {
14+
public let code: String
15+
public let message: String
16+
17+
public enum CodingKeys: String, CodingKey {
18+
case code
19+
case message = "msg"
20+
}
21+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// KucoinFuturesAccountOverviewResponse.swift
3+
//
4+
//
5+
// Created by Fernando Fernandes on 27.01.22.
6+
//
7+
8+
import Foundation
9+
10+
/// Kucoin "Get Account Overview" REST API response.
11+
///
12+
/// https://docs.kucoin.com/futures/#account
13+
public struct KucoinFuturesAccountOverviewResponse: Codable {
14+
public let code: String
15+
public let data: KucoinFuturesAccountData
16+
}
17+
18+
/// Provides an overview of a Kucoin Futures account.
19+
///
20+
/// https://docs.kucoin.com/futures/#account
21+
public struct KucoinFuturesAccountData: Codable {
22+
/// Account equity = marginBalance + Unrealised PNL.
23+
public let accountEquity: Double
24+
25+
public let availableBalance: Double
26+
27+
/// Currency code, e.g.: "XBT", "USDT".
28+
public let currency: String
29+
30+
/// Frozen funds for withdrawal and out-transfer.
31+
public let frozenFunds: Double
32+
33+
/// Margin balance = positionMargin + orderMargin + frozenFunds + availableBalance - unrealisedPNL
34+
public let marginBalance: Double
35+
36+
public let orderMargin: Double
37+
38+
public let positionMargin: Double
39+
40+
/// Unrealised profit and loss.
41+
public let unrealisedPNL: Double
42+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// APIResourceProtocol.swift
3+
//
4+
//
5+
// Created by Fernando Fernandes on 28.01.22.
6+
//
7+
8+
import Foundation
9+
10+
/// Represents a typical API resource that can be requested by its `URL`.
11+
///
12+
/// `URL` example: https://api-futures.kucoin.com/api/v1/account-overview?currency=USDT
13+
public protocol APIResource {
14+
var url: URL { get throws }
15+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Fernando Fernandes on 29.01.22.
6+
//
7+
8+
import Foundation
9+
10+
#if canImport(CryptoKit)
11+
import CryptoKit
12+
#elseif canImport(Vapor)
13+
// [Server-side Support] Vapor includes SwiftCrypto, which is a Linux-compatible port of Apple's CryptoKit library.
14+
// https://docs.vapor.codes/4.0/crypto/
15+
import Vapor
16+
#endif
17+
18+
/// Encapsulates errors that can happen while generating the signature that Kucoin APIs require.
19+
public enum KucoinSignatureError: Error {
20+
case unableToExtractDataFromString(string: String)
21+
}
22+
23+
public extension KucoinAPI {
24+
25+
#warning("TODO: I need this from urlrequest - /api/v1/account-overview?currency=USDT")
26+
27+
/// Creates and returns the signature for the `KC-API-SIGN` header field.
28+
///
29+
/// https://docs.kucoin.com/futures/#authentication
30+
/// - Parameters:
31+
/// - method: `HTTPMethod`. E.g.: `GET`, `POST.`
32+
/// - path: Endpoint path including query parameters. E.g.: *"/api/v1/account-overview?currency=USDT"*
33+
/// - secret: The API secret.
34+
/// - Returns: `Base64` encoded signature.
35+
static func createSignature(for method: HTTPMethod, path: String, secret: String) throws -> String {
36+
guard let secretData = secret.data(using: .utf8) else {
37+
throw KucoinSignatureError.unableToExtractDataFromString(string: secret)
38+
}
39+
let key = SymmetricKey(data: secretData)
40+
let timestamp = Date().timestampMilliseconds
41+
let stringToSign = "\(timestamp)" + HTTPMethod.GET.rawValue + path
42+
guard let stringToSignData = stringToSign.data(using: .utf8) else {
43+
throw KucoinSignatureError.unableToExtractDataFromString(string: stringToSign)
44+
}
45+
let signature = HMAC<SHA256>.authenticationCode(for: stringToSignData, using: key)
46+
let base64signature = Data(signature).base64EncodedString()
47+
return base64signature
48+
}
49+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//
2+
// KucoinAPI.swift
3+
//
4+
//
5+
// Created by Fernando Fernandes on 29.01.22.
6+
//
7+
8+
import Foundation
9+
10+
/// Holds constants related to Kucoin REST APIs.
11+
public struct KucoinAPI {
12+
13+
public struct HeaderField {
14+
static let apiKey = "KC-API-KEY"
15+
static let apiSign = "KC-API-SIGN"
16+
static let apiTimestamp = "KC-API-TIMESTAMP"
17+
static let apiPassphrase = "KC-API-PASSPHRASE"
18+
}
19+
20+
public struct Path {
21+
static let accountOverview = "/api/v1/account-overview"
22+
}
23+
24+
public struct QueryParam {
25+
static let currency = "currency"
26+
}
27+
28+
public struct URL {
29+
static let base = "https://api-futures.kucoin.com"
30+
}
31+
}

0 commit comments

Comments
 (0)