1.x to 2.x Migration Guide

Reference for migrating the Link iOS SDK from 1.x to 2.x

Summary of changes

Plaid released version 2.0.0 of the SDK on September 24th, 2020. Upgrading to the new 2.x SDK allows you to take advantage of a unified mobile API and support all new features, such as link-token based Payment Initiation. This guide describes how to upgrade a Plaid iOS integration from the 1.x SDK to the 2.x SDK.

Remove the custom "Prepare for distribution" Build Phase

LinkKit 2.x is now an XCFramework bundle type, which no longer requires the custom Build Phase to strip the iOS Simulator part from the framework.

Remove setup

Remove any of the preflight setup methods listed below that your application may make use of. They are no longer part of the API and need to be removed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Setup using shared configuration,
PLKPlaidLink.setup { (success, error) in /* … */ }
// using shared configuration and item-add token
PLKPlaidLink.setupWithSharedConfiguration(usingItemAddToken:itemAddToken) { (success, error) in /* … */ }
// using custom configuration,
PLKPlaidLink.setup(with: linkConfiguration) { (success, error) in /* … */ }
// using custom configuration and item-add token,
PLKPlaidLink.setupWithConfiguration(with: linkConfiguration, itemAddToken: itemAddToken)
{ (success, error) in /* … */ }
// using public-token and shared configuration
PLKPlaidLink.setup(withPublicToken:publicToken) { (success, error) in /* … */ }
// using public-token and custom configuration
PLKPlaidLink.setup(withPublicToken:publicToken, configuration:linkConfiguration) { (success, error) in /* … */ }
// using public-token, item-add token, and shared configuration
PLKPlaidLink.setup(withPublicToken:publicToken, itemAddToken:itemAddToken) { (success, error) in /* … */ }
// using public-token, item-add token, and custom configuration
PLKPlaidLink.setup(withPublicToken:publicToken, itemAddToken:itemAddToken, configuration:linkConfiguration)
{ (success, error) in /* … */ }
// using public-token, link-token, and shared configuration
PLKPlaidLink.setup(withPublicToken:publicToken, linkToken:linkToken) { (success, error) in /* … */ }
// using public-token, link-token, and custom configuration
PLKPlaidLink.setup(withPublicToken:publicToken, linkToken:linkToken, configuration:linkConfiguration)
{ (success, error) in /* … */ }

Create a configuration

The recommended way to create a configuration for Link is to use LinkTokenConfiguration, which replaces PLKConfiguration. If you still rely on public key based configurations, we recommend you migrate your application to use Link tokens as soon as possible, and use LinkPublicKeyConfiguration until then.

1
2
3
4
5
6
7
8
9
10
11
12
// For recommended Link Token based configuration use:
let linkTokenConfiguration = LinkTokenConfiguration(token: linkToken)
{ success in /* … */ }
// To continue using public key based configuration for the interim use:
let linkPublicKeyConfiguration = LinkPublicKeyConfiguration(
clientName: "Link Demo",
environment: .sandbox,
products: [.transactions, .auth],
language: "en"
token: .publicKey("<#YOUR_PUBLIC_KEY#>"),
countryCodes: ["US"]) { (success) in /* … */ }

Notice that the PLKPlaidLinkViewDelegate has been replaced by the required onSuccess closure on LinkTokenConfiguration and LinkPublicKeyConfiguration and the optional onExit and onEvent closures.

Handler

A Handler is a one-time use object used to open a Link session. Create it as early as possible in your application lifecycle or account linking setup. If delayed until just before opening Link it can have a perceptible impact on Link startup time.

1
2
3
4
5
6
7
switch Plaid.create(linkTokenConfiguration) {
case .failure(let error):
print("Unable to create Plaid Handler due to: \(error)")
case .success(let handler)
// Store the handler for later use and call open on it when Link should start
self.handler = handler
}

Open Link

Since Handler is not a UIViewController and replaces the PLKPlaidLinkViewController, it is not possible to present it directly. Remove any calls to present Link:

1
present(linkViewController, animated: true)

Instead call open on the Handler you created, specifying your preferred method of presentation:

1
2
3
4
5
// Let the handler present Link using one of the application's view controllers.
handler.open(presentUsing: .viewController(self))
// or present Link yourself in a custom manner using a closure.
handler.open(presentUsing: .custom({ (linkViewController) in /* … */ }))

Handling results

The PLKPlaidLinkViewDelegate methods have been replaced with closures passed to either LinkTokenConfiguration or LinkPublicKeyConfiguration. While OnExitHandler and OnEventHandler are optional, the OnSuccessHandler must be provided.

