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

Commit

Permalink
refactor: enable lint rule to limit line length
Browse files Browse the repository at this point in the history
Following the standards in the other Swift projects at ImmutableX, the
Core SDK now limits the line length to 120 characters.
  • Loading branch information
CassiusPacheco committed Nov 9, 2022
1 parent 35688b6 commit e2c513a
Show file tree
Hide file tree
Showing 17 changed files with 275 additions and 114 deletions.
1 change: 0 additions & 1 deletion .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
disabled_rules:
- trailing_comma
- line_length
- identifier_name # Lots of math operations are written with short variable names as a standard
included:
- Sources
Expand Down
7 changes: 5 additions & 2 deletions Sources/ImmutableXCore/Crypto/BIP32/BIP32Key.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import Foundation
struct BIP32Key {
/// - Parameters:
/// - seed: seed data for derivation, e.g. personal signature
/// - path: hashed values in the expected format as per Starkware docs `m/purpose'/layer'/application'/ethAddress1'/ethAddress2'/index`
/// - path: hashed values in the expected format as per Starkware docs
/// `m/purpose'/layer'/application'/ethAddress1'/ethAddress2'/index`
/// - Returns: derived private key hex
/// - Throws: ``ImmutableXError/invalidKeyData`` if data is not valid
///
Expand Down Expand Up @@ -40,7 +41,9 @@ struct BIP32Key {
let digest = Data(HMAC<SHA512>.authenticationCode(for: data, using: SymmetricKey(data: derivedChainCode)))
let factor = BigInt(data: digest[0 ..< 32])

derivedPrivateKey = (BigInt(data: derivedPrivateKey) + factor).modulus(Constants.secpOrder).as256bitLongData()
derivedPrivateKey = (BigInt(data: derivedPrivateKey) + factor)
.modulus(Constants.secpOrder)
.as256bitLongData()
derivedChainCode = digest[32 ..< 64]
}

Expand Down
22 changes: 5 additions & 17 deletions Sources/ImmutableXCore/Crypto/Stark/StarkKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,13 @@ public extension StarkKey {
return try generateKeyPairFromRawSignature(signature, ethereumAddress: address)
}

/// Generate a Stark key pair from a L1 wallet.
/// - Parameter signer: the signer that the key pair will be derived from
/// - Returns: a Stark key pair as ``KeyPair`` if successful or an ``ImmutableXError``
/// error through the `onCompletion` callback
///
/// - Note: `onCompletion` is executed on the Main Thread
static func generateKeyPair(from signer: Signer, onCompletion: @escaping (Result<KeyPair, ImmutableXError>) -> Void) {
Task { @MainActor in
do {
let pair = try await generateKeyPair(from: signer)
onCompletion(.success(pair))
} catch {
onCompletion(.failure(error.asImmutableXError))
}
}
}

/// Generate a Stark key pair from a L1 wallet.
/// - Parameter signature: the 's' variable of the signature
/// - Parameter ethereumAddress: the connected wallet address
/// - Returns: Stark key pair as ``KeyPair``
/// - Throws: ``ImmutableXError``
static func generateKeyPairFromRawSignature(_ signature: String, ethereumAddress: String) throws -> KeyPair {
// swiftlint:disable:next line_length
// https://github.com/ethers-io/ethers.js/blob/3de1b815014b10d223a42e524fe9c25f9087293b/packages/bytes/src.ts/index.ts#L347
let seed = signature.dropHexPrefix[64 ..< 128]
return try generateStarkKeyPairFromSeed(seed, path: accountPathFromAddress(ethereumAddress))
Expand Down Expand Up @@ -126,8 +110,10 @@ public extension StarkKey {
return starkSignature.serialized()
}

// swiftlint:disable line_length
// Base implementation from https://github.com/Sajjon/EllipticCurveKit/blob/main/Sources/EllipticCurveKit/EllipticCurve/Signing/CommonSigning/ECDSA.swift#L32
// and https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java#L93
// swiftlint:enable line_length
internal static func sign(_ message: Message, using privateKey: PrivateKey) throws -> StarkSignature {
let messageNumber = message.asBigInt
var z = CryptoUtil.truncateToN(message: messageNumber)
Expand All @@ -154,9 +140,11 @@ public extension StarkKey {
return try StarkSignature(r: r, s: s)
}

// swiftlint:disable line_length
// https://datatracker.ietf.org/doc/html/rfc6979#section-3.2
// Base implementation from https://github.com/Sajjon/EllipticCurveKit/blob/main/Sources/EllipticCurveKit/EllipticCurve/Signing/SignatureNonce%2BRFC-6979.swift#L29
// and https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/crypto/signers/HMacDSAKCalculator.java#L104
// swiftlint:enable line_length
internal static func generateK(from privateKey: PrivateKey, for message: Message) throws -> BigInt {
let byteCount = message.hashedData.count
let d = privateKey.number.as256bitLongData()
Expand Down
22 changes: 17 additions & 5 deletions Sources/ImmutableXCore/Custom APIs/MoonpayAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ struct GetBuyCryptoURLRequest: Codable {
let walletAddress: String
let currencies: [String: String]

init(apiKey: String = ImmutableX.shared.base.moonpayApiKey, colorCodeHex: String, externalTransaction: Int, walletAddress: String, currencies: [String: String]) {
init(
apiKey: String = ImmutableX.shared.base.moonpayApiKey,
colorCodeHex: String,
externalTransaction: Int,
walletAddress: String,
currencies: [String: String]
) {
self.apiKey = apiKey
self.colorCodeHex = colorCodeHex
self.externalTransaction = externalTransaction
Expand All @@ -17,11 +23,14 @@ struct GetBuyCryptoURLRequest: Codable {

func asURLEncodedString() throws -> String {
let currenciesJson = try JSONSerialization.data(withJSONObject: currencies, options: .fragmentsAllowed)
let jsonString = try String(data: currenciesJson, encoding: .utf8).orThrow(.invalidRequest(reason: "Invalid Buy Crypto Arguments"))
let jsonString = try String(data: currenciesJson, encoding: .utf8)
.orThrow(.invalidRequest(reason: "Invalid Buy Crypto Arguments"))

// Moonpay won't allow colon or comma as query parameter
let jsonEncoded = try jsonString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed.subtracting(CharacterSet(charactersIn: ":,")))
.orThrow(.invalidRequest(reason: "Invalid Buy Crypto Arguments"))
let jsonEncoded = try jsonString.addingPercentEncoding(
withAllowedCharacters: .urlQueryAllowed.subtracting(CharacterSet(charactersIn: ":,"))
)
.orThrow(.invalidRequest(reason: "Invalid Buy Crypto Arguments"))

// URLComponents applies encoding in a way that won't work with Moonpay
return "apiKey=\(apiKey)" +
Expand All @@ -46,7 +55,10 @@ class MoonpayAPI {
let requestBuilderFactory: RequestBuilderFactory
let core: ImmutableX

init(requestBuilderFactory: RequestBuilderFactory = OpenAPIClientAPI.requestBuilderFactory, core: ImmutableX = ImmutableX.shared) {
init(
requestBuilderFactory: RequestBuilderFactory = OpenAPIClientAPI.requestBuilderFactory,
core: ImmutableX = ImmutableX.shared
) {
self.requestBuilderFactory = requestBuilderFactory
self.core = core
}
Expand Down
4 changes: 3 additions & 1 deletion Sources/ImmutableXCore/Extensions/Double+Extensions.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import Foundation

extension Double {
/// 64-bit floating-point number (double), printed in the style of %e if the exponent is less than –4 or greater than or equal to the precision, in the style of %f otherwise.
/// 64-bit floating-point number (double), printed in the style of %e if the exponent is less than –4 or greater
/// than or equal to the precision, in the style of %f otherwise.
var asString: String {
// swiftlint:disable:next line_length
// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html
String(format: "%g", self)
}
Expand Down
14 changes: 8 additions & 6 deletions Sources/ImmutableXCore/Extensions/String+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ extension String {
/// Pads the string to the specified length at the beginning with the specified character or space.
/// - Parameters:
/// - length: the desired string length.
/// - padding: the character to pad string with, if it has length less than the length specified. "0" is used by default.
/// - Returns: Returns a string of length at least ``length`` consisting of this string prepended with ``padding`` as
/// many times as are necessary to reach that length.
/// - padding: the character to pad string with, if it has length less than the length specified. "0" is used by
/// default.
/// - Returns: Returns a string of length at least ``length`` consisting of this string prepended with ``padding``
/// as many times as are necessary to reach that length.
func padLeft(length: Int, padding: String = "0") -> String {
padString(length: length, left: true, padding: padding)
}
Expand All @@ -45,9 +46,10 @@ extension String {
/// - Parameters:
/// - length: the desired string length.
/// - left: defines whether the padding should be applied to the left of the string
/// - padding: the character to pad string with, if it has length less than the length specified. "0" is used by default.
/// - Returns: Returns a string of length at least ``length`` consisting of this string prepended (when ``left`` is true,
/// otherwise appended) with ``padding`` as many times as are necessary to reach that length.
/// - padding: the character to pad string with, if it has length less than the length specified. "0" is used by
/// default.
/// - Returns: Returns a string of length at least ``length`` consisting of this string prepended (when ``left`` is
/// true, otherwise appended) with ``padding`` as many times as are necessary to reach that length.
func padString(length: Int, left: Bool, padding: String = "0") -> String {
let diff = length - count
var result = self
Expand Down
61 changes: 51 additions & 10 deletions Sources/ImmutableXCore/ImmutableX.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import Foundation

// swiftlint:disable function_parameter_count
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 @@ -36,8 +35,18 @@ public struct ImmutableX {
private let registerWorkflow: RegisterWorkflow.Type
private let buyCryptoWorkflow: BuyCryptoWorkflow.Type

/// Internal init method that includes dependencies. For the public facing API use ``initialize(base:logLevel:)`` instead.
internal init(base: ImmutableXBase = .sandbox, logLevel: ImmutableXHTTPLoggingLevel = .none, buyWorkflow: BuyWorkflow.Type = BuyWorkflow.self, sellWorkflow: SellWorkflow.Type = SellWorkflow.self, cancelOrderWorkflow: CancelOrderWorkflow.Type = CancelOrderWorkflow.self, transferWorkflow: TransferWorkflow.Type = TransferWorkflow.self, registerWorkflow: RegisterWorkflow.Type = RegisterWorkflow.self, buyCryptoWorkflow: BuyCryptoWorkflow.Type = BuyCryptoWorkflow.self) {
/// Internal init method that includes dependencies. For the public facing API use ``initialize(base:logLevel:)``
/// instead.
internal init(
base: ImmutableXBase = .sandbox,
logLevel: ImmutableXHTTPLoggingLevel = .none,
buyWorkflow: BuyWorkflow.Type = BuyWorkflow.self,
sellWorkflow: SellWorkflow.Type = SellWorkflow.self,
cancelOrderWorkflow: CancelOrderWorkflow.Type = CancelOrderWorkflow.self,
transferWorkflow: TransferWorkflow.Type = TransferWorkflow.self,
registerWorkflow: RegisterWorkflow.Type = RegisterWorkflow.self,
buyCryptoWorkflow: BuyCryptoWorkflow.Type = BuyCryptoWorkflow.self
) {
self.base = base
self.logLevel = logLevel
self.buyWorkflow = buyWorkflow
Expand All @@ -48,7 +57,8 @@ public struct ImmutableX {
self.buyCryptoWorkflow = buyCryptoWorkflow
}

/// Initializes the SDK with the given ``base`` and ``logLevel`` by assigning a shared instance accessible via `ImmutableX.shared`.
/// Initializes the SDK with the given ``base`` and ``logLevel`` by assigning a shared instance accessible via
/// `ImmutableX.shared`.
public static func initialize(base: ImmutableXBase = .sandbox, logLevel: ImmutableXHTTPLoggingLevel = .none) {
ImmutableX.shared = ImmutableX(base: base, logLevel: logLevel)
}
Expand All @@ -62,7 +72,12 @@ public struct ImmutableX {
/// - starkSigner: represents the users L2 wallet used to sign and verify the L2 transaction
/// - Returns: a ``CreateTradeResponse`` that will provide the Trade id if successful.
/// - Throws: A variation of ``ImmutableXError``
public func buy(orderId: String, fees: [FeeEntry] = [], signer: Signer, starkSigner: StarkSigner) async throws -> CreateTradeResponse {
public func buy(
orderId: String,
fees: [FeeEntry] = [],
signer: Signer,
starkSigner: StarkSigner
) async throws -> CreateTradeResponse {
try await buyWorkflow.buy(orderId: orderId, fees: fees, signer: signer, starkSigner: starkSigner)
}

Expand All @@ -76,8 +91,20 @@ public struct ImmutableX {
/// - starkSigner: represents the users L2 wallet used to sign and verify the L2 transaction
/// - Returns: ``CreateOrderResponse`` that will provide the Order id if successful.
/// - Throws: A variation of ``ImmutableXError``
public func sell(asset: AssetModel, sellToken: AssetModel, fees: [FeeEntry], signer: Signer, starkSigner: StarkSigner) async throws -> CreateOrderResponse {
try await sellWorkflow.sell(asset: asset, sellToken: sellToken, fees: fees, signer: signer, starkSigner: starkSigner)
public func sell(
asset: AssetModel,
sellToken: AssetModel,
fees: [FeeEntry],
signer: Signer,
starkSigner: StarkSigner
) async throws -> CreateOrderResponse {
try await sellWorkflow.sell(
asset: asset,
sellToken: sellToken,
fees: fees,
signer: signer,
starkSigner: starkSigner
)
}

/// This is a utility function that will chain the necessary calls to cancel an existing order.
Expand All @@ -88,7 +115,11 @@ public struct ImmutableX {
/// - starkSigner: represents the users L2 wallet used to sign and verify the L2 transaction
/// - Returns: ``CancelOrderResponse`` that will provide the cancelled Order id if successful.
/// - Throws: A variation of ``ImmutableXError``
public func cancelOrder(orderId: String, signer: Signer, starkSigner: StarkSigner) async throws -> CancelOrderResponse {
public func cancelOrder(
orderId: String,
signer: Signer,
starkSigner: StarkSigner
) async throws -> CancelOrderResponse {
try await cancelOrderWorkflow.cancel(orderId: orderId, signer: signer, starkSigner: starkSigner)
}

Expand All @@ -101,8 +132,18 @@ public struct ImmutableX {
/// - starkSigner: represents the users L2 wallet used to sign and verify the L2 transaction
/// - Returns: ``CreateTransferResponse`` that will provide the transfer id if successful.
/// - Throws: A variation of ``ImmutableXError``
public func transfer(token: AssetModel, recipientAddress: String, signer: Signer, starkSigner: StarkSigner) async throws -> CreateTransferResponse {
try await transferWorkflow.transfer(token: token, recipientAddress: recipientAddress, signer: signer, starkSigner: starkSigner)
public func transfer(
token: AssetModel,
recipientAddress: String,
signer: Signer,
starkSigner: StarkSigner
) async throws -> CreateTransferResponse {
try await transferWorkflow.transfer(
token: token,
recipientAddress: recipientAddress,
signer: signer,
starkSigner: starkSigner
)
}

/// This is a utility function that will register a user to ImmutableX if they aren't already
Expand Down
3 changes: 2 additions & 1 deletion Sources/ImmutableXCore/Model/AssetModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ public protocol AssetModel {
/// The amount of the asset to be transferred/sold/bought
var quantity: String { get }

/// This converts this convenience model into the ``SignableToken`` API model which will be used for the client calls.
/// This converts this convenience model into the ``SignableToken`` API model which will be used for the client
/// calls.
func asSignableToken() -> SignableToken
}

Expand Down
3 changes: 2 additions & 1 deletion Sources/ImmutableXCore/Model/ERC20Asset.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ public struct ERC20Asset: AssetModel {
public let tokenAddress: String

/// The quantization factor of the ERC20 token.
/// Refer [here](https://docs.starkware.co/starkex-v4/starkex-deep-dive/starkex-specific-concepts#quantization) for more information.
/// Refer [here](https://docs.starkware.co/starkex-v4/starkex-deep-dive/starkex-specific-concepts#quantization) for
/// more information.
public let decimals: Int

public init(quantity: String, tokenAddress: String, decimals: Int) {
Expand Down
6 changes: 4 additions & 2 deletions Sources/ImmutableXCore/Signer.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation

/// This represents an L1 Ethereum wallet. Any wallet provider can be wrapped with this interface and be used with this SDK.
/// This represents an L1 Ethereum wallet. Any wallet provider can be wrapped with this interface and be used with this
/// SDK.
public protocol Signer {
/// This is an async method so that a ``Signer`` can be designed around an asynchronous source,
/// such as hardware wallets.
Expand All @@ -18,7 +19,8 @@ public protocol Signer {
func signMessage(_ message: String) async throws -> String
}

/// This represents the ImmutableX Wallet on Layer 2 and will have reference to the user's Stark key pair for signing L2 transactions.
/// This represents the ImmutableX Wallet on Layer 2 and will have reference to the user's Stark key pair for signing L2
/// transactions.
public protocol StarkSigner {
/// This is an async method so that a ``Signer`` can be designed around an asynchronous source,
/// such as hardware wallets.
Expand Down
14 changes: 12 additions & 2 deletions Sources/ImmutableXCore/Workflows/BuyCryptoWorkflow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ class BuyCryptoWorkflow {
/// - base: the config to be used for API keys and providers URLs
/// - Returns: a website URL string to be used to launch a WebView or Browser to buy crypto
/// - Throws: A variation of ``ImmutableXError``
class func buyCryptoURL(colorCodeHex: String, signer: Signer, base: ImmutableXBase = ImmutableX.shared.base, moonpayAPI: MoonpayAPI = MoonpayAPI(), exchangesAPI: ExchangesAPI = ExchangesAPI(), usersAPI: UsersAPI.Type = UsersAPI.self) async throws -> String {
class func buyCryptoURL(
colorCodeHex: String,
signer: Signer,
base: ImmutableXBase = ImmutableX.shared.base,
moonpayAPI: MoonpayAPI = MoonpayAPI(),
exchangesAPI: ExchangesAPI = ExchangesAPI(),
usersAPI: UsersAPI.Type = UsersAPI.self
) async throws -> String {
let address = try await signer.getAddress()
let isRegistered = try await RegisterWorkflow.isUserRegistered(address: address, api: usersAPI)

Expand Down Expand Up @@ -41,7 +48,10 @@ class BuyCryptoWorkflow {
}
}

private static func getSupportedCurrencies(address: String, api: ExchangesAPI) async throws -> GetCurrenciesResponse {
private static func getSupportedCurrencies(
address: String,
api: ExchangesAPI
) async throws -> GetCurrenciesResponse {
try await Workflow.mapAPIErrors(caller: "Fetch supported currencies") {
try await api.getCurrencies(address: address)
}
Expand Down
Loading

0 comments on commit e2c513a

Please sign in to comment.