From 3d608f58b748d0768b71eae15afd0b6a5f772975 Mon Sep 17 00:00:00 2001 From: Yermek Garifullanov <150758974+YermekG@users.noreply.github.com> Date: Tue, 5 Mar 2024 11:22:44 +1300 Subject: [PATCH] fix: removal of redundant data types, save game load on initialisation * fix: removed redundant data structures * fix: modified load of passport settings which tracks if player connected via pkce * refactor: moved data types and requests data definitions from headers --- .../Private/Immutable/ImmutableDataTypes.cpp | 94 +++++++++++ .../Private/Immutable/ImmutablePassport.cpp | 148 +++--------------- .../Private/Immutable/ImmutableRequests.cpp | 33 ++++ .../Public/Immutable/ImmutableDataTypes.h | 113 ++----------- .../Public/Immutable/ImmutablePassport.h | 6 +- .../Public/Immutable/ImmutableResponses.h | 4 +- 6 files changed, 160 insertions(+), 238 deletions(-) create mode 100644 Source/Immutable/Private/Immutable/ImmutableDataTypes.cpp create mode 100644 Source/Immutable/Private/Immutable/ImmutableRequests.cpp diff --git a/Source/Immutable/Private/Immutable/ImmutableDataTypes.cpp b/Source/Immutable/Private/Immutable/ImmutableDataTypes.cpp new file mode 100644 index 00000000..b5d3caf3 --- /dev/null +++ b/Source/Immutable/Private/Immutable/ImmutableDataTypes.cpp @@ -0,0 +1,94 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "Immutable/ImmutableDataTypes.h" + + +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; +} + +TOptional FImmutablePassportInitDeviceFlowData::FromJsonString(const FString& JsonObjectString) +{ + FImmutablePassportInitDeviceFlowData 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; +} diff --git a/Source/Immutable/Private/Immutable/ImmutablePassport.cpp b/Source/Immutable/Private/Immutable/ImmutablePassport.cpp index 7cea7066..cf9a4107 100644 --- a/Source/Immutable/Private/Immutable/ImmutablePassport.cpp +++ b/Source/Immutable/Private/Immutable/ImmutablePassport.cpp @@ -10,7 +10,6 @@ #include "Kismet/GameplayStatics.h" #include "Policies/CondensedJsonPrintPolicy.h" - #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC #include "GenericPlatform/GenericPlatformHttp.h" #endif @@ -25,119 +24,20 @@ #include "Mac/ImmutableMac.h" #endif -#define PASSPORT_SAVE_GAME_SLOT_NAME TEXT("ImmutablePassport") - -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 FImmutablePassportInitDeviceFlowData::FromJsonString(const FString& JsonObjectString) -{ - FImmutablePassportInitDeviceFlowData 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; -} +#define PASSPORT_SAVE_GAME_SLOT_NAME TEXT("Immutable") void UImmutablePassport::Initialize(const FImmutablePassportInitData& Data, const FImtblPassportResponseDelegate& ResponseDelegate) { check(JSConnector.IsValid()); + + LoadPassportSettings(); + // we check saved settings in case if player has not logged out properly + if (Data.logoutRedirectUri.IsEmpty() && IsStateFlagsSet(IPS_PKCE)) + { + IMTBL_ERR("Logout URI is empty. Previously logged in via PKCE.") + ResetStateFlags(IPS_PKCE); + SavePassportSettings(); + } InitData = Data; @@ -177,7 +77,7 @@ void UImmutablePassport::ConnectPKCE(bool IsConnectImx, const FImtblPassportResp void UImmutablePassport::Logout(bool DoHardLogout, const FImtblPassportResponseDelegate& ResponseDelegate) { #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC - if (IsStateFlagsSet(IPS_PKCE) || bIsPrevConnectedViaPKCEFlow) + if (IsStateFlagsSet(IPS_PKCE)) { PKCELogoutResponseDelegate = ResponseDelegate; } @@ -305,7 +205,7 @@ void UImmutablePassport::Setup(const TWeakObjectPtr Connector if (!Connector.IsValid()) { - IMTBL_ERR("Invalid JSConnector passed to UImmutablePassport::Initialize") + IMTBL_ERR("Invalid JSConnector passed to UImmutablePassport::Initialize.") return; } @@ -329,9 +229,8 @@ void UImmutablePassport::ReinstateConnection(FImtblJSResponse Response) else { #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC - if (bIsPrevConnectedViaPKCEFlow) + if (IsStateFlagsSet(IPS_PKCE)) { - SetStateFlags(IPS_PKCE); PKCEResponseDelegate = ResponseDelegate.GetValue(); CallJS(ImmutablePassportAction::GetPKCEAuthUrl, TEXT(""), PKCEResponseDelegate, FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnGetPKCEAuthUrlResponse)); } @@ -386,8 +285,6 @@ void UImmutablePassport::OnInitializeResponse(FImtblJSResponse Response) { SetStateFlags(IPS_INITIALIZED); IMTBL_LOG("Passport initialization succeeded.") - // we load settings in case if player has not logged out properly - LoadPassportSettings(); } else { @@ -469,7 +366,7 @@ void UImmutablePassport::OnLogoutResponse(FImtblJSResponse Response) if (!Url.IsEmpty()) { #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC - if (IsStateFlagsSet(IPS_PKCE) || bIsPrevConnectedViaPKCEFlow) + if (IsStateFlagsSet(IPS_PKCE)) { OnHandleDeepLink = FImtblPassportHandleDeepLinkDelegate::CreateUObject(this, &UImmutablePassport::OnDeepLinkActivated); #if PLATFORM_ANDROID @@ -575,7 +472,7 @@ void UImmutablePassport::OnGetPKCEAuthUrlResponse(FImtblJSResponse Response) } else { - IMTBL_ERR("Unable to return a response for Connect PKCE"); + IMTBL_ERR("Unable to return a response for Connect PKCE."); } } @@ -606,7 +503,7 @@ void UImmutablePassport::OnConnectPKCEResponse(FImtblJSResponse Response) } else { - IMTBL_ERR("Unable to return a response for Connect PKCE"); + IMTBL_ERR("Unable to return a response for Connect PKCE."); } ResetStateFlags(IPS_COMPLETING_PKCE); } @@ -911,17 +808,12 @@ void UImmutablePassport::SavePassportSettings() void UImmutablePassport::LoadPassportSettings() { - UImmutableSaveGame* SaveGameInstance = Cast(UGameplayStatics::CreateSaveGameObject(UImmutableSaveGame::StaticClass())); - - SaveGameInstance = Cast(UGameplayStatics::LoadGameFromSlot(PASSPORT_SAVE_GAME_SLOT_NAME, 0)); - - if (!SaveGameInstance) + UImmutableSaveGame* SaveGameInstance = Cast(UGameplayStatics::LoadGameFromSlot(PASSPORT_SAVE_GAME_SLOT_NAME, 0)); + + if (SaveGameInstance) { - IMTBL_ERR("Could not find Immutable save game to load") - return; + SaveGameInstance->bWasConnectedViaPKCEFlow ? SetStateFlags(IPS_PKCE) : ResetStateFlags(IPS_PKCE); } - - bIsPrevConnectedViaPKCEFlow = SaveGameInstance->bWasConnectedViaPKCEFlow; } #if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC diff --git a/Source/Immutable/Private/Immutable/ImmutableRequests.cpp b/Source/Immutable/Private/Immutable/ImmutableRequests.cpp new file mode 100644 index 00000000..d39d0959 --- /dev/null +++ b/Source/Immutable/Private/Immutable/ImmutableRequests.cpp @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "Immutable/ImmutableRequests.h" + +#include "JsonObjectConverter.h" +#include "JsonObjectWrapper.h" +#include "Immutable/Misc/ImtblLogging.h" +#include "Policies/CondensedJsonPrintPolicy.h" + + +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; +} diff --git a/Source/Immutable/Public/Immutable/ImmutableDataTypes.h b/Source/Immutable/Public/Immutable/ImmutableDataTypes.h index 0cb96c83..2f20e8be 100644 --- a/Source/Immutable/Public/Immutable/ImmutableDataTypes.h +++ b/Source/Immutable/Public/Immutable/ImmutableDataTypes.h @@ -62,10 +62,13 @@ struct FImmutablePassportInitDeviceFlowData UPROPERTY() FString code; + UPROPERTY() FString deviceCode; + UPROPERTY() FString url; + UPROPERTY() float interval = 0; @@ -76,10 +79,13 @@ USTRUCT() struct FImtblUserProfile { GENERATED_BODY() + UPROPERTY() FString email; + UPROPERTY() FString nickname; + UPROPERTY() FString sub; }; @@ -111,108 +117,6 @@ struct FImmutablePassportZkEvmGetBalanceData FString ToJsonString() const; }; - -/** - * Key Value wrappers for converting to JSON - */ -USTRUCT() -struct FStringCustomData -{ - GENERATED_BODY() - - UPROPERTY() - FString key; - - UPROPERTY() - FString value; -}; - -USTRUCT() -struct FInt64CustomData -{ - GENERATED_BODY() - - UPROPERTY() - FString key; - - UPROPERTY() - int64 value; -}; - -USTRUCT() -struct FFloatCustomData -{ - GENERATED_BODY() - - UPROPERTY() - FString key; - - UPROPERTY() - float value; -}; - -USTRUCT() -struct FBoolCustomData -{ - GENERATED_BODY() - - UPROPERTY() - FString key; - - UPROPERTY() - bool value; -}; - -UENUM(BlueprintType) -enum EImtblCustomDataType { String, Int64, Float, Bool }; - -/** - * Blueprint doesn't support any sort of generics or polymorphism. To workaround - * this select the primitive type for this custom data item and set the - * 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 {}; - } -}; - USTRUCT() struct FImmutablePassportCodeConfirmRequestData { @@ -220,8 +124,10 @@ struct FImmutablePassportCodeConfirmRequestData UPROPERTY() FString deviceCode; + UPROPERTY() float interval = 5; + UPROPERTY() float timeoutMs = 15 * 60 * 1000; }; @@ -238,7 +144,6 @@ struct FImmutablePassportConnectPKCEData FString state; }; - USTRUCT() struct FImmutablePassportResult { @@ -246,13 +151,13 @@ struct FImmutablePassportResult UPROPERTY() bool Success = false; + UPROPERTY() FString Message; FImtblJSResponse Response; }; - USTRUCT(BlueprintType) struct FImtblAccessListItem { diff --git a/Source/Immutable/Public/Immutable/ImmutablePassport.h b/Source/Immutable/Public/Immutable/ImmutablePassport.h index 57605ff2..a539fbde 100644 --- a/Source/Immutable/Public/Immutable/ImmutablePassport.h +++ b/Source/Immutable/Public/Immutable/ImmutablePassport.h @@ -3,12 +3,11 @@ #pragma once #include "CoreMinimal.h" -#include "Immutable/ImtblJSConnector.h" #include "JsonObjectConverter.h" #include "Misc/EngineVersion.h" #include "Runtime/Core/Public/HAL/Platform.h" #include "UObject/Object.h" - +#include "Immutable/ImtblJSConnector.h" #include "Immutable/ImmutableDataTypes.h" #include "Immutable/ImmutableRequests.h" @@ -236,7 +235,7 @@ class IMMUTABLE_API UImmutablePassport : public UObject IPS_NONE = 0, IPS_CONNECTING = 1 << 0, IPS_CONNECTED = 1 << 1, - IPS_IMX = 1 << 2, + IPS_IMX = 1 << 2, // if set player used "connect" instead of "login" IPS_PKCE = 1 << 3, IPS_COMPLETING_PKCE = 1 << 4, IPS_INITIALIZED = 1 << 5, @@ -244,5 +243,4 @@ class IMMUTABLE_API UImmutablePassport : public UObject }; uint8 StateFlags = IPS_NONE; - bool bIsPrevConnectedViaPKCEFlow = false; }; diff --git a/Source/Immutable/Public/Immutable/ImmutableResponses.h b/Source/Immutable/Public/Immutable/ImmutableResponses.h index 70e65fd6..c7bca799 100644 --- a/Source/Immutable/Public/Immutable/ImmutableResponses.h +++ b/Source/Immutable/Public/Immutable/ImmutableResponses.h @@ -15,10 +15,10 @@ struct FImxTransferResponse FString status; UPROPERTY() - float time; + float time = 0.0f; UPROPERTY() - unsigned transferId; + unsigned transferId = 0; }; USTRUCT()