1.x PLKPlaidLinkViewDelegate method2.x Handler
linkViewController:didSucceedWithPublicToken:metadata:OnSuccessHandler
linkViewController:didExitWithError:metadata:OnExitHandler
linkViewController:didHandleEvent:metadata:OnEventHandler

Each 2.x Handler closure receives one specific parameter, containing the two equivalent variables for the parameters that the corresponding PLKPlaidLinkViewDelegate method received.

  • OnSuccessHandler receives LinkSuccess, which contains the publicToken and metadata specific to LinkSuccess
  • OnExitHandler receives LinkExit, which contains an optional error and metadata specific to LinkExit
  • OnEventHandler receives LinkEvent, which contains the eventName and metadata specific to LinkEvent
SuccessMetadata

Link SDK 1.x returned an untyped NSDictionary and provided constants for key names, e.g. kPLKMetadataInstitutionKey. The untyped dictionary has been replaced with the SuccessMetadata type containing success metadata specific properties.

1.x metadata key constant2.x SuccessMetadata property
kPLKMetadataInstitutionKeyinstitution
kPLKMetadataInstitutionIdKeyinstitution.id
kPLKMetadataInstitutionNameKeyinstitution.name
kPLKMetadataAccountsKeyaccounts; see mapping below
kPLKMetadataLinkSessionIdKeylinkSessionID
N/AmetadataJSON
1.x account key constant2.x Account property
kPLKMetadataIdKeyid
kPLKMetadataNameKeyname
kPLKMetadataMaskKeymask
kPLKMetadataTypeKeyN/A; The account type is now encoded within the subtype
kPLKMetadataSubtypeKeysubtype
kPLKMetadataAccountVerificationStatusKeyverificationStatus
ExitMetadata

Link SDK 1.x returned a untyped NSDictionary and provided constants for key names, e.g. kPLKMetadataRequestIdKey The untyped dictionary has been replaced with the ExitMetadata type containing exit metadata specific properties.

1.x key constant2.x ExitMetadata property
kPLKMetadataErrorCodeKeyerror.errorCode; note that error code and error type are combined in a single Swift enum
kPLKMetadataErrorTypeKeysee above
kPLKMetadataErrorMessageKeyerror.errorMessage
N/Aerror.displayMessage
kPLKMetadataStatusKeyexitStatus
kPLKMetadataLinkSessionIdKeylinkSessionID
kPLKMetadataInstitutionIdKeyinstitutionID
kPLKMetadataInstitutionNameKeyinstitutionName
kPLKMetadataInstitutionSearchQueryKeyinstitutionSearchQuery
kPLKMetadataLinkSessionIdKeylinkSessionID
kPLKMetadataMFATypeKeymfaType
kPLKMetadataTimestampKeytimestamp
kPLKMetadataViewNameKeyviewName
N/AmetadataJSON
EventMetadata

Link SDK 1.x returned a untyped NSDictionary and provided constants for key names, e.g. kPLKMetadataRequestIdKey The untyped dictionary has been replaced with the ExitMetadata type containing exit metadata specific properties.

1.x key constant2.x ExitMetadata property
kPLKMetadataInstitutionKeystatus
kPLKMetadataInstitutionIdKeyinstitution.id
kPLKMetadataInstitutionNameKeyinstitution.name
kPLKMetadataLinkSessionIdKeylinkSessionID
kPLKMetadataRequestIdKeyrequestID
N/AmetadataJSON

Every metadata now includes a metadataJSON property which contains unprocessed metadata from the Plaid API.

1
2
3
4
5
let onSuccessHandler: OnSuccessHandler = { (success) in
// Send success.publicToken to your server and exchange it for an access token
// Process any metadata according to your needs, e.g. metadata.institution.name
}
// Pass onSuccessHandler to the onSuccess parameter of the LinkTokenConfiguration or LinkPublicKeyConfiguration initializer
1
2
3
4
5
6
7
8
9
10
11
12
13
let onExitHandler: OnExitHandler = { (exit) in
if let error = exit.error {
// Handle errors according to your app.
switch error.errorCode {
case .rateLimitExceeded(let code):
print("Encountered rate limit \(code)")
default:
print("Unhandled error \(error.errorCode)")
}
}
// Process any metadata depending on your needs, e.g. exit.metadata.institution.name
}
linkConfiguration.onExit = onExitHandler
1
2
3
4
5
6
7
8
9
10
11
12
let onEventHandler: OnEventHandler = { (event) in
// Handle events and metadata according to your app.
let metadata = event.metadata
switch event.eventName {
case .selectInstitution:
// Process any metadata according to your needs, e.g. metadata.institutionName
print("Selected institution \(metadata.institutionName ?? "") (\(metadata.institutionID ?? "")")
default:
print("Ignored event \(event)")
}
}
linkConfiguration.onEvent = onEventHandler