diff --git a/Source/Thirdweb/Private/AsyncTasks/Wallets/InApp/AsyncTaskThirdwebLoginWithSiwe.cpp b/Source/Thirdweb/Private/AsyncTasks/Wallets/InApp/AsyncTaskThirdwebLoginWithSiwe.cpp new file mode 100644 index 0000000..81b3334 --- /dev/null +++ b/Source/Thirdweb/Private/AsyncTasks/Wallets/InApp/AsyncTaskThirdwebLoginWithSiwe.cpp @@ -0,0 +1,82 @@ +// Copyright (c) 2025 Thirdweb. All Rights Reserved. + +#include "AsyncTasks/Wallets/InApp/AsyncTaskThirdwebLoginWithSiwe.h" + +#include "Async/TaskGraphInterfaces.h" +#include "Blueprint/UserWidget.h" +#include "Browser/ThirdwebOAuthBrowserUserWidget.h" +#include "Engine/World.h" +#include "Kismet/GameplayStatics.h" +#include "ThirdwebLog.h" + +void UAsyncTaskThirdwebLoginWithSiwe::Activate() +{ + Browser->OnSiweComplete.AddDynamic(this, &ThisClass::HandleSiweComplete); + Browser->OnError.AddDynamic(this, &ThisClass::HandleFailed); + Browser->AddToViewport(10000); + Browser->Authenticate(Wallet); +} + +UAsyncTaskThirdwebLoginWithSiwe* UAsyncTaskThirdwebLoginWithSiwe::LoginWithSiwe(UObject* WorldContextObject, const FInAppWalletHandle& Wallet) +{ + if (!WorldContextObject) + { + return nullptr; + } + NEW_TASK + Task->Wallet = Wallet; + Task->Browser = CreateWidget(UGameplayStatics::GetGameInstance(WorldContextObject), + UThirdwebOAuthBrowserUserWidget::StaticClass()); + Task->RegisterWithGameInstance(WorldContextObject); + return Task; +} + +void UAsyncTaskThirdwebLoginWithSiwe::HandleSiweComplete(const FString& Payload, const FString& Signature) +{ + if (IsInGameThread()) + { + Success.Broadcast(Payload, Signature); + Browser->RemoveFromParent(); + SetReadyToDestroy(); + } + else + { + // Retry on the GameThread. + TWeakObjectPtr WeakThis = this; + FFunctionGraphTask::CreateAndDispatchWhenReady([WeakThis, Payload, Signature]() + { + if (WeakThis.IsValid()) + { + WeakThis->HandleSiweComplete(Payload, Signature); + } + }, + TStatId(), + nullptr, + ENamedThreads::GameThread); + } +} + +void UAsyncTaskThirdwebLoginWithSiwe::HandleFailed(const FString& Error) +{ + if (IsInGameThread()) + { + Browser->RemoveFromParent(); + Failed.Broadcast(Error); + SetReadyToDestroy(); + } + else + { + // Retry on the GameThread. + TWeakObjectPtr WeakThis = this; + FFunctionGraphTask::CreateAndDispatchWhenReady([WeakThis, Error]() + { + if (WeakThis.IsValid()) + { + WeakThis->HandleFailed(Error); + } + }, + TStatId(), + nullptr, + ENamedThreads::GameThread); + } +} diff --git a/Source/Thirdweb/Private/Browser/ThirdwebOAuthBrowserUserWidget.cpp b/Source/Thirdweb/Private/Browser/ThirdwebOAuthBrowserUserWidget.cpp index f65b26f..f77a9ec 100644 --- a/Source/Thirdweb/Private/Browser/ThirdwebOAuthBrowserUserWidget.cpp +++ b/Source/Thirdweb/Private/Browser/ThirdwebOAuthBrowserUserWidget.cpp @@ -2,13 +2,14 @@ #include "Browser/ThirdwebOAuthBrowserUserWidget.h" -#include "ThirdwebLog.h" -#include "ThirdwebRuntimeSettings.h" +#include "Async/TaskGraphInterfaces.h" #include "Blueprint/WidgetTree.h" #include "Browser/ThirdwebOAuthExternalBrowser.h" #include "Components/Overlay.h" #include "Components/OverlaySlot.h" #include "Components/PanelWidget.h" +#include "ThirdwebLog.h" +#include "ThirdwebRuntimeSettings.h" #if PLATFORM_ANDROID #include "Android/AndroidApplication.h" @@ -70,7 +71,7 @@ void UThirdwebOAuthBrowserUserWidget::BeginDestroy() FString UThirdwebOAuthBrowserUserWidget::GetDummyUrl() { #if PLATFORM_ANDROID - return UThirdwebRuntimeSettings::GetAppUri(); + return UThirdwebRuntimeSettings::GetAppUri(); #else return DummyUrl; #endif @@ -88,8 +89,8 @@ void UThirdwebOAuthBrowserUserWidget::Authenticate(const FInAppWalletHandle& InA TW_LOG(VeryVerbose, TEXT("OAuthBrowserUserWidget::Authenticate::Wallet Type::%s"), Wallet.GetSourceString()); if (Wallet == FInAppWalletHandle::Siwe) { - TW_LOG(VeryVerbose, TEXT("OAuthBrowserUserWidget::Authenticate::Authenticating against SIWE")); - ExternalBrowser->Authenticate(TEXT("SIWE")); + TW_LOG(VeryVerbose, TEXT("OAuthBrowserUserWidget::Authenticate::" "Authenticating against %s"), Wallet.GetSourceString()); + ExternalBrowser->Authenticate(Wallet.GetSourceString()); return; } @@ -102,17 +103,21 @@ void UThirdwebOAuthBrowserUserWidget::Authenticate(const FInAppWalletHandle& InA TW_LOG(VeryVerbose, TEXT("OAuthBrowserUserWidget::Authenticate::Authenticating against %s"), *Link); #if PLATFORM_ANDROID - if (JNIEnv *Env = FAndroidApplication::GetJavaEnv()) - { - jstring JUrl = Env->NewStringUTF(TCHAR_TO_UTF8(*Link)); - jclass JClass = FAndroidApplication::FindJavaClass("com/thirdweb/unrealengine/ThirdwebActivity"); - static jmethodID JLaunchUrl = FJavaWrapper::FindStaticMethod(Env, JClass, "startActivity", "(Landroid/app/Activity;Ljava/lang/String;)V", false); - ThirdwebUtils::Internal::Android::CallJniStaticVoidMethod(Env, JClass, JLaunchUrl, FJavaWrapper::GameActivityThis, JUrl); - TW_LOG(Verbose, TEXT("OAuthBrowserUserWidget::Authenticate::Opening CustomTabs")); - return; - } - TW_LOG(Error, TEXT("OAuthBrowserUserWidget::Authenticate::No JNIEnv found")); - return; + if (JNIEnv *Env = FAndroidApplication::GetJavaEnv()) { + jstring JUrl = Env->NewStringUTF(TCHAR_TO_UTF8(*Link)); + jclass JClass = FAndroidApplication::FindJavaClass( + "com/thirdweb/unrealengine/ThirdwebActivity"); + static jmethodID JLaunchUrl = FJavaWrapper::FindStaticMethod( + Env, JClass, "startActivity", + "(Landroid/app/Activity;Ljava/lang/String;)V", false); + ThirdwebUtils::Internal::Android::CallJniStaticVoidMethod( + Env, JClass, JLaunchUrl, FJavaWrapper::GameActivityThis, JUrl); + TW_LOG(Verbose, + TEXT("OAuthBrowserUserWidget::Authenticate::Opening CustomTabs")); + return; + } + TW_LOG(Error, TEXT("OAuthBrowserUserWidget::Authenticate::No JNIEnv found")); + return; #endif return ExternalBrowser->Authenticate(Link); @@ -156,9 +161,27 @@ void UThirdwebOAuthBrowserUserWidget::HandleAuthenticated(const FString& AuthRes OnAuthenticated.Broadcast(AuthResult); } -void UThirdwebOAuthBrowserUserWidget::HandleSiweComplete(const FString& Signature, const FString& Payload) +void UThirdwebOAuthBrowserUserWidget::HandleSiweComplete(const FString& Payload, const FString& Signature) { - OnSiweComplete.Broadcast(Signature, Payload); + if (IsInGameThread()) + { + OnSiweComplete.Broadcast(Payload, Signature); + } + else + { + // Dispatch to game thread + TWeakObjectPtr WeakThis = this; + FFunctionGraphTask::CreateAndDispatchWhenReady([WeakThis, Payload, Signature]() + { + if (WeakThis.IsValid()) + { + WeakThis->OnSiweComplete.Broadcast(Payload, Signature); + } + }, + TStatId(), + nullptr, + ENamedThreads::GameThread); + } } void UThirdwebOAuthBrowserUserWidget::HandleError(const FString& Error) @@ -167,16 +190,18 @@ void UThirdwebOAuthBrowserUserWidget::HandleError(const FString& Error) } #if PLATFORM_ANDROID -void UThirdwebOAuthBrowserUserWidget::HandleDeepLink(const FString &Url) -{ - TW_LOG(VeryVerbose, TEXT("UThirdwebOAuthBrowserUserWidget::HandleDeepLink::%s"), *Url); - HandleUrlChanged(Url); +void UThirdwebOAuthBrowserUserWidget::HandleDeepLink(const FString &Url) { + TW_LOG(VeryVerbose, + TEXT("UThirdwebOAuthBrowserUserWidget::HandleDeepLink::%s"), *Url); + HandleUrlChanged(Url); } -void UThirdwebOAuthBrowserUserWidget::HandleCustomTabsDismissed(const FString &Url) -{ - TW_LOG(VeryVerbose, TEXT("UThirdwebOAuthBrowserUserWidget::HandleCustomTabsDismissed::%s"), *Url); - HandleUrlChanged(Url); +void UThirdwebOAuthBrowserUserWidget::HandleCustomTabsDismissed( + const FString &Url) { + TW_LOG(VeryVerbose, + TEXT("UThirdwebOAuthBrowserUserWidget::HandleCustomTabsDismissed::%s"), + *Url); + HandleUrlChanged(Url); } #endif @@ -188,7 +213,7 @@ void UThirdwebOAuthBrowserUserWidget::SetVisible(const bool bVisible) if (bCollapseWhenBlank) { #if PLATFORM_IOS | PLATFORM_ANDROID - SetRenderOpacity(1.0f); + SetRenderOpacity(1.0f); #else SetVisibility(ESlateVisibility::Visible); #endif @@ -200,7 +225,7 @@ void UThirdwebOAuthBrowserUserWidget::SetVisible(const bool bVisible) if (bCollapseWhenBlank) { #if PLATFORM_IOS | PLATFORM_ANDROID - SetRenderOpacity(0.01f); + SetRenderOpacity(0.01f); #else SetVisibility(ESlateVisibility::Collapsed); #endif diff --git a/Source/Thirdweb/Private/Browser/ThirdwebOAuthExternalBrowser.cpp b/Source/Thirdweb/Private/Browser/ThirdwebOAuthExternalBrowser.cpp index 67dd310..9e7feb6 100644 --- a/Source/Thirdweb/Private/Browser/ThirdwebOAuthExternalBrowser.cpp +++ b/Source/Thirdweb/Private/Browser/ThirdwebOAuthExternalBrowser.cpp @@ -2,15 +2,15 @@ #include "Browser/ThirdwebOAuthExternalBrowser.h" +#include "Delegates/DelegateSignatureImpl.inl" +#include "GenericPlatform/GenericPlatformHttp.h" +#include "HAL/Event.h" #include "HttpRequestHandler.h" #include "HttpServerModule.h" #include "IHttpRouter.h" +#include "Misc/EngineVersionComparison.h" #include "ThirdwebLog.h" #include "ThirdwebRuntimeSettings.h" -#include "Delegates/DelegateSignatureImpl.inl" -#include "GenericPlatform/GenericPlatformHttp.h" -#include "HAL/Event.h" -#include "Misc/EngineVersionComparison.h" UThirdwebOAuthExternalBrowser::UThirdwebOAuthExternalBrowser() { @@ -21,6 +21,16 @@ UThirdwebOAuthExternalBrowser::UThirdwebOAuthExternalBrowser() void UThirdwebOAuthExternalBrowser::Authenticate(const FString& Link) { + // Clean up any previous authentication session + CleanupAuthentication(); + + // Reset state + State = Initialized; + bIsSiwe = false; + AuthResult.Empty(); + Signature.Empty(); + Payload.Empty(); + FString Url = Link; EModuleLoadResult ModuleResult; FModuleManager::Get().LoadModuleWithFailureReason(FName(TEXT("HTTPServer")), ModuleResult); @@ -34,22 +44,22 @@ void UThirdwebOAuthExternalBrowser::Authenticate(const FString& Link) { return HandleError(TEXT("Failed to get HTTP Router")); } - + AuthEvent = FPlatformProcess::GetSynchEventFromPool(false); #if UE_VERSION_OLDER_THAN(5, 4, 0) - FHttpRequestHandler Handler = [WeakThis = MakeWeakObjectPtr(this)](const FHttpServerRequest& Request, const FHttpResultCallback& OnComplete) - { - if (WeakThis.IsValid()) - { - return WeakThis->CallbackRequestHandler(Request, OnComplete); - } - return false; - }; + FHttpRequestHandler Handler = [WeakThis = MakeWeakObjectPtr(this)]( + const FHttpServerRequest &Request, + const FHttpResultCallback &OnComplete) { + if (WeakThis.IsValid()) { + return WeakThis->CallbackRequestHandler(Request, OnComplete); + } + return false; + }; #else FHttpRequestHandler Handler = FHttpRequestHandler::CreateUObject(this, &UThirdwebOAuthExternalBrowser::CallbackRequestHandler); #endif - + RouteHandle = Router->BindRoute(FHttpPath(TEXT("/callback")), EHttpServerRequestVerbs::VERB_GET, Handler); if (!RouteHandle.IsValid()) @@ -65,11 +75,12 @@ void UThirdwebOAuthExternalBrowser::Authenticate(const FString& Link) bIsSiwe = Url.ToUpper().TrimStartAndEnd().Equals(TEXT("SIWE")); if (bIsSiwe) { - Url = FString::Printf(TEXT("http://static.thirdweb.com/auth/siwe?redirectUrl=%s"), *FGenericPlatformHttp::UrlEncode(TEXT("http://localhost:8789/callback"))); + Url = FString::Printf(TEXT("http://static.thirdweb.com/auth/siwe?redirectUrl=%s"), + *FGenericPlatformHttp::UrlEncode(TEXT("http://localhost:8789/callback"))); } // Open the browser with the login URL - FPlatformProcess::LaunchURL(*Link, nullptr, nullptr); - TW_LOG(Verbose, TEXT("Browser opened with URL: %s"), *Link); + FPlatformProcess::LaunchURL(*Url, nullptr, nullptr); + TW_LOG(Verbose, TEXT("Browser opened with URL: %s"), *Url); State = AuthPending; } @@ -86,36 +97,29 @@ void UThirdwebOAuthExternalBrowser::Tick(float DeltaTime) { return HandleSuccess(); } - } else + } + else { if (!AuthResult.IsEmpty()) { return HandleSuccess(); } } - + HandleError(TEXT("OAuth login flow did not complete in time")); } } void UThirdwebOAuthExternalBrowser::BeginDestroy() { - // Stop the HTTP listener + // Clean up authentication resources (idempotent) + CleanupAuthentication(); + + // Stop the HTTP listener (this stops ALL listeners globally) FHttpServerModule::Get().StopAllListeners(); TW_LOG(VeryVerbose, TEXT("OAuth HTTP Server stopped listening")); - if (Router.IsValid() && RouteHandle.IsValid()) - { - // Unbind the route - Router->UnbindRoute(RouteHandle); - TW_LOG(VeryVerbose, TEXT("Route unbound")); - } - if (AuthEvent) - { - FPlatformProcess::ReturnSynchEventToPool(AuthEvent); - } ConditionalBeginDestroy(); - UObject::BeginDestroy(); } @@ -124,7 +128,11 @@ bool UThirdwebOAuthExternalBrowser::CallbackRequestHandler(const FHttpServerRequ AuthResult = Request.QueryParams.FindRef(TEXT("authResult")); Signature = Request.QueryParams.FindRef(TEXT("signature")); Payload = FGenericPlatformHttp::UrlDecode(Request.QueryParams.FindRef(TEXT("payload"))); - TW_LOG(VeryVerbose, TEXT("UThirdwebOAuthExternalBrowser::CallbackRequestHandler::Signature=%s|Payload=%s|AuthResult=%s"), *Signature, *Payload, *AuthResult) + TW_LOG(VeryVerbose, + TEXT("UThirdwebOAuthExternalBrowser::CallbackRequestHandler::" "Signature=%s|Payload=%s|AuthResult=%s"), + *Signature, + *Payload, + *AuthResult) if (bIsSiwe ? Signature.IsEmpty() || Payload.IsEmpty() : AuthResult.IsEmpty()) { FString Error = FString::Printf(TEXT("%s query parameter is missing"), bIsSiwe ? TEXT("Signature/Payload") : TEXT("AuthResult")); @@ -138,8 +146,7 @@ bool UThirdwebOAuthExternalBrowser::CallbackRequestHandler(const FHttpServerRequ AuthEvent->Trigger(); TUniquePtr Response = FHttpServerResponse::Create( FString::Printf(TEXT(""), *UThirdwebRuntimeSettings::GetExternalAuthRedirectUri()), - TEXT("text/html") - ); + TEXT("text/html")); OnComplete(MoveTemp(Response)); } return true; @@ -151,27 +158,48 @@ void UThirdwebOAuthExternalBrowser::HandleSuccess() { if (OnSiweComplete.IsBound()) { - OnSiweComplete.Execute(Signature, Payload); + OnSiweComplete.Execute(Payload, Signature); } - } else + } + else { if (OnAuthenticated.IsBound()) { OnAuthenticated.Execute(AuthResult); } } - + + // Clean up immediately after delegate fires + CleanupAuthentication(); } void UThirdwebOAuthExternalBrowser::HandleError(const FString& Error) { - TW_LOG(VeryVerbose, TEXT("UThirdwebOAuthExternalBrowser::HandleError::%s"), *Error); if (OnError.IsBound()) { OnError.Execute(Error); } -} + // Clean up immediately after delegate fires + CleanupAuthentication(); +} +void UThirdwebOAuthExternalBrowser::CleanupAuthentication() +{ + // Unbind route if it exists + if (Router.IsValid() && RouteHandle.IsValid()) + { + Router->UnbindRoute(RouteHandle); + RouteHandle = FHttpRouteHandle(); + TW_LOG(VeryVerbose, TEXT("Route unbound in cleanup")); + } + // Return event to pool + if (AuthEvent) + { + FPlatformProcess::ReturnSynchEventToPool(AuthEvent); + AuthEvent = nullptr; + TW_LOG(VeryVerbose, TEXT("AuthEvent returned to pool")); + } +} diff --git a/Source/Thirdweb/Private/ThirdwebUtils.cpp b/Source/Thirdweb/Private/ThirdwebUtils.cpp index ae183cf..0be3613 100644 --- a/Source/Thirdweb/Private/ThirdwebUtils.cpp +++ b/Source/Thirdweb/Private/ThirdwebUtils.cpp @@ -516,7 +516,7 @@ namespace ThirdwebUtils {TEXT("x-bundle-id"), Settings->GetBundleId()}, }); Headers.UpdateRequest(Request); - Request->SetTimeout(5.0f); + Request->SetTimeout(15.0f); // ReSharper disable once CppLocalVariableMayBeConst TSharedPtr JsonObject = MakeShareable(new FJsonObject); diff --git a/Source/Thirdweb/Private/Wallets/ThirdwebInAppWalletHandle.cpp b/Source/Thirdweb/Private/Wallets/ThirdwebInAppWalletHandle.cpp index 31fd0cd..0958484 100644 --- a/Source/Thirdweb/Private/Wallets/ThirdwebInAppWalletHandle.cpp +++ b/Source/Thirdweb/Private/Wallets/ThirdwebInAppWalletHandle.cpp @@ -77,110 +77,114 @@ void FInAppWalletHandle::CreateEmailWallet(const FString& Email, const FCreateIn { CHECK_DELEGATES(SuccessDelegate, ErrorDelegate) - UE::Tasks::Launch(UE_SOURCE_LOCATION, [Email, SuccessDelegate, ErrorDelegate] - { - FString Error; - if (Thirdweb::create_ecosystem_wallet( - TO_RUST_STRING(UThirdwebRuntimeSettings::GetEcosystemId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetPartnerId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetClientId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetBundleId()), - nullptr, - TO_RUST_STRING(Email), - nullptr, - TO_RUST_STRING(UThirdwebRuntimeSettings::GetStorageDirectory()), - nullptr, - nullptr - ).AssignResult(Error)) - { - SuccessDelegate.Execute(FInAppWalletHandle(EInAppSource::Email, Error)); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [Email, SuccessDelegate, ErrorDelegate] + { + FString Error; + if (Thirdweb::create_ecosystem_wallet( + TO_RUST_STRING(UThirdwebRuntimeSettings::GetEcosystemId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetPartnerId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetClientId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetBundleId()), + nullptr, + TO_RUST_STRING(Email), + nullptr, + TO_RUST_STRING(UThirdwebRuntimeSettings::GetStorageDirectory()), + nullptr, + nullptr).AssignResult(Error)) + { + SuccessDelegate.Execute(FInAppWalletHandle(EInAppSource::Email, Error)); + return; + } + ErrorDelegate.Execute(Error); + }); } -void FInAppWalletHandle::CreateOAuthWallet(const EThirdwebOAuthProvider Provider, const FCreateInAppWalletDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) +void FInAppWalletHandle::CreateOAuthWallet(const EThirdwebOAuthProvider Provider, + const FCreateInAppWalletDelegate& SuccessDelegate, + const FStringDelegate& ErrorDelegate) { CHECK_DELEGATES(SuccessDelegate, ErrorDelegate) - UE::Tasks::Launch(UE_SOURCE_LOCATION, [Provider, SuccessDelegate, ErrorDelegate] - { - FString Error; - if (Thirdweb::create_ecosystem_wallet( - TO_RUST_STRING(UThirdwebRuntimeSettings::GetEcosystemId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetPartnerId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetClientId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetBundleId()), - nullptr, - nullptr, - nullptr, - TO_RUST_STRING(UThirdwebRuntimeSettings::GetStorageDirectory()), - TO_RUST_STRING(ThirdwebUtils::ToString(Provider)), - nullptr - ).AssignResult(Error)) - { - SuccessDelegate.Execute(FInAppWalletHandle(Provider, Error)); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [Provider, SuccessDelegate, ErrorDelegate] + { + FString Error; + if (Thirdweb::create_ecosystem_wallet( + TO_RUST_STRING(UThirdwebRuntimeSettings::GetEcosystemId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetPartnerId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetClientId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetBundleId()), + nullptr, + nullptr, + nullptr, + TO_RUST_STRING(UThirdwebRuntimeSettings::GetStorageDirectory()), + TO_RUST_STRING(ThirdwebUtils::ToString(Provider)), + nullptr).AssignResult(Error)) + { + SuccessDelegate.Execute(FInAppWalletHandle(Provider, Error)); + return; + } + ErrorDelegate.Execute(Error); + }); } void FInAppWalletHandle::CreatePhoneWallet(const FString& Phone, const FCreateInAppWalletDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) { CHECK_DELEGATES(SuccessDelegate, ErrorDelegate) - UE::Tasks::Launch(UE_SOURCE_LOCATION, [Phone, SuccessDelegate, ErrorDelegate] - { - FString Error; - if (Thirdweb::create_ecosystem_wallet( - TO_RUST_STRING(UThirdwebRuntimeSettings::GetEcosystemId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetPartnerId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetClientId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetBundleId()), - nullptr, - nullptr, - TO_RUST_STRING(Phone), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetStorageDirectory()), - nullptr, - nullptr - ).AssignResult(Error)) - { - SuccessDelegate.Execute(FInAppWalletHandle(EInAppSource::Phone, Error)); - return; - } - - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [Phone, SuccessDelegate, ErrorDelegate] + { + FString Error; + if (Thirdweb::create_ecosystem_wallet( + TO_RUST_STRING(UThirdwebRuntimeSettings::GetEcosystemId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetPartnerId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetClientId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetBundleId()), + nullptr, + nullptr, + TO_RUST_STRING(Phone), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetStorageDirectory()), + nullptr, + nullptr).AssignResult(Error)) + { + SuccessDelegate.Execute(FInAppWalletHandle(EInAppSource::Phone, Error)); + return; + } + + ErrorDelegate.Execute(Error); + }); } void FInAppWalletHandle::CreateSiweWallet(const FCreateInAppWalletDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) { CHECK_DELEGATES(SuccessDelegate, ErrorDelegate) - UE::Tasks::Launch(UE_SOURCE_LOCATION, [SuccessDelegate, ErrorDelegate] - { - static FString Provider = TEXT("SIWE"); - FString Error; - if (Thirdweb::create_ecosystem_wallet( - TO_RUST_STRING(UThirdwebRuntimeSettings::GetEcosystemId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetPartnerId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetClientId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetBundleId()), - nullptr, - nullptr, - nullptr, - TO_RUST_STRING(UThirdwebRuntimeSettings::GetStorageDirectory()), - TO_RUST_STRING(Provider), - nullptr - ).AssignResult(Error)) - { - SuccessDelegate.Execute(FInAppWalletHandle(Siwe, Error)); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [SuccessDelegate, ErrorDelegate] + { + static FString Provider = TEXT("Siwe"); + FString Error; + if (Thirdweb::create_ecosystem_wallet( + TO_RUST_STRING(UThirdwebRuntimeSettings::GetEcosystemId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetPartnerId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetClientId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetBundleId()), + nullptr, + nullptr, + nullptr, + TO_RUST_STRING(UThirdwebRuntimeSettings::GetStorageDirectory()), + TO_RUST_STRING(Provider), + nullptr).AssignResult(Error)) + { + SuccessDelegate.Execute(FInAppWalletHandle(Siwe, Error)); + return; + } + ErrorDelegate.Execute(Error); + }); } -void FInAppWalletHandle::CreateCustomAuthWallet(const EInAppSource Source, const FCreateInAppWalletDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) +void FInAppWalletHandle::CreateCustomAuthWallet(const EInAppSource Source, + const FCreateInAppWalletDelegate& SuccessDelegate, + const FStringDelegate& ErrorDelegate) { CHECK_DELEGATES(SuccessDelegate, ErrorDelegate) if (Source != Jwt && Source != AuthEndpoint && Source != Guest) @@ -191,28 +195,27 @@ void FInAppWalletHandle::CreateCustomAuthWallet(const EInAppSource Source, const } return; } - UE::Tasks::Launch(UE_SOURCE_LOCATION, [Source, SuccessDelegate, ErrorDelegate] - { - FString Error; - if (Thirdweb::create_ecosystem_wallet( - TO_RUST_STRING(UThirdwebRuntimeSettings::GetEcosystemId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetPartnerId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetClientId()), - TO_RUST_STRING(UThirdwebRuntimeSettings::GetBundleId()), - nullptr, - nullptr, - nullptr, - TO_RUST_STRING(UThirdwebRuntimeSettings::GetStorageDirectory()), - TO_RUST_STRING(FString(GetSourceString(Source))), - // legacy, will be used if migrating only - TO_RUST_STRING(UThirdwebRuntimeSettings::GetEncryptionKey()) - ).AssignResult(Error)) - { - SuccessDelegate.Execute(FInAppWalletHandle(Source, Error)); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [Source, SuccessDelegate, ErrorDelegate] + { + FString Error; + if (Thirdweb::create_ecosystem_wallet(TO_RUST_STRING(UThirdwebRuntimeSettings::GetEcosystemId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetPartnerId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetClientId()), + TO_RUST_STRING(UThirdwebRuntimeSettings::GetBundleId()), + nullptr, + nullptr, + nullptr, + TO_RUST_STRING(UThirdwebRuntimeSettings::GetStorageDirectory()), + TO_RUST_STRING(FString(GetSourceString(Source))), + // legacy, will be used if migrating only + TO_RUST_STRING(UThirdwebRuntimeSettings::GetEncryptionKey())).AssignResult(Error)) + { + SuccessDelegate.Execute(FInAppWalletHandle(Source, Error)); + return; + } + ErrorDelegate.Execute(Error); + }); } bool FInAppWalletHandle::IsConnected() const @@ -230,36 +233,37 @@ void FInAppWalletHandle::SendOTP(const FStreamableDelegate& SuccessDelegate, con CHECK_DELEGATES(SuccessDelegate, ErrorDelegate) CHECK_VALIDITY(ErrorDelegate) FInAppWalletHandle ThisCopy = *this; - UE::Tasks::Launch(UE_SOURCE_LOCATION, [ThisCopy, SuccessDelegate, ErrorDelegate] - { - FString Error; - switch (ThisCopy.GetSource()) - { - case Phone: - { - if (Thirdweb::ecosystem_wallet_send_otp_phone(ThisCopy.GetID()).AssignResult(Error, true)) - { - SuccessDelegate.Execute(); - return; - } - break; - } - case Email: - { - if (Thirdweb::ecosystem_wallet_send_otp_email(ThisCopy.GetID()).AssignResult(Error, true)) - { - SuccessDelegate.Execute(); - return; - } - break; - } - default: - { - Error = TEXT("Wallet handle is not email/phone source"); - } - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [ThisCopy, SuccessDelegate, ErrorDelegate] + { + FString Error; + switch (ThisCopy.GetSource()) + { + case Phone: + { + if (Thirdweb::ecosystem_wallet_send_otp_phone(ThisCopy.GetID()).AssignResult(Error, true)) + { + SuccessDelegate.Execute(); + return; + } + break; + } + case Email: + { + if (Thirdweb::ecosystem_wallet_send_otp_email(ThisCopy.GetID()).AssignResult(Error, true)) + { + SuccessDelegate.Execute(); + return; + } + break; + } + default: + { + Error = TEXT("Wallet handle is not email/phone source"); + } + } + ErrorDelegate.Execute(Error); + }); } void FInAppWalletHandle::SignInWithOTP(const FString& OTP, const FStreamableDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) @@ -272,38 +276,42 @@ void FInAppWalletHandle::SignInWithOTP(const FString& OTP, const FStreamableDele return; } FInAppWalletHandle ThisCopy = *this; - UE::Tasks::Launch(UE_SOURCE_LOCATION, [ThisCopy, OTP, SuccessDelegate, ErrorDelegate] - { - FString Error; - switch (ThisCopy.GetSource()) - { - case Phone: - { - if (Thirdweb::ecosystem_wallet_sign_in_with_otp_phone(ThisCopy.GetID(), TO_RUST_STRING(OTP)).AssignResult(Error, true)) - { - ThirdwebUtils::Internal::SendConnectEvent(ThisCopy); - SuccessDelegate.Execute(); - return; - } - break; - } - case Email: - { - if (Thirdweb::ecosystem_wallet_sign_in_with_otp_email(ThisCopy.GetID(), TO_RUST_STRING(OTP)).AssignResult(Error, true)) - { - ThirdwebUtils::Internal::SendConnectEvent(ThisCopy); - SuccessDelegate.Execute(); - return; - } - break; - } - default: return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [ThisCopy, OTP, SuccessDelegate, ErrorDelegate] + { + FString Error; + switch (ThisCopy.GetSource()) + { + case Phone: + { + if (Thirdweb::ecosystem_wallet_sign_in_with_otp_phone(ThisCopy.GetID(), TO_RUST_STRING(OTP)).AssignResult(Error, true)) + { + ThirdwebUtils::Internal::SendConnectEvent(ThisCopy); + SuccessDelegate.Execute(); + return; + } + break; + } + case Email: + { + if (Thirdweb::ecosystem_wallet_sign_in_with_otp_email(ThisCopy.GetID(), TO_RUST_STRING(OTP)).AssignResult(Error, true)) + { + ThirdwebUtils::Internal::SendConnectEvent(ThisCopy); + SuccessDelegate.Execute(); + return; + } + break; + } + default: return; + } + ErrorDelegate.Execute(Error); + }); } -void FInAppWalletHandle::LinkOTP(const FInAppWalletHandle& Wallet, const FString& OTP, const FStreamableDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) +void FInAppWalletHandle::LinkOTP(const FInAppWalletHandle& Wallet, + const FString& OTP, + const FStreamableDelegate& SuccessDelegate, + const FStringDelegate& ErrorDelegate) { CHECK_DELEGATES(SuccessDelegate, ErrorDelegate) CHECK_VALIDITY(ErrorDelegate) @@ -313,26 +321,25 @@ void FInAppWalletHandle::LinkOTP(const FInAppWalletHandle& Wallet, const FString return; } FInAppWalletHandle ThisCopy = *this; - UE::Tasks::Launch(UE_SOURCE_LOCATION, [ThisCopy, Wallet, OTP, SuccessDelegate, ErrorDelegate] - { - FString Error; - if (Thirdweb::ecosystem_wallet_link_account( - ThisCopy.GetID(), - Wallet.GetID(), - TO_RUST_STRING(OTP), - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr - ).AssignResult(Error, true)) - { - SuccessDelegate.Execute(); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [ThisCopy, Wallet, OTP, SuccessDelegate, ErrorDelegate] + { + FString Error; + if (Thirdweb::ecosystem_wallet_link_account(ThisCopy.GetID(), + Wallet.GetID(), + TO_RUST_STRING(OTP), + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr).AssignResult(Error, true)) + { + SuccessDelegate.Execute(); + return; + } + ErrorDelegate.Execute(Error); + }); } bool FInAppWalletHandle::FetchOAuthLoginURL(const FString& RedirectUrl, FString& LoginLink, FString& Error) @@ -370,21 +377,25 @@ void FInAppWalletHandle::SignInWithOAuth(const FString& AuthResult, const FStrea } FString Result = ThirdwebUtils::ParseAuthResult(AuthResult); FInAppWalletHandle ThisCopy = *this; - UE::Tasks::Launch(UE_SOURCE_LOCATION, [ThisCopy, Result, SuccessDelegate, ErrorDelegate] - { - FString Error; - TW_LOG(VeryVerbose, TEXT("FInAppWalletHandle::SignInWithOAuth::Task::%s"), *Result) - if (Thirdweb::ecosystem_wallet_sign_in_with_oauth(ThisCopy.GetID(), TO_RUST_STRING(Result)).AssignResult(Error, true)) - { - ThirdwebUtils::Internal::SendConnectEvent(ThisCopy); - SuccessDelegate.Execute(); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [ThisCopy, Result, SuccessDelegate, ErrorDelegate] + { + FString Error; + TW_LOG(VeryVerbose, TEXT("FInAppWalletHandle::SignInWithOAuth::Task::%s"), *Result) + if (Thirdweb::ecosystem_wallet_sign_in_with_oauth(ThisCopy.GetID(), TO_RUST_STRING(Result)).AssignResult(Error, true)) + { + ThirdwebUtils::Internal::SendConnectEvent(ThisCopy); + SuccessDelegate.Execute(); + return; + } + ErrorDelegate.Execute(Error); + }); } -void FInAppWalletHandle::LinkOAuth(const FInAppWalletHandle& Wallet, const FString& AuthResult, const FStreamableDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) +void FInAppWalletHandle::LinkOAuth(const FInAppWalletHandle& Wallet, + const FString& AuthResult, + const FStreamableDelegate& SuccessDelegate, + const FStringDelegate& ErrorDelegate) { CHECK_DELEGATES(SuccessDelegate, ErrorDelegate) CHECK_VALIDITY(ErrorDelegate) @@ -392,26 +403,25 @@ void FInAppWalletHandle::LinkOAuth(const FInAppWalletHandle& Wallet, const FStri FString Result = ThirdwebUtils::ParseAuthResult(AuthResult); FInAppWalletHandle ThisCopy = *this; - UE::Tasks::Launch(UE_SOURCE_LOCATION, [ThisCopy, Wallet, Result, SuccessDelegate, ErrorDelegate] - { - FString Error; - if (Thirdweb::ecosystem_wallet_link_account( - ThisCopy.GetID(), - Wallet.GetID(), - nullptr, - TO_RUST_STRING(Result), - nullptr, - nullptr, - nullptr, - nullptr, - nullptr - ).AssignResult(Error, true)) - { - SuccessDelegate.Execute(); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [ThisCopy, Wallet, Result, SuccessDelegate, ErrorDelegate] + { + FString Error; + if (Thirdweb::ecosystem_wallet_link_account(ThisCopy.GetID(), + Wallet.GetID(), + nullptr, + TO_RUST_STRING(Result), + nullptr, + nullptr, + nullptr, + nullptr, + nullptr).AssignResult(Error, true)) + { + SuccessDelegate.Execute(); + return; + } + ErrorDelegate.Execute(Error); + }); } void FInAppWalletHandle::SignInWithJwt(const FString& Jwt, const FStreamableDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) @@ -421,46 +431,49 @@ void FInAppWalletHandle::SignInWithJwt(const FString& Jwt, const FStreamableDele CHECK_SOURCE(EInAppSource::Jwt, ErrorDelegate) FInAppWalletHandle ThisCopy = *this; - UE::Tasks::Launch(UE_SOURCE_LOCATION, [ThisCopy, Jwt, SuccessDelegate, ErrorDelegate] - { - FString Error; - if (Thirdweb::ecosystem_wallet_sign_in_with_jwt(ThisCopy.GetID(), TO_RUST_STRING(Jwt)).AssignResult(Error, true)) - { - ThirdwebUtils::Internal::SendConnectEvent(ThisCopy); - SuccessDelegate.Execute(); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [ThisCopy, Jwt, SuccessDelegate, ErrorDelegate] + { + FString Error; + if (Thirdweb::ecosystem_wallet_sign_in_with_jwt(ThisCopy.GetID(), TO_RUST_STRING(Jwt)).AssignResult(Error, true)) + { + ThirdwebUtils::Internal::SendConnectEvent(ThisCopy); + SuccessDelegate.Execute(); + return; + } + ErrorDelegate.Execute(Error); + }); } -void FInAppWalletHandle::LinkJwt(const FInAppWalletHandle& Wallet, const FString& Jwt, const FStreamableDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) +void FInAppWalletHandle::LinkJwt(const FInAppWalletHandle& Wallet, + const FString& Jwt, + const FStreamableDelegate& SuccessDelegate, + const FStringDelegate& ErrorDelegate) { CHECK_DELEGATES(SuccessDelegate, ErrorDelegate) CHECK_VALIDITY(ErrorDelegate) CHECK_WALLET_SOURCE(Wallet, EInAppSource::Jwt, ErrorDelegate) FInAppWalletHandle ThisCopy = *this; - UE::Tasks::Launch(UE_SOURCE_LOCATION, [ThisCopy, Wallet, Jwt, SuccessDelegate, ErrorDelegate] - { - FString Error; - if (Thirdweb::ecosystem_wallet_link_account( - ThisCopy.GetID(), - Wallet.GetID(), - nullptr, - nullptr, - TO_RUST_STRING(Jwt), - nullptr, - nullptr, - nullptr, - nullptr - ).AssignResult(Error, true)) - { - SuccessDelegate.Execute(); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [ThisCopy, Wallet, Jwt, SuccessDelegate, ErrorDelegate] + { + FString Error; + if (Thirdweb::ecosystem_wallet_link_account(ThisCopy.GetID(), + Wallet.GetID(), + nullptr, + nullptr, + TO_RUST_STRING(Jwt), + nullptr, + nullptr, + nullptr, + nullptr).AssignResult(Error, true)) + { + SuccessDelegate.Execute(); + return; + } + ErrorDelegate.Execute(Error); + }); } void FInAppWalletHandle::SignInWithAuthEndpoint(const FString& Payload, const FStreamableDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) @@ -470,46 +483,49 @@ void FInAppWalletHandle::SignInWithAuthEndpoint(const FString& Payload, const FS CHECK_SOURCE(AuthEndpoint, ErrorDelegate) FInAppWalletHandle ThisCopy = *this; - UE::Tasks::Launch(UE_SOURCE_LOCATION, [ThisCopy, Payload, SuccessDelegate, ErrorDelegate] - { - FString Error; - if (Thirdweb::ecosystem_wallet_sign_in_with_auth_endpoint(ThisCopy.GetID(), TO_RUST_STRING(Payload)).AssignResult(Error, true)) - { - ThirdwebUtils::Internal::SendConnectEvent(ThisCopy); - SuccessDelegate.Execute(); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [ThisCopy, Payload, SuccessDelegate, ErrorDelegate] + { + FString Error; + if (Thirdweb::ecosystem_wallet_sign_in_with_auth_endpoint(ThisCopy.GetID(), TO_RUST_STRING(Payload)).AssignResult(Error, true)) + { + ThirdwebUtils::Internal::SendConnectEvent(ThisCopy); + SuccessDelegate.Execute(); + return; + } + ErrorDelegate.Execute(Error); + }); } -void FInAppWalletHandle::LinkAuthEndpoint(const FInAppWalletHandle& Wallet, const FString& Payload, const FStreamableDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) +void FInAppWalletHandle::LinkAuthEndpoint(const FInAppWalletHandle& Wallet, + const FString& Payload, + const FStreamableDelegate& SuccessDelegate, + const FStringDelegate& ErrorDelegate) { CHECK_DELEGATES(SuccessDelegate, ErrorDelegate) CHECK_VALIDITY(ErrorDelegate) CHECK_WALLET_SOURCE(Wallet, AuthEndpoint, ErrorDelegate) FInAppWalletHandle ThisCopy = *this; - UE::Tasks::Launch(UE_SOURCE_LOCATION, [ThisCopy, Wallet, Payload, SuccessDelegate, ErrorDelegate] - { - FString Error; - if (Thirdweb::ecosystem_wallet_link_account( - ThisCopy.GetID(), - Wallet.GetID(), - nullptr, - nullptr, - nullptr, - TO_RUST_STRING(Payload), - nullptr, - nullptr, - nullptr - ).AssignResult(Error, true)) - { - SuccessDelegate.Execute(); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [ThisCopy, Wallet, Payload, SuccessDelegate, ErrorDelegate] + { + FString Error; + if (Thirdweb::ecosystem_wallet_link_account(ThisCopy.GetID(), + Wallet.GetID(), + nullptr, + nullptr, + nullptr, + TO_RUST_STRING(Payload), + nullptr, + nullptr, + nullptr).AssignResult(Error, true)) + { + SuccessDelegate.Execute(); + return; + } + ErrorDelegate.Execute(Error); + }); } void FInAppWalletHandle::SignInWithGuest(const FStreamableDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) @@ -519,17 +535,20 @@ void FInAppWalletHandle::SignInWithGuest(const FStreamableDelegate& SuccessDeleg CHECK_SOURCE(Guest, ErrorDelegate) FInAppWalletHandle ThisCopy = *this; - UE::Tasks::Launch(UE_SOURCE_LOCATION, [ThisCopy, SuccessDelegate, ErrorDelegate] - { - FString Error; - if (Thirdweb::ecosystem_wallet_sign_in_with_guest(ThisCopy.GetID(), TO_RUST_STRING(FPlatformMisc::GetLoginId())).AssignResult(Error, true)) - { - ThirdwebUtils::Internal::SendConnectEvent(ThisCopy); - SuccessDelegate.Execute(); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [ThisCopy, SuccessDelegate, ErrorDelegate] + { + FString Error; + if (Thirdweb::ecosystem_wallet_sign_in_with_guest(ThisCopy.GetID(), TO_RUST_STRING(FPlatformMisc::GetLoginId())).AssignResult( + Error, + true)) + { + ThirdwebUtils::Internal::SendConnectEvent(ThisCopy); + SuccessDelegate.Execute(); + return; + } + ErrorDelegate.Execute(Error); + }); } void FInAppWalletHandle::LinkGuest(const FInAppWalletHandle& Wallet, const FStreamableDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) @@ -539,73 +558,83 @@ void FInAppWalletHandle::LinkGuest(const FInAppWalletHandle& Wallet, const FStre CHECK_WALLET_SOURCE(Wallet, Guest, ErrorDelegate) FInAppWalletHandle ThisCopy = *this; - UE::Tasks::Launch(UE_SOURCE_LOCATION, [ThisCopy, Wallet, SuccessDelegate, ErrorDelegate] - { - FString Error; - if (Thirdweb::ecosystem_wallet_link_account( - ThisCopy.GetID(), - Wallet.GetID(), - nullptr, - nullptr, - nullptr, - nullptr, - TO_RUST_STRING(FPlatformMisc::GetLoginId()), - nullptr, - nullptr).AssignResult(Error, true)) - { - SuccessDelegate.Execute(); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [ThisCopy, Wallet, SuccessDelegate, ErrorDelegate] + { + FString Error; + if (Thirdweb::ecosystem_wallet_link_account(ThisCopy.GetID(), + Wallet.GetID(), + nullptr, + nullptr, + nullptr, + nullptr, + TO_RUST_STRING(FPlatformMisc::GetLoginId()), + nullptr, + nullptr).AssignResult(Error, true)) + { + SuccessDelegate.Execute(); + return; + } + ErrorDelegate.Execute(Error); + }); } -void FInAppWalletHandle::SignInWithEthereum(const FString& Payload, const FString& Signature, const FStreamableDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) +void FInAppWalletHandle::SignInWithEthereum(const FString& Payload, + const FString& Signature, + const FStreamableDelegate& SuccessDelegate, + const FStringDelegate& ErrorDelegate) { CHECK_DELEGATES(SuccessDelegate, ErrorDelegate) CHECK_VALIDITY(ErrorDelegate) CHECK_SOURCE(Siwe, ErrorDelegate) FInAppWalletHandle ThisCopy = *this; - UE::Tasks::Launch(UE_SOURCE_LOCATION, [ThisCopy, Payload, Signature, SuccessDelegate, ErrorDelegate] - { - FString Error; - if (Thirdweb::ecosystem_wallet_sign_in_with_siwe(ThisCopy.GetID(), TO_RUST_STRING(Payload), TO_RUST_STRING(Signature)).AssignResult(Error, true)) - { - ThirdwebUtils::Internal::SendConnectEvent(ThisCopy); - SuccessDelegate.Execute(); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [ThisCopy, Payload, Signature, SuccessDelegate, ErrorDelegate] + { + FString Error; + if (Thirdweb::ecosystem_wallet_sign_in_with_siwe(ThisCopy.GetID(), TO_RUST_STRING(Payload), TO_RUST_STRING(Signature)).AssignResult( + Error, + true)) + { + ThirdwebUtils::Internal::SendConnectEvent(ThisCopy); + SuccessDelegate.Execute(); + return; + } + ErrorDelegate.Execute(Error); + }); } -void FInAppWalletHandle::LinkSiwe(const FInAppWalletHandle& Wallet, const FString& Payload, const FString& Signature, const FStreamableDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) +void FInAppWalletHandle::LinkSiwe(const FInAppWalletHandle& Wallet, + const FString& Payload, + const FString& Signature, + const FStreamableDelegate& SuccessDelegate, + const FStringDelegate& ErrorDelegate) { CHECK_DELEGATES(SuccessDelegate, ErrorDelegate) CHECK_VALIDITY(ErrorDelegate) CHECK_WALLET_SOURCE(Wallet, Siwe, ErrorDelegate) FInAppWalletHandle ThisCopy = *this; - UE::Tasks::Launch(UE_SOURCE_LOCATION, [ThisCopy, Wallet, Payload, Signature, SuccessDelegate, ErrorDelegate] - { - FString Error; - if (Thirdweb::ecosystem_wallet_link_account( - ThisCopy.GetID(), - Wallet.GetID(), - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - TO_RUST_STRING(Signature), - TO_RUST_STRING(Payload)).AssignResult(Error, true)) - { - SuccessDelegate.Execute(); - return; - } - ErrorDelegate.Execute(Error); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [ThisCopy, Wallet, Payload, Signature, SuccessDelegate, ErrorDelegate] + { + FString Error; + if (Thirdweb::ecosystem_wallet_link_account(ThisCopy.GetID(), + Wallet.GetID(), + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + TO_RUST_STRING(Payload), + TO_RUST_STRING(Signature)).AssignResult(Error, true)) + { + SuccessDelegate.Execute(); + return; + } + ErrorDelegate.Execute(Error); + }); } void FInAppWalletHandle::GetLinkedAccounts(const FGetLinkedAccountsDelegate& SuccessDelegate, const FStringDelegate& ErrorDelegate) @@ -614,25 +643,26 @@ void FInAppWalletHandle::GetLinkedAccounts(const FGetLinkedAccountsDelegate& Suc CHECK_VALIDITY(ErrorDelegate) FInAppWalletHandle ThisCopy = *this; - UE::Tasks::Launch(UE_SOURCE_LOCATION, [ThisCopy, SuccessDelegate, ErrorDelegate] - { - FString Output; - if (Thirdweb::ecosystem_wallet_get_linked_accounts(ThisCopy.GetID()).AssignResult(Output)) - { - TArray LinkedAccounts; - TArray> JsonValueArray = ThirdwebUtils::Json::ToJsonArray(Output); - for (int i = 0; i < JsonValueArray.Num(); i++) - { - if (JsonValueArray[i]->Type == EJson::Object) - { - LinkedAccounts.Emplace(FThirdwebLinkedAccount::FromJson(JsonValueArray[i]->AsObject())); - } - } - SuccessDelegate.Execute(LinkedAccounts); - return; - } - ErrorDelegate.Execute(Output); - }); + UE::Tasks::Launch(UE_SOURCE_LOCATION, + [ThisCopy, SuccessDelegate, ErrorDelegate] + { + FString Output; + if (Thirdweb::ecosystem_wallet_get_linked_accounts(ThisCopy.GetID()).AssignResult(Output)) + { + TArray LinkedAccounts; + TArray> JsonValueArray = ThirdwebUtils::Json::ToJsonArray(Output); + for (int i = 0; i < JsonValueArray.Num(); i++) + { + if (JsonValueArray[i]->Type == EJson::Object) + { + LinkedAccounts.Emplace(FThirdwebLinkedAccount::FromJson(JsonValueArray[i]->AsObject())); + } + } + SuccessDelegate.Execute(LinkedAccounts); + return; + } + ErrorDelegate.Execute(Output); + }); } FString FInAppWalletHandle::GetDisplayName() const diff --git a/Source/Thirdweb/Public/AsyncTasks/Wallets/InApp/AsyncTaskThirdwebLoginWithSiwe.h b/Source/Thirdweb/Public/AsyncTasks/Wallets/InApp/AsyncTaskThirdwebLoginWithSiwe.h new file mode 100644 index 0000000..671a549 --- /dev/null +++ b/Source/Thirdweb/Public/AsyncTasks/Wallets/InApp/AsyncTaskThirdwebLoginWithSiwe.h @@ -0,0 +1,48 @@ +// Copyright (c) 2025 Thirdweb. All Rights Reserved. + +#pragma once + +#include "AsyncTaskThirdwebInAppBase.h" +#include "Wallets/ThirdwebInAppWalletHandle.h" +#include "AsyncTaskThirdwebLoginWithSiwe.generated.h" + +class UThirdwebOAuthBrowserUserWidget; + +/** + * High-level SIWE login async task that handles browser widget creation and + * authentication flow + */ +UCLASS(Blueprintable, BlueprintType) +class THIRDWEB_API UAsyncTaskThirdwebLoginWithSiwe : public UAsyncTaskThirdwebInAppBase +{ + GENERATED_BODY() + +public: + virtual void Activate() override; + + UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Thirdweb|Wallets|In App") + static UAsyncTaskThirdwebLoginWithSiwe* + LoginWithSiwe(UObject* WorldContextObject, const FInAppWalletHandle& Wallet); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FSiweCompleteDelegate, const FString &, Payload, const FString &, Signature); + + UPROPERTY(BlueprintAssignable) + FSiweCompleteDelegate Success; + + UPROPERTY(BlueprintAssignable) + FErrorOnlyDelegate Failed; + +protected: + UPROPERTY(Transient) + UThirdwebOAuthBrowserUserWidget* Browser; + + UPROPERTY(Transient) + FInAppWalletHandle Wallet; + +private: + UFUNCTION() + void HandleSiweComplete(const FString& Payload, const FString& Signature); + + UFUNCTION() + void HandleFailed(const FString& Error); +}; diff --git a/Source/Thirdweb/Public/Browser/ThirdwebOAuthBrowserUserWidget.h b/Source/Thirdweb/Public/Browser/ThirdwebOAuthBrowserUserWidget.h index 721bee2..c8834fc 100644 --- a/Source/Thirdweb/Public/Browser/ThirdwebOAuthBrowserUserWidget.h +++ b/Source/Thirdweb/Public/Browser/ThirdwebOAuthBrowserUserWidget.h @@ -6,6 +6,7 @@ #include "Wallets/ThirdwebInAppWalletHandle.h" #include "ThirdwebOAuthBrowserUserWidget.generated.h" + UCLASS(DisplayName = "OAuth Browser") class THIRDWEB_API UThirdwebOAuthBrowserUserWidget : public UUserWidget { @@ -17,7 +18,7 @@ class THIRDWEB_API UThirdwebOAuthBrowserUserWidget : public UUserWidget UPROPERTY(BlueprintAssignable, Category = "Thirdweb|OAuth Browser") FOnAuthenticatedDelegate OnAuthenticated; - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSiweCompleteDelegate, const FString &, Signature, const FString &, Payload); + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSiweCompleteDelegate, const FString &, Payload, const FString &, Signature); UPROPERTY(BlueprintAssignable, Category = "Thirdweb|OAuth Browser") FOnSiweCompleteDelegate OnSiweComplete; @@ -45,7 +46,8 @@ class THIRDWEB_API UThirdwebOAuthBrowserUserWidget : public UUserWidget UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Browser") bool bCollapseWhenBlank = true; - /** Automatically authenticate on Construct. Only works when created with a Wallet */ + /** Automatically authenticate on Construct. Only works when created with a + * Wallet */ UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Browser") bool bAuthenticateOnConstruct = false; @@ -77,13 +79,13 @@ class THIRDWEB_API UThirdwebOAuthBrowserUserWidget : public UUserWidget virtual void HandleOnBeforePopup(const FString& Url, const FString& Frame); virtual void HandleAuthenticated(const FString& AuthResult); - virtual void HandleSiweComplete(const FString& Signature, const FString& Payload); + virtual void HandleSiweComplete(const FString& Payload, const FString& Signature); virtual void HandleError(const FString& Error); public: #if PLATFORM_ANDROID - void HandleDeepLink(const FString &Url); - void HandleCustomTabsDismissed(const FString &Url); + void HandleDeepLink(const FString &Url); + void HandleCustomTabsDismissed(const FString &Url); #endif UFUNCTION(BlueprintCallable, Category = "Thirdweb|OAuth Browser") diff --git a/Source/Thirdweb/Public/Browser/ThirdwebOAuthExternalBrowser.h b/Source/Thirdweb/Public/Browser/ThirdwebOAuthExternalBrowser.h index b48cb93..7f4d908 100644 --- a/Source/Thirdweb/Public/Browser/ThirdwebOAuthExternalBrowser.h +++ b/Source/Thirdweb/Public/Browser/ThirdwebOAuthExternalBrowser.h @@ -7,10 +7,11 @@ #include "UObject/Object.h" #include "ThirdwebOAuthExternalBrowser.generated.h" + class IHttpRouter; /** - * + * */ UCLASS(NotBlueprintable, NotBlueprintType, MinimalAPI) class UThirdwebOAuthExternalBrowser : public UObject, public FTickableGameObject @@ -19,34 +20,30 @@ class UThirdwebOAuthExternalBrowser : public UObject, public FTickableGameObject public: UThirdwebOAuthExternalBrowser(); - + void Authenticate(const FString& Link); - + /** FTickableGameObject implementation */ virtual void Tick(float DeltaTime) override; virtual TStatId GetStatId() const override { return TStatId(); }; virtual void BeginDestroy() override; - + private: bool CallbackRequestHandler(const FHttpServerRequest& Request, const FHttpResultCallback& OnComplete); void HandleSuccess(); void HandleError(const FString& Error); + void CleanupAuthentication(); public: - DECLARE_DELEGATE_OneParam(FSimpleStringDelegate, const FString&); + DECLARE_DELEGATE_OneParam(FSimpleStringDelegate, const FString &); FSimpleStringDelegate OnAuthenticated; FSimpleStringDelegate OnError; - - DECLARE_DELEGATE_TwoParams(FDoubleStringDelegate, const FString&, const FString&); + + DECLARE_DELEGATE_TwoParams(FDoubleStringDelegate, const FString &, const FString &); FDoubleStringDelegate OnSiweComplete; + private: - enum EState - { - Initialized, - AuthPending, - AuthComplete, - Complete - }; + enum EState { Initialized, AuthPending, AuthComplete, Complete }; // OAuth FString AuthResult; @@ -54,7 +51,7 @@ class UThirdwebOAuthExternalBrowser : public UObject, public FTickableGameObject FString Signature; FString Payload; bool bIsSiwe; - + FEvent* AuthEvent; FHttpRouteHandle RouteHandle; TSharedPtr Router; diff --git a/Source/Thirdweb/Public/Wallets/ThirdwebInAppWalletHandle.h b/Source/Thirdweb/Public/Wallets/ThirdwebInAppWalletHandle.h index fca370c..9fc2fe4 100644 --- a/Source/Thirdweb/Public/Wallets/ThirdwebInAppWalletHandle.h +++ b/Source/Thirdweb/Public/Wallets/ThirdwebInAppWalletHandle.h @@ -331,7 +331,7 @@ struct THIRDWEB_API FInAppWalletHandle : public FWalletHandle {Phone, TEXT("Phone")}, {Jwt, TEXT("JWT")}, {AuthEndpoint, TEXT("AuthEndpoint")}, - {Siwe, TEXT("SIWE")}, + {Siwe, TEXT("Siwe")}, {Guest, TEXT("Guest")}, }; return Map.Contains(Source) ? Map[Source] : TEXT("Unknown");