diff --git a/android/build.gradle b/android/build.gradle index f21eb03..dd442e4 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -49,7 +49,7 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4' - implementation 'com.github.Web3Auth:single-factor-auth-android:1.2.0' + implementation 'com.github.Web3Auth:single-factor-auth-android:3.0.1' implementation 'org.torusresearch:fetch-node-details-java:5.0.0' - implementation 'com.google.code.gson:gson:2.9.1' + implementation 'com.google.code.gson:gson:2.10.1' } diff --git a/android/src/main/kotlin/com/web3auth/single_factor_auth_flutter/SingleFactorAuthFlutterPlugin.kt b/android/src/main/kotlin/com/web3auth/single_factor_auth_flutter/SingleFactorAuthFlutterPlugin.kt index b182227..d9f68c7 100644 --- a/android/src/main/kotlin/com/web3auth/single_factor_auth_flutter/SingleFactorAuthFlutterPlugin.kt +++ b/android/src/main/kotlin/com/web3auth/single_factor_auth_flutter/SingleFactorAuthFlutterPlugin.kt @@ -6,9 +6,8 @@ import androidx.annotation.NonNull import com.google.gson.Gson import com.web3auth.singlefactorauth.SingleFactorAuth import com.web3auth.singlefactorauth.types.LoginParams -import com.web3auth.singlefactorauth.types.SFAKey -import com.web3auth.singlefactorauth.types.SFAParams -import com.web3auth.singlefactorauth.types.TorusSubVerifierInfo +import com.web3auth.singlefactorauth.types.SessionData +import com.web3auth.singlefactorauth.types.Web3AuthOptions import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel @@ -27,7 +26,7 @@ class SingleFactorAuthFlutterPlugin : FlutterPlugin, MethodCallHandler { private lateinit var channel: MethodChannel private lateinit var context: Context private lateinit var singleFactorAuth: SingleFactorAuth - private lateinit var sfaParams: SFAParams + private lateinit var web3AuthOptions: Web3AuthOptions private lateinit var loginParams: LoginParams private var gson: Gson = Gson() @@ -76,9 +75,9 @@ class SingleFactorAuthFlutterPlugin : FlutterPlugin, MethodCallHandler { "init" -> { val initArgs = call.arguments() val params = gson.fromJson(initArgs, SFAOptions::class.java) - sfaParams = - SFAParams(getNetwork(params.network), params.clientId, params.sessionTime) - singleFactorAuth = SingleFactorAuth(sfaParams, context) + web3AuthOptions = + Web3AuthOptions(params.clientId, getNetwork(params.network), params.sessionTime) + singleFactorAuth = SingleFactorAuth(web3AuthOptions, context) return null } @@ -86,11 +85,7 @@ class SingleFactorAuthFlutterPlugin : FlutterPlugin, MethodCallHandler { try { val sfaKey = singleFactorAuth.initialize(context) Log.d("${SingleFactorAuthFlutterPlugin::class.qualifiedName}", "#initialize") - return if (sfaKey.get() != null) { - prepareResultFromSFAkey(sfaKey.get()) - } else { - "" - } + return null } catch (e: Throwable) { throw Error(e) } @@ -99,41 +94,53 @@ class SingleFactorAuthFlutterPlugin : FlutterPlugin, MethodCallHandler { "connect" -> { try { val initArgs = call.arguments() - val params = gson.fromJson(initArgs, Web3AuthOptions::class.java) - if (params.aggregateVerifier.isNullOrEmpty()) { - loginParams = LoginParams( - params.verifier, params.verifierId, - params.idToken - ) - } else { - loginParams = LoginParams( - params.aggregateVerifier, params.verifierId, - params.idToken, - arrayOf( - TorusSubVerifierInfo( - params.verifier, - params.idToken - ) - ) - ) - } - val sfaKeyCF = singleFactorAuth.connect(loginParams, context) + val loginParams = gson.fromJson(initArgs, LoginParams::class.java) + val sessionData = singleFactorAuth.connect(loginParams, context) Log.d("${SingleFactorAuthFlutterPlugin::class.qualifiedName}", "#connect") - val sfaKey = sfaKeyCF - return prepareResult(sfaKey) + val result: SessionData = sessionData + return gson.toJson(result) + } catch (e: Throwable) { + throw Error(e) + } + } + + "logout" -> { + try { + val logoutCF = singleFactorAuth.logout(context) + Log.d("${SingleFactorAuthFlutterPlugin::class.qualifiedName}", "#logout") + return null } catch (e: Throwable) { throw Error(e) } } - "isSessionIdExists" -> { + "getSessionData" -> { try { - val result = singleFactorAuth.isSessionIdExists() Log.d( "${SingleFactorAuthFlutterPlugin::class.qualifiedName}", - "#isSessionIdExists" + "#getSessionData" ) - return result + singleFactorAuth.initialize(context).get() + var sessionData = singleFactorAuth.getSessionData() + val loginResult: SessionData? = sessionData + return if (loginResult == null) { + null + } else { + gson.toJson(loginResult) + } + } catch (e: Throwable) { + Log.e( + "${SingleFactorAuthFlutterPlugin::class.qualifiedName}", + "Error retrieving session data", + e + ) + return gson.toJson(mapOf("error" to "Failed to retrieve session data")) + } + } + + "connected" -> { + try { + return singleFactorAuth.isConnected() } catch (e: Throwable) { throw Error(e) } @@ -141,18 +148,4 @@ class SingleFactorAuthFlutterPlugin : FlutterPlugin, MethodCallHandler { } throw NotImplementedError() } - - private fun prepareResult(sfaKey: SFAKey?): String { - val hashMap: HashMap = HashMap(2) - hashMap["privateKey"] = sfaKey?.getPrivateKey() as String - hashMap["publicAddress"] = sfaKey?.getPublicAddress() as String - return gson.toJson(hashMap) - } - - private fun prepareResultFromSFAkey(sfaKey: SFAKey): String { - val hashMap: HashMap = HashMap(2) - hashMap["privateKey"] = sfaKey.getPrivateKey() as String ?: "" - hashMap["publicAddress"] = sfaKey.getPublicAddress() as String ?: "" - return gson.toJson(hashMap) - } } diff --git a/android/src/main/kotlin/com/web3auth/single_factor_auth_flutter/Web3AuthOptions.kt b/android/src/main/kotlin/com/web3auth/single_factor_auth_flutter/Web3AuthOptions.kt deleted file mode 100644 index 06f237b..0000000 --- a/android/src/main/kotlin/com/web3auth/single_factor_auth_flutter/Web3AuthOptions.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.web3auth.single_factor_auth_flutter - -data class Web3AuthOptions( - val verifier: String, - val verifierId: String, - val idToken: String, - val aggregateVerifier: String? = null -) - - diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 9325125..e99dbaf 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,23 +1,23 @@ PODS: - BigInt (5.2.0) - - curvelib.swift (1.0.1) + - curvelib.swift (2.0.0) - Flutter (1.0.0) + - JWTDecode (3.2.0) - KeychainSwift (20.0.0) - single_factor_auth_flutter (0.0.1): - Flutter - - SingleFactorAuth (= 8.0.0) - - SingleFactorAuth (8.0.0): - - curvelib.swift (~> 1.0.1) - - Torus-fetchNodeDetails (~> 6.0.3) - - Torus-utils (~> 9.0.1) - - TorusSessionManager (~> 5.0.0) - - Torus-fetchNodeDetails (6.0.3): + - SingleFactorAuth (= 9.0.4) + - SingleFactorAuth (9.0.4): + - JWTDecode (~> 3.2) + - Torus-utils (~> 10.0.0) + - TorusSessionManager (~> 6.0.2) + - Torus-fetchNodeDetails (8.0.0): - BigInt (~> 5.2.0) - - Torus-utils (9.0.1): - - curvelib.swift (~> 1.0.1) - - Torus-fetchNodeDetails (~> 6.0.3) - - TorusSessionManager (5.0.0): - - curvelib.swift (~> 1.0.1) + - Torus-utils (10.0.0): + - curvelib.swift (~> 2.0.0) + - Torus-fetchNodeDetails (~> 8.0.0) + - TorusSessionManager (6.0.2): + - curvelib.swift (~> 2.0.0) - KeychainSwift (~> 20.0.0) DEPENDENCIES: @@ -28,6 +28,7 @@ SPEC REPOS: trunk: - BigInt - curvelib.swift + - JWTDecode - KeychainSwift - SingleFactorAuth - Torus-fetchNodeDetails @@ -42,14 +43,15 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: BigInt: f668a80089607f521586bbe29513d708491ef2f7 - curvelib.swift: d0746ae82bee34016c06da3567a97e493b3c979f + curvelib.swift: b9223e5cac801effed8a5fe8968e952b3fe427a5 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + JWTDecode: 7dae24cb9bf9b608eae61e5081029ec169bb5527 KeychainSwift: 0ce6a4d13f7228054d1a71bb1b500448fb2ab837 - single_factor_auth_flutter: 9617e5ffce9c0251bddb19cbe49293f921c13b79 - SingleFactorAuth: 2bfa8ad0fe8d0023fffdf1a5f0c9634ca3ee66d8 - Torus-fetchNodeDetails: 6c349f47cbca36a4b3f276fe26d03c1b39b20949 - Torus-utils: 1d23e6eedf9ee7df9ecc2605b765ad68eb194f71 - TorusSessionManager: 42c21f100d895976fabe3806cb9c575392f6e424 + single_factor_auth_flutter: aab0e8cb32b6e76fe5cb8a2036489367bc549338 + SingleFactorAuth: 6a2639e2d25d4cec901753193b97f8503734734d + Torus-fetchNodeDetails: 2a5fbb222ec28af4128d64e4c2d520c7db456b78 + Torus-utils: 4a1db3d9c1aa221df312ffa7ec154e7e4719850a + TorusSessionManager: 3c47c2a4c4d6173a10006eb0af4b86317ee45ff8 PODFILE CHECKSUM: d5c402b2f74646de5c7f24c1231886362b49b38f diff --git a/example/lib/main.dart b/example/lib/main.dart index c45eddf..6bae85f 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -3,6 +3,7 @@ import 'dart:developer'; import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:single_factor_auth_flutter/enums.dart'; import 'package:single_factor_auth_flutter/input.dart'; import 'package:single_factor_auth_flutter/output.dart'; import 'package:single_factor_auth_flutter/single_factor_auth_flutter.dart'; @@ -21,7 +22,7 @@ class MyApp extends StatefulWidget { } class _MyAppState extends State { - final _singleFactorAuthFlutterPlugin = SingleFactAuthFlutter(); + final _singleFactorAuthFlutterPlugin = SingleFactorAuthFlutter(); String _result = ''; bool logoutVisible = false; Web3AuthNetwork web3AuthNetwork = Web3AuthNetwork.sapphire_mainnet; @@ -35,31 +36,27 @@ class _MyAppState extends State { Future initSdk() async { if (Platform.isAndroid) { await init(); - if (await _singleFactorAuthFlutterPlugin.isSessionIdExists()) { - initialize(); - } + getSessionData(); } else if (Platform.isIOS) { await init(); - if (await _singleFactorAuthFlutterPlugin.isSessionIdExists()) { - initialize(); - } + getSessionData(); } else {} } Future init() async { - await _singleFactorAuthFlutterPlugin.init(SFAParams( + await _singleFactorAuthFlutterPlugin.init(Web3AuthOptions( network: web3AuthNetwork, clientId: 'YOUR_CLIENT_ID', sessionTime: 86400)); } - Future initialize() async { - log("initialize() called"); - final SFAKey? sfaKey = await _singleFactorAuthFlutterPlugin.initialize(); - if (sfaKey != null) { + Future getSessionData() async { + log("getSessionData() called"); + final SessionData? sessionData = + await _singleFactorAuthFlutterPlugin.getSessionData(); + if (sessionData?.publicAddress != null) { setState(() { - _result = - "Public Add : ${sfaKey.publicAddress} , Private Key : ${sfaKey.privateKey}"; + _result = "Session Data: ${sessionData.toString()}"; }); } } @@ -139,14 +136,13 @@ class _MyAppState extends State { ); } - VoidCallback _getKey(Future Function() method) { + VoidCallback _getKey(Future Function() method) { return () async { try { - final SFAKey response = await method(); + final SessionData sessionData = await method(); setState(() { - _result = - "Public Add : ${response.publicAddress} , Private Key : ${response.privateKey}"; - log(response.publicAddress); + _result = "Session Data: ${sessionData.toString()}"; + log("Full Session Data: ${sessionData.toString()}"); }); } on MissingParamException catch (error) { log("Missing Param: ${error.paramName}"); @@ -160,25 +156,43 @@ class _MyAppState extends State { Future _initialize() async { try { - final SFAKey? response = - await _singleFactorAuthFlutterPlugin.initialize(); + final SessionData? sessionData = + await _singleFactorAuthFlutterPlugin.getSessionData(); + setState(() { - _result = - "Public Add : ${response?.publicAddress} , Private Key : ${response?.privateKey}"; - log(response!.publicAddress); + _result = "Session Data: ${sessionData.toString()}"; }); - } on PrivateKeyNotGeneratedException { - log("Private key not generated"); } on UnKnownException { log("Unknown exception occurred"); + } catch (e, stackTrace) { + log("An unexpected error occurred: $e"); + log("Stack trace: $stackTrace"); } } - Future getKey() { + //Get key example + Future getKey() { return _singleFactorAuthFlutterPlugin.connect(LoginParams( - verifier: 'torus-test-health', - verifierId: 'hello@tor.us', - idToken: Utils().es256Token("hello@tor.us"), + verifier: 'torus-test-health', + verifierId: 'hello@tor.us', + idToken: Utils().es256Token("hello@tor.us"), )); } + + //Aggregate verifier key example + Future getAggregateKey() { + return _singleFactorAuthFlutterPlugin.connect(LoginParams( + verifier: 'torus-aggregate-sapphire-mainnet', + verifierId: 'devnettestuser@tor.us', + idToken: Utils().es256Token("devnettestuser@tor.us"), + subVerifierInfoArray: [ + TorusSubVerifierInfo( + 'torus-test-health', Utils().es256Token("devnettestuser@tor.us")) + ])); + } + + //Logout example + Future logout() { + return _singleFactorAuthFlutterPlugin.logout(); + } } diff --git a/example/pubspec.lock b/example/pubspec.lock index 3e6b4c0..c755561 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -53,18 +53,18 @@ packages: dependency: transitive description: name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" crypto: dependency: transitive description: name: crypto - sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" cupertino_icons: dependency: "direct main" description: @@ -77,10 +77,10 @@ packages: dependency: "direct main" description: name: dart_jsonwebtoken - sha256: "346e9a21e4bf6e6a431e19ece00ebb2e3668e1e339cabdf6f46d18d88692a848" + sha256: "866787dc17afaef46a9ea7dd33eefe60c6d82084b4a36d70e8e788d091cd04ef" url: "https://pub.dev" source: hosted - version: "2.14.0" + version: "2.14.2" ed25519_edwards: dependency: transitive description: @@ -101,10 +101,10 @@ packages: dependency: transitive description: name: fixnum - sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" flutter: dependency: "direct main" description: flutter @@ -217,7 +217,7 @@ packages: path: ".." relative: true source: path - version: "5.3.0" + version: "6.0.0" sky_engine: dependency: transitive description: flutter @@ -275,10 +275,10 @@ packages: dependency: transitive description: name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.4.0" vector_math: dependency: transitive description: @@ -296,5 +296,5 @@ packages: source: hosted version: "14.2.5" sdks: - dart: ">=3.4.0 <4.0.0" + dart: ">=3.5.0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/ios/Classes/SingleFactorAuthFlutterPlugin.swift b/ios/Classes/SingleFactorAuthFlutterPlugin.swift index 742fa99..1931e03 100644 --- a/ios/Classes/SingleFactorAuthFlutterPlugin.swift +++ b/ios/Classes/SingleFactorAuthFlutterPlugin.swift @@ -1,5 +1,6 @@ import Flutter import UIKit +import FetchNodeDetails import SingleFactorAuth public class SingleFactorAuthFlutterPlugin: NSObject, FlutterPlugin { @@ -16,25 +17,25 @@ public class SingleFactorAuthFlutterPlugin: NSObject, FlutterPlugin { private func getNetwork(_ network: String) -> Web3AuthNetwork { switch network { case "mainnet": - return .legacy(.MAINNET) + return .MAINNET case "testnet": - return .legacy(.TESTNET) + return .TESTNET case "aqua": - return .legacy(.AQUA) + return .AQUA case "cyan": - return .legacy(.CYAN) + return .CYAN case "sapphire_devnet": - return .sapphire(.SAPPHIRE_DEVNET) + return .SAPPHIRE_DEVNET case "sapphire_mainnet": - return .sapphire(.SAPPHIRE_MAINNET) + return .SAPPHIRE_MAINNET default: - return .sapphire(.SAPPHIRE_MAINNET) + return .SAPPHIRE_MAINNET } } var decoder = JSONDecoder() var encoder = JSONEncoder() - var sfaParams: SFAParams? + var web3AuthOptions: Web3AuthOptions? var singleFactorAuth: SingleFactorAuth? public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { @@ -51,28 +52,24 @@ public class SingleFactorAuthFlutterPlugin: NSObject, FlutterPlugin { let params = try self.decoder.decode(InitParams.self, from: data) - sfaParams = SFAParams( - web3AuthClientId: params.clientId, - network: self.getNetwork(params.network), + web3AuthOptions = Web3AuthOptions( + clientId: params.clientId, + web3AuthNetwork: self.getNetwork(params.network), sessionTime: params.sessionTime ?? 86400 ) let singleFactorAuth = try SingleFactorAuth( - params: sfaParams! + params: web3AuthOptions! ) self.singleFactorAuth = singleFactorAuth return result(nil) + break case "initialize": do { - guard let torusKeyCF = try await singleFactorAuth?.initialize() else { - return result(nil) - } - - let resultData: Data = try encoder.encode(torusKeyCF) - let resultJson = String(decoding: resultData, as: UTF8.self) - return result(resultJson) + try await singleFactorAuth?.initialize() + return result(nil) } catch { result(FlutterError( code: (error as NSError).domain, @@ -80,6 +77,7 @@ public class SingleFactorAuthFlutterPlugin: NSObject, FlutterPlugin { details: String(describing: error) )) } + break case "connect": let args = call.arguments as? String @@ -87,28 +85,7 @@ public class SingleFactorAuthFlutterPlugin: NSObject, FlutterPlugin { return result(throwParamMissingError(param: args)) } - let params = try self.decoder.decode(getTorusKeyParams.self, from: data) - - let loginParams: LoginParams - if params.aggregateVerifier?.isEmpty ?? true { - loginParams = LoginParams( - verifier: params.verifier, - verifierId: params.verifierId, - idToken: params.idToken - ) - } else { - loginParams = LoginParams( - verifier: params.aggregateVerifier!, - verifierId: params.verifierId, - idToken: params.idToken, - subVerifierInfoArray: [ - TorusSubVerifierInfo( - verifier: params.verifier, - idToken: params.idToken - ) - ] - ) - } + let loginParams = try self.decoder.decode(LoginParams.self, from: data) do { @@ -128,14 +105,39 @@ public class SingleFactorAuthFlutterPlugin: NSObject, FlutterPlugin { } break - case "isSessionIdExists": + case "logout": + do { + try await singleFactorAuth?.logout() + return result(nil) + } catch { + result(FlutterError( + code: (error as NSError).domain, + message: error.localizedDescription, + details: String(describing: error) + )) + } + break + + case "getSessionData": + do { + try await singleFactorAuth?.initialize() + let sessionData = try await singleFactorAuth?.getSessionData() + let resultData = try encoder.encode(sessionData) + let resultJson = String(decoding: resultData, as: UTF8.self) + return result(resultJson) + } catch { + result(FlutterError( + code: (error as NSError).domain, + message: error.localizedDescription, + details: String(describing: error) + )) + } + break + + case "connected": do { - if singleFactorAuth == nil { - return result(false) - } else { - let isSessionExists = try await singleFactorAuth?.isSessionIdExists() ?? false - return result(isSessionExists) - } + let connected = try await singleFactorAuth?.connected() ?? false + result(connected) } catch { result(FlutterError( code: (error as NSError).domain, diff --git a/ios/single_factor_auth_flutter.podspec b/ios/single_factor_auth_flutter.podspec index 0fddef6..5da3df6 100644 --- a/ios/single_factor_auth_flutter.podspec +++ b/ios/single_factor_auth_flutter.podspec @@ -3,22 +3,39 @@ # Run `pod lib lint single_factor_auth_flutter.podspec` to validate before publishing. # Pod::Spec.new do |s| - s.name = 'single_factor_auth_flutter' - s.version = '0.0.1' - s.summary = 'A new Flutter plugin project.' - s.description = <<-DESC -A new Flutter plugin project. - DESC - s.homepage = 'http://example.com' - s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } - s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - s.dependency 'Flutter' - s.dependency 'SingleFactorAuth', '8.0.0' - s.platform = :ios, '14.0' +s.name = 'single_factor_auth_flutter' +s.version = '0.0.1' +s. +summary = 'A new Flutter plugin project.' +s. +description = +<<- +DESC + A +new +Flutter plugin +project. +DESC + s +. +homepage = 'http://example.com' +s. +license = {:file => '../LICENSE'} +s. +author = {'Your Company' => 'email@example.com'} +s. +source = {:path => '.'} +s. +source_files = 'Classes/**/*' +s.dependency 'Flutter' +s.dependency 'SingleFactorAuth', '9.0.4' +s. +platform = +:ios, '14.0' - # Flutter.framework does not contain a i386 slice. - s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } - s.swift_version = '5.0' -end +# Flutter.framework does not contain a i386 slice. +s. +pod_target_xcconfig = {'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386'} +s. +swift_version = '5.0' +end \ No newline at end of file diff --git a/lib/enums.dart b/lib/enums.dart new file mode 100644 index 0000000..7c3b3c8 --- /dev/null +++ b/lib/enums.dart @@ -0,0 +1,9 @@ +enum Web3AuthNetwork { + mainnet, + testnet, + cyan, + aqua, + celeste, + sapphire_devnet, + sapphire_mainnet +} diff --git a/lib/input.dart b/lib/input.dart index 35fe405..8072d63 100644 --- a/lib/input.dart +++ b/lib/input.dart @@ -1,32 +1,53 @@ +import 'enums.dart'; + class LoginParams { final String verifier; final String verifierId; final String idToken; - final String? aggregateVerifier; + List? subVerifierInfoArray; LoginParams({ required this.verifier, required this.verifierId, required this.idToken, - this.aggregateVerifier, + this.subVerifierInfoArray, //Optional }); Map toJson() { - return { + final Map data = { 'verifier': verifier, 'verifierId': verifierId, 'idToken': idToken, - 'aggregateVerifier': aggregateVerifier, + }; + + if (subVerifierInfoArray != null) { + data['subVerifierInfoArray'] = subVerifierInfoArray!.map((v) => v.toJson()).toList(); + } + + return data; + } +} + +class TorusSubVerifierInfo { + String verifier; + String idToken; + + TorusSubVerifierInfo(this.verifier, this.idToken); + + Map toJson() { + return { + 'verifier': verifier, + 'idToken': idToken, }; } } -class SFAParams { +class Web3AuthOptions { final Web3AuthNetwork network; final String clientId; final int sessionTime; - SFAParams( + Web3AuthOptions( {required this.network, required this.clientId, this.sessionTime = 86400}); @@ -40,16 +61,6 @@ class SFAParams { } } -enum Web3AuthNetwork { - mainnet, - testnet, - cyan, - aqua, - celeste, - sapphire_devnet, - sapphire_mainnet -} - class UserCancelledException implements Exception {} class PrivateKeyNotGeneratedException implements Exception {} diff --git a/lib/output.dart b/lib/output.dart index 6070f22..fc77e12 100644 --- a/lib/output.dart +++ b/lib/output.dart @@ -1,19 +1,239 @@ -import 'dart:convert'; -SFAKey sfaKeyFromJson(String string) => SFAKey.fromJson( - jsonDecode(string), - ); - -class SFAKey { +class SessionData { final String privateKey; final String publicAddress; + final Session_Data? signatures; + final UserInfo? userInfo; - SFAKey({required this.privateKey, required this.publicAddress}); + SessionData({ + required this.privateKey, + required this.publicAddress, + this.signatures, + this.userInfo, + }); - factory SFAKey.fromJson(Map json) { - return SFAKey( + // Factory constructor to create an instance from a JSON map + factory SessionData.fromJson(Map json) { + return SessionData( privateKey: json['privateKey'], publicAddress: json['publicAddress'], + signatures: json['signatures'] != null + ? Session_Data.fromJson(json['signatures']) + : null, + userInfo: + json['userInfo'] != null ? UserInfo.fromJson(json['userInfo']) : null, + ); + } + + Map toJson() { + return { + 'privateKey': privateKey, + 'publicAddress': publicAddress, + 'signatures': signatures?.toJson(), + 'userInfo': userInfo?.toJson(), + }; + } + + @override + String toString() { + return 'SessionData(privateKey: $privateKey, publicAddress: $publicAddress, signatures: ${signatures?.toString()}, userInfo: ${userInfo?.toString()})'; + } +} + +class UserInfo { + final String email; + final String name; + final String profileImage; + final String? aggregateVerifier; + final String verifier; + final String verifierId; + final LoginType typeOfLogin; + final String? ref; + final String? accessToken; + final String? idToken; + final String? extraParams; + final String? extraParamsPassed; + final TorusGenericContainer state; + + UserInfo({ + required this.email, + required this.name, + required this.profileImage, + this.aggregateVerifier, + required this.verifier, + required this.verifierId, + required this.typeOfLogin, + this.ref, + this.accessToken, + this.idToken, + this.extraParams, + this.extraParamsPassed, + required this.state, + }); + + // Factory constructor to create an instance from a JSON map + factory UserInfo.fromJson(Map json) { + return UserInfo( + email: json['email'], + name: json['name'], + profileImage: json['profileImage'], + aggregateVerifier: json['aggregateVerifier'], + verifier: json['verifier'], + verifierId: json['verifierId'], + typeOfLogin: LoginTypeExtension.fromJson(json['typeOfLogin']), + ref: json['ref'], + accessToken: json['accessToken'], + idToken: json['idToken'], + extraParams: json['extraParams'], + extraParamsPassed: json['extraParamsPassed'], + state: TorusGenericContainer.fromJson(json['state']), + ); + } + + // Method to convert an instance to a JSON map + Map toJson() { + return { + 'email': email, + 'name': name, + 'profileImage': profileImage, + 'aggregateVerifier': aggregateVerifier, + 'verifier': verifier, + 'verifierId': verifierId, + 'typeOfLogin': typeOfLogin.toJson(), + 'ref': ref, + 'accessToken': accessToken, + 'idToken': idToken, + 'extraParams': extraParams, + 'extraParamsPassed': extraParamsPassed, + 'state': state.toJson(), + }; + } + + @override + String toString() { + return 'UserInfo(email: $email, name: $name, profileImage: $profileImage, aggregateVerifier: $aggregateVerifier, verifier: $verifier, verifierId: $verifierId, typeOfLogin: ${typeOfLogin.toString()}, ref: $ref, accessToken: $accessToken, idToken: $idToken, extraParams: $extraParams, extraParamsPassed: $extraParamsPassed, state: ${state.toString()})'; + } +} + +enum LoginType { + google, + facebook, + discord, + reddit, + twitch, + apple, + github, + linkedin, + twitter, + weibo, + line, + email_password, + email_passwordless, + sms_passwordless, + jwt; +} + +extension LoginTypeExtension on LoginType { + String toJson() { + return toString().split('.').last; + } + + static LoginType fromJson(String value) { + return LoginType.values.firstWhere( + (type) => type.toJson() == value, + orElse: () => throw ArgumentError('Invalid LoginType: $value'), + ); + } +} + +class Session_Data { + final List sessionTokenData; + final String sessionAuthKey; + + Session_Data({ + required this.sessionTokenData, + required this.sessionAuthKey, + }); + + factory Session_Data.fromJson(Map json) { + return Session_Data( + sessionTokenData: (json['sessionTokenData'] as List) + .map((item) => SessionToken.fromJson(item as Map)) + .toList(), + sessionAuthKey: json['sessionAuthKey'] as String, + ); + } + + Map toJson() { + return { + 'sessionTokenData': + sessionTokenData.map((token) => token.toJson()).toList(), + 'sessionAuthKey': sessionAuthKey, + }; + } + + @override + String toString() { + return 'Session_Data(sessionTokenData: $sessionTokenData, sessionAuthKey: $sessionAuthKey)'; + } +} + +class SessionToken { + final String token; + final String signature; + final String nodePubx; + final String nodePuby; + + SessionToken({ + required this.token, + required this.signature, + required this.nodePubx, + required this.nodePuby, + }); + + factory SessionToken.fromJson(Map json) { + return SessionToken( + token: json['token'] as String, + signature: json['signature'] as String, + nodePubx: json['node_pubx'] as String, + nodePuby: json['node_puby'] as String, ); } + + Map toJson() { + return { + 'token': token, + 'signature': signature, + 'node_pubx': nodePubx, + 'node_puby': nodePuby, + }; + } + + @override + String toString() { + return 'SessionToken(token: $token, signature: $signature, nodePubx: $nodePubx, nodePuby: $nodePuby)'; + } +} + +class TorusGenericContainer { + final Map params; + + TorusGenericContainer({required this.params}); + + factory TorusGenericContainer.fromJson(Map json) { + return TorusGenericContainer( + params: Map.from(json['params']), + ); + } + + Map toJson() { + return { + 'params': params, + }; + } + + @override + String toString() { + return 'TorusGenericContainer(params: $params)'; + } } diff --git a/lib/single_factor_auth_flutter.dart b/lib/single_factor_auth_flutter.dart index 92011c8..9e63ef2 100644 --- a/lib/single_factor_auth_flutter.dart +++ b/lib/single_factor_auth_flutter.dart @@ -7,7 +7,7 @@ import 'package:single_factor_auth_flutter/output.dart'; import 'single_factor_auth_flutter_platform_interface.dart'; -class SingleFactAuthFlutter { +class SingleFactorAuthFlutter { static const MethodChannel _channel = MethodChannel('single_factor_auth_flutter'); @@ -15,45 +15,57 @@ class SingleFactAuthFlutter { return SingleFactAuthFlutterPlatform.instance.getPlatformVersion(); } - Future init(SFAParams initParams) async { - Map initParamsJson = initParams.toJson(); + Future init(Web3AuthOptions web3AuthOptions) async { + Map initParamsJson = web3AuthOptions.toJson(); initParamsJson.removeWhere((key, value) => value == null); await _channel.invokeMethod('init', jsonEncode(initParamsJson)); } - Future initialize() async { + Future initialize() async { try { - final String? sfaKeyJson = await _channel.invokeMethod( - 'initialize', - ); - - if (sfaKeyJson != null) { - return sfaKeyFromJson(sfaKeyJson); - } - return null; + await _channel.invokeMethod('initialize'); } on PlatformException catch (e) { throw _hanldePlatformException(e); } } - Future connect(LoginParams loginParams) async { + Future connect(LoginParams loginParams) async { try { Map loginParamsJson = loginParams.toJson(); loginParamsJson.removeWhere((key, value) => value == null); - final String torusKeyJson = await _channel.invokeMethod( + final String sessionData = await _channel.invokeMethod( 'connect', - jsonEncode(loginParams), + jsonEncode(loginParamsJson), ); - return sfaKeyFromJson(torusKeyJson); + return SessionData.fromJson(jsonDecode(sessionData)); + } on PlatformException catch (e) { + throw _hanldePlatformException(e); + } + } + + Future getSessionData() async { + try { + final String? sessionData = await _channel.invokeMethod('getSessionData'); + if (sessionData == null || sessionData.isEmpty) { + return null; + } + return SessionData.fromJson(jsonDecode(sessionData)); + } on PlatformException catch (e) { + throw _hanldePlatformException(e); + } + } + + Future logout() async { + try { + await _channel.invokeMethod('logout'); } on PlatformException catch (e) { throw _hanldePlatformException(e); } } - Future isSessionIdExists() async { + Future connected() async { try { - bool response = await _channel.invokeMethod('isSessionIdExists'); - return response; + return await _channel.invokeMethod('connected'); } on PlatformException catch (e) { throw _hanldePlatformException(e); } diff --git a/pubspec.yaml b/pubspec.yaml index 0530b81..fff679e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: single_factor_auth_flutter description: Single Factor Auth Flutter SDK -version: 5.3.0 +version: 6.0.0 homepage: "https://github.com/web3auth/single-factor-auth-flutter" environment: diff --git a/test/single_factor_auth_flutter_test.dart b/test/single_factor_auth_flutter_test.dart index 4287d12..dfaf851 100644 --- a/test/single_factor_auth_flutter_test.dart +++ b/test/single_factor_auth_flutter_test.dart @@ -1,5 +1,4 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:single_factor_auth_flutter/single_factor_auth_flutter.dart'; import 'package:single_factor_auth_flutter/single_factor_auth_flutter_platform_interface.dart'; import 'package:single_factor_auth_flutter/single_factor_auth_flutter_method_channel.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart';