In order to integrate with Portal into your Flutter App currently you will need to write custom platform-specific code using platform channels.
On the client side, MethodChannel enables sending messages that correspond to method calls. On the platform side, MethodChannel on Android (MethodChannelAndroid) and FlutterMethodChannel on iOS (MethodChanneliOS) enable receiving method calls and sending back a result. These classes allow you to develop a platform plugin with very little 'boilerplate' code.
You can check the Flutter official documentation for platform channels.
Add Portal implementation for iOS:
Open the iOS host portion of your Flutter app in Xcode.
Open AppDelegate.swift located under Runner > Runner in the project navigation.
Override the application:didFinishLaunchingWithOptions: function and create a FlutterMethodChannel
The client and host sides of a channel are connected through a channel name passed in the channel constructor. All channel names used in a single app must be unique; prefix the channel name with a unique 'identifier', for example: your.bundle.identifier/portal.
Then define a callback to handle any method invocation that comes from the Flutter side and they Switch on those Methods then execute the proper Swift implementation for each one and reply back to Flutter using a regular callback of type FlutterResult which expected to be passed from Flutter side as a completion handler.
classPortalWrapper {staticvar portal: Portal?staticfuncinitializePortal(apiKey: String, result: @escaping FlutterResult) {// Initialize portal here using the portal iOS SDKTask {do { portal =tryPortal( apiKey, withRpcConfig: ["solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp":"https://api.mainnet-beta.solana.com","solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1":"https://api.devnet.solana.com" ])result(["success":true,"message":"Portal initialized" ]) } catch {result(FlutterError(code:"FAILED", message:"Error registering portal with exception: \(error.localizedDescription)", details:nil)) } } }staticfunccreateWallet(result: @escaping FlutterResult) {// Create wallet here using the portal iOS SDKguardlet portal = portal else {result(FlutterError(code:"UNAVAILABLE", message:"Portal is not initialized", details:nil))return }Task {do {let(ethereum, solana)=tryawait portal.createWallet()result(["success":true,"addresses": ["ethereum": ethereum,"solana": solana ] ]) } catch {result(FlutterError(code:"FAILED", message:"Error creating portal wallet", details:nil)) } } }}
Calling platform-specific code using platform channels
Now Portal iOS implementation is ready for Flutter, Let's create the Flutter platform client:
We will use the same channel name we defined above to initialize MethodChannel
Next, invoke a method on the method channel, specifying the concrete method to call using the String identifier initializePortal. The call might fail, so wrap the invokeMethod call in a try-catch statement.
Future<void> _initializePortal(String apiKey) async {String message;try {finalMap<String, dynamic> params = {'apiKey': apiKey, };final result =await platform.invokeMethod<Map>('initializePortal', params); message ='Success with message ${result['message']}'; } onPlatformExceptioncatch (e) { message ="Failed to initialize portal with error: '${e.message}'."; }}
Finally, your Flutter function _initializePortal to initialize portal is ready to be called. You can call it from Flutter side passing the apiKey to initialize Portal.