diff --git a/Content/BlueprintSampleContent/PassportFeaturesWidget4_26.uasset b/Content/BlueprintSampleContent/PassportFeaturesWidget4_26.uasset
index 2ab066cb..682e2533 100644
Binary files a/Content/BlueprintSampleContent/PassportFeaturesWidget4_26.uasset and b/Content/BlueprintSampleContent/PassportFeaturesWidget4_26.uasset differ
diff --git a/Content/BlueprintSampleContent/PassportLoginWidget4_26.uasset b/Content/BlueprintSampleContent/PassportLoginWidget4_26.uasset
index ca6926fe..457eb7e1 100644
Binary files a/Content/BlueprintSampleContent/PassportLoginWidget4_26.uasset and b/Content/BlueprintSampleContent/PassportLoginWidget4_26.uasset differ
diff --git a/Content/ImtblSampleLevel4_26.umap b/Content/ImtblSampleLevel4_26.umap
index 7b11615d..a9e9bae1 100644
Binary files a/Content/ImtblSampleLevel4_26.umap and b/Content/ImtblSampleLevel4_26.umap differ
diff --git a/Content/PackagedResources/index.uasset b/Content/PackagedResources/index.uasset
index 21de0eb0..e1c12e1c 100644
Binary files a/Content/PackagedResources/index.uasset and b/Content/PackagedResources/index.uasset differ
diff --git a/Source/Immutable/Immutable.Build.cs b/Source/Immutable/Immutable.Build.cs
index 9bb9c4da..27b42bca 100644
--- a/Source/Immutable/Immutable.Build.cs
+++ b/Source/Immutable/Immutable.Build.cs
@@ -79,6 +79,11 @@ public Immutable(ReadOnlyTargetRules Target) : base(Target)
// ... add any modules that your module loads dynamically here ...
}
);
+
+ if (Target.bBuildEditor == true)
+ {
+ PrivateDependencyModuleNames.Add("UnrealEd");
+ }
if (Target.Platform == UnrealTargetPlatform.Android)
{
diff --git a/Source/Immutable/Immutable_UPL_Android.xml b/Source/Immutable/Immutable_UPL_Android.xml
index bbcebe6c..ea9a9cf6 100644
--- a/Source/Immutable/Immutable_UPL_Android.xml
+++ b/Source/Immutable/Immutable_UPL_Android.xml
@@ -55,11 +55,11 @@
public native void handleDeepLink(String Deeplink);
- public native void handleOnCustomTabsDismissed();
+ public native void handleOnCustomTabsDismissed(String Url);
@Override
- public void onCustomTabsDismissed() {
- handleOnCustomTabsDismissed();
+ public void onCustomTabsDismissed(String Url) {
+ handleOnCustomTabsDismissed(Url);
}
diff --git a/Source/Immutable/Private/Immutable/Actions/ImtblPassportConnectSilentAsyncAction.cpp b/Source/Immutable/Private/Immutable/Actions/ImtblPassportConnectSilentAsyncAction.cpp
new file mode 100644
index 00000000..91762cb4
--- /dev/null
+++ b/Source/Immutable/Private/Immutable/Actions/ImtblPassportConnectSilentAsyncAction.cpp
@@ -0,0 +1,53 @@
+
+#include "Immutable/Actions/ImtblPassportConnectSilentAsyncAction.h"
+
+#include "Immutable/ImmutablePassport.h"
+#include "Immutable/ImmutableSubsystem.h"
+#include "Immutable/Misc/ImtblLogging.h"
+
+
+UImtblPassportConnectSilentAsyncAction * UImtblPassportConnectSilentAsyncAction::ConnectSilent(UObject *WorldContextObject)
+{
+ UImtblPassportConnectSilentAsyncAction *PassportInitBlueprintNode = NewObject();
+
+ PassportInitBlueprintNode->WorldContextObject = WorldContextObject;
+
+ return PassportInitBlueprintNode;
+}
+
+void UImtblPassportConnectSilentAsyncAction::Activate()
+{
+ if (!WorldContextObject || !WorldContextObject->GetWorld())
+ {
+ FString Err = "Reconnect failed due to missing world or world context object.";
+ IMTBL_WARN("%s", *Err)
+ OnFailure.Broadcast(Err);
+ return;
+ }
+
+ GetSubsystem()->WhenReady(this, &UImtblPassportConnectSilentAsyncAction:: DoConnectSilent);
+}
+
+void UImtblPassportConnectSilentAsyncAction::DoConnectSilent(TWeakObjectPtr JSConnector)
+{
+ auto Passport = GetSubsystem()->GetPassport();
+
+ if (Passport.IsValid())
+ {
+ Passport->ConnectSilent(UImmutablePassport::FImtblPassportResponseDelegate::CreateUObject(this, &UImtblPassportConnectSilentAsyncAction::OnConnectSilentResponse));
+ }
+}
+
+void UImtblPassportConnectSilentAsyncAction::OnConnectSilentResponse(FImmutablePassportResult Result)
+{
+ if (Result.Success)
+ {
+ IMTBL_LOG("Reconnect success")
+ OnSuccess.Broadcast(Result.Message);
+ }
+ else
+ {
+ IMTBL_LOG("Reconnect failed")
+ OnFailure.Broadcast(Result.Message);
+ }
+}
diff --git a/Source/Immutable/Private/Immutable/Actions/ImtblPassportInitializationAsyncAction.cpp b/Source/Immutable/Private/Immutable/Actions/ImtblPassportInitializationAsyncAction.cpp
index d7c960f0..3f07dc70 100644
--- a/Source/Immutable/Private/Immutable/Actions/ImtblPassportInitializationAsyncAction.cpp
+++ b/Source/Immutable/Private/Immutable/Actions/ImtblPassportInitializationAsyncAction.cpp
@@ -4,49 +4,50 @@
#include "Immutable/ImmutablePassport.h"
#include "Immutable/ImmutableSubsystem.h"
-#include "Immutable/Misc/ImtblLogging.h"
-
-UImtblPassportInitializationAsyncAction *
-UImtblPassportInitializationAsyncAction::InitializePassport(
- UObject *WorldContextObject, const FString &ClientID,
- const FString &RedirectUri, const FString &Environment) {
- UImtblPassportInitializationAsyncAction *PassportInitBlueprintNode =
- NewObject();
- PassportInitBlueprintNode->ClientId = ClientID;
- PassportInitBlueprintNode->RedirectUri = RedirectUri;
- PassportInitBlueprintNode->Environment = Environment;
- PassportInitBlueprintNode->WorldContextObject = WorldContextObject;
- return PassportInitBlueprintNode;
+
+
+UImtblPassportInitializationAsyncAction* UImtblPassportInitializationAsyncAction::InitializePassport(UObject* WorldContextObject, const FString& ClientID, const FString& RedirectUri,
+ const FString& LogoutUri, const FString& Environment)
+{
+ UImtblPassportInitializationAsyncAction* PassportInitBlueprintNode = NewObject();
+
+ PassportInitBlueprintNode->ClientId = ClientID;
+ PassportInitBlueprintNode->RedirectUri = RedirectUri;
+ PassportInitBlueprintNode->LogoutUri = LogoutUri;
+ PassportInitBlueprintNode->Environment = Environment;
+ PassportInitBlueprintNode->WorldContextObject = WorldContextObject;
+
+ return PassportInitBlueprintNode;
}
-void UImtblPassportInitializationAsyncAction::Activate() {
- if (!WorldContextObject || !WorldContextObject->GetWorld()) {
- Failed.Broadcast(
- "Initialization failed due to missing world or world context object.");
- return;
- }
+void UImtblPassportInitializationAsyncAction::Activate()
+{
+ if (!WorldContextObject || !WorldContextObject->GetWorld())
+ {
+ Failed.Broadcast("Initialization failed due to missing world or world context object.");
+ return;
+ }
- GetSubsystem()->WhenReady(
- this, &UImtblPassportInitializationAsyncAction::DoInit); //, /* timoutSec
- //*/ 15.0f);
+ GetSubsystem()->WhenReady(this, &UImtblPassportInitializationAsyncAction::DoInit);
}
-void UImtblPassportInitializationAsyncAction::DoInit(
- TWeakObjectPtr JSConnector) {
- // Get Passport
- auto Passport = GetSubsystem()->GetPassport();
- // Run Initialize
- Passport->Initialize(
- FImmutablePassportInitData{ClientId, RedirectUri, Environment},
- UImmutablePassport::FImtblPassportResponseDelegate::CreateUObject(
- this, &UImtblPassportInitializationAsyncAction::OnInitialized));
+void UImtblPassportInitializationAsyncAction::DoInit(TWeakObjectPtr JSConnector)
+{
+ // Get Passport
+ auto Passport = GetSubsystem()->GetPassport();
+ // Run Initialize
+ Passport->Initialize(FImmutablePassportInitData{ ClientId, RedirectUri, LogoutUri, Environment },
+ UImmutablePassport::FImtblPassportResponseDelegate::CreateUObject(this, &UImtblPassportInitializationAsyncAction::OnInitialized));
}
-void UImtblPassportInitializationAsyncAction::OnInitialized(
- FImmutablePassportResult Result) {
- if (Result.Success) {
- Initialized.Broadcast(Result.Message);
- } else {
- Failed.Broadcast(Result.Message);
- }
+void UImtblPassportInitializationAsyncAction::OnInitialized(FImmutablePassportResult Result)
+{
+ if (Result.Success)
+ {
+ Initialized.Broadcast(Result.Message);
+ }
+ else
+ {
+ Failed.Broadcast(Result.Message);
+ }
}
diff --git a/Source/Immutable/Private/Immutable/Actions/ImtblPassportLogoutAsyncAction.cpp b/Source/Immutable/Private/Immutable/Actions/ImtblPassportLogoutAsyncAction.cpp
index c3dc2f4e..a606a379 100644
--- a/Source/Immutable/Private/Immutable/Actions/ImtblPassportLogoutAsyncAction.cpp
+++ b/Source/Immutable/Private/Immutable/Actions/ImtblPassportLogoutAsyncAction.cpp
@@ -6,42 +6,44 @@
#include "Immutable/ImmutableSubsystem.h"
#include "Immutable/Misc/ImtblLogging.h"
-UImtblPassportLogoutAsyncAction *
-UImtblPassportLogoutAsyncAction::Logout(UObject *WorldContextObject) {
- UImtblPassportLogoutAsyncAction *PassportInitBlueprintNode =
- NewObject();
- PassportInitBlueprintNode->WorldContextObject = WorldContextObject;
- return PassportInitBlueprintNode;
+UImtblPassportLogoutAsyncAction* UImtblPassportLogoutAsyncAction::Logout(UObject* WorldContextObject)
+{
+ UImtblPassportLogoutAsyncAction* PassportInitBlueprintNode = NewObject();
+
+ PassportInitBlueprintNode->WorldContextObject = WorldContextObject;
+
+ return PassportInitBlueprintNode;
}
-void UImtblPassportLogoutAsyncAction::Activate() {
- if (!WorldContextObject || !WorldContextObject->GetWorld()) {
- FString Err = "Logout failed due to missing world or world context object.";
- IMTBL_WARN("%s", *Err)
- Failed.Broadcast(Err);
- return;
- }
-
- GetSubsystem()->WhenReady(
- this,
- &UImtblPassportLogoutAsyncAction::DoLogout); //, /* timoutSec */ 15.0f);
+void UImtblPassportLogoutAsyncAction::Activate()
+{
+ if (!WorldContextObject || !WorldContextObject->GetWorld())
+ {
+ FString Err = "Logout failed due to missing world or world context object.";
+ IMTBL_WARN("%s", *Err)
+ OnFailure.Broadcast(Err);
+ return;
+ }
+
+ GetSubsystem()->WhenReady(this, &UImtblPassportLogoutAsyncAction::DoLogout); //, /* timoutSec */ 15.0f);
}
-void UImtblPassportLogoutAsyncAction::DoLogout(
- TWeakObjectPtr JSConnector) {
- // Get Passport
- auto Passport = GetSubsystem()->GetPassport();
- // Run Logout
- Passport->Logout(
- UImmutablePassport::FImtblPassportResponseDelegate::CreateUObject(
- this, &UImtblPassportLogoutAsyncAction::OnLogoutResponse));
+void UImtblPassportLogoutAsyncAction::DoLogout(TWeakObjectPtr JSConnector)
+{
+ // Get Passport
+ auto Passport = GetSubsystem()->GetPassport();
+ // Run Logout
+ Passport->Logout(UImmutablePassport::FImtblPassportResponseDelegate::CreateUObject(this, &UImtblPassportLogoutAsyncAction::OnLogoutResponse));
}
-void UImtblPassportLogoutAsyncAction::OnLogoutResponse(
- FImmutablePassportResult Result) {
- if (Result.Success) {
- LoggedOut.Broadcast(Result.Message);
- } else {
- Failed.Broadcast(Result.Message);
- }
+void UImtblPassportLogoutAsyncAction::OnLogoutResponse(FImmutablePassportResult Result) const
+{
+ if (Result.Success)
+ {
+ OnSuccess.Broadcast(Result.Message);
+ }
+ else
+ {
+ OnFailure.Broadcast(Result.Message);
+ }
}
diff --git a/Source/Immutable/Private/Immutable/Actions/ImtblPassportReconnectAsyncAction.cpp b/Source/Immutable/Private/Immutable/Actions/ImtblPassportReconnectAsyncAction.cpp
deleted file mode 100644
index 3a6d2dbc..00000000
--- a/Source/Immutable/Private/Immutable/Actions/ImtblPassportReconnectAsyncAction.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-
-#include "Immutable/Actions/ImtblPassportReconnectAsyncAction.h"
-
-#include "Immutable/ImmutablePassport.h"
-#include "Immutable/ImmutableSubsystem.h"
-#include "Immutable/Misc/ImtblLogging.h"
-
-
-UImtblPassportReconnectAsyncAction * UImtblPassportReconnectAsyncAction::Reconnect(UObject *WorldContextObject)
-{
- UImtblPassportReconnectAsyncAction *PassportInitBlueprintNode = NewObject();
-
- PassportInitBlueprintNode->WorldContextObject = WorldContextObject;
-
- return PassportInitBlueprintNode;
-}
-
-void UImtblPassportReconnectAsyncAction::Activate()
-{
- if (!WorldContextObject || !WorldContextObject->GetWorld())
- {
- FString Err = "Reconnect failed due to missing world or world context object.";
- IMTBL_WARN("%s", *Err)
- OnFailure.Broadcast(Err);
- return;
- }
-
- GetSubsystem()->WhenReady(this, &UImtblPassportReconnectAsyncAction:: DoReconnect);
-}
-
-void UImtblPassportReconnectAsyncAction::DoReconnect(TWeakObjectPtr JSConnector)
-{
- auto Passport = GetSubsystem()->GetPassport();
-
- if (Passport.IsValid())
- {
- Passport->Reconnect(UImmutablePassport::FImtblPassportResponseDelegate::CreateUObject(this, &UImtblPassportReconnectAsyncAction::OnReconnectResponse));
- }
-}
-
-void UImtblPassportReconnectAsyncAction::OnReconnectResponse(FImmutablePassportResult Result)
-{
- if (Result.Success)
- {
- IMTBL_LOG("Reconnect success")
- OnSuccess.Broadcast(Result.Message);
- }
- else
- {
- IMTBL_LOG("Reconnect failed")
- OnFailure.Broadcast(Result.Message);
- }
-}
diff --git a/Source/Immutable/Private/Immutable/Android/ImmutableAndroidJNI.cpp b/Source/Immutable/Private/Immutable/Android/ImmutableAndroidJNI.cpp
index 7b7fa25d..7ca3a033 100644
--- a/Source/Immutable/Private/Immutable/Android/ImmutableAndroidJNI.cpp
+++ b/Source/Immutable/Private/Immutable/Android/ImmutableAndroidJNI.cpp
@@ -1,23 +1,71 @@
#include "ImmutableAndroidJNI.h"
-#include "Immutable/ImmutablePassport.h"
#if PLATFORM_ANDROID
-JNI_METHOD void
-Java_com_epicgames_unreal_GameActivity_handleDeepLink(JNIEnv *env, jobject obj,
- jstring jDeeplink) {
- if (env->IsSameObject(jDeeplink, NULL)) {
- return;
- }
-
- const char *deeplinkCStr = env->GetStringUTFChars(jDeeplink, NULL);
- const FString deeplink = FString(UTF8_TO_TCHAR(deeplinkCStr));
- UImmutablePassport::HandleDeepLink(deeplink);
- env->ReleaseStringUTFChars(jDeeplink, deeplinkCStr);
+
+#include "Immutable/ImmutablePassport.h"
+#include "Immutable/ImmutableSubsystem.h"
+#include "Engine/GameEngine.h"
+
+UImmutablePassport* GetPassport()
+{
+ UGameEngine* GameEngine = Cast(GEngine);
+
+ if (!GameEngine)
+ {
+ return nullptr;
+ }
+
+ UWorld* World = GameEngine ? GameEngine->GetGameWorld() : NULL;
+
+ if (!World)
+ {
+ return nullptr;
+ }
+
+ auto ImmutableSubsystem = World->GetGameInstance()->GetSubsystem();
+
+ if (!ImmutableSubsystem)
+ {
+ return nullptr;
+ }
+
+ auto Passport = ImmutableSubsystem->GetPassport();
+
+ if (!Passport.IsValid())
+ {
+ return nullptr;
+ }
+
+ return Passport.Get();
+}
+
+JNI_METHOD void Java_com_epicgames_unreal_GameActivity_handleDeepLink(JNIEnv *env, jobject obj, jstring jDeeplink)
+{
+ if (env->IsSameObject(jDeeplink, NULL))
+ {
+ return;
+ }
+
+ const char *deeplinkCStr = env->GetStringUTFChars(jDeeplink, NULL);
+ const FString deeplink = FString(UTF8_TO_TCHAR(deeplinkCStr));
+
+ if (auto Passport = GetPassport())
+ {
+ Passport->HandleDeepLink(deeplink);
+ }
+ env->ReleaseStringUTFChars(jDeeplink, deeplinkCStr);
}
-JNI_METHOD void
-Java_com_epicgames_unreal_GameActivity_handleOnCustomTabsDismissed(
- JNIEnv *env, jobject obj) {
- UImmutablePassport::HandleCustomTabsDismissed();
+JNI_METHOD void Java_com_epicgames_unreal_GameActivity_handleOnCustomTabsDismissed(JNIEnv *env, jobject obj, jstring jUrl)
+{
+ if (env->IsSameObject(jUrl, NULL))
+ {
+ return;
+ }
+
+ if (auto Passport = GetPassport())
+ {
+ Passport->HandleCustomTabsDismissed(FString(UTF8_TO_TCHAR(env->GetStringUTFChars(jUrl, NULL))));
+ }
}
#endif
\ No newline at end of file
diff --git a/Source/Immutable/Private/Immutable/Android/ImmutableAndroidJNI.h b/Source/Immutable/Private/Immutable/Android/ImmutableAndroidJNI.h
index 386cd50c..8f21b095 100644
--- a/Source/Immutable/Private/Immutable/Android/ImmutableAndroidJNI.h
+++ b/Source/Immutable/Private/Immutable/Android/ImmutableAndroidJNI.h
@@ -3,14 +3,11 @@
#if PLATFORM_ANDROID
#include "Android/AndroidJNI.h"
-extern "C" {
-JNI_METHOD void Java_com_epicgames_unreal_GameActivity_handleDeepLink(JNIEnv *,
- jobject,
- jstring);
+extern "C"
+{
+JNI_METHOD void Java_com_epicgames_unreal_GameActivity_handleDeepLink(JNIEnv *, jobject, jstring);
-JNI_METHOD void
-Java_com_epicgames_unreal_GameActivity_handleOnCustomTabsDismissed(JNIEnv *,
- jobject);
+JNI_METHOD void Java_com_epicgames_unreal_GameActivity_handleOnCustomTabsDismissed(JNIEnv *, jobject, jstring);
}
#endif
diff --git a/Source/Immutable/Private/Immutable/Android/Java/ImmutableAndroid.java b/Source/Immutable/Private/Immutable/Android/Java/ImmutableAndroid.java
index 0d6546c5..378648e6 100644
--- a/Source/Immutable/Private/Immutable/Android/Java/ImmutableAndroid.java
+++ b/Source/Immutable/Private/Immutable/Android/Java/ImmutableAndroid.java
@@ -43,7 +43,7 @@ private static int getCustomTabsHeight(Activity context) {
}
}
- public static void launchUrl(Activity context, String url) {
+ public static void launchUrl(final Activity context, final String url) {
// Get all apps that can support Custom Tabs Service
// i.e. services that can handle ACTION_CUSTOM_TABS_CONNECTION intents
PackageManager packageManager = context.getPackageManager();
@@ -84,7 +84,7 @@ public void onNavigationEvent(int navigationEvent, @Nullable Bundle extras) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
- ((Callback) context).onCustomTabsDismissed();
+ ((Callback) context).onCustomTabsDismissed(url);
}
}, 1000);
}
@@ -107,6 +107,6 @@ public void run() {
}
public interface Callback {
- void onCustomTabsDismissed();
+ void onCustomTabsDismissed(String url);
}
}
\ No newline at end of file
diff --git a/Source/Immutable/Private/Immutable/IOS/ImmutableIOS.cpp b/Source/Immutable/Private/Immutable/IOS/ImmutableIOS.cpp
index 6043284a..85fdfb89 100644
--- a/Source/Immutable/Private/Immutable/IOS/ImmutableIOS.cpp
+++ b/Source/Immutable/Private/Immutable/IOS/ImmutableIOS.cpp
@@ -1,5 +1,7 @@
#include "ImmutableIOS.h"
#include "Immutable/ImmutablePassport.h"
+#include "Immutable/ImmutableSubsystem.h"
+#include "Engine/GameEngine.h"
API_AVAILABLE(ios(12.0))
ASWebAuthenticationSession *_authSession;
@@ -20,6 +22,34 @@ ASWebAuthenticationSession *_authSession;
return staticImmutableIOS;
}
++ (UImmutablePassport*) getPassport {
+ UGameEngine* GameEngine = Cast(GEngine);
+
+ if (!GameEngine) {
+ return nil;
+ }
+
+ UWorld* World = GameEngine ? GameEngine->GetGameWorld() : NULL;
+
+ if (!World) {
+ return nil;
+ }
+
+ auto ImmutableSubsystem = World->GetGameInstance()->GetSubsystem();
+
+ if (!ImmutableSubsystem) {
+ return nil;
+ }
+
+ auto Passport = ImmutableSubsystem->GetPassport();
+
+ if (!Passport.IsValid()) {
+ return nil;
+ }
+
+ return Passport.Get();
+}
+
- (void)launchUrl:(const char *)url {
NSURL *URL = [NSURL URLWithString:[[NSString alloc] initWithUTF8String:url]];
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
@@ -31,7 +61,11 @@ ASWebAuthenticationSession *_authSession;
NSError *_Nullable error) {
_authSession = nil;
if (callbackURL) {
- UImmutablePassport::HandleDeepLink(callbackURL.absoluteString);
+ UImmutablePassport* passport = [ImmutableIOS getPassport];
+
+ if (passport) {
+ passport->HandleDeepLink(callbackURL.absoluteString);
+ }
} else {
return;
}
diff --git a/Source/Immutable/Private/Immutable/ImmutablePassport.cpp b/Source/Immutable/Private/Immutable/ImmutablePassport.cpp
index 2c59541f..5959be6c 100644
--- a/Source/Immutable/Private/Immutable/ImmutablePassport.cpp
+++ b/Source/Immutable/Private/Immutable/ImmutablePassport.cpp
@@ -5,6 +5,8 @@
#include "Immutable/Misc/ImtblLogging.h"
#include "ImtblJSConnector.h"
#include "JsonObjectConverter.h"
+#include "Policies/CondensedJsonPrintPolicy.h"
+
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
#include "GenericPlatform/GenericPlatformHttp.h"
@@ -20,427 +22,467 @@
#include "Mac/ImmutableMac.h"
#endif
-FString FImmutablePassportInitData::ToJsonString() const {
- FString OutString;
-
- FJsonObjectWrapper Wrapper;
- Wrapper.JsonObject = MakeShared();
- FJsonObjectConverter::UStructToJsonObject(
- FImmutablePassportInitData::StaticStruct(), this,
- Wrapper.JsonObject.ToSharedRef(), 0, 0);
-
- if (!Wrapper.JsonObject.IsValid()) {
- IMTBL_ERR("Could not convert FImmutablePassportInitData to JSON")
- return "";
- }
- // Remove redirectUri field if it's empty so that the bridge doesn't try to
- // use it
- if (Wrapper.JsonObject->HasField("redirectUri") &&
- Wrapper.JsonObject->GetStringField("redirectUri").IsEmpty())
- Wrapper.JsonObject->RemoveField("redirectUri");
- Wrapper.JsonObjectToString(OutString);
-
- return OutString;
-}
-
-FString FImxBatchNftTransferRequest::ToJsonString() const {
- FString OutString;
- FJsonObjectWrapper Wrapper;
- Wrapper.JsonObject = MakeShared();
- FJsonObjectConverter::UStructToJsonObject(
- FImxBatchNftTransferRequest::StaticStruct(), this,
- Wrapper.JsonObject.ToSharedRef(), 0, 0);
-
- if (!Wrapper.JsonObject.IsValid()) {
- IMTBL_ERR("Could not convert FImxBatchNftTransferRequest to JSON")
- return "";
- }
-
- if (Wrapper.JsonObject->HasField("nftTransferDetails")) {
- const auto Writer =
- TJsonWriterFactory>::Create(
- &OutString);
- FJsonSerializer::Serialize(
- Wrapper.JsonObject->GetArrayField("nftTransferDetails"), Writer);
- IMTBL_LOG("FImxBatchNftTransferRequest Serialised: %s", *OutString);
- Writer->Close();
- }
- return OutString;
-}
-
-TOptional
-FImmutablePassportConnectData::FromJsonString(const FString &JsonObjectString) {
- FImmutablePassportConnectData PassportConnect;
- if (!FJsonObjectConverter::JsonObjectStringToUStruct(
- JsonObjectString, &PassportConnect, 0, 0)) {
- IMTBL_WARN("Could not parse response from JavaScript into the expected "
- "Passport connect format")
- return TOptional();
- }
- return PassportConnect;
-}
-
-FString FImmutablePassportZkEvmRequestAccountsData::ToJsonString() const {
- FString OutString;
- FJsonObjectConverter::UStructToJsonObjectString(*this, OutString, 0, 0, 0,
- nullptr, false);
- return OutString;
-}
-
-TOptional
-FImmutablePassportZkEvmRequestAccountsData::FromJsonString(
- const FString &JsonObjectString) {
- FImmutablePassportZkEvmRequestAccountsData RequestAccounts;
- if (!FJsonObjectConverter::JsonObjectStringToUStruct(
- JsonObjectString, &RequestAccounts, 0, 0)) {
- IMTBL_WARN("Could not parse response from JavaScript into the expected "
- "Passport ZkEvm request accounts format")
- return TOptional();
- }
- return RequestAccounts;
-}
-
-TOptional
-FImmutablePassportZkEvmRequestAccountsData::FromJsonObject(
- const TSharedPtr &JsonObject) {
- if (!JsonObject.IsValid())
- return TOptional();
-
- // Parse the JSON
- FImmutablePassportZkEvmRequestAccountsData RequestAccounts;
- if (!FJsonObjectConverter::JsonObjectToUStruct(JsonObject.ToSharedRef(),
- &RequestAccounts, 0, 0)) {
- IMTBL_ERR("Could not parse response from JavaScript into the expected "
- "Passport ZkEvm request accounts format")
- return TOptional();
- }
- return RequestAccounts;
-}
-
-FString FImmutablePassportZkEvmGetBalanceData::ToJsonString() const {
- FString OutString;
-
- FJsonObjectWrapper Wrapper;
- Wrapper.JsonObject = MakeShared();
- FJsonObjectConverter::UStructToJsonObject(
- FImmutablePassportZkEvmGetBalanceData::StaticStruct(), this,
- Wrapper.JsonObject.ToSharedRef(), 0, 0);
-
- if (!Wrapper.JsonObject.IsValid()) {
- IMTBL_ERR("Could not convert FImmutablePassportZkEvmGetBalanceData to JSON")
- return "";
- }
- Wrapper.JsonObjectToString(OutString);
-
- return OutString;
+FString FImmutablePassportInitData::ToJsonString() const
+{
+ FString OutString;
+
+ FJsonObjectWrapper Wrapper;
+ Wrapper.JsonObject = MakeShared();
+ FJsonObjectConverter::UStructToJsonObject(StaticStruct(), this, Wrapper.JsonObject.ToSharedRef(), 0, 0);
+
+ if (!Wrapper.JsonObject.IsValid())
+ {
+ IMTBL_ERR("Could not convert FImmutablePassportInitData to JSON")
+ return "";
+ }
+ // Remove redirectUri field if it's empty so that the bridge doesn't try to
+ // use it
+ if (Wrapper.JsonObject->HasField("redirectUri") && Wrapper.JsonObject->GetStringField("redirectUri").IsEmpty())
+ {
+ Wrapper.JsonObject->RemoveField("redirectUri");
+ }
+ Wrapper.JsonObjectToString(OutString);
+
+ return OutString;
+}
+
+FString FImxBatchNftTransferRequest::ToJsonString() const
+{
+ FString OutString;
+ FJsonObjectWrapper Wrapper;
+ Wrapper.JsonObject = MakeShared();
+ FJsonObjectConverter::UStructToJsonObject(StaticStruct(), this, Wrapper.JsonObject.ToSharedRef(), 0, 0);
+
+ if (!Wrapper.JsonObject.IsValid())
+ {
+ IMTBL_ERR("Could not convert FImxBatchNftTransferRequest to JSON")
+ return "";
+ }
+
+ if (Wrapper.JsonObject->HasField("nftTransferDetails"))
+ {
+ const auto Writer = TJsonWriterFactory>::Create(&OutString);
+ FJsonSerializer::Serialize(Wrapper.JsonObject->GetArrayField("nftTransferDetails"), Writer);
+ IMTBL_LOG("FImxBatchNftTransferRequest Serialised: %s", *OutString);
+ Writer->Close();
+ }
+ return OutString;
+}
+
+TOptional FImmutablePassportConnectData::FromJsonString(const FString& JsonObjectString)
+{
+ FImmutablePassportConnectData PassportConnect;
+ if (!FJsonObjectConverter::JsonObjectStringToUStruct(JsonObjectString, &PassportConnect, 0, 0))
+ {
+ IMTBL_WARN("Could not parse response from JavaScript into the expected " "Passport connect format")
+ return TOptional();
+ }
+ return PassportConnect;
+}
+
+FString FImmutablePassportZkEvmRequestAccountsData::ToJsonString() const
+{
+ FString OutString;
+ FJsonObjectConverter::UStructToJsonObjectString(*this, OutString, 0, 0, 0, nullptr, false);
+ return OutString;
+}
+
+TOptional FImmutablePassportZkEvmRequestAccountsData::FromJsonString(
+ const FString& JsonObjectString)
+{
+ FImmutablePassportZkEvmRequestAccountsData RequestAccounts;
+ if (!FJsonObjectConverter::JsonObjectStringToUStruct(JsonObjectString, &RequestAccounts, 0, 0))
+ {
+ IMTBL_WARN("Could not parse response from JavaScript into the expected "
+ "Passport ZkEvm request accounts format")
+ return TOptional();
+ }
+ return RequestAccounts;
+}
+
+TOptional FImmutablePassportZkEvmRequestAccountsData::FromJsonObject(
+ const TSharedPtr& JsonObject)
+{
+ if (!JsonObject.IsValid()) { return TOptional(); }
+
+ // Parse the JSON
+ FImmutablePassportZkEvmRequestAccountsData RequestAccounts;
+ if (!FJsonObjectConverter::JsonObjectToUStruct(JsonObject.ToSharedRef(), &RequestAccounts, 0, 0))
+ {
+ IMTBL_ERR("Could not parse response from JavaScript into the expected "
+ "Passport ZkEvm request accounts format")
+ return TOptional();
+ }
+ return RequestAccounts;
+}
+
+FString FImmutablePassportZkEvmGetBalanceData::ToJsonString() const
+{
+ FString OutString;
+
+ FJsonObjectWrapper Wrapper;
+ Wrapper.JsonObject = MakeShared();
+ FJsonObjectConverter::UStructToJsonObject(StaticStruct(), this, Wrapper.JsonObject.ToSharedRef(), 0, 0);
+
+ if (!Wrapper.JsonObject.IsValid())
+ {
+ IMTBL_ERR("Could not convert FImmutablePassportZkEvmGetBalanceData to JSON")
+ return "";
+ }
+ Wrapper.JsonObjectToString(OutString);
+
+ return OutString;
}
// @param Environment can be one of ImmutablePassportAction::EnvSandbox or
// ImmutablePassportAction::EnvProduction
-void UImmutablePassport::Initialize(
- const FImmutablePassportInitData &Data,
- const FImtblPassportResponseDelegate &ResponseDelegate) {
- check(JSConnector.IsValid());
-
- InitData = Data;
+void UImmutablePassport::Initialize(const FImmutablePassportInitData& Data,
+ const FImtblPassportResponseDelegate& ResponseDelegate)
+{
+ check(JSConnector.IsValid());
- CallJS(ImmutablePassportAction::Initialize, InitData.ToJsonString(),
- ResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(
- this, &UImmutablePassport::OnInitializeResponse),
- false);
+ InitData = Data;
+
+ CallJS(ImmutablePassportAction::Initialize, InitData.ToJsonString(), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnInitializeResponse), false);
}
-void UImmutablePassport::Logout(
- const FImtblPassportResponseDelegate &ResponseDelegate) {
- CallJS(ImmutablePassportAction::Logout, TEXT(""), ResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(
- this, &UImmutablePassport::OnLogoutResponse));
+void UImmutablePassport::Logout(const FImtblPassportResponseDelegate& ResponseDelegate)
+{
+#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
+ if (bIsLoggedIn && IsPKCEConnected)
+ {
+ PKCELogoutResponseDelegate = ResponseDelegate;
+ }
+#endif
+ CallJS(ImmutablePassportAction::Logout, TEXT(""), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnLogoutResponse));
}
-void UImmutablePassport::Connect(
- const FImtblPassportResponseDelegate &ResponseDelegate) {
- CallJS(ImmutablePassportAction::Connect, TEXT(""), ResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(
- this, &UImmutablePassport::OnConnectResponse));
+void UImmutablePassport::Connect(const FImtblPassportResponseDelegate& ResponseDelegate)
+{
+ CallJS(ImmutablePassportAction::Connect, TEXT(""), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnConnectResponse));
}
-void UImmutablePassport::Reconnect(const FImtblPassportResponseDelegate& ResponseDelegate)
+void UImmutablePassport::ConnectSilent(const FImtblPassportResponseDelegate& ResponseDelegate)
{
- CallJS(ImmutablePassportAction::Reconnect, TEXT(""), ResponseDelegate, FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnReconnectResponse));
+ CallJS(ImmutablePassportAction::ConnectSilent, TEXT(""), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnConnectSilentResponse));
}
-void UImmutablePassport::ConnectEvm(
- const FImtblPassportResponseDelegate &ResponseDelegate) {
- CallJS(ImmutablePassportAction::ConnectEvm, TEXT(""), ResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(
- this, &UImmutablePassport::OnConnectEvmResponse));
+void UImmutablePassport::ConnectEvm(const FImtblPassportResponseDelegate& ResponseDelegate)
+{
+ CallJS(ImmutablePassportAction::ConnectEvm, TEXT(""), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnConnectEvmResponse));
}
-void UImmutablePassport::ZkEvmRequestAccounts(
- const FImtblPassportResponseDelegate &ResponseDelegate) {
- CallJS(ImmutablePassportAction::ZkEvmRequestAccounts, TEXT(""),
- ResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(
- this, &UImmutablePassport::OnZkEvmRequestAccountsResponse));
+void UImmutablePassport::ZkEvmRequestAccounts(const FImtblPassportResponseDelegate& ResponseDelegate)
+{
+ CallJS(ImmutablePassportAction::ZkEvmRequestAccounts, TEXT(""), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnZkEvmRequestAccountsResponse));
}
-void UImmutablePassport::ZkEvmGetBalance(
- const FImmutablePassportZkEvmGetBalanceData &Data,
- const FImtblPassportResponseDelegate &ResponseDelegate) {
- CallJS(ImmutablePassportAction::ZkEvmGetBalance, Data.ToJsonString(),
- ResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(
- this, &UImmutablePassport::OnZkEvmGetBalanceResponse));
+void UImmutablePassport::ZkEvmGetBalance(const FImmutablePassportZkEvmGetBalanceData& Data,
+ const FImtblPassportResponseDelegate& ResponseDelegate)
+{
+ CallJS(ImmutablePassportAction::ZkEvmGetBalance, Data.ToJsonString(), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnZkEvmGetBalanceResponse));
}
-void UImmutablePassport::ZkEvmSendTransaction(
- const FImtblTransactionRequest &Request,
- const FImtblPassportResponseDelegate &ResponseDelegate) {
- CallJS(ImmutablePassportAction::ZkEvmSendTransaction,
- UStructToJsonString(Request), ResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(
- this, &UImmutablePassport::OnZkEvmSendTransactionResponse));
+void UImmutablePassport::ZkEvmSendTransaction(const FImtblTransactionRequest& Request,
+ const FImtblPassportResponseDelegate& ResponseDelegate)
+{
+ CallJS(ImmutablePassportAction::ZkEvmSendTransaction, UStructToJsonString(Request), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnZkEvmSendTransactionResponse));
}
-void UImmutablePassport::ConfirmCode(
- const FString &DeviceCode, const float Interval,
- const FImtblPassportResponseDelegate &ResponseDelegate) {
- FImmutablePassportCodeConfirmRequestData Data;
- Data.deviceCode = DeviceCode;
- Data.interval = Interval;
- CallJS(ImmutablePassportAction::ConfirmCode, UStructToJsonString(Data),
- ResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(
- this, &UImmutablePassport::OnConfirmCodeResponse));
+void UImmutablePassport::ConfirmCode(const FString& DeviceCode, const float Interval,
+ const FImtblPassportResponseDelegate& ResponseDelegate)
+{
+ FImmutablePassportCodeConfirmRequestData Data;
+
+ Data.deviceCode = DeviceCode;
+ Data.interval = Interval;
+ CallJS(ImmutablePassportAction::ConfirmCode, UStructToJsonString(Data), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnConfirmCodeResponse));
}
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
-void UImmutablePassport::ConnectPKCE(
- const FImtblPassportResponseDelegate &ResponseDelegate) {
+void UImmutablePassport::ConnectPKCE(const FImtblPassportResponseDelegate &ResponseDelegate)
+{
#if PLATFORM_ANDROID
- completingPKCE = false;
+ completingPKCE = false;
#endif
- PKCEResponseDelegate = ResponseDelegate;
- CallJS(ImmutablePassportAction::GetPKCEAuthUrl, TEXT(""),
- PKCEResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(
- this, &UImmutablePassport::OnGetPKCEAuthUrlResponse));
+ PKCEResponseDelegate = ResponseDelegate;
+ CallJS(ImmutablePassportAction::GetPKCEAuthUrl, TEXT(""), PKCEResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnGetPKCEAuthUrlResponse));
}
#endif
-void UImmutablePassport::GetIdToken(const FImtblPassportResponseDelegate &ResponseDelegate) {
- CallJS(ImmutablePassportAction::GetIdToken, TEXT(""),
- ResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnGetIdTokenResponse));
+void UImmutablePassport::GetIdToken(const FImtblPassportResponseDelegate& ResponseDelegate)
+{
+ CallJS(ImmutablePassportAction::GetIdToken, TEXT(""), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnGetIdTokenResponse));
}
-void UImmutablePassport::GetAccessToken(const FImtblPassportResponseDelegate &ResponseDelegate) {
- CallJS(ImmutablePassportAction::GetAccessToken, TEXT(""),
- ResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnGetAccessTokenResponse));
+void UImmutablePassport::GetAccessToken(const FImtblPassportResponseDelegate& ResponseDelegate)
+{
+ CallJS(ImmutablePassportAction::GetAccessToken, TEXT(""), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnGetAccessTokenResponse));
}
-void UImmutablePassport::GetAddress(
- const FImtblPassportResponseDelegate &ResponseDelegate) {
- CallJS(ImmutablePassportAction::GetAddress, TEXT(""), ResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(
- this, &UImmutablePassport::OnGetAddressResponse));
+void UImmutablePassport::GetAddress(const FImtblPassportResponseDelegate& ResponseDelegate)
+{
+ CallJS(ImmutablePassportAction::GetAddress, TEXT(""), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnGetAddressResponse));
}
-void UImmutablePassport::GetEmail(
- const FImtblPassportResponseDelegate &ResponseDelegate) {
- CallJS(ImmutablePassportAction::GetEmail, TEXT(""), ResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(
- this, &UImmutablePassport::OnGetEmailResponse));
+void UImmutablePassport::GetEmail(const FImtblPassportResponseDelegate& ResponseDelegate)
+{
+ CallJS(ImmutablePassportAction::GetEmail, TEXT(""), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnGetEmailResponse));
}
-void UImmutablePassport::ImxTransfer(
- const FImxTransferRequest &RequestData,
- const FImtblPassportResponseDelegate &ResponseDelegate) {
- IMTBL_LOG("Tranfer Request: %s", *UStructToJsonString(RequestData))
- CallJS(ImmutablePassportAction::ImxTransfer, UStructToJsonString(RequestData),
- ResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(
- this, &UImmutablePassport::OnTransferResponse));
+void UImmutablePassport::ImxTransfer(const FImxTransferRequest& RequestData,
+ const FImtblPassportResponseDelegate& ResponseDelegate)
+{
+ IMTBL_LOG("Tranfer Request: %s", *UStructToJsonString(RequestData))
+ CallJS(ImmutablePassportAction::ImxTransfer, UStructToJsonString(RequestData), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnTransferResponse));
}
-void UImmutablePassport::ImxBatchNftTransfer(
- const FImxBatchNftTransferRequest &RequestData,
- const FImtblPassportResponseDelegate &ResponseDelegate) {
- CallJS(ImmutablePassportAction::ImxBatchNftTransfer,
- RequestData.ToJsonString(), ResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(
- this, &UImmutablePassport::OnBatchNftTransferResponse));
+void UImmutablePassport::ImxBatchNftTransfer(const FImxBatchNftTransferRequest& RequestData,
+ const FImtblPassportResponseDelegate& ResponseDelegate)
+{
+ CallJS(ImmutablePassportAction::ImxBatchNftTransfer, RequestData.ToJsonString(), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnBatchNftTransferResponse));
}
void UImmutablePassport::ImxIsRegisteredOffchain(const FImtblPassportResponseDelegate& ResponseDelegate)
{
- CallJS(ImmutablePassportAction::ImxIsRegisteredOffchain, TEXT(""), ResponseDelegate, FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnImxIsRegisteredOffchain));
+ CallJS(ImmutablePassportAction::ImxIsRegisteredOffchain, TEXT(""), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnImxIsRegisteredOffchain));
}
void UImmutablePassport::ImxRegisterOffchain(const FImtblPassportResponseDelegate& ResponseDelegate)
{
- CallJS(ImmutablePassportAction::ImxRegisterOffchain, TEXT(""), ResponseDelegate, FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnImxRegisterOffchain));
+ CallJS(ImmutablePassportAction::ImxRegisterOffchain, TEXT(""), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnImxRegisterOffchain));
}
void UImmutablePassport::HasStoredCredentials(const FImtblPassportResponseDelegate& ResponseDelegate)
{
// we do check credentials into two steps, we check accessToken and then IdToken
// check access token
- CallJS(ImmutablePassportAction::GetAccessToken, TEXT(""), ResponseDelegate,
- FImtblJSResponseDelegate::CreateLambda([=](FImtblJSResponse Response)
+ CallJS(ImmutablePassportAction::GetAccessToken, TEXT(""), ResponseDelegate, FImtblJSResponseDelegate::CreateLambda(
+ [=](FImtblJSResponse Response)
+ {
+ FString AccessToken;
+
+ Response.JsonObject->TryGetStringField(TEXT("result"), AccessToken);
+ if (!Response.success || AccessToken.IsEmpty())
+ {
+ ResponseDelegate.ExecuteIfBound(FImmutablePassportResult{
+ false,
+ Response.JsonObject->HasField(TEXT("error"))
+ ? Response.JsonObject->GetStringField(TEXT("error"))
+ : "Failed to retrieve Access Token.",
+ Response
+ });
+ }
+ else
+ {
+ // check for id token
+ CallJS(ImmutablePassportAction::GetIdToken, TEXT(""), ResponseDelegate,
+ FImtblJSResponseDelegate::CreateLambda([ResponseDelegate](FImtblJSResponse Response)
+ {
+ FString IdToken;
+
+ Response.JsonObject->TryGetStringField(TEXT("result"), IdToken);
+ if (!Response.success || IdToken.IsEmpty())
+ {
+ ResponseDelegate.ExecuteIfBound(FImmutablePassportResult{
+ false,
+ Response.JsonObject->HasField(TEXT("error"))
+ ? Response.JsonObject->GetStringField(TEXT("error"))
+ : "Failed to retrieve Id Token.",
+ Response
+ });
+ }
+ else
+ {
+ ResponseDelegate.ExecuteIfBound(FImmutablePassportResult{
+ Response.success, "", Response
+ });
+ }
+ }));
+ }
+ }));
+}
+
+void UImmutablePassport::Setup(const TWeakObjectPtr Connector)
+{
+ IMTBL_LOG_FUNCSIG
+
+ if (!Connector.IsValid())
+ {
+ IMTBL_ERR("Invalid JSConnector passed to UImmutablePassport::Initialize")
+ return;
+ }
+
+ JSConnector = Connector.Get();
+}
+
+bool UImmutablePassport::CheckIsInitialized(const FString& Action,
+ const FImtblPassportResponseDelegate& ResponseDelegate) const
+{
+ if (!bIsInitialized)
+ {
+ IMTBL_WARN("Attempting action '%s' before Passport is initialized", *Action)
+ ResponseDelegate.ExecuteIfBound(FImmutablePassportResult{false, "Passport is not initialized"});
+ }
+ return bIsInitialized;
+}
+
+void UImmutablePassport::CallJS(const FString& Action, const FString& Data,
+ const FImtblPassportResponseDelegate& ClientResponseDelegate,
+ const FImtblJSResponseDelegate& HandleJSResponse,
+ const bool bCheckInitialized /*= true*/)
+{
+ if (bCheckInitialized && !CheckIsInitialized(Action, ClientResponseDelegate)) { return; }
+
+ check(JSConnector.IsValid());
+ const FString Guid = JSConnector->CallJS(Action, Data, HandleJSResponse);
+ ResponseDelegates.Add(Guid, ClientResponseDelegate);
+}
+
+TOptional UImmutablePassport::GetResponseDelegate(
+ const FImtblJSResponse& Response)
+{
+ FImtblPassportResponseDelegate ResponseDelegate;
+ if (!ResponseDelegates.RemoveAndCopyValue(Response.requestId, ResponseDelegate))
+ {
+ IMTBL_WARN("Couldn't find delegate for %s response", *Response.responseFor)
+ return TOptional();
+ }
+ return ResponseDelegate;
+}
+
+void UImmutablePassport::OnInitializeResponse(FImtblJSResponse Response)
+{
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ FString Msg;
+ if (Response.success)
{
- FString AccessToken;
-
- Response.JsonObject->TryGetStringField(TEXT("result"), AccessToken);
- if (!Response.success || AccessToken.IsEmpty())
- {
- ResponseDelegate.ExecuteIfBound(FImmutablePassportResult{false,
- Response.JsonObject->HasField(TEXT("error")) ? Response.JsonObject->GetStringField(TEXT("error")) : "Failed to retrieve Access Token.",
- Response});
- }
- else
+ bIsInitialized = true;
+ IMTBL_LOG("Passport initialization succeeded.")
+ }
+ else
+ {
+ IMTBL_ERR("Passport initialization failed.")
+ Response.Error.IsSet()
+ ? Msg = Response.Error->ToString()
+ : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ }
+
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ Response.success, Msg, Response });
+ }
+}
+
+void UImmutablePassport::OnLogoutResponse(FImtblJSResponse Response)
+{
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ if (Response.success)
+ {
+ FString Url;
+ FString Err;
+
+ Response.JsonObject->TryGetStringField(TEXT("result"), Url);
+ if (!Url.IsEmpty())
{
- // check for id token
- CallJS(ImmutablePassportAction::GetIdToken, TEXT(""), ResponseDelegate,
- FImtblJSResponseDelegate::CreateLambda([ResponseDelegate](FImtblJSResponse Response)
+#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
+ if (IsPKCEConnected)
{
- FString IdToken;
-
- Response.JsonObject->TryGetStringField(TEXT("result"), IdToken);
- if (!Response.success || IdToken.IsEmpty())
- {
- ResponseDelegate.ExecuteIfBound(FImmutablePassportResult{false,
- Response.JsonObject->HasField(TEXT("error")) ? Response.JsonObject->GetStringField(TEXT("error")) : "Failed to retrieve Id Token.",
- Response});
- }
- else
+ OnHandleDeepLink = FImtblPassportHandleDeepLinkDelegate::CreateUObject(this, &UImmutablePassport::OnDeepLinkActivated);
+#if PLATFORM_ANDROID
+ LaunchAndroidUrl(Url);
+#elif PLATFORM_IOS
+ [[ImmutableIOS instance] launchUrl:TCHAR_TO_ANSI(*Url)];
+#elif PLATFORM_MAC
+ [[ImmutableMac instance] launchUrl:TCHAR_TO_ANSI(*Url) forRedirectUri:TCHAR_TO_ANSI(*InitData.logoutRedirectUri)];
+#endif
+ }
+ else
+ {
+#endif
+ FPlatformProcess::LaunchURL(*Url, nullptr, &Err);
+ if (Err.Len())
{
- ResponseDelegate.ExecuteIfBound(FImmutablePassportResult{Response.success, "", Response});
+ FString Msg = "Failed to connect to Browser: " + Err;
+ IMTBL_ERR("%s", *Msg);
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ false, Msg, Response });
+ return;
}
- }));
- }
- }));
-}
-
-void UImmutablePassport::Setup(
- const TWeakObjectPtr Connector) {
- IMTBL_LOG_FUNCSIG
-
- if (!Connector.IsValid()) {
- IMTBL_ERR("Invalid JSConnector passed to UImmutablePassport::Initialize")
- return;
- }
-
- JSConnector = Connector.Get();
-}
-
-bool UImmutablePassport::CheckIsInitialized(
- const FString &Action,
- const FImtblPassportResponseDelegate &ResponseDelegate) const {
- if (!bIsInitialized) {
- IMTBL_WARN("Attempting action '%s' before Passport is initialized", *Action)
- ResponseDelegate.ExecuteIfBound(
- FImmutablePassportResult{false, "Passport is not initialized"});
- }
- return bIsInitialized;
-}
-
-void UImmutablePassport::CallJS(
- const FString &Action, const FString &Data,
- const FImtblPassportResponseDelegate &ClientResponseDelegate,
- const FImtblJSResponseDelegate &HandleJSResponse,
- const bool bCheckInitialized /*= true*/) {
- if (bCheckInitialized && !CheckIsInitialized(Action, ClientResponseDelegate))
- return;
-
- check(JSConnector.IsValid());
- const FString Guid = JSConnector->CallJS(Action, Data, HandleJSResponse);
- ResponseDelegates.Add(Guid, ClientResponseDelegate);
-}
-
-TOptional
-UImmutablePassport::GetResponseDelegate(const FImtblJSResponse &Response) {
- FImtblPassportResponseDelegate ResponseDelegate;
- if (!ResponseDelegates.RemoveAndCopyValue(Response.requestId,
- ResponseDelegate)) {
- IMTBL_WARN("Couldn't find delegate for %s response", *Response.responseFor)
- return TOptional();
- }
- return ResponseDelegate;
-}
-
-void UImmutablePassport::OnInitializeResponse(FImtblJSResponse Response) {
- if (auto ResponseDelegate = GetResponseDelegate(Response)) {
- FString Msg;
- if (Response.success) {
- bIsInitialized = true;
- IMTBL_LOG("Passport initialization succeeded.")
- } else {
- IMTBL_ERR("Passport initialization failed.")
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- }
-
- ResponseDelegate->ExecuteIfBound(
- FImmutablePassportResult{Response.success, Msg, Response});
- }
-}
-
-void UImmutablePassport::OnLogoutResponse(FImtblJSResponse Response) {
- if (auto ResponseDelegate = GetResponseDelegate(Response)) {
- FString Msg;
- if (Response.success) {
- IMTBL_LOG("Logged out.")
- bIsLoggedIn = false;
- } else {
- IMTBL_ERR("Error logging out.")
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- }
- ResponseDelegate->ExecuteIfBound(
- FImmutablePassportResult{Response.success, Msg, Response});
- }
-}
-
-void UImmutablePassport::OnConnectResponse(FImtblJSResponse Response) {
- if (auto ResponseDelegate = GetResponseDelegate(Response)) {
- const auto ConnectData =
- JsonObjectToUStruct(Response.JsonObject);
- if (!Response.success || !ConnectData || !ConnectData->code.Len()) {
- FString Msg;
- IMTBL_WARN("Connect attempt failed.");
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- ResponseDelegate->ExecuteIfBound(
- FImmutablePassportResult{false, Msg, Response});
- return;
- }
- FString Err;
- FPlatformProcess::LaunchURL(*ConnectData->url, nullptr, &Err);
- if (Err.Len()) {
- FString Msg = "Failed to connect to Browser: " + Err;
- IMTBL_ERR("%s", *Msg);
- ResponseDelegate->ExecuteIfBound(
- FImmutablePassportResult{false, Msg, Response});
- return;
- }
- ConfirmCode(ConnectData->deviceCode, ConnectData->interval,
- ResponseDelegate.GetValue());
- }
-}
-
-void UImmutablePassport::OnReconnectResponse(FImtblJSResponse Response)
-{
- if (auto ResponseDelegate = GetResponseDelegate(Response)) {
+ IMTBL_LOG("Logged out.")
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ Response.success, "Logged out" });
+#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
+ }
+#endif
+ }
+ else
+ {
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ false, "Logout Url is empty", Response });
+ }
+ bIsLoggedIn = false;
+ }
+ else
+ {
+ FString Msg = Response.Error.IsSet() ? Response.Error->ToString() : Response.JsonObject->GetStringField(TEXT("error"));
+
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ Response.success, Msg, Response });
+
+ IMTBL_ERR("Error logging out.")
+ }
+ }
+}
+
+void UImmutablePassport::OnConnectResponse(FImtblJSResponse Response)
+{
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ const auto ConnectData = JsonObjectToUStruct(Response.JsonObject);
+ if (!Response.success || !ConnectData || !ConnectData->code.Len())
+ {
+ FString Msg;
+ IMTBL_WARN("Connect attempt failed.");
+ Response.Error.IsSet() ? Msg = Response.Error->ToString() : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ false, Msg, Response });
+ return;
+ }
+ FString Err;
+ FPlatformProcess::LaunchURL(*ConnectData->url, nullptr, &Err);
+ if (Err.Len())
+ {
+ FString Msg = "Failed to connect to Browser: " + Err;
+ IMTBL_ERR("%s", *Msg);
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ false, Msg, Response });
+ return;
+ }
+ ConfirmCode(ConnectData->deviceCode, ConnectData->interval, ResponseDelegate.GetValue());
+ }
+}
+
+void UImmutablePassport::OnConnectSilentResponse(FImtblJSResponse Response)
+{
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
FString Msg;
-
+
if (Response.success)
{
IMTBL_LOG("Reconnected.")
@@ -448,491 +490,543 @@ void UImmutablePassport::OnReconnectResponse(FImtblJSResponse Response)
else
{
IMTBL_ERR("Failed to reconnect.")
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ Response.Error.IsSet() ? Msg = Response.Error->ToString() : Msg = Response.JsonObject->GetStringField(TEXT("error"));
}
- ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{Response.success, Msg, Response});
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ Response.success, Msg, Response });
}
}
-void UImmutablePassport::OnConnectEvmResponse(FImtblJSResponse Response) {
- if (auto ResponseDelegate = GetResponseDelegate(Response)) {
- FString Msg;
- if (Response.success) {
- IMTBL_LOG("Connected to Evm.")
- } else {
- IMTBL_WARN("Error connecting to Evm.")
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- }
- ResponseDelegate->ExecuteIfBound(
- FImmutablePassportResult{Response.success, Msg});
- }
+void UImmutablePassport::OnConnectEvmResponse(FImtblJSResponse Response)
+{
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ FString Msg;
+ if (Response.success)
+ {
+ IMTBL_LOG("Connected to Evm.")
+ }
+ else
+ {
+ IMTBL_WARN("Error connecting to Evm.")
+ Response.Error.IsSet()
+ ? Msg = Response.Error->ToString()
+ : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ }
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{Response.success, Msg});
+ }
}
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
-void UImmutablePassport::OnGetPKCEAuthUrlResponse(FImtblJSResponse Response) {
- if (PKCEResponseDelegate.IsBound()) {
- FString Msg;
- bool bSuccess = true;
- if (!Response.success ||
- !Response.JsonObject->HasTypedField(TEXT("result"))) {
- IMTBL_LOG("Could not get PKCE auth URL from Passport.");
- } else {
- // Handle deeplink calls
- OnHandleDeepLink = FImtblPassportHandleDeepLinkDelegate::CreateUObject(
- this, &UImmutablePassport::OnDeepLinkActivated);
-
- FString Err;
- Msg = Response.JsonObject->GetStringField(TEXT("result"))
- .Replace(TEXT(" "), TEXT("+"));
+void UImmutablePassport::OnGetPKCEAuthUrlResponse(FImtblJSResponse Response)
+{
+ if (PKCEResponseDelegate.IsBound())
+ {
+ FString Msg;
+ bool bSuccess = true;
+
+ if (!Response.success || !Response.JsonObject->HasTypedField(TEXT("result")))
+ {
+ IMTBL_LOG("Could not get PKCE auth URL from Passport.");
+ }
+ else
+ {
+ // Handle deeplink calls
+ OnHandleDeepLink = FImtblPassportHandleDeepLinkDelegate::CreateUObject(this, &UImmutablePassport::OnDeepLinkActivated);
+
+ Msg = Response.JsonObject->GetStringField(TEXT("result")).Replace(TEXT(" "), TEXT("+"));
#if PLATFORM_ANDROID
- OnPKCEDismissed = FImtblPassportOnPKCEDismissedDelegate::CreateUObject(
- this, &UImmutablePassport::HandleOnPKCEDismissed);
-
- JNIEnv *Env = FAndroidApplication::GetJavaEnv();
- if (Env) {
- jstring jurl = Env->NewStringUTF(TCHAR_TO_UTF8(*Msg));
- jclass jimmutableAndroidClass = FAndroidApplication::FindJavaClass(
- "com/immutable/unreal/ImmutableAndroid");
- static jmethodID jlaunchUrl = FJavaWrapper::FindStaticMethod(
- Env, jimmutableAndroidClass, "launchUrl",
- "(Landroid/app/Activity;Ljava/lang/String;)V", false);
- CallJniStaticVoidMethod(Env, jimmutableAndroidClass, jlaunchUrl,
- FJavaWrapper::GameActivityThis, jurl);
- }
+ OnPKCEDismissed = FImtblPassportOnPKCEDismissedDelegate::CreateUObject(this, &UImmutablePassport::HandleOnLoginPKCEDismissed);
+ LaunchAndroidUrl(Msg);
#elif PLATFORM_IOS
- [[ImmutableIOS instance] launchUrl:TCHAR_TO_ANSI(*Msg)];
+ [[ImmutableIOS instance] launchUrl:TCHAR_TO_ANSI(*Msg)];
#elif PLATFORM_MAC
- [[ImmutableMac instance] launchUrl:TCHAR_TO_ANSI(*Msg)
- forRedirectUri:TCHAR_TO_ANSI(*InitData.redirectUri)];
+ [[ImmutableMac instance] launchUrl:TCHAR_TO_ANSI(*Msg) forRedirectUri:TCHAR_TO_ANSI(*InitData.redirectUri)];
#endif
+ }
+ }
+ else
+ {
+ IMTBL_ERR("Unable to return a response for Connect PKCE");
+ }
+}
- if (Err.Len()) {
- Msg = "Failed to connect to Browser: " + Err;
- IMTBL_ERR("%s", *Msg);
- bSuccess = false;
- } else {
- return;
- }
- }
- PKCEResponseDelegate.ExecuteIfBound(
- FImmutablePassportResult{bSuccess, Msg});
- PKCEResponseDelegate = nullptr;
- } else {
- IMTBL_ERR("Unable to return a response for Connect PKCE");
- }
-}
-
-void UImmutablePassport::OnConnectPKCEResponse(FImtblJSResponse Response) {
- if (PKCEResponseDelegate.IsBound()) {
- FString Msg;
- if (Response.success) {
- IMTBL_LOG("Successfully connected via PKCE")
- bIsLoggedIn = true;
- } else {
- IMTBL_WARN("Connect PKCE attempt failed.");
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- }
- PKCEResponseDelegate.ExecuteIfBound(
- FImmutablePassportResult{Response.success, Msg});
- PKCEResponseDelegate = nullptr;
- } else {
- IMTBL_ERR("Unable to return a response for Connect PKCE");
- }
+void UImmutablePassport::OnConnectPKCEResponse(FImtblJSResponse Response)
+{
+ if (PKCEResponseDelegate.IsBound())
+ {
+ FString Msg;
+
+ if (Response.success)
+ {
+ IMTBL_LOG("Successfully connected via PKCE")
+ bIsLoggedIn = true;
+ IsPKCEConnected = true;
+ }
+ else
+ {
+ IMTBL_WARN("Connect PKCE attempt failed.");
+ Response.Error.IsSet() ? Msg = Response.Error->ToString() : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ }
+ PKCEResponseDelegate.ExecuteIfBound(FImmutablePassportResult{Response.success, Msg});
+ PKCEResponseDelegate = nullptr;
+ }
+ else
+ {
+ IMTBL_ERR("Unable to return a response for Connect PKCE");
+ }
#if PLATFORM_ANDROID
- completingPKCE = false;
+ completingPKCE = false;
#endif
}
#endif
void UImmutablePassport::OnGetIdTokenResponse(FImtblJSResponse Response)
{
- if (auto ResponseDelegate = GetResponseDelegate(Response))
- {
- FString IdToken;
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ FString IdToken;
- Response.JsonObject->TryGetStringField(TEXT("result"), IdToken);
+ Response.JsonObject->TryGetStringField(TEXT("result"), IdToken);
- if (!Response.success || IdToken.IsEmpty())
- {
- IMTBL_LOG("Failed to retrieve Id Token.");
+ if (!Response.success || IdToken.IsEmpty())
+ {
+ IMTBL_LOG("Failed to retrieve Id Token.");
- const FString Msg = Response.JsonObject->HasField(TEXT("error")) ? Response.JsonObject->GetStringField(TEXT("error")) : "Failed to retrieve Id Token.";
+ const FString Msg = Response.JsonObject->HasField(TEXT("error"))
+ ? Response.JsonObject->GetStringField(TEXT("error"))
+ : "Failed to retrieve Id Token.";
- ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ false, Msg, Response });
- }
- else
- {
- IMTBL_LOG("Retrieved Id Token.");
- ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ true, IdToken });
- }
- }
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{false, Msg, Response});
+ }
+ else
+ {
+ IMTBL_LOG("Retrieved Id Token.");
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{true, IdToken});
+ }
+ }
}
void UImmutablePassport::OnGetAccessTokenResponse(FImtblJSResponse Response)
{
- if (auto ResponseDelegate = GetResponseDelegate(Response))
- {
- FString AccessToken;
-
- Response.JsonObject->TryGetStringField(TEXT("result"), AccessToken);
-
- if (!Response.success || AccessToken.IsEmpty())
- {
- IMTBL_LOG("Failed to retrieve Access Token");
-
- const FString Msg = Response.JsonObject->HasField(TEXT("error")) ? Response.JsonObject->GetStringField(TEXT("error")) : "Failed to retrieve Access Token.";
-
- ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ false, Msg, Response });
- }
- else
- {
- IMTBL_LOG("Retrieved Access Token.");
- ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ true, AccessToken });
- }
- }
-}
-
-void UImmutablePassport::OnGetAddressResponse(FImtblJSResponse Response) {
- if (auto ResponseDelegate = GetResponseDelegate(Response)) {
- auto ConnectData =
- JsonObjectToUStruct(Response.JsonObject);
-
- FString Msg;
- bool bSuccess = true;
- if (!Response.success ||
- !Response.JsonObject->HasTypedField(TEXT("result"))) {
- IMTBL_WARN("Could not fetch address from Passport.");
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- bSuccess = false;
- } else {
- Msg = Response.JsonObject->GetStringField(TEXT("result"));
- }
- ResponseDelegate->ExecuteIfBound(
- FImmutablePassportResult{bSuccess, Msg, Response});
- }
-}
-
-void UImmutablePassport::OnZkEvmRequestAccountsResponse(
- FImtblJSResponse Response) {
- if (auto ResponseDelegate = GetResponseDelegate(Response)) {
- const auto RequestAccountstData =
- FImmutablePassportZkEvmRequestAccountsData::FromJsonObject(
- Response.JsonObject);
- FString Msg;
- bool bSuccess = true;
- if (!Response.success ||
- !Response.JsonObject->HasTypedField(TEXT("accounts"))) {
- IMTBL_WARN("Error requesting zkevm accounts.")
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- bSuccess = false;
- } else {
- const auto size = RequestAccountstData->accounts.Num();
- for (int32 Index = 0; Index != size; ++Index) {
- Msg += RequestAccountstData->accounts[Index];
- if (Index < size - 1) {
- Msg += TEXT(",");
- }
- }
- }
- ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{bSuccess, Msg});
- }
-}
-
-void UImmutablePassport::OnZkEvmGetBalanceResponse(FImtblJSResponse Response) {
- if (auto ResponseDelegate = GetResponseDelegate(Response)) {
- FString Msg;
- bool bSuccess = true;
- if (!Response.success ||
- !Response.JsonObject->HasTypedField(TEXT("result"))) {
- IMTBL_WARN("Could not get balance.");
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- bSuccess = false;
- } else {
- Msg = Response.JsonObject->GetStringField(TEXT("result"));
- }
- ResponseDelegate->ExecuteIfBound(
- FImmutablePassportResult{bSuccess, Msg, Response});
- }
-}
-
-void UImmutablePassport::OnZkEvmSendTransactionResponse(
- FImtblJSResponse Response) {
- if (auto ResponseDelegate = GetResponseDelegate(Response)) {
- FString Msg;
- bool bSuccess = true;
- if (!Response.success ||
- !Response.JsonObject->HasTypedField(TEXT("result"))) {
- IMTBL_WARN("Could not fetch send transaction.");
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- bSuccess = false;
- } else {
- Msg = Response.JsonObject->GetStringField(TEXT("result"));
- }
- ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{bSuccess, Msg});
- }
-}
-
-void UImmutablePassport::OnConfirmCodeResponse(FImtblJSResponse Response) {
- if (auto ResponseDelegate = GetResponseDelegate(Response)) {
- FString Msg;
- if (Response.success) {
- IMTBL_LOG("Log in code confirmed.")
- bIsLoggedIn = true;
- } else {
- IMTBL_WARN("Login code not confirmed.")
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- }
- ResponseDelegate->ExecuteIfBound(
- FImmutablePassportResult{Response.success, Msg, Response});
- }
-}
-
-void UImmutablePassport::OnGetEmailResponse(FImtblJSResponse Response) {
- if (auto ResponseDelegate = GetResponseDelegate(Response)) {
- auto ConnectData =
- JsonObjectToUStruct(Response.JsonObject);
-
- FString Msg;
- bool bSuccess = true;
- if (!Response.success ||
- !Response.JsonObject->HasTypedField(TEXT("result"))) {
- IMTBL_WARN("Connect attempt failed.");
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- bSuccess = false;
- } else {
- Msg = Response.JsonObject->GetStringField(TEXT("result"));
- }
- ResponseDelegate->ExecuteIfBound(
- FImmutablePassportResult{bSuccess, Msg, Response});
- }
-}
-
-void UImmutablePassport::OnTransferResponse(FImtblJSResponse Response) {
- if (auto ResponseDelegate = GetResponseDelegate(Response)) {
- FString Msg;
- bool bSuccess = true;
- if (!Response.success) {
- IMTBL_WARN("ImxTransfer failed.");
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- bSuccess = false;
- } else {
- Msg = Response.JsonObject->GetStringField(TEXT("status"));
- }
- ResponseDelegate->ExecuteIfBound(
- FImmutablePassportResult{bSuccess, Msg, Response});
- }
-}
-
-void UImmutablePassport::OnBatchNftTransferResponse(FImtblJSResponse Response) {
- if (auto ResponseDelegate = GetResponseDelegate(Response)) {
- auto BatchNftTransferResponse =
- JsonObjectToUStruct(Response.JsonObject);
-
- FString Msg;
- bool bSuccess = true;
- if (!Response.success ||
- !Response.JsonObject->HasTypedField(TEXT("result"))) {
- IMTBL_WARN("ImxBatchNftTransfer failed.");
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- bSuccess = false;
- } else {
- Msg = UStructToJsonString(*BatchNftTransferResponse);
- }
- ResponseDelegate->ExecuteIfBound(
- FImmutablePassportResult{bSuccess, Msg, Response});
- }
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ FString AccessToken;
+
+ Response.JsonObject->TryGetStringField(TEXT("result"), AccessToken);
+
+ if (!Response.success || AccessToken.IsEmpty())
+ {
+ IMTBL_LOG("Failed to retrieve Access Token");
+
+ const FString Msg = Response.JsonObject->HasField(TEXT("error"))
+ ? Response.JsonObject->GetStringField(TEXT("error"))
+ : "Failed to retrieve Access Token.";
+
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{false, Msg, Response});
+ }
+ else
+ {
+ IMTBL_LOG("Retrieved Access Token.");
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{true, AccessToken});
+ }
+ }
+}
+
+void UImmutablePassport::OnGetAddressResponse(FImtblJSResponse Response)
+{
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ auto ConnectData = JsonObjectToUStruct(Response.JsonObject);
+
+ FString Msg;
+ bool bSuccess = true;
+ if (!Response.success || !Response.JsonObject->HasTypedField(TEXT("result")))
+ {
+ IMTBL_WARN("Could not fetch address from Passport.");
+ Response.Error.IsSet()
+ ? Msg = Response.Error->ToString()
+ : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ bSuccess = false;
+ }
+ else
+ {
+ Msg = Response.JsonObject->GetStringField(TEXT("result"));
+ }
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{bSuccess, Msg, Response});
+ }
+}
+
+void UImmutablePassport::OnZkEvmRequestAccountsResponse(FImtblJSResponse Response)
+{
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ const auto RequestAccountstData = FImmutablePassportZkEvmRequestAccountsData::FromJsonObject(
+ Response.JsonObject);
+ FString Msg;
+ bool bSuccess = true;
+ if (!Response.success || !Response.JsonObject->HasTypedField(TEXT("accounts")))
+ {
+ IMTBL_WARN("Error requesting zkevm accounts.")
+ Response.Error.IsSet()
+ ? Msg = Response.Error->ToString()
+ : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ bSuccess = false;
+ }
+ else
+ {
+ const auto size = RequestAccountstData->accounts.Num();
+ for (int32 Index = 0; Index != size; ++Index)
+ {
+ Msg += RequestAccountstData->accounts[Index];
+ if (Index < size - 1)
+ {
+ Msg += TEXT(",");
+ }
+ }
+ }
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{bSuccess, Msg});
+ }
+}
+
+void UImmutablePassport::OnZkEvmGetBalanceResponse(FImtblJSResponse Response)
+{
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ FString Msg;
+ bool bSuccess = true;
+ if (!Response.success || !Response.JsonObject->HasTypedField(TEXT("result")))
+ {
+ IMTBL_WARN("Could not get balance.");
+ Response.Error.IsSet()
+ ? Msg = Response.Error->ToString()
+ : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ bSuccess = false;
+ }
+ else
+ {
+ Msg = Response.JsonObject->GetStringField(TEXT("result"));
+ }
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{bSuccess, Msg, Response});
+ }
+}
+
+void UImmutablePassport::OnZkEvmSendTransactionResponse(FImtblJSResponse Response)
+{
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ FString Msg;
+ bool bSuccess = true;
+ if (!Response.success || !Response.JsonObject->HasTypedField(TEXT("result")))
+ {
+ IMTBL_WARN("Could not fetch send transaction.");
+ Response.Error.IsSet()
+ ? Msg = Response.Error->ToString()
+ : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ bSuccess = false;
+ }
+ else
+ {
+ Msg = Response.JsonObject->GetStringField(TEXT("result"));
+ }
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{bSuccess, Msg});
+ }
+}
+
+void UImmutablePassport::OnConfirmCodeResponse(FImtblJSResponse Response)
+{
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ FString Msg;
+
+ if (Response.success)
+ {
+ IMTBL_LOG("Log in code confirmed.")
+ bIsLoggedIn = true;
+ }
+ else
+ {
+ IMTBL_WARN("Login code not confirmed.")
+ Response.Error.IsSet() ? Msg = Response.Error->ToString() : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ }
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ Response.success, Msg, Response });
+ }
+}
+
+void UImmutablePassport::OnGetEmailResponse(FImtblJSResponse Response)
+{
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ auto ConnectData = JsonObjectToUStruct(Response.JsonObject);
+
+ FString Msg;
+ bool bSuccess = true;
+ if (!Response.success || !Response.JsonObject->HasTypedField(TEXT("result")))
+ {
+ IMTBL_WARN("Connect attempt failed.");
+ Response.Error.IsSet()
+ ? Msg = Response.Error->ToString()
+ : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ bSuccess = false;
+ }
+ else
+ {
+ Msg = Response.JsonObject->GetStringField(TEXT("result"));
+ }
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{bSuccess, Msg, Response});
+ }
+}
+
+void UImmutablePassport::OnTransferResponse(FImtblJSResponse Response)
+{
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ FString Msg;
+ bool bSuccess = true;
+ if (!Response.success)
+ {
+ IMTBL_WARN("ImxTransfer failed.");
+ Response.Error.IsSet()
+ ? Msg = Response.Error->ToString()
+ : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ bSuccess = false;
+ }
+ else
+ {
+ Msg = Response.JsonObject->GetStringField(TEXT("status"));
+ }
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{bSuccess, Msg, Response});
+ }
+}
+
+void UImmutablePassport::OnBatchNftTransferResponse(FImtblJSResponse Response)
+{
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ auto BatchNftTransferResponse = JsonObjectToUStruct(Response.JsonObject);
+
+ FString Msg;
+ bool bSuccess = true;
+ if (!Response.success || !Response.JsonObject->HasTypedField(TEXT("result")))
+ {
+ IMTBL_WARN("ImxBatchNftTransfer failed.");
+ Response.Error.IsSet()
+ ? Msg = Response.Error->ToString()
+ : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ bSuccess = false;
+ }
+ else
+ {
+ Msg = UStructToJsonString(*BatchNftTransferResponse);
+ }
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{bSuccess, Msg, Response});
+ }
}
void UImmutablePassport::OnImxIsRegisteredOffchain(FImtblJSResponse Response)
{
- if (auto ResponseDelegate = GetResponseDelegate(Response))
- {
- FString Msg;
- bool bResult = false;
-
- if (!Response.success)
- {
- IMTBL_WARN("ImxIsRegisteredOffchain failed.");
- Response.Error.IsSet() ? Msg = Response.Error->ToString() : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- }
- else
- {
- bResult = Response.JsonObject->GetBoolField(TEXT("result"));
- }
- ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ bResult, Msg, Response });
- }
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ FString Msg;
+ bool bResult = false;
+
+ if (!Response.success)
+ {
+ IMTBL_WARN("ImxIsRegisteredOffchain failed.");
+ Response.Error.IsSet()
+ ? Msg = Response.Error->ToString()
+ : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ }
+ else
+ {
+ bResult = Response.JsonObject->GetBoolField(TEXT("result"));
+ }
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{bResult, Msg, Response});
+ }
}
void UImmutablePassport::OnImxRegisterOffchain(FImtblJSResponse Response)
{
- if (auto ResponseDelegate = GetResponseDelegate(Response))
- {
- FString Msg;
-
- if (!Response.success)
- {
- IMTBL_WARN("ImxRegisterOffchain failed.");
- Response.Error.IsSet() ? Msg = Response.Error->ToString() : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- }
-
- ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ Response.success, Msg, Response });
- }
-}
-
-void UImmutablePassport::LogAndIgnoreResponse(FImtblJSResponse Response) {
- if (Response.success && !Response.Error) {
- IMTBL_LOG("Received success response from Passport for action %s",
- *Response.responseFor);
- } else {
- FString Msg;
- Response.Error.IsSet()
- ? Msg = Response.Error->ToString()
- : Msg = Response.JsonObject->GetStringField(TEXT("error"));
- IMTBL_WARN("Received error response from Passport for action %s -- %s",
- *Response.responseFor, *Msg);
- }
+ if (auto ResponseDelegate = GetResponseDelegate(Response))
+ {
+ FString Msg;
+
+ if (!Response.success)
+ {
+ IMTBL_WARN("ImxRegisterOffchain failed.");
+ Response.Error.IsSet()
+ ? Msg = Response.Error->ToString()
+ : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ }
+
+ ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{Response.success, Msg, Response});
+ }
+}
+
+void UImmutablePassport::LogAndIgnoreResponse(FImtblJSResponse Response)
+{
+ if (Response.success && !Response.Error)
+ {
+ IMTBL_LOG("Received success response from Passport for action %s", *Response.responseFor);
+ }
+ else
+ {
+ FString Msg;
+ Response.Error.IsSet()
+ ? Msg = Response.Error->ToString()
+ : Msg = Response.JsonObject->GetStringField(TEXT("error"));
+ IMTBL_WARN("Received error response from Passport for action %s -- %s", *Response.responseFor, *Msg);
+ }
}
-#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
-void UImmutablePassport::OnDeepLinkActivated(FString DeepLink) {
- IMTBL_LOG("On Deep Link Activated: %s", *DeepLink);
- OnHandleDeepLink = nullptr;
- if (DeepLink.StartsWith(InitData.redirectUri)) {
- CompletePKCEFlow(DeepLink);
- }
+#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
+void UImmutablePassport::OnDeepLinkActivated(FString DeepLink)
+{
+ IMTBL_LOG_FUNC("URL : %s", *DeepLink);
+ OnHandleDeepLink = nullptr;
+ if (DeepLink.StartsWith(InitData.logoutRedirectUri))
+ {
+ // execute on game thread
+ if (FTaskGraphInterface::IsRunning())
+ {
+ FGraphEventRef GameThreadTask = FFunctionGraphTask::CreateAndDispatchWhenReady([this]()
+ {
+ PKCELogoutResponseDelegate.ExecuteIfBound(FImmutablePassportResult{ true, "Logged out" });
+ PKCELogoutResponseDelegate = nullptr;
+ }, TStatId(), nullptr, ENamedThreads::GameThread);
+ }
+
+ IsPKCEConnected = false;
+ }
+ else if (DeepLink.StartsWith(InitData.redirectUri))
+ {
+ CompleteLoginPKCEFlow(DeepLink);
+ }
}
-void UImmutablePassport::CompletePKCEFlow(FString Url) {
+void UImmutablePassport::CompleteLoginPKCEFlow(FString Url)
+{
#if PLATFORM_ANDROID
- completingPKCE = true;
+ completingPKCE = true;
#endif
- // Get code and state from deeplink URL
- TOptional Code, State;
- FString Endpoint, Params;
- Url.Split(TEXT("?"), &Endpoint, &Params);
- TArray ParamsArray;
- Params.ParseIntoArray(ParamsArray, TEXT("&"));
- for (FString Param : ParamsArray) {
- FString Key, Value;
- if (Param.StartsWith("code")) {
- Param.Split(TEXT("="), &Key, &Value);
- Code = Value;
- } else if (Param.StartsWith("state")) {
- Param.Split(TEXT("="), &Key, &Value);
- State = Value;
- }
- }
-
- if (!Code.IsSet() || !State.IsSet()) {
- const FString ErrorMsg =
- "Uri was missing state and/or code. Please call ConnectPKCE() again";
- IMTBL_ERR("%s", *ErrorMsg);
- PKCEResponseDelegate.ExecuteIfBound(
- FImmutablePassportResult{false, ErrorMsg});
- PKCEResponseDelegate = nullptr;
+ // Get code and state from deeplink URL
+ TOptional Code, State;
+ FString Endpoint, Params;
+ Url.Split(TEXT("?"), &Endpoint, &Params);
+ TArray ParamsArray;
+
+ Params.ParseIntoArray(ParamsArray, TEXT("&"));
+ for (FString Param : ParamsArray)
+ {
+ FString Key, Value;
+
+ if (Param.StartsWith("code"))
+ {
+ Param.Split(TEXT("="), &Key, &Value);
+ Code = Value;
+ }
+ else if (Param.StartsWith("state"))
+ {
+ Param.Split(TEXT("="), &Key, &Value);
+ State = Value;
+ }
+ }
+
+ if (!Code.IsSet() || !State.IsSet())
+ {
+ const FString ErrorMsg = "Uri was missing state and/or code. Please call ConnectPKCE() again";
+
+ IMTBL_ERR("%s", *ErrorMsg);
+ PKCEResponseDelegate.ExecuteIfBound(FImmutablePassportResult{false, ErrorMsg});
+ PKCEResponseDelegate = nullptr;
#if PLATFORM_ANDROID
- completingPKCE = false;
+ completingPKCE = false;
#endif
- } else {
- FImmutablePassportConnectPKCEData Data =
- FImmutablePassportConnectPKCEData{Code.GetValue(), State.GetValue()};
- CallJS(ImmutablePassportAction::ConnectPKCE, UStructToJsonString(Data),
- PKCEResponseDelegate,
- FImtblJSResponseDelegate::CreateUObject(
- this, &UImmutablePassport::OnConnectPKCEResponse));
- }
+ }
+ else
+ {
+ FImmutablePassportConnectPKCEData Data = FImmutablePassportConnectPKCEData{Code.GetValue(), State.GetValue()};
+
+ CallJS(ImmutablePassportAction::ConnectPKCE, UStructToJsonString(Data), PKCEResponseDelegate,
+ FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnConnectPKCEResponse));
+ }
}
#endif
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
#if PLATFORM_ANDROID
// Called from Android JNI
-void UImmutablePassport::HandleDeepLink(FString DeepLink) {
+void UImmutablePassport::HandleDeepLink(FString DeepLink) const
+{
#elif PLATFORM_IOS | PLATFORM_MAC
// Called from iOS Objective C
-void UImmutablePassport::HandleDeepLink(NSString *sDeepLink) {
- FString DeepLink = FString(UTF8_TO_TCHAR([sDeepLink UTF8String]));
- IMTBL_LOG("Handle Deep Link: %s", *DeepLink);
+void UImmutablePassport::HandleDeepLink(NSString *sDeepLink) const
+{
+ FString DeepLink = FString(UTF8_TO_TCHAR([sDeepLink UTF8String]));
+ IMTBL_LOG("Handle Deep Link: %s", *DeepLink);
#endif
- if (!OnHandleDeepLink.ExecuteIfBound(DeepLink)) {
- IMTBL_WARN("OnHandleDeepLink delegate was not called");
- }
+ if (!OnHandleDeepLink.ExecuteIfBound(DeepLink))
+ {
+ IMTBL_WARN("OnHandleDeepLink delegate was not called");
+ }
}
#endif
#if PLATFORM_ANDROID
-void UImmutablePassport::HandleOnPKCEDismissed() {
- IMTBL_LOG("Handle On PKCE Dismissed");
- OnPKCEDismissed = nullptr;
- if (!completingPKCE) {
- // User hasn't entered all required details (e.g. email address) into
- // Passport yet
- IMTBL_LOG("PKCE dismissed before completing the flow");
- if (!PKCEResponseDelegate.ExecuteIfBound(
- FImmutablePassportResult{false, "Cancelled"})) {
- IMTBL_WARN("PKCEResponseDelegate delegate was not called");
- }
- PKCEResponseDelegate = nullptr;
- } else {
- IMTBL_LOG("PKCE dismissed by user or SDK");
- }
-}
-
-void UImmutablePassport::HandleCustomTabsDismissed() {
- IMTBL_LOG("On PKCE Dismissed");
- if (!OnPKCEDismissed.ExecuteIfBound()) {
- IMTBL_WARN("OnPKCEDismissed delegate was not called");
- }
-}
-
-void UImmutablePassport::CallJniStaticVoidMethod(JNIEnv *Env,
- const jclass Class,
- jmethodID Method, ...) {
- va_list Args;
- va_start(Args, Method);
- Env->CallStaticVoidMethodV(Class, Method, Args);
- va_end(Args);
-
- Env->DeleteLocalRef(Class);
+void UImmutablePassport::HandleOnLoginPKCEDismissed()
+{
+ IMTBL_LOG("Handle On Login PKCE Dismissed");
+ OnPKCEDismissed = nullptr;
+
+ if (!completingPKCE)
+ {
+ // User hasn't entered all required details (e.g. email address) into
+ // Passport yet
+ IMTBL_LOG("Login PKCE dismissed before completing the flow");
+ if (!PKCEResponseDelegate.ExecuteIfBound(FImmutablePassportResult{ false, "Cancelled" }))
+ {
+ IMTBL_WARN("Login PKCEResponseDelegate delegate was not called");
+ }
+ PKCEResponseDelegate = nullptr;
+ }
+ else
+ {
+ IMTBL_LOG("PKCE dismissed by user or SDK");
+ }
}
-#endif
-// void UImmutablePassport::OnReady(const FOnPassportReadyDelegate::FDelegate&
-// Delegate)
-// {
-// if (JSConnector->IsBridgeReady())
-// {
-// // TODO: run on next tick rather than immediately
-// Delegate.ExecuteIfBound();
-// }
-// else
-// {
-// OnPassportReady.Add(Delegate);
-// }
-// }
\ No newline at end of file
+void UImmutablePassport::HandleCustomTabsDismissed(FString Url)
+{
+ IMTBL_LOG("On PKCE Dismissed");
+
+ if (!OnPKCEDismissed.ExecuteIfBound())
+ {
+ IMTBL_WARN("OnPKCEDismissed delegate was not called");
+ }
+}
+
+void UImmutablePassport::CallJniStaticVoidMethod(JNIEnv *Env, const jclass Class, jmethodID Method, ...)
+{
+ va_list Args;
+
+ va_start(Args, Method);
+ Env->CallStaticVoidMethodV(Class, Method, Args);
+ va_end(Args);
+ Env->DeleteLocalRef(Class);
+}
+
+void UImmutablePassport::LaunchAndroidUrl(FString Url)
+{
+ if (JNIEnv *Env = FAndroidApplication::GetJavaEnv())
+ {
+ jstring jurl = Env->NewStringUTF(TCHAR_TO_UTF8(*Url));
+ jclass jimmutableAndroidClass = FAndroidApplication::FindJavaClass("com/immutable/unreal/ImmutableAndroid");
+ static jmethodID jlaunchUrl = FJavaWrapper::FindStaticMethod(Env, jimmutableAndroidClass, "launchUrl", "(Landroid/app/Activity;Ljava/lang/String;)V", false);
+
+ CallJniStaticVoidMethod(Env, jimmutableAndroidClass, jlaunchUrl, FJavaWrapper::GameActivityThis, jurl);
+ }
+}
+#endif
diff --git a/Source/Immutable/Private/Immutable/ImtblBlui.cpp b/Source/Immutable/Private/Immutable/ImtblBlui.cpp
index 88a44fd5..ffe03772 100644
--- a/Source/Immutable/Private/Immutable/ImtblBlui.cpp
+++ b/Source/Immutable/Private/Immutable/ImtblBlui.cpp
@@ -141,6 +141,10 @@ void UImtblBlui::Init() {
this, &UImtblBlui::WorldTickStart);
}
}
+ else
+ {
+ IMTBL_ERR("Failed to load Immutable bridge asset.")
+ }
// Do this after the the page is given to the browser and being loaded...
JSConnector->Init(!BluEye->IsBrowserLoading());
diff --git a/Source/Immutable/Private/Immutable/Mac/ImmutableMac.cpp b/Source/Immutable/Private/Immutable/Mac/ImmutableMac.cpp
index 7c7efa00..411f7445 100644
--- a/Source/Immutable/Private/Immutable/Mac/ImmutableMac.cpp
+++ b/Source/Immutable/Private/Immutable/Mac/ImmutableMac.cpp
@@ -1,5 +1,11 @@
#include "ImmutableMac.h"
#include "Immutable/ImmutablePassport.h"
+#include "Immutable/ImmutableSubsystem.h"
+#include "Engine/GameEngine.h"
+
+#if WITH_EDITOR
+#include "Editor.h"
+#endif
ASWebAuthenticationSession *_authSession;
@@ -19,6 +25,47 @@ ASWebAuthenticationSession *_authSession;
return staticImmutableMac;
}
++ (UImmutablePassport*) getPassport {
+ UWorld* World = nullptr;
+
+#if WITH_EDITOR
+ if (GEditor)
+ {
+ for (const auto& Context : GEditor->GetWorldContexts())
+ {
+ if (Context.WorldType == EWorldType::PIE && Context.World())
+ {
+ World = Context.World();
+ break;
+ }
+ }
+ }
+#else
+ if (UGameEngine* GameEngine = Cast(GEngine))
+ {
+ World = GameEngine->GetGameWorld();
+ }
+#endif
+
+ if (!World) {
+ return nil;
+ }
+
+ auto ImmutableSubsystem = World->GetGameInstance()->GetSubsystem();
+
+ if (!ImmutableSubsystem) {
+ return nil;
+ }
+
+ auto Passport = ImmutableSubsystem->GetPassport();
+
+ if (!Passport.IsValid()) {
+ return nil;
+ }
+
+ return Passport.Get();
+}
+
- (void)launchUrl:(const char *)url forRedirectUri:(const char *)redirectUri {
if (@available(macOS 10.15, *)) {
NSURL *URL =
@@ -40,7 +87,11 @@ ASWebAuthenticationSession *_authSession;
_authSession = nil;
if (callbackURL) {
- UImmutablePassport::HandleDeepLink(callbackURL.absoluteString);
+ UImmutablePassport* passport = [ImmutableMac getPassport];
+
+ if (passport) {
+ passport->HandleDeepLink(callbackURL.absoluteString);
+ }
} else {
return;
}
diff --git a/Source/Immutable/Public/Immutable/Actions/ImtblBlueprintAsyncAction.h b/Source/Immutable/Public/Immutable/Actions/ImtblBlueprintAsyncAction.h
index 465dbcef..03894205 100644
--- a/Source/Immutable/Public/Immutable/Actions/ImtblBlueprintAsyncAction.h
+++ b/Source/Immutable/Public/Immutable/Actions/ImtblBlueprintAsyncAction.h
@@ -4,21 +4,21 @@
#include "CoreMinimal.h"
#include "Kismet/BlueprintAsyncActionBase.h"
-// clang-format off
+
#include "ImtblBlueprintAsyncAction.generated.h"
-// clang-format on
/**
- *
+
+ * base class for asynchronous actions
*/
UCLASS()
-class IMMUTABLE_API UImtblBlueprintAsyncAction
- : public UBlueprintAsyncActionBase {
- GENERATED_BODY()
+class IMMUTABLE_API UImtblBlueprintAsyncAction : public UBlueprintAsyncActionBase
+{
+ GENERATED_BODY()
protected:
- UObject *WorldContextObject;
+ UObject* WorldContextObject;
- // Get subsystem
- class UImmutableSubsystem *GetSubsystem() const;
+ // Get subsystem
+ class UImmutableSubsystem* GetSubsystem() const;
};
diff --git a/Source/Immutable/Public/Immutable/Actions/ImtblPassportReconnectAsyncAction.h b/Source/Immutable/Public/Immutable/Actions/ImtblPassportConnectSilentAsyncAction.h
similarity index 58%
rename from Source/Immutable/Public/Immutable/Actions/ImtblPassportReconnectAsyncAction.h
rename to Source/Immutable/Public/Immutable/Actions/ImtblPassportConnectSilentAsyncAction.h
index 5659a56b..e6eaf0ac 100644
--- a/Source/Immutable/Public/Immutable/Actions/ImtblPassportReconnectAsyncAction.h
+++ b/Source/Immutable/Public/Immutable/Actions/ImtblPassportConnectSilentAsyncAction.h
@@ -3,13 +3,13 @@
#include "CoreMinimal.h"
#include "ImtblBlueprintAsyncAction.h"
-#include "ImtblPassportReconnectAsyncAction.generated.h"
+#include "ImtblPassportConnectSilentAsyncAction.generated.h"
/**
*
*/
UCLASS()
-class IMMUTABLE_API UImtblPassportReconnectAsyncAction : public UImtblBlueprintAsyncAction
+class IMMUTABLE_API UImtblPassportConnectSilentAsyncAction : public UImtblBlueprintAsyncAction
{
GENERATED_BODY()
@@ -18,7 +18,7 @@ class IMMUTABLE_API UImtblPassportReconnectAsyncAction : public UImtblBlueprintA
public:
UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "Immutable")
- static UImtblPassportReconnectAsyncAction* Reconnect(UObject* WorldContextObject);
+ static UImtblPassportConnectSilentAsyncAction* ConnectSilent(UObject* WorldContextObject);
void Activate() override;
@@ -29,6 +29,6 @@ class IMMUTABLE_API UImtblPassportReconnectAsyncAction : public UImtblBlueprintA
UPROPERTY(BlueprintAssignable)
FPassportConnectSilentOutputPin OnFailure;
- void DoReconnect(TWeakObjectPtr JSGetConnector);
- void OnReconnectResponse(struct FImmutablePassportResult Result);
+ void DoConnectSilent(TWeakObjectPtr JSGetConnector);
+ void OnConnectSilentResponse(struct FImmutablePassportResult Result);
};
diff --git a/Source/Immutable/Public/Immutable/Actions/ImtblPassportInitializationAsyncAction.h b/Source/Immutable/Public/Immutable/Actions/ImtblPassportInitializationAsyncAction.h
index 8227dc98..b0c9ad85 100644
--- a/Source/Immutable/Public/Immutable/Actions/ImtblPassportInitializationAsyncAction.h
+++ b/Source/Immutable/Public/Immutable/Actions/ImtblPassportInitializationAsyncAction.h
@@ -5,40 +5,36 @@
#include "CoreMinimal.h"
#include "Immutable/ImmutablePassport.h"
#include "ImtblBlueprintAsyncAction.h"
+
#include "ImtblPassportInitializationAsyncAction.generated.h"
/**
- *
+ * Async action to instantiate
*/
UCLASS()
-class IMMUTABLE_API UImtblPassportInitializationAsyncAction
- : public UImtblBlueprintAsyncAction {
- GENERATED_BODY()
+class IMMUTABLE_API UImtblPassportInitializationAsyncAction : public UImtblBlueprintAsyncAction
+{
+ GENERATED_BODY()
- DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPassportInitializationOutputPin,
- FString, Message);
+ DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPassportInitializationOutputPin, FString, Message);
public:
- UFUNCTION(BlueprintCallable,
- meta = (WorldContext = "WorldContextObject",
- BlueprintInternalUseOnly = "true"),
- Category = "Immutable")
- static UImtblPassportInitializationAsyncAction *
- InitializePassport(UObject *WorldContextObject, const FString &ClientID,
- const FString &RedirectUri, const FString &Environment);
+ UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "Immutable")
+ static UImtblPassportInitializationAsyncAction* InitializePassport(UObject* WorldContextObject, const FString& ClientID, const FString& RedirectUri, const FString& LogoutUri, const FString& Environment);
- void Activate() override;
+ virtual void Activate() override;
private:
- FString ClientId;
- FString RedirectUri;
- FString Environment;
-
- UPROPERTY(BlueprintAssignable)
- FPassportInitializationOutputPin Initialized;
- UPROPERTY(BlueprintAssignable)
- FPassportInitializationOutputPin Failed;
-
- void DoInit(TWeakObjectPtr JSConnector);
- void OnInitialized(FImmutablePassportResult Result);
+ FString ClientId;
+ FString RedirectUri;
+ FString LogoutUri;
+ FString Environment;
+
+ UPROPERTY(BlueprintAssignable)
+ FPassportInitializationOutputPin Initialized;
+ UPROPERTY(BlueprintAssignable)
+ FPassportInitializationOutputPin Failed;
+
+ void DoInit(TWeakObjectPtr JSConnector);
+ void OnInitialized(FImmutablePassportResult Result);
};
diff --git a/Source/Immutable/Public/Immutable/Actions/ImtblPassportLogoutAsyncAction.h b/Source/Immutable/Public/Immutable/Actions/ImtblPassportLogoutAsyncAction.h
index 88da5866..fe24f7b6 100644
--- a/Source/Immutable/Public/Immutable/Actions/ImtblPassportLogoutAsyncAction.h
+++ b/Source/Immutable/Public/Immutable/Actions/ImtblPassportLogoutAsyncAction.h
@@ -1,6 +1,4 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-#pragma once
+#pragma once
#include "CoreMinimal.h"
#include "Immutable/ImmutablePassport.h"
@@ -12,28 +10,29 @@
*/
// UCLASS(meta = (HasDedicatedAsyncNode))
UCLASS()
-class IMMUTABLE_API UImtblPassportLogoutAsyncAction
- : public UImtblBlueprintAsyncAction {
- GENERATED_BODY()
+class IMMUTABLE_API UImtblPassportLogoutAsyncAction : public UImtblBlueprintAsyncAction
+{
+ GENERATED_BODY()
- DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPassportLogoutOutputPin, FString,
- ErrorMessage);
+ DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPassportLogoutOutPin, FString, Message);
public:
- UFUNCTION(BlueprintCallable,
- meta = (WorldContext = "WorldContextObject",
- BlueprintInternalUseOnly = "true"),
- Category = "Immutable")
- static UImtblPassportLogoutAsyncAction *Logout(UObject *WorldContextObject);
+
+ UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "Immutable")
+ static UImtblPassportLogoutAsyncAction* Logout(UObject* WorldContextObject);
+
+ virtual void Activate() override;
+
+private:
- void Activate() override;
+ void DoLogout(TWeakObjectPtr JSConnector);
+ void OnLogoutResponse(FImmutablePassportResult Result) const;
private:
- void DoLogout(TWeakObjectPtr JSConnector);
- void OnLogoutResponse(FImmutablePassportResult Result);
- UPROPERTY(BlueprintAssignable)
- FPassportLogoutOutputPin LoggedOut;
- UPROPERTY(BlueprintAssignable)
- FPassportLogoutOutputPin Failed;
+ UPROPERTY(BlueprintAssignable)
+ FPassportLogoutOutPin OnSuccess;
+ UPROPERTY(BlueprintAssignable)
+ FPassportLogoutOutPin OnFailure;
+
};
diff --git a/Source/Immutable/Public/Immutable/ImmutablePassport.h b/Source/Immutable/Public/Immutable/ImmutablePassport.h
index fa4befc2..d7101cd6 100644
--- a/Source/Immutable/Public/Immutable/ImmutablePassport.h
+++ b/Source/Immutable/Public/Immutable/ImmutablePassport.h
@@ -8,218 +8,226 @@
#include "Misc/EngineVersion.h"
#include "Runtime/Core/Public/HAL/Platform.h"
#include "UObject/Object.h"
-// clang-format off
+
#include "ImmutablePassport.generated.h"
-// clang-format on
+
struct FImtblJSResponse;
-namespace ImmutablePassportAction {
-const FString Initialize = TEXT("init");
-const FString Logout = TEXT("logout");
-const FString Connect = TEXT("connect");
-const FString Reconnect = TEXT("reconnect");
-const FString ConnectEvm = TEXT("connectEvm");
-const FString ZkEvmRequestAccounts = TEXT("zkEvmRequestAccounts");
-const FString ZkEvmGetBalance = TEXT("zkEvmGetBalance");
-const FString ZkEvmSendTransaction = TEXT("zkEvmSendTransaction");
-const FString ConfirmCode = TEXT("confirmCode");
+namespace ImmutablePassportAction
+{
+ const FString Initialize = TEXT("init");
+ const FString Logout = TEXT("logout");
+ const FString Connect = TEXT("connect");
+ const FString ConnectSilent = TEXT("reconnect");
+ const FString ConnectEvm = TEXT("connectEvm");
+ const FString ZkEvmRequestAccounts = TEXT("zkEvmRequestAccounts");
+ const FString ZkEvmGetBalance = TEXT("zkEvmGetBalance");
+ const FString ZkEvmSendTransaction = TEXT("zkEvmSendTransaction");
+ const FString ConfirmCode = TEXT("confirmCode");
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
-const FString GetPKCEAuthUrl = TEXT("getPKCEAuthUrl");
-const FString ConnectPKCE = TEXT("connectPKCE");
+ const FString GetPKCEAuthUrl = TEXT("getPKCEAuthUrl");
+ const FString ConnectPKCE = TEXT("connectPKCE");
#endif
-const FString GetAddress = TEXT("getAddress");
-const FString GetEmail = TEXT("getEmail");
-const FString GetAccessToken = TEXT("getAccessToken");
-const FString GetIdToken = TEXT("getIdToken");
-const FString ImxTransfer = TEXT("imxTransfer");
-const FString ImxBatchNftTransfer = TEXT("imxBatchNftTransfer");
-const FString EnvSandbox = TEXT("sandbox");
-const FString EnvProduction = TEXT("production");
-const FString ImxIsRegisteredOffchain = TEXT("isRegisteredOffchain");
-const FString ImxRegisterOffchain = TEXT("registerOffchain");
+ const FString GetAddress = TEXT("getAddress");
+ const FString GetEmail = TEXT("getEmail");
+ const FString GetAccessToken = TEXT("getAccessToken");
+ const FString GetIdToken = TEXT("getIdToken");
+ const FString ImxTransfer = TEXT("imxTransfer");
+ const FString ImxBatchNftTransfer = TEXT("imxBatchNftTransfer");
+ const FString EnvSandbox = TEXT("sandbox");
+ const FString EnvProduction = TEXT("production");
+ const FString ImxIsRegisteredOffchain = TEXT("isRegisteredOffchain");
+ const FString ImxRegisterOffchain = TEXT("registerOffchain");
} // namespace ImmutablePassportAction
-template
-FString UStructToJsonString(const UStructType &InStruct) {
- FString OutString;
- FJsonObjectConverter::UStructToJsonObjectString(InStruct, OutString, 0, 0, 0,
- nullptr, false);
- return OutString;
+template FString UStructToJsonString(const UStructType& InStruct)
+{
+ FString OutString;
+ FJsonObjectConverter::UStructToJsonObjectString(InStruct, OutString, 0, 0, 0, nullptr, false);
+ return OutString;
}
-template
-TOptional
-JsonObjectToUStruct(const TSharedPtr &JsonObject) {
- if (!JsonObject.IsValid()) {
- return TOptional();
- }
-
- // Parse the JSON
- UStructType StructInstance;
- if (!FJsonObjectConverter::JsonObjectToUStruct(JsonObject.ToSharedRef(),
- &StructInstance, 0, 0)) {
- IMTBL_ERR(
- "Could not parse response from JavaScript into the expected Ustruct")
- return TOptional();
- }
- return StructInstance;
+template TOptional JsonObjectToUStruct(const TSharedPtr& JsonObject)
+{
+ if (!JsonObject.IsValid())
+ {
+ return TOptional();
+ }
+
+ // Parse the JSON
+ UStructType StructInstance;
+ if (!FJsonObjectConverter::JsonObjectToUStruct(JsonObject.ToSharedRef(), &StructInstance, 0, 0))
+ {
+ IMTBL_ERR("Could not parse response from JavaScript into the expected Ustruct")
+ return TOptional();
+ }
+ return StructInstance;
}
USTRUCT()
-struct FImmutablePassportResult {
- GENERATED_BODY()
+struct FImmutablePassportResult
+{
+ GENERATED_BODY()
- UPROPERTY()
- bool Success = false;
- UPROPERTY()
- FString Message;
+ UPROPERTY()
+ bool Success = false;
+ UPROPERTY()
+ FString Message;
- FImtblJSResponse Response;
+ FImtblJSResponse Response;
};
USTRUCT()
-struct FImmutableEngineVersionData {
- GENERATED_BODY()
-
- UPROPERTY()
- FString engine = TEXT("unreal");
-
- // cannot have spaces
- UPROPERTY()
- FString engineVersion =
- FEngineVersion::Current().ToString().Replace(TEXT(" "), TEXT("_"));
-
- // cannot have spaces
- UPROPERTY()
- FString platform = FString(FPlatformProperties::IniPlatformName())
- .Replace(TEXT(" "), TEXT("_"));
-
- // cannot have spaces
- UPROPERTY()
- FString platformVersion =
- FPlatformMisc::GetOSVersion().Replace(TEXT(" "), TEXT("_"));
+struct FImmutableEngineVersionData
+{
+ GENERATED_BODY()
+
+ UPROPERTY()
+ FString engine = TEXT("unreal");
+
+ // cannot have spaces
+ UPROPERTY()
+ FString engineVersion = FEngineVersion::Current().ToString().Replace(TEXT(" "), TEXT("_"));
+
+ // cannot have spaces
+ UPROPERTY()
+ FString platform = FString(FPlatformProperties::IniPlatformName()).Replace(TEXT(" "), TEXT("_"));
+
+ // cannot have spaces
+ UPROPERTY()
+ FString platformVersion = FPlatformMisc::GetOSVersion().Replace(TEXT(" "), TEXT("_"));
};
USTRUCT()
-struct FImmutablePassportInitData {
- GENERATED_BODY()
+struct FImmutablePassportInitData
+{
+ GENERATED_BODY()
- UPROPERTY()
- FString clientId;
+ UPROPERTY()
+ FString clientId;
- UPROPERTY()
- FString redirectUri;
+ UPROPERTY()
+ FString redirectUri;
- UPROPERTY()
- FString environment = ImmutablePassportAction::EnvSandbox;
+ UPROPERTY()
+ FString logoutRedirectUri;
- UPROPERTY()
- FImmutableEngineVersionData engineVersion;
+ UPROPERTY()
+ FString environment = ImmutablePassportAction::EnvSandbox;
- FString ToJsonString() const;
+ UPROPERTY()
+ FImmutableEngineVersionData engineVersion;
+
+ FString ToJsonString() const;
};
USTRUCT()
-struct FImmutablePassportConnectData {
- GENERATED_BODY()
-
- UPROPERTY()
- FString code;
- UPROPERTY()
- FString deviceCode;
- UPROPERTY()
- FString url;
- UPROPERTY()
- float interval = 0;
-
- static TOptional
- FromJsonString(const FString &JsonObjectString);
+struct FImmutablePassportConnectData
+{
+ GENERATED_BODY()
+
+ UPROPERTY()
+ FString code;
+ UPROPERTY()
+ FString deviceCode;
+ UPROPERTY()
+ FString url;
+ UPROPERTY()
+ float interval = 0;
+
+ static TOptional FromJsonString(const FString& JsonObjectString);
};
USTRUCT()
-struct FImmutablePassportZkEvmRequestAccountsData {
- GENERATED_BODY()
+struct FImmutablePassportZkEvmRequestAccountsData
+{
+ GENERATED_BODY()
- UPROPERTY()
- TArray accounts;
+ UPROPERTY()
+ TArray accounts;
- FString ToJsonString() const;
- static TOptional
- FromJsonString(const FString &JsonObjectString);
- static TOptional
- FromJsonObject(const TSharedPtr &JsonObject);
+ FString ToJsonString() const;
+ static TOptional FromJsonString(const FString& JsonObjectString);
+ static TOptional FromJsonObject(
+ const TSharedPtr& JsonObject);
};
USTRUCT()
-struct FImmutablePassportZkEvmGetBalanceData {
- GENERATED_BODY()
+struct FImmutablePassportZkEvmGetBalanceData
+{
+ GENERATED_BODY()
- UPROPERTY()
- FString address;
+ UPROPERTY()
+ FString address;
- UPROPERTY()
- FString blockNumberOrTag = "latest";
+ UPROPERTY()
+ FString blockNumberOrTag = "latest";
- FString ToJsonString() const;
+ FString ToJsonString() const;
};
USTRUCT(BlueprintType)
-struct FImtblAccessListItem {
- GENERATED_BODY()
+struct FImtblAccessListItem
+{
+ GENERATED_BODY()
- UPROPERTY(BlueprintReadWrite, EditAnywhere)
- FString address;
+ UPROPERTY(BlueprintReadWrite, EditAnywhere)
+ FString address;
- UPROPERTY(BlueprintReadWrite, EditAnywhere)
- TArray storageKeys;
+ UPROPERTY(BlueprintReadWrite, EditAnywhere)
+ TArray storageKeys;
};
/**
* Key Value wrappers for converting to JSON
*/
USTRUCT()
-struct FStringCustomData {
- GENERATED_BODY()
+struct FStringCustomData
+{
+ GENERATED_BODY()
- UPROPERTY()
- FString key;
+ UPROPERTY()
+ FString key;
- UPROPERTY()
- FString value;
+ UPROPERTY()
+ FString value;
};
USTRUCT()
-struct FInt64CustomData {
- GENERATED_BODY()
+struct FInt64CustomData
+{
+ GENERATED_BODY()
- UPROPERTY()
- FString key;
+ UPROPERTY()
+ FString key;
- UPROPERTY()
- int64 value;
+ UPROPERTY()
+ int64 value;
};
USTRUCT()
-struct FFloatCustomData {
- GENERATED_BODY()
+struct FFloatCustomData
+{
+ GENERATED_BODY()
- UPROPERTY()
- FString key;
+ UPROPERTY()
+ FString key;
- UPROPERTY()
- float value;
+ UPROPERTY()
+ float value;
};
USTRUCT()
-struct FBoolCustomData {
- GENERATED_BODY()
+struct FBoolCustomData
+{
+ GENERATED_BODY()
- UPROPERTY()
- FString key;
+ UPROPERTY()
+ FString key;
- UPROPERTY()
- bool value;
+ UPROPERTY()
+ bool value;
};
UENUM(BlueprintType)
@@ -231,364 +239,359 @@ enum EImtblCustomDataType { String, Int64, Float, Bool };
* corresponding value. This will later be mapped to the proper API structure.
*/
USTRUCT(BlueprintType)
-struct FImtblCustomData {
- GENERATED_BODY()
-
- UPROPERTY(BlueprintReadWrite, EditAnywhere)
- FString key;
-
- UPROPERTY(BlueprintReadWrite, EditAnywhere)
- FString stringValue;
-
- UPROPERTY(BlueprintReadWrite, EditAnywhere)
- int64 intValue;
-
- UPROPERTY(BlueprintReadWrite, EditAnywhere)
- float floatValue;
-
- UPROPERTY(BlueprintReadWrite, EditAnywhere)
- bool boolValue;
-
- UPROPERTY(BlueprintReadWrite, EditAnywhere)
- TEnumAsByte type;
-
- /**
- * Convert from blueprint structure to the expected API data structure
- */
- TSharedPtr ToJsonObject() const {
- switch (type) {
- case String:
- return FJsonObjectConverter::UStructToJsonObject(
- {key, stringValue});
- case Int64:
- return FJsonObjectConverter::UStructToJsonObject(
- {key, intValue});
- case Float:
- return FJsonObjectConverter::UStructToJsonObject(
- {key, floatValue});
- case Bool:
- return FJsonObjectConverter::UStructToJsonObject(
- {key, boolValue});
- default: {
- }
- }
- return {};
- }
+struct FImtblCustomData
+{
+ GENERATED_BODY()
+
+ UPROPERTY(BlueprintReadWrite, EditAnywhere)
+ FString key;
+
+ UPROPERTY(BlueprintReadWrite, EditAnywhere)
+ FString stringValue;
+
+ UPROPERTY(BlueprintReadWrite, EditAnywhere)
+ int64 intValue;
+
+ UPROPERTY(BlueprintReadWrite, EditAnywhere)
+ float floatValue;
+
+ UPROPERTY(BlueprintReadWrite, EditAnywhere)
+ bool boolValue;
+
+ UPROPERTY(BlueprintReadWrite, EditAnywhere)
+ TEnumAsByte type;
+
+ /**
+ * Convert from blueprint structure to the expected API data structure
+ */
+ TSharedPtr ToJsonObject() const
+ {
+ switch (type)
+ {
+ case String: return FJsonObjectConverter::UStructToJsonObject({key, stringValue});
+ case Int64: return FJsonObjectConverter::UStructToJsonObject({key, intValue});
+ case Float: return FJsonObjectConverter::UStructToJsonObject({key, floatValue});
+ case Bool: return FJsonObjectConverter::UStructToJsonObject({key, boolValue});
+ default:
+ {
+ }
+ }
+ return {};
+ }
};
USTRUCT(BlueprintType)
-struct FImtblTransactionRequest {
- GENERATED_BODY()
+struct FImtblTransactionRequest
+{
+ GENERATED_BODY()
- UPROPERTY(BlueprintReadWrite, EditAnywhere)
- FString to;
+ UPROPERTY(BlueprintReadWrite, EditAnywhere)
+ FString to;
- UPROPERTY(BlueprintReadWrite, EditAnywhere)
- FString data = "0x";
+ UPROPERTY(BlueprintReadWrite, EditAnywhere)
+ FString data = "0x";
- UPROPERTY(BlueprintReadWrite, EditAnywhere)
- FString value;
+ UPROPERTY(BlueprintReadWrite, EditAnywhere)
+ FString value;
};
USTRUCT()
-struct FImmutablePassportCodeConfirmRequestData {
- GENERATED_BODY()
-
- UPROPERTY()
- FString deviceCode;
- UPROPERTY()
- float interval = 5;
- UPROPERTY()
- float timeoutMs = 15 * 60 * 1000;
+struct FImmutablePassportCodeConfirmRequestData
+{
+ GENERATED_BODY()
+
+ UPROPERTY()
+ FString deviceCode;
+ UPROPERTY()
+ float interval = 5;
+ UPROPERTY()
+ float timeoutMs = 15 * 60 * 1000;
};
USTRUCT()
-struct FImxTransferRequest {
- GENERATED_BODY()
+struct FImxTransferRequest
+{
+ GENERATED_BODY()
- UPROPERTY()
- FString receiver;
+ UPROPERTY()
+ FString receiver;
- UPROPERTY()
- FString type;
+ UPROPERTY()
+ FString type;
- UPROPERTY()
- FString amount;
+ UPROPERTY()
+ FString amount;
- UPROPERTY()
- FString tokenId;
+ UPROPERTY()
+ FString tokenId;
- UPROPERTY()
- FString tokenAddress;
+ UPROPERTY()
+ FString tokenAddress;
- FString ToJsonString() const;
+ FString ToJsonString() const;
};
USTRUCT()
-struct FImxTransferResponse {
- GENERATED_BODY()
+struct FImxTransferResponse
+{
+ GENERATED_BODY()
- UPROPERTY()
- FString sentSignature;
+ UPROPERTY()
+ FString sentSignature;
- UPROPERTY()
- FString status;
+ UPROPERTY()
+ FString status;
- UPROPERTY()
- float time;
+ UPROPERTY()
+ float time;
- UPROPERTY()
- unsigned transferId;
+ UPROPERTY()
+ unsigned transferId;
};
USTRUCT(BlueprintType)
-struct FNftTransferDetails {
- GENERATED_BODY()
+struct FNftTransferDetails
+{
+ GENERATED_BODY()
- UPROPERTY(BlueprintReadWrite)
- FString receiver;
+ UPROPERTY(BlueprintReadWrite)
+ FString receiver;
- UPROPERTY(BlueprintReadWrite)
- FString tokenId;
+ UPROPERTY(BlueprintReadWrite)
+ FString tokenId;
- UPROPERTY(BlueprintReadWrite)
- FString tokenAddress;
+ UPROPERTY(BlueprintReadWrite)
+ FString tokenAddress;
};
USTRUCT()
-struct FImxBatchNftTransferRequest {
- GENERATED_BODY()
+struct FImxBatchNftTransferRequest
+{
+ GENERATED_BODY()
- UPROPERTY()
- TArray nftTransferDetails;
+ UPROPERTY()
+ TArray nftTransferDetails;
- FString ToJsonString() const;
+ FString ToJsonString() const;
};
USTRUCT()
-struct FImxBatchNftTransferResponse {
- GENERATED_BODY()
+struct FImxBatchNftTransferResponse
+{
+ GENERATED_BODY()
- UPROPERTY()
- TArray transferIds;
+ UPROPERTY()
+ TArray transferIds;
};
USTRUCT()
-struct FImmutablePassportConnectPKCEData {
- GENERATED_BODY()
+struct FImmutablePassportConnectPKCEData
+{
+ GENERATED_BODY()
- UPROPERTY()
- FString authorizationCode;
+ UPROPERTY()
+ FString authorizationCode;
- UPROPERTY()
- FString state;
+ UPROPERTY()
+ FString state;
};
USTRUCT()
-struct FImxRegisterOffchainResponse {
- GENERATED_BODY()
+struct FImxRegisterOffchainResponse
+{
+ GENERATED_BODY()
- UPROPERTY()
- FString tx_hash;
+ UPROPERTY()
+ FString tx_hash;
};
-#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
-DECLARE_DELEGATE_OneParam(FImtblPassportHandleDeepLinkDelegate, FString);
-FImtblPassportHandleDeepLinkDelegate OnHandleDeepLink;
-#endif
-#if PLATFORM_ANDROID
-DECLARE_DELEGATE(FImtblPassportOnPKCEDismissedDelegate);
-FImtblPassportOnPKCEDismissedDelegate OnPKCEDismissed;
-#endif
/**
*
*/
UCLASS()
-class IMMUTABLE_API UImmutablePassport : public UObject {
- GENERATED_BODY()
- friend class UImmutableSubsystem;
+class IMMUTABLE_API UImmutablePassport : public UObject
+{
+ GENERATED_BODY()
+ friend class UImmutableSubsystem;
public:
- DECLARE_MULTICAST_DELEGATE(FOnPassportReadyDelegate);
+ DECLARE_MULTICAST_DELEGATE(FOnPassportReadyDelegate);
- DECLARE_DELEGATE_OneParam(FImtblPassportResponseDelegate,
- FImmutablePassportResult);
+ DECLARE_DELEGATE_OneParam(FImtblPassportResponseDelegate, FImmutablePassportResult);
#if PLATFORM_ANDROID
- static void HandleDeepLink(FString DeepLink);
- static void HandleCustomTabsDismissed();
+ void HandleDeepLink(FString DeepLink) const;
+ void HandleCustomTabsDismissed(FString Url);
#elif PLATFORM_IOS | PLATFORM_MAC
- static void HandleDeepLink(NSString *sDeepLink);
+ void HandleDeepLink(NSString* sDeepLink) const;
#endif
- void Initialize(const FImmutablePassportInitData &InitData,
- const FImtblPassportResponseDelegate &ResponseDelegate);
- void Logout(const FImtblPassportResponseDelegate &ResponseDelegate);
- void Connect(const FImtblPassportResponseDelegate &ResponseDelegate);
- void Reconnect(const FImtblPassportResponseDelegate &ResponseDelegate);
+ void Initialize(const FImmutablePassportInitData& InitData, const FImtblPassportResponseDelegate& ResponseDelegate);
+ void Logout(const FImtblPassportResponseDelegate& ResponseDelegate);
+ void Connect(const FImtblPassportResponseDelegate& ResponseDelegate);
+ void ConnectSilent(const FImtblPassportResponseDelegate& ResponseDelegate);
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
- void ConnectPKCE(const FImtblPassportResponseDelegate &ResponseDelegate);
+ void ConnectPKCE(const FImtblPassportResponseDelegate& ResponseDelegate);
#endif
- /**
- * Initializes the zkEVM provider.
- * @param ResponseDelegate The response delegate of type
- * FImtblPassportResponseDelegate to call on response from JS.
- */
- void ConnectEvm(const FImtblPassportResponseDelegate &ResponseDelegate);
-
- /**
- * This method attempts to authenticate the user and initialises their
- * Passport wallet before returning an array of wallet addresses.
- *
- * This must be called before using other zkEVM functions.
- * @param ResponseDelegate The response delegate of type
- * FImtblPassportResponseDelegate to call on response from JS.
- */
- void
- ZkEvmRequestAccounts(const FImtblPassportResponseDelegate &ResponseDelegate);
-
- /**
- * Returns the balance of the account of given address in wei.
- * @param Data The address and block number for the request
- * @param ResponseDelegate The response delegate of type
- * FImtblPassportResponseDelegate to call on response from JS.
- */
- void ZkEvmGetBalance(const FImmutablePassportZkEvmGetBalanceData &Data,
- const FImtblPassportResponseDelegate &ResponseDelegate);
-
- /**
- * Creates new message call transaction or a contract creation, if the data
- * field contains code.
- * @param Request The request data to perform the transaction.
- * @param ResponseDelegate The response delegate of type
- * FImtblPassportResponseDelegate to call on response from JS.
- */
- void
- ZkEvmSendTransaction(const FImtblTransactionRequest &Request,
- const FImtblPassportResponseDelegate &ResponseDelegate);
- void GetIdToken(const FImtblPassportResponseDelegate &ResponseDelegate);
- void GetAccessToken(const FImtblPassportResponseDelegate &ResponseDelegate);
- void GetAddress(const FImtblPassportResponseDelegate &ResponseDelegate);
- void GetEmail(const FImtblPassportResponseDelegate &ResponseDelegate);
-
- /**
- * Create a new imx transfer request.
- * @param RequestData The transfer details structure of type
- * FImxTransferRequest
- * @param ResponseDelegate The response delegate of type
- * FImtblPassportResponseDelegate to call on response from JS.
- */
- void ImxTransfer(const FImxTransferRequest &RequestData,
- const FImtblPassportResponseDelegate &ResponseDelegate);
-
- /**
- * Creates a new imx batch nft transfer request with the given transfer
- * details.
- * @param RequestData The transfer details structure of type
- * FImxBatchNftTransferRequest
- * @param ResponseDelegate The response delegate of type
- * FImtblPassportResponseDelegate to call on response from JS.
- */
- void
- ImxBatchNftTransfer(const FImxBatchNftTransferRequest &RequestData,
- const FImtblPassportResponseDelegate &ResponseDelegate);
-
- /**
- *
- * Checks if the user is registered off-chain.
- * @param ResponseDelegate The response delegate of type
- * FImtblPassportResponseDelegate to call on response from JS.
- */
- void ImxIsRegisteredOffchain(const FImtblPassportResponseDelegate& ResponseDelegate);
-
- /**
- * Register the user to Immutable X if they are not already registered
- * @param ResponseDelegate The response delegate of type
- * FImtblPassportResponseDelegate to call on response from JS.
- */
- void ImxRegisterOffchain(const FImtblPassportResponseDelegate& ResponseDelegate);
-
- /**
- * Checks if the user's credentials have been stored
- * @param ResponseDelegate The response delegate of type
- * FImtblPassportResponseDelegate to call on response from JS.
- */
- void HasStoredCredentials(const FImtblPassportResponseDelegate& ResponseDelegate);
+ /**
+ * Initializes the zkEVM provider.
+ * @param ResponseDelegate The response delegate of type
+ * FImtblPassportResponseDelegate to call on response from JS.
+ */
+ void ConnectEvm(const FImtblPassportResponseDelegate& ResponseDelegate);
+
+ /**
+ * This method attempts to authenticate the user and initialises their
+ * Passport wallet before returning an array of wallet addresses.
+ *
+ * This must be called before using other zkEVM functions.
+ * @param ResponseDelegate The response delegate of type
+ * FImtblPassportResponseDelegate to call on response from JS.
+ */
+ void ZkEvmRequestAccounts(const FImtblPassportResponseDelegate& ResponseDelegate);
+
+ /**
+ * Returns the balance of the account of given address in wei.
+ * @param Data The address and block number for the request
+ * @param ResponseDelegate The response delegate of type
+ * FImtblPassportResponseDelegate to call on response from JS.
+ */
+ void ZkEvmGetBalance(const FImmutablePassportZkEvmGetBalanceData& Data, const FImtblPassportResponseDelegate& ResponseDelegate);
+
+ /**
+ * Creates new message call transaction or a contract creation, if the data
+ * field contains code.
+ * @param Request The request data to perform the transaction.
+ * @param ResponseDelegate The response delegate of type
+ * FImtblPassportResponseDelegate to call on response from JS.
+ */
+ void ZkEvmSendTransaction(const FImtblTransactionRequest& Request,
+ const FImtblPassportResponseDelegate& ResponseDelegate);
+ void GetIdToken(const FImtblPassportResponseDelegate& ResponseDelegate);
+ void GetAccessToken(const FImtblPassportResponseDelegate& ResponseDelegate);
+ void GetAddress(const FImtblPassportResponseDelegate& ResponseDelegate);
+ void GetEmail(const FImtblPassportResponseDelegate& ResponseDelegate);
+
+ /**
+ * Create a new imx transfer request.
+ * @param RequestData The transfer details structure of type
+ * FImxTransferRequest
+ * @param ResponseDelegate The response delegate of type
+ * FImtblPassportResponseDelegate to call on response from JS.
+ */
+ void ImxTransfer(const FImxTransferRequest& RequestData, const FImtblPassportResponseDelegate& ResponseDelegate);
+
+ /**
+ * Creates a new imx batch nft transfer request with the given transfer
+ * details.
+ * @param RequestData The transfer details structure of type
+ * FImxBatchNftTransferRequest
+ * @param ResponseDelegate The response delegate of type
+ * FImtblPassportResponseDelegate to call on response from JS.
+ */
+ void ImxBatchNftTransfer(const FImxBatchNftTransferRequest& RequestData,
+ const FImtblPassportResponseDelegate& ResponseDelegate);
+
+ /**
+ *
+ * Checks if the user is registered off-chain.
+ * @param ResponseDelegate The response delegate of type
+ * FImtblPassportResponseDelegate to call on response from JS.
+ */
+ void ImxIsRegisteredOffchain(const FImtblPassportResponseDelegate& ResponseDelegate);
+
+ /**
+ * Register the user to Immutable X if they are not already registered
+ * @param ResponseDelegate The response delegate of type
+ * FImtblPassportResponseDelegate to call on response from JS.
+ */
+ void ImxRegisterOffchain(const FImtblPassportResponseDelegate& ResponseDelegate);
+
+ /**
+ * Checks if the user's credentials have been stored
+ * @param ResponseDelegate The response delegate of type
+ * FImtblPassportResponseDelegate to call on response from JS.
+ */
+ void HasStoredCredentials(const FImtblPassportResponseDelegate& ResponseDelegate);
protected:
- void Setup(TWeakObjectPtr Connector);
+ void Setup(TWeakObjectPtr Connector);
private:
- bool bIsInitialized = false;
- bool bIsLoggedIn = false;
+ bool bIsInitialized = false;
+ bool bIsLoggedIn = false;
#if PLATFORM_ANDROID
- bool completingPKCE = false; // Used for the PKCE callback
+ DECLARE_DELEGATE(FImtblPassportOnPKCEDismissedDelegate);
+
+ FImtblPassportOnPKCEDismissedDelegate OnPKCEDismissed;
+
+ bool completingPKCE = false; // Used for the PKCE callback
#endif
- TWeakObjectPtr JSConnector;
- FImmutablePassportInitData InitData;
- FDelegateHandle BridgeReadyHandle;
- TMap ResponseDelegates;
+ TWeakObjectPtr JSConnector;
+ FImmutablePassportInitData InitData;
+ FDelegateHandle BridgeReadyHandle;
+ TMap ResponseDelegates;
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
- // Since the second part of PKCE is triggered by deep links, saving the
- // response delegate here so it's easier to get
- FImtblPassportResponseDelegate PKCEResponseDelegate;
+ DECLARE_DELEGATE_OneParam(FImtblPassportHandleDeepLinkDelegate, FString);
+
+ FImtblPassportHandleDeepLinkDelegate OnHandleDeepLink;
+ // Since the second part of PKCE is triggered by deep links, saving the
+ // response delegate here so it's easier to get
+ FImtblPassportResponseDelegate PKCEResponseDelegate;
+ FImtblPassportResponseDelegate PKCELogoutResponseDelegate;
+ bool IsPKCEConnected = false;
#endif
- // Ensures that Passport has been initialized before calling JS
- bool CheckIsInitialized(
- const FString &Action,
- const FImtblPassportResponseDelegate &ResponseDelegate) const;
- // Calls JS with the given Action and Data, and registers the given
- // ResponseDelegate to be called when JS responds
- void CallJS(const FString &Action, const FString &Data,
- const FImtblPassportResponseDelegate &ClientResponseDelegate,
- const FImtblJSResponseDelegate &HandleJSResponse,
- const bool bCheckInitialized = true);
- // Pulls the ResponseDelegate from the ResponseDelegates map and returns it
- TOptional
- GetResponseDelegate(const FImtblJSResponse &Response);
- void ConfirmCode(const FString &DeviceCode, const float Interval,
- const FImtblPassportResponseDelegate &ResponseDelegate);
-
- void OnInitializeResponse(FImtblJSResponse Response);
- void OnLogoutResponse(FImtblJSResponse Response);
- void OnConnectResponse(FImtblJSResponse Response);
- void OnReconnectResponse(FImtblJSResponse Response);
- void OnConnectEvmResponse(FImtblJSResponse Response);
- void OnZkEvmRequestAccountsResponse(FImtblJSResponse Response);
- void OnZkEvmGetBalanceResponse(FImtblJSResponse Response);
- void OnZkEvmSendTransactionResponse(FImtblJSResponse Response);
- void OnConfirmCodeResponse(FImtblJSResponse Response);
+ // Ensures that Passport has been initialized before calling JS
+ bool CheckIsInitialized(const FString& Action, const FImtblPassportResponseDelegate& ResponseDelegate) const;
+ // Calls JS with the given Action and Data, and registers the given
+ // ResponseDelegate to be called when JS responds
+ void CallJS(const FString& Action, const FString& Data,
+ const FImtblPassportResponseDelegate& ClientResponseDelegate,
+ const FImtblJSResponseDelegate& HandleJSResponse, const bool bCheckInitialized = true);
+ // Pulls the ResponseDelegate from the ResponseDelegates map and returns it
+ TOptional GetResponseDelegate(const FImtblJSResponse& Response);
+ void ConfirmCode(const FString& DeviceCode, const float Interval,
+ const FImtblPassportResponseDelegate& ResponseDelegate);
+
+ void OnInitializeResponse(FImtblJSResponse Response);
+ void OnLogoutResponse(FImtblJSResponse Response);
+ void OnConnectResponse(FImtblJSResponse Response);
+ void OnConnectSilentResponse(FImtblJSResponse Response);
+ void OnConnectEvmResponse(FImtblJSResponse Response);
+ void OnZkEvmRequestAccountsResponse(FImtblJSResponse Response);
+ void OnZkEvmGetBalanceResponse(FImtblJSResponse Response);
+ void OnZkEvmSendTransactionResponse(FImtblJSResponse Response);
+ void OnConfirmCodeResponse(FImtblJSResponse Response);
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
- void OnGetPKCEAuthUrlResponse(FImtblJSResponse Response);
- void OnConnectPKCEResponse(FImtblJSResponse Response);
+ void OnGetPKCEAuthUrlResponse(FImtblJSResponse Response);
+ void OnConnectPKCEResponse(FImtblJSResponse Response);
#endif
- void OnGetIdTokenResponse(FImtblJSResponse Response);
- void OnGetAccessTokenResponse(FImtblJSResponse Response);
- void OnGetAddressResponse(FImtblJSResponse Response);
- void OnGetEmailResponse(FImtblJSResponse Response);
- void OnTransferResponse(FImtblJSResponse Response);
- void OnBatchNftTransferResponse(FImtblJSResponse Response);
- void OnImxIsRegisteredOffchain(FImtblJSResponse Response);
- void OnImxRegisterOffchain(FImtblJSResponse Response);
+ void OnGetIdTokenResponse(FImtblJSResponse Response);
+ void OnGetAccessTokenResponse(FImtblJSResponse Response);
+ void OnGetAddressResponse(FImtblJSResponse Response);
+ void OnGetEmailResponse(FImtblJSResponse Response);
+ void OnTransferResponse(FImtblJSResponse Response);
+ void OnBatchNftTransferResponse(FImtblJSResponse Response);
+ void OnImxIsRegisteredOffchain(FImtblJSResponse Response);
+ void OnImxRegisterOffchain(FImtblJSResponse Response);
- void LogAndIgnoreResponse(FImtblJSResponse Response);
+ void LogAndIgnoreResponse(FImtblJSResponse Response);
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
- void OnDeepLinkActivated(FString DeepLink);
- void CompletePKCEFlow(FString Url);
+ void OnDeepLinkActivated(FString DeepLink);
+ void CompleteLoginPKCEFlow(FString Url);
#endif
#if PLATFORM_ANDROID
- void HandleOnPKCEDismissed();
- void CallJniStaticVoidMethod(JNIEnv *Env, const jclass Class,
- jmethodID Method, ...);
+ void HandleOnLoginPKCEDismissed();
+ void CallJniStaticVoidMethod(JNIEnv* Env, const jclass Class, jmethodID Method, ...);
+ void LaunchAndroidUrl(FString Url);
#endif
};
-