-
Notifications
You must be signed in to change notification settings - Fork 25
Custom Integration
Custom integration refers to using the TradeItSDK.linkedBrokerManager
object as a programmatic workflow upon which you can build your own workflow and screens or use the user's raw balance/positions data in your app. The linkedBrokerManager
can be used to link/relink/unlink a user's broker logins. It holds the list of linked brokers in TradeItSDK.linkedBrokerManager.linkedBrokers
. Each of these TradeItLinkedBroker
objects can be used to authenticate an active session with the broker. Once this has been done, the list of trading accounts associated with the linked broker are stored in linkedBroker.accounts
. Each of these TradeItLinkedBrokerAccount
objects can be used to trade and retrieve balances and positions. See below for further details and explicit code examples.
Any methods which have an error/failure callback will return a TradeItErrorResult
object that has an error code errorCode
enum property. These codes, and how to handle them, are detailed here: https://www.trade.it/documentation/api#ErrorHandling
Brokers are linked using an OAuth flow to ensure security and privacy. Linked brokers are persisted by the SDK between app launches so should only need to be linked once unless the OAuth token expires or becomes invalidated or the user reinstalls the app. To use a linked broker for TradeIt functionality the linked broker must be authenticated to obtain a valid session.
The list of brokers available for use in your app is determined by your API key, and can also change due to intermittent service interruptions so it is important to retrieve a fresh list of available brokers when presenting the choice to users.
TradeItSDK.linkedBrokerManager.getAvailableBrokers(
onSuccess: { availableBrokers in
if let firstBroker = availableBrokers.first {
firstBroker.brokerShortName // Use this string to indicate choice of broker to the SDK/API when linking or requesting the OAuth URL
firstBroker.brokerLongName // Use this string to display in the UI
}
}
After initializing TradeItSDK
, use the linkedBrokerManager
instance to get the URL for the OAuth login popup. The oAuthCallbackUrl
should be a deep link back into your app and will be used to pass the OAuthVerifier token back into the app. On success, launch the resulting URL in the system browser or a UIWebView
/SFSafariViewController
and the user will be presented with an OAuth login page.
TradeItSDK.linkedBrokerManager.getOAuthLoginPopupUrl(
withBroker: "dummy",
oAuthCallbackUrl: "yourAppScheme://completeOAuth",
onSuccess: { url in
// Do this OR load URL in a UIWebView/SFSafariViewController
UIApplication.shared.openURL(NSURL(string:url) as! URL)
}, onFailure: { errorResult in
AlertManager().showError(errorResult,
onViewController: self)
}
)
If the user needs to relink an already linked broker in order to update the OAuth token (the OAuth token has expired or become invalidated) then use this method instead of the above:
TradeItSDK.linkedBrokerManager.getOAuthLoginPopupForTokenUpdateUrl(
forLinkedBroker: linkedBroker, // The linked broker that needs to be relinked
onSuccess: { url in
// Do this OR load URL in a UIWebView/SFSafariViewController
UIApplication.shared.openURL(NSURL(string:url) as! URL)
}, onFailure: { errorResult in
AlertManager().showError(
errorResult,
onViewController: self
)
}
)
A successful OAuth login results in the browser redirecting to the provided callback with an appended query string including the oAuthVerifier
. Example:
tradeItExampleApp://completeOAuth?oAuthVerifier=123-456-789-000
This should be set up to deep link back into your app. If you already have deep linking in your app, make sure to use a unique host/path for the Trade.it OAuth flow. Deep linking is handled in AppDelegate
. Intercept the deep link and extract the OAuth verifier token from the deep link URL and pass it in to the SDK to complete linking:
TradeItSDK.linkedBrokerManager.completeOAuth(
withOAuthVerifier: oAuthVerifier,
onSuccess: { linkedBroker in
print("=====> OAuth successful for \(linkedBroker.brokerName)!")
},
onFailure: { errorResult in
print("=====> ERROR: OAuth failed! \(errorResult.errorCode): \(errorResult.shortMessage): \(errorResult.longMessages?.first)")
}
)
Authenticating a linked broker creates a temporary session (~30 minutes) with the broker that allows for all other actions to be taken, such as trading and retrieving portfolio information.
linkedBroker.authenticateIfNeeded(
onSuccess: {},
onSecurityQuestion: { securityQuestion, answerSecurityQuestion, cancelQuestion in
// Manually prompt the user for an answer and then submit it to finish authenticating
answerSecurityQuestion("answer")
// OR use the provided alert manager
self.alertManager.promptUserToAnswerSecurityQuestion(
securityQuestion,
onViewController: self,
onAnswerSecurityQuestion: answerSecurityQuestion,
onCancelSecurityQuestion: cancelQuestion)
}, onFailure: { (errorResult) in
// handle error
})
This can be used when the app starts up and none of the linked brokers have a valid session yet. NOTE: This method does not have a callback for authentication errors. If a linked broker could not be authenticated, the linkedBroker.error
property will be set.
TradeItSDK.linkedBrokerManager.authenticateAll(onSecurityQuestion: { securityQuestion, answerSecurityQuestion in
// Manually prompt the user for an answer and then submit it to finish authenticating
answerSecurityQuestion(/* answer from user */)
// OR use the provided alert manager
self.alertManager.promptUserToAnswerSecurityQuestion(
securityQuestion,
onViewController: self,
onAnswerSecurityQuestion: answerSecurityQuestion,
onCancelSecurityQuestion: cancelQuestion)
}, onFinished: {
// Brokers that did not successfully authenticate will have the TradeItErrorResult error property set: linkedBroker.error?
print("\(TradeItSDK.linkedBrokerManager.linkedBrokers.map { $0.error == nil }.count) brokers authenticated.")
})
// Account balances - given an authenticated broker account
linkedBrokerAccount.getAccountOverview(onSuccess: {
print(linkedBrokerAccount.balance)
}, onFailure: { errorResult in
print(errorResult)
})
// Account positions - given an authenticated broker account
linkedBrokerAccount.getPositions(onSuccess: { positions in
print(positions.map({ position in
return position.position
}))
}, onFailure: { errorResult in
print(errorResult)
})
// Trading - given an authenticated broker account
let order = TradeItOrder()
order.linkedBrokerAccount = linkedBrokerAccount
order.symbol = "CMG"
order.action = .buy
order.type = .limit
order.expiration = .goodUntilCanceled
quantity = 100.0
limitPrice = 395.65
order.preview(onSuccess: { previewOrder, placeOrderCallback in
// Display previewOrder contents to user for review
// When the user confirms, call the placeOrderCallback to place the trade
placeOrderCallback({ result in
// Display result contents to the user
}, { errorResult in
// Display errorResult contents to user
})
}, onFailure: { errorResult in
// Display errorResult contents to user
})
The SDK automatically persists linked brokers locally on the device between usages of your app. However, it is also possible to manually initialize linked brokers and the associated accounts if you have persisted the data elsewhere remotely. This can be used to sync a user's linked accounts between instances of the app on other devices/platforms without the user having to relink.
First, capture and persist the necessary data when a new broker is linked:
class MyViewController: UIViewController, TradeItOAuthDelegate {
override func viewDidLoad() {
TradeItSDK.linkedBrokerManager.oAuthDelegate = self
}
func didLink(linkedBroker: TradeItLinkedBroker, userId: String, userToken: String) {
linkedBroker.authenticate(
onSuccess: {
// Remotely persist the following data:
// userId
// userToken
// linkedBroker.brokerName
// linkedBroker.brokerLongName
// linkedBroker.accounts.map { return ($0.accountName, $0.accountNumber, $0.baseCurrency, $0.userCanDisableMargin) }
},
onSecurityQuestion: { (securityQuestion, answerSecurityQuestion, cancel) in
// handle security question
},
onFailure: { errorResult in
// handle failure
}
)
}
}
If you want you can also fetch and store account balances and positions after you authenticate.
Then, later when the app is relaunched, you can sync/load from the remotely persisted data. The SDK loads locally persisted linked brokers from the device when it is configured so make sure any manual intervention is done after configuring the SDK via the call to TradeItSDK.configure()
.
Sync linked brokers/accounts from remotely persisted data:
let remoteBrokersToSync = [
LinkedBrokerData(
userId: "userId", // persisted data
userToken: "userToken", // persisted data
broker: "broker", // persisted data
brokerLongName: "broker long name", // persisted data
accounts: [
LinkedBrokerAccountData(
name: "account name", // persisted data
number: "account number", // persisted data
baseCurrency: "USD", // persisted data
userCanDisableMargin: false // persisted data
)
]
)
]
TradeItSDK.linkedBrokerManager.syncLocal(
withRemoteLinkedBrokers: remoteBrokersToSync,
onFailure: { errorResult in
print("=====> Failed to sync linked brokers manually: \(String(describing: errorResult.shortMessage)) - \(String(describing: errorResult.longMessages?.first))")
},
onFinished: {
print("=====> MANUALLY SYNC LINKED BROKERS!")
TradeItSDK.linkedBrokerManager.linkedBrokers.forEach {
// do something
}
TradeItSDK.linkedBrokerManager.printLinkedBrokers()
}
)