Handovers
Handovers¶
Handovers are communication services between the InvestSuite SDK (Flutter) and the host application. They use gRPC-based services defined in Protocol Buffer (protobuf) format and are auto-generated for each platform (Android, iOS, React Native, Web).
There are two types of handover services:
- HandoversToHostService - Calls from Flutter to the host app. Your app must implement this service to respond to SDK requests.
- HandoversToFlutterService - Calls from the host app to Flutter. Use these to control the SDK from your app.
HandoversToHostService (Flutter → Host App)¶
Your app must implement these methods to handle callbacks from the SDK. All methods use request/response patterns.
Authentication Methods¶
| Method | Request | Response | Description |
|---|---|---|---|
provideAccessToken |
ProvideAccessTokenRequest |
ProvideAccessTokenResponse { accessToken } |
SDK requests the current access token. Return the user's valid JWT token. |
provideAnonymousAccessToken |
ProvideAnonymousAccessTokenRequest |
ProvideAnonymousAccessTokenResponse { anonymousAccessToken } |
SDK requests an anonymous token for unauthenticated operations. |
Navigation Methods¶
| Method | Request | Response | Description |
|---|---|---|---|
onExit |
OnExitRequest |
OnExitResponse |
User wants to close the SDK. Dismiss the Flutter view/activity. |
startFaq |
StartFaqRequest { module } |
StartFaqResponse |
Navigate to your FAQ screen. |
startOnboarding |
StartOnboardingRequest |
StartOnboardingResponse { success } |
Start your onboarding flow. Return success when complete. |
startFundPortfolio |
StartFundPortfolioRequest { portfolioData } |
StartFundPortfolioResponse { success } |
Start the funding flow for a portfolio. |
startAddMoney |
StartAddMoneyRequest { portfolioData } |
StartAddMoneyResponse { success } |
Start the add money flow. |
Security Methods¶
| Method | Request | Response | Description |
|---|---|---|---|
startAuthorization |
StartAuthorizationRequest |
StartAuthorizationResponse { success } |
Perform authorization (biometric, PIN, etc.) for sensitive operations. |
startTransactionSigning |
StartTransactionSigningRequest { portfolioId, amount, ... } |
StartTransactionSigningResponse { success } |
Sign a transaction with enhanced security. |
Logging & Analytics Methods¶
| Method | Request | Response | Description |
|---|---|---|---|
receiveAnalyticsEvent |
ReceiveAnalyticsEventRequest { name, parameters, eventLocation } |
ReceiveAnalyticsEventResponse |
Forward analytics events to your analytics service. See Analytics Events for all available events. |
receiveDebugLog |
ReceiveDebugLogRequest { level, message } |
ReceiveDebugLogResponse |
Receive debug logs from the SDK. |
receiveError |
ReceiveErrorRequest { errorCode, data } |
ReceiveErrorResponse |
Handle error events from the SDK. |
Analytics Events
The SDK sends ~50 different analytics events covering user journeys like portfolio creation, investment planning, and instrument discovery. The eventLocation parameter contains the deeplink path of the current screen, making it easy to track where events occur. See Analytics Events for the complete list.
HandoversToFlutterService (Host App → Flutter)¶
Use these methods to communicate with and control the SDK from your host application.
Configuration Methods¶
| Method | Request | Response | Description |
|---|---|---|---|
changeLanguage |
ChangeLanguageRequest { language } |
ChangeLanguageResponse |
Change the SDK language. |
changeThemeMode |
ChangeThemeModeRequest { themeMode } |
ChangeThemeModeResponse |
Change the SDK theme (light/dark/system). |
Navigation Methods¶
| Method | Request | Response | Description |
|---|---|---|---|
reset |
ResetRequest { clearData } |
ResetResponse |
Reset SDK to home screen. Set clearData=true to also clear cached data. |
navigateTo |
NavigateToRequest { deeplink } |
NavigateToResponse |
Navigate to a specific screen using a deeplink path. |
Notification Methods¶
| Method | Request | Response | Description |
|---|---|---|---|
handleNotification |
HandleNotificationRequest { notificationData } |
HandleNotificationResponse |
Pass a notification to the SDK for handling. |
Data Types¶
Language Enum¶
enum Language {
LANGUAGE_UNSPECIFIED = 0;
LANGUAGE_EN = 1; // English
LANGUAGE_NL = 2; // Dutch
LANGUAGE_FR = 3; // French
LANGUAGE_AR = 4; // Arabic
LANGUAGE_TR = 5; // Turkish
}
ThemeMode Enum¶
enum ThemeMode {
THEME_MODE_UNSPECIFIED = 0;
THEME_MODE_LIGHT = 1;
THEME_MODE_DARK = 2;
THEME_MODE_SYSTEM = 3;
}
StartParams Message¶
message StartParams {
string environment = 1; // "MOCK", "TST", "UAT", "PROD"
Language language = 2;
ThemeMode themeMode = 3;
}
InvestSuiteNotificationData Message¶
message InvestSuiteNotificationData {
string id = 1;
string title = 2;
string body = 3;
string type = 4;
string module = 5;
int64 createdAt = 6;
map<string, string> data = 7;
}
PortfolioData Message¶
message PortfolioData {
string portfolioId = 1;
string portfolioName = 2;
string portfolioType = 3;
string module = 4;
}
AnalyticsEvent Message¶
message ReceiveAnalyticsEventRequest {
string name = 1;
map<string, string> parameters = 2;
string eventLocation = 3;
}
Platform-Specific Implementations¶
Android (Kotlin)¶
// Implementing HandoversToHostService
class MyHandoversToHostService : HandoversToHostServiceGrpc.HandoversToHostServiceImplBase() {
override fun provideAccessToken(
request: ProvideAccessTokenRequest?,
responseObserver: StreamObserver<ProvideAccessTokenResponse?>?
) {
val response = ProvideAccessTokenResponse.newBuilder()
.setAccessToken(getCurrentAccessToken())
.build()
responseObserver?.onNext(response)
responseObserver?.onCompleted()
}
// ... implement other methods
}
// Calling HandoversToFlutterService
val request = ChangeLanguageRequest.newBuilder()
.setLanguage(Language.LANGUAGE_FR)
.build()
InvestSuiteEmbedding.instance().handoversToFlutterService().changeLanguage(request)
iOS (Swift)¶
// Implementing HandoversToHostService
@available(iOS 18.0, *)
class MyHandoversToHostService: HandoversToHostService.SimpleServiceProtocol {
func provideAccessToken(
request: ProvideAccessTokenRequest,
context: ServerContext
) async throws -> ProvideAccessTokenResponse {
var response = ProvideAccessTokenResponse()
response.accessToken = getCurrentAccessToken()
return response
}
// ... implement other methods
}
// Calling HandoversToFlutterService
Task {
var request = ChangeLanguageRequest()
request.language = .fr
let clientRequest = ClientRequest<ChangeLanguageRequest>(message: request)
try await InvestSuiteEmbedding.shared.handoversToFlutterService().changeLanguage(request: clientRequest)
}
React Native (TypeScript)¶
// Implementing HandoversToHostService
const handoversToHostService: IHandoversToHostService = {
provideAccessToken(request, context): Promise<ProvideAccessTokenResponse> {
return Promise.resolve(
ProvideAccessTokenResponse.create({ accessToken: getCurrentAccessToken() })
);
},
// ... implement other methods
};
// Calling HandoversToFlutterService
const request = ChangeLanguageRequest.create({ language: Language.FR });
await handoversToFlutterServiceClient.changeLanguage(request);
Web React (TypeScript)¶
// Implementing HandoversToHostService
const handoversToHostService: IHandoversToHostService = {
provideAccessToken(request, context): Promise<ProvideAccessTokenResponse> {
return Promise.resolve(
ProvideAccessTokenResponse.create({ accessToken: getCurrentAccessToken() })
);
},
// ... implement other methods
};
// Calling HandoversToFlutterService
const request = ChangeLanguageRequest.create({ language: Language.FR });
await handoversToFlutterServiceClient.changeLanguage(request);
Web Angular (TypeScript)¶
// Implementing HandoversToHostService
const handoversToHostService: IHandoversToHostService = {
provideAccessToken(request, context): Promise<ProvideAccessTokenResponse> {
return Promise.resolve(
ProvideAccessTokenResponse.create({ accessToken: this.getCurrentAccessToken() })
);
},
// ... implement other methods
};
// Calling HandoversToFlutterService
const request = ChangeLanguageRequest.create({ language: Language.FR });
await this.handoversToFlutterServiceClient.changeLanguage(request);
Error Handling¶
All handover methods should handle errors gracefully. The SDK will wait for responses and may retry or show error states if responses fail.
Best Practices¶
- Always respond - Even if you can't fulfill a request, return a response (e.g.,
success: false). - Handle async operations - Use proper async patterns (callbacks, promises, async/await) as appropriate for your platform.
- Log errors - Implement
receiveErrorto capture and log SDK errors for debugging. - Thread safety - UI operations (like dismissing views) must happen on the main/UI thread.