diff --git a/.vsconfig b/.vsconfig index 7f5f4b38f..b3c233d09 100644 --- a/.vsconfig +++ b/.vsconfig @@ -2,9 +2,11 @@ "version": "1.0", "components": [ "Microsoft.Net.Component.4.6.2.TargetingPack", + "Microsoft.VisualStudio.Component.Unreal.Workspace", + "Microsoft.VisualStudio.Component.VC.14.38.17.8.ATL", "Microsoft.VisualStudio.Component.VC.14.38.17.8.x86.x64", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", - "Microsoft.VisualStudio.Component.Windows10SDK.22621", + "Microsoft.VisualStudio.Component.Windows11SDK.22621", "Microsoft.VisualStudio.Workload.CoreEditor", "Microsoft.VisualStudio.Workload.ManagedDesktop", "Microsoft.VisualStudio.Workload.NativeDesktop", diff --git a/Config/SequenceConfig.ini b/Config/SequenceConfig.ini index 14f8e8436..a50f50219 100644 --- a/Config/SequenceConfig.ini +++ b/Config/SequenceConfig.ini @@ -1,7 +1,7 @@ [/Script/Sequence.Config] FallbackEncryptionKey = "aaaabbbbccccddddaaaabbbbccccdddd" -WaaSConfigKey = "eyJwcm9qZWN0SWQiOjM3MDY2LCJycGNTZXJ2ZXIiOiJodHRwczovL3dhYXMuc2VxdWVuY2UuYXBwIn0=" -ProjectAccessKey = "AQAAAAAAAJDKR9cs25gJSSKzszRT9STo9hk" +WaaSConfigKey = "eyJwcm9qZWN0SWQiOjQxMDg3LCJycGNTZXJ2ZXIiOiJodHRwczovL3dhYXMuc2VxdWVuY2UuYXBwIn0=" +ProjectAccessKey = "AQAAAAAAAKB_eaItDuiSDnsDrg1TM5Izj_k" GoogleClientID = "970987756660-35a6tc48hvi8cev9cnknp0iugv9poa23.apps.googleusercontent.com" AppleClientID = "com.horizon.sequence.waas" FacebookClientID = "" diff --git a/Plugins/SequencePlugin/Config/DefaultSequencePlugin.ini b/Plugins/SequencePlugin/Config/DefaultSequencePlugin.ini new file mode 100644 index 000000000..7ee715fab --- /dev/null +++ b/Plugins/SequencePlugin/Config/DefaultSequencePlugin.ini @@ -0,0 +1,3 @@ +[CoreRedirects] ++FunctionRedirects=(OldName="/Script/SequencePlugin.SequenceMarketplaceBP.GetCollectiblesWithLowestListingsAsync",NewName="/Script/SequencePlugin.SequenceMarketplaceBP.GetCollectiblesWithLowestListingsFirstAsync") ++FunctionRedirects=(OldName="/Script/SequencePlugin.SequenceMarketplaceBP.GetCollectiblesWithHighestListingsFirstAsync",NewName="/Script/SequencePlugin.SequenceMarketplaceBP.GetCollectiblesWithHighestPricedOffersFirstAsync") \ No newline at end of file diff --git a/Plugins/SequencePlugin/Content/Core/Sqn_Mngrs/BP_SequenceManager.uasset b/Plugins/SequencePlugin/Content/Core/Sqn_Mngrs/BP_SequenceManager.uasset index 11ff6d7c5..ede8cf932 100644 --- a/Plugins/SequencePlugin/Content/Core/Sqn_Mngrs/BP_SequenceManager.uasset +++ b/Plugins/SequencePlugin/Content/Core/Sqn_Mngrs/BP_SequenceManager.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:671ee0065607782a801ef3cbd180b941111a36852179400bf65a26765b449f6d -size 1554024 +oid sha256:d8ba87d7572303bb099d0373d1202b9095f0cd97dc73c4edeed1dc34b839ac2f +size 1537279 diff --git a/Plugins/SequencePlugin/Content/Core/Testing/BP_CheckoutTesting.uasset b/Plugins/SequencePlugin/Content/Core/Testing/BP_CheckoutTesting.uasset new file mode 100644 index 000000000..e2f6f717f --- /dev/null +++ b/Plugins/SequencePlugin/Content/Core/Testing/BP_CheckoutTesting.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd032eaeed29bbf5bbc30da2a870ee3fbf7c9da6159919898b1dc68b4f3a883c +size 168834 diff --git a/Plugins/SequencePlugin/Content/Core/Testing/BP_GeneralTesting.uasset b/Plugins/SequencePlugin/Content/Core/Testing/BP_GeneralTesting.uasset index bafd3d6d4..786828c4d 100644 --- a/Plugins/SequencePlugin/Content/Core/Testing/BP_GeneralTesting.uasset +++ b/Plugins/SequencePlugin/Content/Core/Testing/BP_GeneralTesting.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3183b6879d17efddc01e76bcdea24fffaa9c6468f54851ac4a3b47b3f1b6c87d -size 251442 +oid sha256:3ecdcc26276c1ac78a45ae1ad5ee4525d02cc38fe3552e8fc1ec366bd247db39 +size 287134 diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/ABI/ABIElement.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/ABI/ABIElement.cpp index 2799dbc2c..b555fb4e5 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/ABI/ABIElement.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/ABI/ABIElement.cpp @@ -345,6 +345,11 @@ void TDynamicABIData::EncodeTail(TArray &Data, int HeadPosition, int Offs PushEmptyBlock(Data); CopyInUInt32(Data, MyData.Num(), BlockPos); + if (MyData.IsEmpty()) + { + return; + } + // Encode Data uint32 BlockLen = (MyData.Num() + GBlockByteLength - 1) / GBlockByteLength; Data.Append(&MyData[0], MyData.Num()); diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Checkout/SequenceCheckout.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Checkout/SequenceCheckout.cpp new file mode 100644 index 000000000..d3cd2f0ae --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Checkout/SequenceCheckout.cpp @@ -0,0 +1,417 @@ +#include "Checkout/SequenceCheckout.h" + +#include "Checkout/Structs/GenerateBuyTransaction.h" +#include "Checkout/Structs/GenerateCancelTransactionRequest.h" +#include "Checkout/Structs/GenerateListingTransactionArgs.h" +#include "Checkout/Structs/GenerateOfferTransactionArgs.h" +#include "Checkout/Structs/GenerateSellTransaction.h" +#include "Checkout/Structs/GetCheckoutOptionsArgs.h" +#include "Checkout/Structs/GetCheckoutOptionsResponse.h" +#include "Checkout/Structs/OrderData.h" +#include "Util/Log.h" + +FString USequenceCheckout::Url(const int64& TargetChainID, const FString& EndPoint) const +{ + FString Out_URL = HostName(TargetChainID); + Out_URL.Append(this->Path); + + if (EndPoint.Len() > 0) + { + Out_URL.Append(EndPoint); + } + return Out_URL; +} + +FString USequenceCheckout::HostName(int64 TargetChainID) +{ + FString Hostname = "https://"; + Hostname.Append("marketplace-api.sequence.app/"); + Hostname.Append(USequenceSupport::GetNetworkNameForUrl(TargetChainID)); + return Hostname; +} + +void USequenceCheckout::HTTPPost(const int64& TargetChainID, const FString& Endpoint, const FString& Args, + const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const +{ + const FString RequestURL = this->Url(TargetChainID, Endpoint); + + const TSharedRef HTTP_Post_Req = FHttpModule::Get().CreateRequest(); + + FString AccessKey = UConfigFetcher::GetConfigVar("ProjectAccessKey"); + if (AccessKey.IsEmpty()) + { + UE_LOG(LogTemp, Error, TEXT("AccessKey is empty! Failed to set HTTP header.")); + return; + } + + HTTP_Post_Req->SetVerb("POST"); + HTTP_Post_Req->SetHeader(TEXT("Content-Type"), TEXT("application/json")); + HTTP_Post_Req->SetHeader(TEXT("Accept"), TEXT("application/json")); + + + HTTP_Post_Req->SetHeader(TEXT("X-Access-Key"), *AccessKey); + HTTP_Post_Req->SetTimeout(30); + HTTP_Post_Req->SetURL(RequestURL); + HTTP_Post_Req->SetContentAsString(Args); + + FString CurlCommand = FString::Printf( + TEXT("curl -X %s \"%s\" -H \"Content-Type: application/json\" -H \"Accept: application/json\" -H \"X-Access-Key: %s\" --data \"%s\""), + *HTTP_Post_Req->GetVerb(), + *HTTP_Post_Req->GetURL(), + *HTTP_Post_Req->GetHeader("X-Access-Key"), + *FString(UTF8_TO_TCHAR(HTTP_Post_Req->GetContent().GetData())).Replace(TEXT("\""), TEXT("\\\"")) + ); + + SEQ_LOG_EDITOR(Log, TEXT("%s"), *CurlCommand); + + + HTTP_Post_Req->OnProcessRequestComplete().BindLambda([OnSuccess, OnFailure](const FHttpRequestPtr& Request, FHttpResponsePtr Response, const bool bWasSuccessful) + { + if (bWasSuccessful) + { + const FString Content = Response->GetContentAsString(); + UE_LOG(LogTemp, Display, TEXT("Response: %s"), *Content); + OnSuccess(Content); + } + else + { + if (Request.IsValid() && Response.IsValid()) + { + const FString ErrorMessage = Response->GetContentAsString(); + UE_LOG(LogTemp, Error, TEXT("Request failed: %s"), *ErrorMessage); + OnFailure(FSequenceError(RequestFail, "Request failed: " + ErrorMessage)); + } + else + { + UE_LOG(LogTemp, Error, TEXT("Request failed: Invalid Request Pointer")); + OnFailure(FSequenceError(RequestFail, "Request failed: Invalid Request Pointer")); + } + } + }); + + // Process the request + HTTP_Post_Req->ProcessRequest(); +} + +TArray USequenceCheckout::AssembleOrderData(TArray Orders, int64 amount) +{ + int64 AmountLeft = amount; + TArray OrderDatas; + const int Length = Orders.Num(); + for (int i = 0; i < Length; i++) + { + const int64 Available = FCString::Atoi(*Orders[i].QuantityAvailable); + if(AmountLeft <= Available) + { + OrderDatas.Add(FOrderData { + Orders[i].OrderId, + FString::Printf(TEXT("%lld"), AmountLeft) + }); + break; + } + + OrderDatas.Add(FOrderData { + Orders[i].OrderId, + FString::Printf(TEXT("%lld"), Available) + }); + + AmountLeft -= Available; + if(AmountLeft == 0) + { + break; + } + } + + return OrderDatas; +} + +void USequenceCheckout::GenerateBuyTransaction(const FString& WalletAddress, const TArray OrderDatas, + FString CollectionContractAddress, EMarketplaceKind MarketplaceKind, const FAdditionalFee& AdditionalFee, + const EWalletKind WalletKind, TSuccessCallback OnSuccess, + FFailureCallback OnFailure) const +{ + const TArray AdditionalFees { AdditionalFee }; + + const FString Endpoint = "GenerateBuyTransaction"; + const FString Args = BuildArgs(FGenerateBuyTransaction{ CollectionContractAddress, WalletAddress, MarketplaceKind, OrderDatas, AdditionalFees, WalletKind }); + + HTTPPost(ChainID, Endpoint, Args, [this, OnSuccess](const FString& Content) + { + const FGenerateTransactionResponse Response = BuildResponse(Content); + OnSuccess(Response); + }, OnFailure); +} + +USequenceCheckout::USequenceCheckout() +{ + this->ChainID = 0; +} + +USequenceCheckout::USequenceCheckout(const int64& InChainID) +{ + this->ChainID = InChainID; +} + +template < typename T> FString USequenceCheckout::BuildArgs(T StructIn) const +{ + FString Result = "[FAILED TO PARSE]"; + if (StructIn.customGetter) + { + Result = StructIn.GetArgs(); + } + else + { + if (!FJsonObjectConverter::UStructToJsonObjectString(StructIn, Result)) + { + UE_LOG(LogTemp, Display, TEXT("Failed to convert specified UStruct to a json object\n")); + } + } + return Result; +} + + +template T USequenceCheckout::BuildResponse(const FString Text) const +{ + //Take the FString and convert it to a JSON object first! + TSharedPtr JSON_Step; + //Then take the json object we make and convert it to a USTRUCT of type T then we return that! + T Ret_Struct; + + if (!FJsonSerializer::Deserialize(TJsonReaderFactory<>::Create(Text), JSON_Step)) + { + UE_LOG(LogTemp, Display, TEXT("Failed to convert String: %s to Json object"), *Text); + return T(); + } + //this next line with throw an exception in null is used as an entry in json attributes! we need to remove null entries + if (Ret_Struct.customConstructor) + {//use the custom constructor! + Ret_Struct.Construct(*JSON_Step.Get()); + } + else + {//use unreal parsing! + if (!FJsonObjectConverter::JsonObjectToUStruct(JSON_Step.ToSharedRef(), &Ret_Struct)) + { + UE_LOG(LogTemp, Display, TEXT("Failed to convert Json Object: %s to USTRUCT of type T"), *Text); + return T(); + } + } + Ret_Struct.Setup(*JSON_Step.Get());//now for the edge cases we will manually inject the data where it needs to be! + return Ret_Struct; +} + +void USequenceCheckout::SetChainID(const int64& InChainID) +{ + this->ChainID = InChainID; +} + +void USequenceCheckout::GetCheckoutOptions(const FString& WalletAddress, const TArray& Orders, const int64 AdditionalFeeBps, + const FOnGetCheckoutOptionsResponseSuccess OnSuccess, const FOnCheckoutFailure OnFailure) const +{ + const FString Endpoint = "CheckoutOptionsMarketplace"; + const FString Args = BuildArgs(FGetCheckoutOptionsArgs { WalletAddress, Orders, AdditionalFeeBps }); + + HTTPPost(ChainID, Endpoint, Args, [this, OnSuccess](const FString& Content) + { + const FGetCheckoutOptionsResponse Response = BuildResponse(Content); + if (OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [this, OnFailure](const FSequenceError& Error) + { + if (OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +void USequenceCheckout::GetCheckoutOptionsByOrders(const FString& WalletAddress, const TArray& Orders, const int64 AdditionalFeeBps, + const FOnGetCheckoutOptionsResponseSuccess OnSuccess, const FOnCheckoutFailure OnFailure) const +{ + TArray Options; + Options.Reserve(Orders.Num()); + for (int32 i = 0; i < Orders.Num(); i++) + { + Options[i] = FCheckoutOptionsMarketplaceOrder(Orders[i].CollectionContractAddress, Orders[i].OrderId, Orders[i].Marketplace); + } + + GetCheckoutOptions(WalletAddress, Options, AdditionalFeeBps, OnSuccess, OnFailure); +} + +void USequenceCheckout::GenerateBuyTransaction(const FString& WalletAddress, const FSeqOrder& Order, const int64 Amount, const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, + FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const +{ + GenerateBuyTransaction(WalletAddress, Order, Amount, AdditionalFee, WalletKind, [OnSuccess](FGenerateTransactionResponse Response) + { + if(OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [OnFailure](FSequenceError Error) + { + if(OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +void USequenceCheckout::GenerateBuyTransaction(const FString& WalletAddress, const FSeqOrder& Order, const int64 Amount, + const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, + TSuccessCallback OnSuccess, FFailureCallback OnFailure) const +{ + TArray OrdersData; + OrdersData.Reserve(1); + OrdersData.Add(FOrderData(Order.OrderId, FString::Printf(TEXT("%lld"), Amount))); + + GenerateBuyTransaction(WalletAddress, OrdersData, Order.CollectionContractAddress, Order.Marketplace, AdditionalFee, WalletKind, OnSuccess, OnFailure); +} + +void USequenceCheckout::GenerateBuyTransactionMultipleOrders(const FString& WalletAddress, const TArray Orders, + const int64 Amount, const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, + FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const +{ + GenerateBuyTransaction(WalletAddress, Orders, Amount, AdditionalFee, WalletKind, [OnSuccess](FGenerateTransactionResponse Response) + { + if(OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [OnFailure](FSequenceError Error) + { + if(OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +void USequenceCheckout::GenerateBuyTransaction(const FString& WalletAddress, const TArray Orders, + const int64 Amount, const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, + TSuccessCallback OnSuccess, FFailureCallback OnFailure) const +{ + TArray SortedOrders = Orders; + SortedOrders.Sort([](const FSeqOrder& A, const FSeqOrder& B) + { + return A.PriceUSD < B.PriceUSD; + }); + + TArray OrderDatas = AssembleOrderData(SortedOrders, Amount); + GenerateBuyTransaction(WalletAddress, OrderDatas, SortedOrders[0].CollectionContractAddress, SortedOrders[0].Marketplace, AdditionalFee, WalletKind, OnSuccess, OnFailure); + +} + +void USequenceCheckout::GenerateSellTransaction(const FString& WalletAddress, const FSeqOrder& Order, const int64 Amount, const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, + FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const +{ + TArray OrdersData; + OrdersData.Reserve(1); + OrdersData.Add(FOrderData(Order.OrderId, FString::Printf(TEXT("%lld"), Amount))); + + const TArray AdditionalFees { AdditionalFee }; + + const FString Endpoint = "GenerateSellTransaction"; + const FString Args = BuildArgs(FGenerateSellTransaction{ Order.CollectionContractAddress, WalletAddress, Order.Marketplace, OrdersData, AdditionalFees, WalletKind });; + + HTTPPost(ChainID, Endpoint, Args, [this, OnSuccess](const FString& Content) + { + const FGenerateTransactionResponse Response = BuildResponse(Content); + if (OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [this, OnFailure](const FSequenceError& Error) + { + if (OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +void USequenceCheckout::GenerateListingTransaction(const FString& WalletAddress, const FString& CollectionAddress, const FString& TokenId, const int64 Amount, const EContractType ContractType, + const FString& CurrencyTokenAddress, const int64 PricePerToken, const FDateTime Expiry, const EOrderbookKind OrderbookKind, const EWalletKind WalletKind, + FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const +{ + const int64 EpochTime = Expiry.ToUnixTimestamp(); + const FString Endpoint = "GenerateListingTransaction"; + const FString Args = BuildArgs(FGenerateListingTransactionArgs { + CollectionAddress, WalletAddress, ContractType, OrderbookKind, FCreateReq { + TokenId, FString::Printf(TEXT("%lld"), Amount), FString::Printf(TEXT("%lld"), EpochTime), CurrencyTokenAddress, FString::Printf(TEXT("%lld"), PricePerToken) + }, WalletKind + }); + + HTTPPost(ChainID, Endpoint, Args, [this, OnSuccess](const FString& Content) + { + const FGenerateTransactionResponse Response = BuildResponse(Content); + if (OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [this, OnFailure](const FSequenceError& Error) + { + if (OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +void USequenceCheckout::GenerateOfferTransaction(const FString& WalletAddress, const FString& CollectionAddress, const FString& TokenId, const int64 Amount, + const EContractType ContractType, const FString& CurrencyTokenAddress, const int64 PricePerToken, const FDateTime Expiry, + const EOrderbookKind OrderbookKind, const EWalletKind WalletKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const +{ + int64 EpochTime = Expiry.ToUnixTimestamp(); + const FString Endpoint = "GenerateOfferTransaction"; + const FString Args = BuildArgs(FGenerateOfferTransactionArgs { + CollectionAddress, WalletAddress, ContractType, OrderbookKind, FCreateReq { + TokenId, FString::Printf(TEXT("%lld"), Amount), FString::Printf(TEXT("%lld"), EpochTime), CurrencyTokenAddress, FString::Printf(TEXT("%lld"), PricePerToken) + }, WalletKind + }); + + HTTPPost(ChainID, Endpoint, Args, [this, OnSuccess](const FString& Content) + { + const FGenerateTransactionResponse Response = BuildResponse(Content); + if (OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [this, OnFailure](const FSequenceError& Error) + { + if (OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +void USequenceCheckout::GenerateCancelTransaction(const FString& WalletAddress, const FString& CollectionAddress, const FString& OrderId, + const EMarketplaceKind MarketplaceKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const +{ + const FString Endpoint = "GenerateCancelTransaction"; + const FString Args = BuildArgs(FGenerateCancelTransactionRequest { + CollectionAddress, WalletAddress, MarketplaceKind, OrderId + }); + + HTTPPost(ChainID, Endpoint, Args, [this, OnSuccess](const FString& Content) + { + const FGenerateTransactionResponse Response = BuildResponse(Content); + if (OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [this, OnFailure](const FSequenceError& Error) + { + if (OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +void USequenceCheckout::GenerateCancelTransactionByOrder(const FString& WalletAddress, const FString& CollectionAddress, const FSeqOrder& Order, + const EMarketplaceKind MarketplaceKind, const FOnGenerateTransactionResponseSuccess OnSuccess, const FOnCheckoutFailure OnFailure) const +{ + GenerateCancelTransaction(WalletAddress, CollectionAddress, Order.OrderId, MarketplaceKind, OnSuccess, OnFailure); +} diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Errors.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Errors.cpp index ffa454c04..d0ba089bd 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Errors.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Errors.cpp @@ -1,6 +1,8 @@ // Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. #include "Errors.h" -FSequenceError::FSequenceError(const EErrorType Type, const FString Message) : Message(Message), Type(Type) -{ -} +FSequenceError::FSequenceError(const EErrorType Type, const FString& Message) : + Response(nullptr), Message(Message), Type(Type) { } + +FSequenceError::FSequenceError(const EErrorType Type, const FHttpResponsePtr& Response, const FString& Message) : + Response(Response), Message(Message), Type(Type) { } \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/GeneralTesting.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/GeneralTesting.cpp index 8a96bbbdf..c99ff8414 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/GeneralTesting.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/GeneralTesting.cpp @@ -220,6 +220,156 @@ void AGeneralTesting::TestGuestLogin() Auth->GuestLogin(false); } +void AGeneralTesting::TestListCurrencies() const +{ + const TFunction OnSuccess = [this](FString State) + { + CallbackPassed(State); + }; + + const TFunction OnFailure = [this](FString Data, FSequenceError Err) + { + CallbackFailed(Data, Err); + }; + + SequenceAPITest::ListCurrencies(OnSuccess, OnFailure); +} + +void AGeneralTesting::TestListAllCollectibleListingsWithLowestPriceListingsFirst() const +{ + const TFunction OnSuccess = [this](FString State) + { + CallbackPassed(State); + }; + + const TFunction OnFailure = [this](FString Data, FSequenceError Err) + { + CallbackFailed(Data, Err); + }; + + SequenceAPITest::ListAllCollectibleListingsWithLowestPriceListingsFirst(OnSuccess, OnFailure); +} + +void AGeneralTesting::TestListAllCollectibleOffersWithHighestPricedOfferFirst() const +{ + const TFunction OnSuccess = [this](FString State) + { + CallbackPassed(State); + }; + + const TFunction OnFailure = [this](FString Data, FSequenceError Err) + { + CallbackFailed(Data, Err); + }; + + SequenceAPITest::ListAllCollectibleOffersWithHighestPricedOfferFirst(OnSuccess, OnFailure); +} + +void AGeneralTesting::TestGetLowestPriceOfferForCollectible() const +{ + const TFunction OnSuccess = [this](FString State) + { + CallbackPassed(State); + }; + + const TFunction OnFailure = [this](FString Data, FSequenceError Err) + { + CallbackFailed(Data, Err); + }; + + SequenceAPITest::GetLowestPriceOfferForCollectible(OnSuccess, OnFailure); +} + +void AGeneralTesting::TestGetHighestPriceOfferForCollectible() const +{ + const TFunction OnSuccess = [this](FString State) + { + CallbackPassed(State); + }; + + const TFunction OnFailure = [this](FString Data, FSequenceError Err) + { + CallbackFailed(Data, Err); + }; + + SequenceAPITest::GetHighestPriceOfferForCollectible(OnSuccess, OnFailure); +} + +void AGeneralTesting::TestGetLowestPriceListingForCollectible() const +{ + const TFunction OnSuccess = [this](FString State) + { + CallbackPassed(State); + }; + + const TFunction OnFailure = [this](FString Data, FSequenceError Err) + { + CallbackFailed(Data, Err); + }; + + SequenceAPITest::GetLowestPriceListingForCollectible(OnSuccess, OnFailure); +} + +void AGeneralTesting::TestGetHighestPriceListingForCollectible() const +{ + const TFunction OnSuccess = [this](FString State) + { + CallbackPassed(State); + }; + + const TFunction OnFailure = [this](FString Data, FSequenceError Err) + { + CallbackFailed(Data, Err); + }; + + SequenceAPITest::GetHighestPriceListingForCollectible(OnSuccess, OnFailure); +} + +void AGeneralTesting::TestListAllListingsForCollectible() const +{ + const TFunction OnSuccess = [this](FString State) + { + CallbackPassed(State); + }; + + const TFunction OnFailure = [this](FString Data, FSequenceError Err) + { + CallbackFailed(Data, Err); + }; + + SequenceAPITest::ListAllListingsForCollectible(OnSuccess, OnFailure); +} + +void AGeneralTesting::TestListAllOffersForCollectible() const +{ + const TFunction OnSuccess = [this](FString State) + { + CallbackPassed(State); + }; + + const TFunction OnFailure = [this](FString Data, FSequenceError Err) + { + CallbackFailed(Data, Err); + }; + + SequenceAPITest::ListAllOffersForCollectible(OnSuccess, OnFailure); +} + +void AGeneralTesting::TestGetFloorOrder() const +{ + const TFunction OnSuccess = [this](FString State) + { + CallbackPassed(State); + }; + + const TFunction OnFailure = [this](FString Data, FSequenceError Err) + { + CallbackFailed(Data, Err); + }; + + SequenceAPITest::GetFloorOrder(OnSuccess, OnFailure); +} + void AGeneralTesting::TestIndexer() { TFunction OnSuccess = [this](FString State) diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/GeneralTesting.h b/Plugins/SequencePlugin/Source/SequencePlugin/Private/GeneralTesting.h index 48e5a977f..99e34d1bd 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/GeneralTesting.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/GeneralTesting.h @@ -77,6 +77,37 @@ class SEQUENCEPLUGIN_API AGeneralTesting : public AActor UFUNCTION(BlueprintCallable, CATEGORY = "Test_API") void TestGuestLogin(); + + UFUNCTION(BlueprintCallable, CATEGORY = "Test_API") + void TestListCurrencies() const; + + UFUNCTION(BlueprintCallable, CATEGORY = "Test_API") + void TestListAllCollectibleListingsWithLowestPriceListingsFirst() const; + + UFUNCTION(BlueprintCallable, CATEGORY = "Test_API") + void TestListAllCollectibleOffersWithHighestPricedOfferFirst() const; + + UFUNCTION(BlueprintCallable, CATEGORY = "Test_API") + void TestGetLowestPriceOfferForCollectible() const; + + UFUNCTION(BlueprintCallable, CATEGORY = "Test_API") + void TestGetHighestPriceOfferForCollectible() const; + + UFUNCTION(BlueprintCallable, CATEGORY = "Test_API") + void TestGetLowestPriceListingForCollectible() const; + + UFUNCTION(BlueprintCallable, CATEGORY = "Test_API") + void TestGetHighestPriceListingForCollectible() const; + + UFUNCTION(BlueprintCallable, CATEGORY = "Test_API") + void TestListAllListingsForCollectible() const; + + UFUNCTION(BlueprintCallable, CATEGORY = "Test_API") + void TestListAllOffersForCollectible() const; + + UFUNCTION(BlueprintCallable, CATEGORY = "Test_API") + void TestGetFloorOrder() const; + /* * Called by frontend to test the indexer diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Integrators/SardineCheckoutBP.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Integrators/SardineCheckoutBP.cpp new file mode 100644 index 000000000..2ee6ecc77 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Integrators/SardineCheckoutBP.cpp @@ -0,0 +1,232 @@ +#include "Integrators/SardineCheckoutBP.h" + +USardineCheckoutBP::USardineCheckoutBP(): SardineCheckout(NewObject()) +{ +} + +void USardineCheckoutBP::CheckSardineWhiteListStatus(FString Address, FOnCheckSardineWhiteListStatus OnSuccess, + FOnSardineCheckoutFailure OnFailure) +{ + SardineCheckout->CheckSardineWhiteListStatus(Address, [OnSuccess](bool Response) + { + if(OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [OnFailure](FSequenceError Error) + { + if(OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +void USardineCheckoutBP::SardineGetQuote(FOnSardineGetQuote OnSuccess, FOnSardineCheckoutFailure OnFailure, + FString WalletAddress, FSardineToken Token, int Amount, FSardineFiatCurrency QuotedCurrency, ESardinePaymentType PaymentType,ESardineQuoteType QuoteType) +{ + SardineCheckout->SardineGetQuote([OnSuccess](FSardineQuote Response) + { + if(OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [OnFailure](FSequenceError Error) + { + if(OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }, WalletAddress, Token, Amount, PaymentType, QuotedCurrency, QuoteType); +} + +void USardineCheckoutBP::SardineGetClientToken(FOnSardineGetClientToken OnSuccess, FOnSardineCheckoutFailure OnFailure) +{ + SardineCheckout->SardineGetClientToken([OnSuccess](FString Response) + { + if(OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [OnFailure](FSequenceError Error) + { + if(OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +void USardineCheckoutBP::OnRamp(const FString& ClientToken) +{ + SardineCheckout->OnRamp(ClientToken); +} + +void USardineCheckoutBP::SardineGetNFTCheckoutTokenOrders(int64 ChainId, const FString& WalletAddress, + TArray Orders, int Quantity, FString RecipientAddress, TArray AdditionalFee, + FString MarketPlaceContractAddress, FOnSardineGetNFTCheckoutToken OnSuccess, FOnSardineCheckoutFailure OnFailure) +{ + SardineCheckout->SardineGetNFTCheckoutToken(ChainId, WalletAddress, Orders, Quantity, RecipientAddress, AdditionalFee, MarketPlaceContractAddress, + [OnSuccess](FSardineNFTCheckout Response) + { + if(OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [OnFailure](FSequenceError Error) + { + if(OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +void USardineCheckoutBP::SardineGetNFTCheckoutTokenERC1155(int64 ChainId, UERC1155SaleContract* SaleContract, + FString CollectionAddress, int TokenID, int Amount, FOnSardineGetNFTCheckoutToken OnSuccess, + FOnSardineCheckoutFailure OnFailure, TArray data, TArray Proof, FString RecipientAddress) +{ + SardineCheckout->SardineGetNFTCheckoutToken(ChainId, SaleContract, CollectionAddress, TokenID, Amount, [OnSuccess](FSardineNFTCheckout Response) + { + if(OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [OnFailure](FSequenceError Error) + { + if(OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }, RecipientAddress, data, Proof); +} + +void USardineCheckoutBP::SardineGetNFTCheckoutTokenERC721(int64 ChainID, UERC721SaleContract* SaleContract, + FString CollectionAddress, int TokenID, int Amount, FOnSardineGetNFTCheckoutToken OnSuccess, + FOnSardineCheckoutFailure OnFailure, FString RecipientAddress, TArray data, TArray Proof) +{ + SardineCheckout->SardineGetNFTCheckoutToken(ChainID, SaleContract, CollectionAddress, TokenID, Amount, [OnSuccess](FSardineNFTCheckout Response) + { + if(OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [OnFailure](FSequenceError Error) + { + if(OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }, RecipientAddress, data, Proof); +} + +void USardineCheckoutBP::SardineGetNFTCheckoutOrderStatus(FString OrderID, + FOnSardineGetNFTCheckoutOrderStatus OnSuccess, FOnSardineCheckoutFailure OnFailure) +{ + SardineCheckout->SardineGetNFTCheckoutOrderStatus(OrderID, [OnSuccess](FSardineOrder Response) + { + if(OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [OnFailure](FSequenceError Error) + { + if(OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +void USardineCheckoutBP::SardineGetSupportedRegions(FOnSardineGetSupportedRegions OnSuccess, + FOnSardineCheckoutFailure OnFailure) +{ + SardineCheckout->SardineGetSupportedRegions([OnSuccess](TArray Response) + { + if(OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [OnFailure](FSequenceError Error) + { + if(OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +void USardineCheckoutBP::SardineGetSupportedFiatCurrencies(FOnSardineGetSupportedFiatCurrencies OnSuccess, + FOnSardineCheckoutFailure OnFailure) +{ + SardineCheckout->SardineGetSupportedFiatCurrencies([OnSuccess](TArray Response) + { + if(OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [OnFailure](FSequenceError Error) + { + if(OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +void USardineCheckoutBP::SardineGetSupportedTokens(FOnSardineGetSupportedTokens OnSuccess, + FOnSardineCheckoutFailure OnFailure) +{ + SardineCheckout->SardineGetSupportedTokens([OnSuccess](TArray Response) + { + if(OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [OnFailure](FSequenceError Error) + { + if(OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +void USardineCheckoutBP::SardineGetEnabledTokens(FOnSardineGetEnabledTokens OnSuccess, + FOnSardineCheckoutFailure OnFailure) +{ + SardineCheckout->SardineGetEnabledTokens([OnSuccess](TArray Response) + { + if(OnSuccess.IsBound()) + { + OnSuccess.Execute(Response); + } + }, [OnFailure](FSequenceError Error) + { + if(OnFailure.IsBound()) + { + OnFailure.Execute(); + } + }); +} + +FString USardineCheckoutBP::CheckoutURL(FString ClientToken) +{ + return SardineCheckout->CheckoutURL(ClientToken); +} + +FString USardineCheckoutBP::CheckoutURLFromToken(FSardineNFTCheckout Token) +{ + return SardineCheckout->CheckoutURL(Token); +} + +void USardineCheckoutBP::Checkout(FSardineNFTCheckout Token) +{ + SardineCheckout->Checkout(Token); +} + + + + + + diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Integrators/SequenceCheckoutBP.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Integrators/SequenceCheckoutBP.cpp new file mode 100644 index 000000000..e0e6e1d3a --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Integrators/SequenceCheckoutBP.cpp @@ -0,0 +1,104 @@ +#include "Integrators/SequenceCheckoutBP.h" + +void USequenceCheckoutBP::Initialize(FSubsystemCollectionBase& Collection) +{ + Super::Initialize(Collection); + + UE_LOG(LogTemp, Warning, TEXT("SequenceCheckoutBP::Initialize")); +} + +void USequenceCheckoutBP::Deinitialize() +{ + Super::Deinitialize(); + UE_LOG(LogTemp, Warning, TEXT("SequenceCheckoutBP::Deinitialize")); +} + +USequenceCheckoutBP::USequenceCheckoutBP() +{ + UE_LOG(LogTemp, Warning, TEXT("SequenceCheckoutBP::Constructor")); + + this->Checkout = NewObject(); +} + +// Do NOT add const for this function, breaks how we get the chainID +void USequenceCheckoutBP::SetChainID(const int64& InChainID) +{ + this->Checkout->SetChainID(InChainID); +} + +void USequenceCheckoutBP::GetCheckoutOptions(const FString& WalletAddress, + const TArray& Orders, const int64 AdditionalFeeBps, + const FOnGetCheckoutOptionsResponseSuccess OnSuccess, const FOnCheckoutFailure OnFailure) const +{ + this->Checkout->GetCheckoutOptions(WalletAddress, Orders, AdditionalFeeBps, OnSuccess, OnFailure); +} + +void USequenceCheckoutBP::GetCheckoutOptionsByOrders(const FString& WalletAddress, const TArray& Orders, + const int64 AdditionalFeeBps, const FOnGetCheckoutOptionsResponseSuccess OnSuccess, const FOnCheckoutFailure OnFailure) const +{ + this->Checkout->GetCheckoutOptionsByOrders(WalletAddress, Orders, AdditionalFeeBps, OnSuccess, OnFailure); +} + +void USequenceCheckoutBP::GenerateBuyTransaction(const FString& WalletAddress, const FSeqOrder& Order, + const int64 Amount, const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, + const FOnGenerateTransactionResponseSuccess OnSuccess, const FOnCheckoutFailure OnFailure) const +{ + this->Checkout->GenerateBuyTransaction(WalletAddress, Order, Amount, AdditionalFee, WalletKind, OnSuccess, OnFailure); +} + +void USequenceCheckoutBP::GenerateSellTransaction(const FString& WalletAddress, const FSeqOrder& Order, + const int64 Amount, const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, + const FOnGenerateTransactionResponseSuccess OnSuccess, const FOnCheckoutFailure OnFailure) const +{ + this->Checkout->GenerateSellTransaction(WalletAddress, Order, Amount, AdditionalFee, WalletKind, OnSuccess, OnFailure); +} + +void USequenceCheckoutBP::GenerateListingTransaction(const FString& WalletAddress, const FString& CollectionAddress, + const FString& TokenId, const int64 Amount, const EContractType ContractType, const FString& CurrencyTokenAddress, + const int64 PricePerToken, const FDateTime Expiry, const EOrderbookKind OrderbookKind, const EWalletKind WalletKind, + const FOnGenerateTransactionResponseSuccess OnSuccess, const FOnCheckoutFailure OnFailure) const +{ + this->Checkout->GenerateListingTransaction(WalletAddress, CollectionAddress, TokenId, Amount, ContractType, CurrencyTokenAddress, PricePerToken, Expiry, OrderbookKind, WalletKind, OnSuccess, OnFailure); +} + +void USequenceCheckoutBP::GenerateOfferTransaction(const FString& WalletAddress, const FString& CollectionAddress, + const FString& TokenId, const int64 Amount, const EContractType ContractType, const FString& CurrencyTokenAddress, + const int64 PricePerToken, const FDateTime Expiry, const EOrderbookKind OrderbookKind, const EWalletKind WalletKind, + const FOnGenerateTransactionResponseSuccess OnSuccess, const FOnCheckoutFailure OnFailure) const +{ + this->Checkout->GenerateOfferTransaction(WalletAddress, CollectionAddress, TokenId, Amount, ContractType, CurrencyTokenAddress, PricePerToken, Expiry, OrderbookKind, WalletKind, OnSuccess, OnFailure); +} + +void USequenceCheckoutBP::GenerateCancelTransaction(const FString& WalletAddress, const FString& CollectionAddress, + const FString& OrderId, const EMarketplaceKind MarketplaceKind, const FOnGenerateTransactionResponseSuccess OnSuccess, + const FOnCheckoutFailure OnFailure) const +{ + this->Checkout->GenerateCancelTransaction(WalletAddress, CollectionAddress, OrderId, MarketplaceKind, OnSuccess, OnFailure); +} + +void USequenceCheckoutBP::GenerateCancelTransactionByOrder(const FString& WalletAddress, + const FString& CollectionAddress, const FSeqOrder& Order, const EMarketplaceKind MarketplaceKind, + const FOnGenerateTransactionResponseSuccess OnSuccess, const FOnCheckoutFailure OnFailure) const +{ + this->Checkout->GenerateCancelTransactionByOrder(WalletAddress, CollectionAddress, Order, MarketplaceKind, OnSuccess, OnFailure); +} + +UTransactions* USequenceCheckoutBP::StepsToTransactions(const TArray& Steps) +{ + UTransactions* Transactions = CreateTransaction(); + + for (const FTransactionStep& Step : Steps) + { + FRawTransaction RawTransaction = FRawTransaction(Step.To, Step.Data, Step.Value.IsEmpty() ? TEXT("0") : Step.Value); + + Transactions->AddRaw(RawTransaction); + } + + return Transactions; +} + +UTransactions* USequenceCheckoutBP::CreateTransaction() +{ + return NewObject(this); +} + diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Integrators/SequenceMarketplaceBP.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Integrators/SequenceMarketplaceBP.cpp index b46302f41..c798adec7 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Integrators/SequenceMarketplaceBP.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Integrators/SequenceMarketplaceBP.cpp @@ -1,6 +1,7 @@ #include "Integrators/SequenceMarketplaceBP.h" #include "Engine/Engine.h" #include "Engine/GameInstance.h" +#include "Marketplace/Structs/SeqListCollectibleListingsArgs.h" #include "Util/Log.h" USequenceMarketplaceBP::USequenceMarketplaceBP() @@ -9,28 +10,357 @@ USequenceMarketplaceBP::USequenceMarketplaceBP() } -void USequenceMarketplaceBP::GetGetCollectiblesWithLowestListingsAsync(const int64 ChainId, const FSeqGetCollectiblesWithLowestListingsArgs& Args) +void USequenceMarketplaceBP::GetCollectiblesWithLowestListingsFirstAsync(const int64 ChainId, const FSeqListCollectiblesArgs& Args) { - const TSuccessCallback OnSuccess = [this, ChainId, Args](const FSeqGetCollectiblesWithLowestListingsReturn& CollectiblesWithLowestListings) + const TSuccessCallback OnSuccess = [this, ChainId](const FSeqListCollectiblesReturn& CollectiblesWithLowestListings) { - this->CallCollectiblesWithLowestListingsReceived(true, ChainId, CollectiblesWithLowestListings); + this->CallCollectiblesWithLowestListingsFirstReceived(true, ChainId, CollectiblesWithLowestListings); }; const FFailureCallback OnFailure = [this, ChainId, Args](const FSequenceError& Error) { SEQ_LOG(Error, TEXT("Error getting Collectibles with Lowest Listings: %s"), *Error.Message); - FSeqGetCollectiblesWithLowestListingsReturn CollectiblesWithLowestListings; - this->CallCollectiblesWithLowestListingsReceived(false, ChainId, CollectiblesWithLowestListings); + FSeqListCollectiblesReturn CollectiblesWithLowestListings; + this->CallCollectiblesWithLowestListingsFirstReceived(false, ChainId, CollectiblesWithLowestListings); }; - this->Marketplace->GetCollectiblesWithLowestListings(ChainId, Args, OnSuccess, OnFailure); + this->Marketplace->ListCollectibleListingsWithLowestPriceListingsFirst(ChainId, Args.ContractAddress, Args.Filter, Args.Page, OnSuccess, OnFailure); } -void USequenceMarketplaceBP::CallCollectiblesWithLowestListingsReceived(const bool Status, const int64 ChainId, const FSeqGetCollectiblesWithLowestListingsReturn& Response) +void USequenceMarketplaceBP::GetAllCollectiblesWithLowestListingsFirstAsync(const int64 ChainId, + const FSeqListCollectiblesArgs& Args) +{ + const TSuccessCallback> OnSuccess = [this, ChainId](const TArray& CollectiblesWithLowestListings) + { + this->CallAllCollectiblesWithLowestListingsFirstReceived(true, ChainId, CollectiblesWithLowestListings); + }; + + const FFailureCallback OnFailure = [this, ChainId](const FSequenceError& Error) + { + SEQ_LOG(Error, TEXT("Error getting All Collectibles with Lowest Listings First: %s"), *Error.Message); + const TArray CollectiblesWithLowestListings; + this->CallAllCollectiblesWithLowestListingsFirstReceived(false, ChainId, CollectiblesWithLowestListings); + }; + + + this->Marketplace->ListAllCollectibleListingsWithLowestPriceListingsFirst(ChainId, Args.ContractAddress, Args.Filter, OnSuccess, OnFailure); + +} + +void USequenceMarketplaceBP::GetCollectiblesWithHighestPricedOffersFirstAsync(const int64 ChainId, + const FSeqListCollectiblesArgs& Args) +{ + const TSuccessCallback OnSuccess = [this, ChainId](const FSeqListCollectiblesReturn& CollectiblesWithLowestListings) + { + this->CallCollectiblesWithHighestPricedOffersFirstReceived(true, ChainId, CollectiblesWithLowestListings); + }; + + const FFailureCallback OnFailure = [this, ChainId](const FSequenceError& Error) + { + SEQ_LOG(Error, TEXT("Error getting Collectibles with Highest Priced Offers First: %s"), *Error.Message); + FSeqListCollectiblesReturn CollectiblesWithHighestOffers; + this->CallCollectiblesWithHighestPricedOffersFirstReceived(false, ChainId, CollectiblesWithHighestOffers); + }; + + + this->Marketplace->ListCollectibleOffersWithHighestPricedOfferFirst(ChainId, Args.ContractAddress, Args.Filter, Args.Page, OnSuccess, OnFailure); + +} + +void USequenceMarketplaceBP::GetAllCollectiblesWithHighestPricedOffersFirstAsync(const int64 ChainId, + const FSeqListCollectiblesArgs& Args) +{ + const TSuccessCallback> OnSuccess = [this, ChainId](const TArray& CollectiblesWithHighestPricedOffers) + { + this->CallAllCollectiblesWithHighestPricedOffersFirstReceived(true, ChainId, CollectiblesWithHighestPricedOffers); + }; + + const FFailureCallback OnFailure = [this, ChainId](const FSequenceError& Error) + { + SEQ_LOG(Error, TEXT("Error getting All Collectibles with Highest Priced Offers First: %s"), *Error.Message); + const TArray CollectiblesWithHighestPricedOffers; + this->CallAllCollectiblesWithHighestPricedOffersFirstReceived(false, ChainId, CollectiblesWithHighestPricedOffers); + }; + + + this->Marketplace->ListAllCollectibleOffersWithHighestPricedOfferFirst(ChainId, Args.ContractAddress, Args.Filter, OnSuccess, OnFailure); + +} + +void USequenceMarketplaceBP::GetLowestPriceOfferForCollectibleAsync(const int64 ChainId, + const FSeqGetCollectibleOrderArgs& Args) +{ + const TSuccessCallback OnSuccess = [this, ChainId](const FSeqCollectibleOrder& LowestPriceOffer) + { + this->CallLowestPriceOfferForCollectibleReceived(true, ChainId, LowestPriceOffer); + }; + + const FFailureCallback OnFailure = [this, ChainId](const FSequenceError& Error) + { + SEQ_LOG(Error, TEXT("Error getting Lowest Price Offer for Collectible: %s"), *Error.Message); + FSeqCollectibleOrder LowestPriceOffer; + this->CallLowestPriceOfferForCollectibleReceived(false, ChainId, LowestPriceOffer); + }; + + this->Marketplace->GetLowestPriceOfferForCollectible(ChainId, Args.ContractAddress, Args.TokenID, Args.Filter, OnSuccess, OnFailure); +} + +void USequenceMarketplaceBP::GetHighestPriceOfferForCollectibleAsync(const int64 ChainId, + const FSeqGetCollectibleOrderArgs& Args) +{ + const TSuccessCallback OnSuccess = [this, ChainId](const FSeqCollectibleOrder& HighestPriceOffer) + { + this->CallHighestPriceOfferForCollectibleReceived(true, ChainId, HighestPriceOffer); + }; + + const FFailureCallback OnFailure = [this, ChainId](const FSequenceError& Error) + { + SEQ_LOG(Error, TEXT("Error getting Highest Price Offer for Collectible: %s"), *Error.Message); + FSeqCollectibleOrder HighestPriceOffer; + this->CallHighestPriceOfferForCollectibleReceived(false, ChainId, HighestPriceOffer); + }; + + this->Marketplace->GetHighestPriceOfferForCollectible(ChainId, Args.ContractAddress, Args.TokenID, Args.Filter, OnSuccess, OnFailure); +} + +void USequenceMarketplaceBP::GetLowestPriceListingForCollectibleAsync(const int64 ChainId, + const FSeqGetCollectibleOrderArgs& Args) +{ + const TSuccessCallback OnSuccess = [this, ChainId](const FSeqCollectibleOrder& LowestPriceListing) + { + this->CallLowestPriceListingForCollectibleReceived(true, ChainId, LowestPriceListing); + }; + + const FFailureCallback OnFailure = [this, ChainId](const FSequenceError& Error) + { + SEQ_LOG(Error, TEXT("Error getting Lowest Price Listing for Collectible: %s"), *Error.Message); + FSeqCollectibleOrder LowestPriceListing; + this->CallLowestPriceListingForCollectibleReceived(false, ChainId, LowestPriceListing); + }; + + this->Marketplace->GetLowestPriceListingForCollectible(ChainId, Args.ContractAddress, Args.TokenID, Args.Filter, OnSuccess, OnFailure); +} + +void USequenceMarketplaceBP::GetHighestPriceListingForCollectibleAsync(const int64 ChainId, + const FSeqGetCollectibleOrderArgs& Args) +{ + const TSuccessCallback OnSuccess = [this, ChainId](const FSeqCollectibleOrder& HighestPriceListing) + { + this->CallHighestPriceListingForCollectibleReceived(true, ChainId, HighestPriceListing); + }; + + const FFailureCallback OnFailure = [this, ChainId](const FSequenceError& Error) + { + SEQ_LOG(Error, TEXT("Error getting Highest Price Listing for Collectible: %s"), *Error.Message); + FSeqCollectibleOrder HighestPriceListing; + this->CallHighestPriceListingForCollectibleReceived(false, ChainId, HighestPriceListing); + }; + + this->Marketplace->GetHighestPriceListingForCollectible(ChainId, Args.ContractAddress, Args.TokenID, Args.Filter, OnSuccess, OnFailure); +} + +void USequenceMarketplaceBP::ListListingsForCollectibleAsync(const int64 ChainId, + const FSeqListCollectibleListingsArgs& Args) +{ + const TSuccessCallback OnSuccess = [this, ChainId](const FSeqListCollectibleListingsReturn& Listings) + { + this->FOnListListingsForCollectibleResponse.Broadcast(true, ChainId, Listings); + }; + + const FFailureCallback OnFailure = [this, ChainId](const FSequenceError& Error) + { + SEQ_LOG(Error, TEXT("Error getting Listings for Collectible: %s"), *Error.Message); + FSeqListCollectibleListingsReturn Listings; + this->FOnListListingsForCollectibleResponse.Broadcast(false, ChainId, Listings); + }; + + this->Marketplace->ListListingsForCollectible(ChainId, Args.ContractAddress, Args.TokenID, Args.Filter, Args.Page, OnSuccess, OnFailure); +} + +void USequenceMarketplaceBP::ListAllListingsForCollectibleAsync(const int64 ChainId, + const FSeqListCollectibleListingsArgs& Args) +{ + const TSuccessCallback> OnSuccess = [this, ChainId](const TArray& Listings) + { + this->CallListAllListingsForCollectibleReceived(true, ChainId, Listings); + }; + + const FFailureCallback OnFailure = [this, ChainId](const FSequenceError& Error) + { + SEQ_LOG(Error, TEXT("Error getting All Listings for Collectible: %s"), *Error.Message); + TArray Listings; + this->CallListAllListingsForCollectibleReceived(false, ChainId, Listings); + }; + + this->Marketplace->ListAllListingsForCollectible(ChainId, Args.ContractAddress, Args.TokenID, Args.Filter, OnSuccess, OnFailure); +} + +void USequenceMarketplaceBP::ListOffersForCollectibleAsync(const int64 ChainId, + const FSeqListCollectibleListingsArgs& Args) +{ + const TSuccessCallback OnSuccess = [this, ChainId](const FSeqListCollectibleOffersReturn& Offers) + { + this->FOnListOffersForCollectibleResponse.Broadcast(true, ChainId, Offers); + }; + + const FFailureCallback OnFailure = [this, ChainId](const FSequenceError& Error) + { + SEQ_LOG(Error, TEXT("Error getting Offers for Collectible: %s"), *Error.Message); + FSeqListCollectibleOffersReturn Offers; + this->FOnListOffersForCollectibleResponse.Broadcast(false, ChainId, Offers); + }; + + this->Marketplace->ListOffersForCollectible(ChainId, Args.ContractAddress, Args.TokenID, Args.Filter, Args.Page, OnSuccess, OnFailure); +} + +void USequenceMarketplaceBP::ListAllOffersForCollectibleAsync(const int64 ChainId, + const FSeqListCollectibleListingsArgs& Args) +{ + const TSuccessCallback> OnSuccess = [this, ChainId](const TArray& Offers) + { + this->FOnListAllOffersForCollectibleResponse.Broadcast(true, ChainId, Offers); + }; + + const FFailureCallback OnFailure = [this, ChainId](const FSequenceError& Error) + { + SEQ_LOG(Error, TEXT("Error getting All Offers for Collectible: %s"), *Error.Message); + TArray Offers; + this->FOnListAllOffersForCollectibleResponse.Broadcast(false, ChainId, Offers); + }; + + this->Marketplace->ListAllOffersForCollectible(ChainId, Args.ContractAddress, Args.TokenID, Args.Filter, OnSuccess, OnFailure); +} + +void USequenceMarketplaceBP::GetFloorOrderAsync(const int64 ChainId, const FSeqListCollectiblesArgs& Args) +{ + const TSuccessCallback OnSuccess = [this, ChainId](const FSeqCollectibleOrder& FloorOrder) + { + this->FOnGetFloorOrderResponse.Broadcast(true, ChainId, FloorOrder); + }; + + const FFailureCallback OnFailure = [this, ChainId](const FSequenceError& Error) + { + SEQ_LOG(Error, TEXT("Error getting Floor Order: %s"), *Error.Message); + FSeqCollectibleOrder FloorOrder; + this->FOnGetFloorOrderResponse.Broadcast(false, ChainId, FloorOrder); + }; + + this->Marketplace->GetFloorOrder(ChainId, Args.ContractAddress, Args.Filter, OnSuccess, OnFailure); +} + +void USequenceMarketplaceBP::CallCollectiblesWithLowestListingsFirstReceived(const bool Status, const int64 ChainId, const FSeqListCollectiblesReturn& Response) { if (this->CollectiblesWithLowestListingsResponse.IsBound()) this->CollectiblesWithLowestListingsResponse.Broadcast(Status, ChainId, Response); else - SEQ_LOG(Error, TEXT("Nothing bound to delegate: CollectiblesWithLowestListingsResponse")); + SEQ_LOG(Error, TEXT("Nothing bound to delegate: CollectiblesWithLowestListingsFirstResponse")); +} + +void USequenceMarketplaceBP::CallAllCollectiblesWithLowestListingsFirstReceived(const bool Status, const int64 ChainId, + const TArray& Response) +{ + if (this->AllCollectiblesWithLowestListingsResponse.IsBound()) + this->AllCollectiblesWithLowestListingsResponse.Broadcast(Status, ChainId, Response); + else + SEQ_LOG(Error, TEXT("Nothing bound to delegate: AllCollectiblesWithLowestListingsFirstResponse")); +} + +void USequenceMarketplaceBP::CallCollectiblesWithHighestPricedOffersFirstReceived(const bool Status, const int64 ChainId, + const FSeqListCollectiblesReturn& Response) +{ + if (this->CollectiblesWithHighestListingsResponse.IsBound()) + this->CollectiblesWithHighestListingsResponse.Broadcast(Status, ChainId, Response); + else + SEQ_LOG(Error, TEXT("Nothing bound to delegate: CollectiblesWithHighestPricedOffersFirstResponse")); +} + +void USequenceMarketplaceBP::CallAllCollectiblesWithHighestPricedOffersFirstReceived(const bool Status, + const int64 ChainId, const TArray& Response) +{ + if (this->AllCollectiblesWithHighestPricedOffersResponse.IsBound()) + this->AllCollectiblesWithHighestPricedOffersResponse.Broadcast(Status, ChainId, Response); + else + SEQ_LOG(Error, TEXT("Nothing bound to delegate: AllCollectiblesWithHighestPricedOffersFirstResponse")); +} + +void USequenceMarketplaceBP::CallLowestPriceOfferForCollectibleReceived(const bool Status, const int64 ChainId, + const FSeqCollectibleOrder& Response) +{ + if (this->GetLowestPriceOfferForCollectibleResponse.IsBound()) + this->GetLowestPriceOfferForCollectibleResponse.Broadcast(Status, ChainId, Response); + else + SEQ_LOG(Error, TEXT("Nothing bound to delegate: GetLowestPriceOfferForCollectibleResponse")); +} + +void USequenceMarketplaceBP::CallHighestPriceOfferForCollectibleReceived(const bool Status, const int64 ChainId, + const FSeqCollectibleOrder& Response) +{ + if (this->GetHighestPriceOfferForCollectibleResponse.IsBound()) + this->GetHighestPriceOfferForCollectibleResponse.Broadcast(Status, ChainId, Response); + else + SEQ_LOG(Error, TEXT("Nothing bound to delegate: GetHighestPriceOfferForCollectibleResponse")); +} + +void USequenceMarketplaceBP::CallLowestPriceListingForCollectibleReceived(const bool Status, const int64 ChainId, + const FSeqCollectibleOrder& Response) +{ + if (this->GetLowestPriceListingForCollectibleResponse.IsBound()) + this->GetLowestPriceListingForCollectibleResponse.Broadcast(Status, ChainId, Response); + else + SEQ_LOG(Error, TEXT("Nothing bound to delegate: GetLowestPriceListingForCollectibleResponse")); +} + +void USequenceMarketplaceBP::CallHighestPriceListingForCollectibleReceived(const bool Status, const int64 ChainId, + const FSeqCollectibleOrder& Response) +{ + if (this->GetHighestPriceListingForCollectibleResponse.IsBound()) + this->GetHighestPriceListingForCollectibleResponse.Broadcast(Status, ChainId, Response); + else + SEQ_LOG(Error, TEXT("Nothing bound to delegate: GetHighestPriceListingForCollectibleResponse")); +} + +void USequenceMarketplaceBP::CallListListingsForCollectibleReceived(const bool Status, const int64 ChainId, + const FSeqListCollectibleListingsReturn& Response) +{ + if (this->FOnListListingsForCollectibleResponse.IsBound()) + this->FOnListListingsForCollectibleResponse.Broadcast(Status, ChainId, Response); + else + SEQ_LOG(Error, TEXT("Nothing bound to delegate: ListListingsForCollectibleResponse")); +} + +void USequenceMarketplaceBP::CallListAllListingsForCollectibleReceived(const bool Status, const int64 ChainId, + const TArray& Response) +{ + if (this->FOnListAllListingsForCollectibleResponse.IsBound()) + this->FOnListAllListingsForCollectibleResponse.Broadcast(Status, ChainId, Response); + else + SEQ_LOG(Error, TEXT("Nothing bound to delegate: ListAllListingsForCollectibleResponse")); +} + +void USequenceMarketplaceBP::CallListOffersForCollectibleReceived(const bool Status, const int64 ChainId, + const FSeqListCollectibleOffersReturn& Response) +{ + if (this->FOnListOffersForCollectibleResponse.IsBound()) + this->FOnListOffersForCollectibleResponse.Broadcast(Status, ChainId, Response); + else + SEQ_LOG(Error, TEXT("Nothing bound to delegate: ListOffersForCollectibleResponse")); +} + +void USequenceMarketplaceBP::CallListAllOffersForCollectibleReceived(const bool Status, const int64 ChainId, + const TArray& Response) +{ + if (this->FOnListAllOffersForCollectibleResponse.IsBound()) + this->FOnListAllOffersForCollectibleResponse.Broadcast(Status, ChainId, Response); + else + SEQ_LOG(Error, TEXT("Nothing bound to delegate: ListAllOffersForCollectibleResponse")); +} + +void USequenceMarketplaceBP::CallGetFloorOrderReceived(const bool Status, const int64 ChainId, + const FSeqCollectibleOrder& Response) +{ + if (this->FOnGetFloorOrderResponse.IsBound()) + this->FOnGetFloorOrderResponse.Broadcast(Status, ChainId, Response); + else + SEQ_LOG(Error, TEXT("Nothing bound to delegate: GetFloorOrderResponse")); } diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Marketplace/Marketplace.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Marketplace/Marketplace.cpp index 36887b654..cc21c1ee5 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Marketplace/Marketplace.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Marketplace/Marketplace.cpp @@ -8,6 +8,15 @@ #include "Util/Log.h" #include "ConfigFetcher.h" #include "HttpManager.h" +#include "Marketplace/Structs/SeqGetCollectibleArgs.h" +#include "Marketplace/Structs/SeqGetCollectibleOrderArgs.h" +#include "Marketplace/Structs/SeqGetCollectibleOrderReturn.h" +#include "Marketplace/Structs/SeqGetCollectibleReturn.h" +#include "Marketplace/Structs/SeqGetFloorOrderArgs.h" +#include "Marketplace/Structs/SeqGetOrderReturn.h" +#include "Marketplace/Structs/SeqListCollectibleListingsArgs.h" +#include "Marketplace/Structs/SeqListCollectibleOffersReturn.h" +#include "Marketplace/Structs/SeqListCurrenciesReturn.h" UMarketplace::UMarketplace(){} @@ -32,6 +41,8 @@ FString UMarketplace::HostName(const int64 ChainID) return Hostname; } + + void UMarketplace::HTTPPost(const int64& ChainID, const FString& Endpoint, const FString& Args, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const { const FString RequestURL = this->Url(ChainID, Endpoint); @@ -94,17 +105,6 @@ void UMarketplace::HTTPPost(const int64& ChainID, const FString& Endpoint, const HTTP_Post_Req->ProcessRequest(); } -void UMarketplace::GetCollectiblesWithLowestListings(const int64 ChainID, const FSeqGetCollectiblesWithLowestListingsArgs& Args, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure) -{ - const FString Endpoint = "ListCollectiblesWithLowestListing"; - - HTTPPost(ChainID, Endpoint, BuildArgs(Args), [this, OnSuccess](const FString& Content) - { - const FSeqGetCollectiblesWithLowestListingsReturn Response = this->BuildResponse(Content); - OnSuccess(Response); - }, OnFailure); -} - template < typename T> FString UMarketplace::BuildArgs(T StructIn) { FString Result = "[FAILED TO PARSE]"; @@ -150,4 +150,309 @@ template T UMarketplace::BuildResponse(const FString Text) } Ret_Struct.Setup(*JSON_Step.Get());//now for the edge cases we will manually inject the data where it needs to be! return Ret_Struct; -} \ No newline at end of file +} + +void UMarketplace::ListCurrencies(const int64 ChainID, TSuccessCallback OnSuccess, + const FFailureCallback& OnFailure) +{ + const FString Endpoint = "ListCurrencies"; + const FString Args = ""; + HTTPPost(ChainID, Endpoint, Args, [this, OnSuccess](const FString& Content) + { + const FSeqListCurrenciesReturn Response = this->BuildResponse(Content); + OnSuccess(Response); + }, OnFailure); +} + +void UMarketplace::ListCollectibleListingsWithLowestPriceListingsFirst(const int64 ChainID, const FString& ContractAddress, + const FSeqCollectiblesFilter& Filter, const FSeqMarketplacePage& Page, TSuccessCallback OnSuccess, + const FFailureCallback& OnFailure) +{ + const FString Endpoint = "ListCollectiblesWithLowestListing"; + const FString Args = BuildArgs(FSeqListCollectiblesArgs{LISTING, ContractAddress, Filter, Page}); + HTTPPost(ChainID, Endpoint, Args, [this, OnSuccess](const FString& Content) + { + const FSeqListCollectiblesReturn Response = this->BuildResponse(Content); + OnSuccess(Response); + }, OnFailure); +} + +void UMarketplace::ListAllCollectibleListingsWithLowestPriceListingsFirst(const int64 ChainID, + const FString& ContractAddress, const FSeqCollectiblesFilter& Filter, + TSuccessCallback> OnSuccess, const FFailureCallback& OnFailure) +{ + const FString Args = BuildArgs(FSeqListCollectiblesArgs{LISTING, ContractAddress, Filter, FSeqMarketplacePage::Empty()}); + OrderArray.Empty(); + + return ListAllCollectibleListingsWithLowestPriceListingsFirstHelper(ChainID, ContractAddress, Filter, FSeqMarketplacePage::Empty(), [this, OnSuccess](const TArray& Orders, const bool IsDone) + { + OrderArray.Append(Orders); + + if(IsDone) + { + OnSuccess(OrderArray); + } + }, OnFailure); +} + +void UMarketplace::ListCollectibleOffersWithHighestPricedOfferFirst( + const int64 ChainID, + const FString& ContractAddress, + const FSeqCollectiblesFilter& Filter, + const FSeqMarketplacePage& Page, + TSuccessCallback OnSuccess, + const FFailureCallback& OnFailure) +{ + const FString Endpoint = "ListCollectibleOffersWithHighestPricedOfferFirst"; + const FString Args = BuildArgs(FSeqListCollectiblesArgs{OFFER, ContractAddress, Filter, Page}); + HTTPPost(ChainID, Endpoint, Args, [this, OnSuccess](const FString& Content) + { + const FSeqListCollectiblesReturn Response = this->BuildResponse(Content); + OnSuccess(Response); + }, OnFailure); +} + +void UMarketplace::ListAllCollectibleOffersWithHighestPricedOfferFirst( + const int64 ChainID, + const FString& ContractAddress, + const FSeqCollectiblesFilter& Filter, + TSuccessCallback> OnSuccess, + const FFailureCallback& OnFailure) +{ + const FString Args = BuildArgs(FSeqListCollectiblesArgs{LISTING, ContractAddress, Filter, FSeqMarketplacePage::Empty()}); + OrderArray.Empty(); + + return ListAllCollectibleOffersWithHighestPricedOfferFirstHelper(ChainID, ContractAddress, Filter, FSeqMarketplacePage::Empty(), [this, OnSuccess](const TArray& Orders, const bool IsDone) + { + OrderArray.Append(Orders); + + if(IsDone) + { + OnSuccess(OrderArray); + } + }, OnFailure); +} + +void UMarketplace::GetCollectible(const int64 ChainID, const FString& ContractAddress, const FString& TokenId, + TSuccessCallback OnSuccess, const FFailureCallback& OnFailure) +{ + const FString Endpoint = "GetCollectible"; + const FSeqGetCollectibleArgs Args = FSeqGetCollectibleArgs{ContractAddress, TokenId}; + HTTPPost(ChainID, Endpoint, BuildArgs(Args), [this, OnSuccess](const FString& Content) + { + const FSeqGetCollectibleReturn Response = this->BuildResponse(Content); + OnSuccess(Response.MetaData); + }, OnFailure); +} + +void UMarketplace::GetLowestPriceOfferForCollectible( + const int64 ChainID, + const FString& ContractAddress, + const FString& TokenID, + const FSeqCollectiblesFilter& Filter, + const TSuccessCallback& OnSuccess, + const FFailureCallback& OnFailure) +{ + const FString Endpoint = "GetLowestPriceOfferForCollectible"; + const FSeqGetCollectibleOrderArgs Args = FSeqGetCollectibleOrderArgs{ ContractAddress, TokenID, Filter}; + GetCollectibleOrder(ChainID, Endpoint, Args, OnSuccess, OnFailure); +} + +void UMarketplace::GetHighestPriceOfferForCollectible(const int64 ChainID, const FString& ContractAddress, + const FString& TokenID, const FSeqCollectiblesFilter& Filter, const TSuccessCallback& OnSuccess, + const FFailureCallback& OnFailure) +{ + const FString Endpoint = "GetHighestPriceOfferForCollectible"; + const FSeqGetCollectibleOrderArgs Args = FSeqGetCollectibleOrderArgs{ContractAddress, TokenID, Filter}; + GetCollectibleOrder(ChainID, Endpoint, Args, OnSuccess, OnFailure); +} + +void UMarketplace::GetLowestPriceListingForCollectible(const int64 ChainID, const FString& ContractAddress, + const FString& TokenID, const FSeqCollectiblesFilter& Filter, const TSuccessCallback& OnSuccess, + const FFailureCallback& OnFailure) +{ + const FString Endpoint = "GetLowestPriceListingForCollectible"; + const FSeqGetCollectibleOrderArgs Args = FSeqGetCollectibleOrderArgs{ContractAddress, TokenID, Filter}; + GetCollectibleOrder(ChainID, Endpoint, Args, OnSuccess, OnFailure); +} + +void UMarketplace::GetHighestPriceListingForCollectible(const int64 ChainID, const FString& ContractAddress, + const FString& TokenID, const FSeqCollectiblesFilter& Filter, const TSuccessCallback& OnSuccess, + const FFailureCallback& OnFailure) +{ + const FString Endpoint = "GetHighestPriceListingForCollectible"; + const FSeqGetCollectibleOrderArgs Args = FSeqGetCollectibleOrderArgs{ContractAddress, TokenID, Filter}; + GetCollectibleOrder(ChainID, Endpoint, Args, OnSuccess, OnFailure); +} + +void UMarketplace::ListListingsForCollectible(const int64 ChainID, const FString& ContractAddress, + const FString& TokenID, const FSeqCollectiblesFilter& Filter, const FSeqMarketplacePage& Page, + TSuccessCallback OnSuccess, const FFailureCallback& OnFailure) +{ + const FString Endpoint = "ListListingsForCollectible"; + const FSeqListCollectibleListingsArgs Args = FSeqListCollectibleListingsArgs{ContractAddress, TokenID, Filter, Page}; + HTTPPost(ChainID, Endpoint, BuildArgs(Args), [this, OnSuccess](const FString& Content) + { + const FSeqListCollectibleListingsReturn Response = this->BuildResponse(Content); + OnSuccess(Response); + }, OnFailure); +} + +void UMarketplace::ListAllListingsForCollectible(const int64 ChainID, + const FString& ContractAddress, const FString& TokenID, const FSeqCollectiblesFilter& Filter, + TSuccessCallback> OnSuccess, const FFailureCallback& OnFailure) +{ + const FString Args = BuildArgs(FSeqListCollectibleListingsArgs{ ContractAddress, TokenID, Filter, FSeqMarketplacePage::Empty()}); + OrderArray.Empty(); + + return ListAllListingsForCollectibleHelper(ChainID, ContractAddress, TokenID, Filter, FSeqMarketplacePage::Empty(), [this, OnSuccess](const TArray& Orders, const bool IsDone) + { + OrderArray.Append(Orders); + + if(IsDone) + { + OnSuccess(OrderArray); + } + }, OnFailure); +} + +void UMarketplace::ListOffersForCollectible(const int64 ChainID, const FString& ContractAddress, const FString& TokenID, + const FSeqCollectiblesFilter& Filter, const FSeqMarketplacePage& Page, + TSuccessCallback OnSuccess, const FFailureCallback& OnFailure) +{ + const FString Endpoint = "ListOffersForCollectible"; + const FSeqListCollectibleListingsArgs Args = FSeqListCollectibleListingsArgs{ContractAddress, TokenID, Filter, Page}; + HTTPPost(ChainID, Endpoint, BuildArgs(Args), [this, OnSuccess](const FString& Content) + { + const FSeqListCollectibleOffersReturn Response = this->BuildResponse(Content); + OnSuccess(Response); + }, OnFailure); +} + +void UMarketplace::ListAllOffersForCollectible(const int64 ChainID, const FString& ContractAddress, const FString& TokenID, const FSeqCollectiblesFilter& Filter, TSuccessCallback> OnSuccess, const FFailureCallback& OnFailure) +{ + const FString Args = BuildArgs(FSeqListCollectibleListingsArgs{ ContractAddress, TokenID, Filter, FSeqMarketplacePage::Empty()}); + OrderArray.Empty(); + + return ListAllOffersForCollectibleHelper(ChainID, ContractAddress, TokenID, Filter, FSeqMarketplacePage::Empty(), [this, OnSuccess](const TArray& Orders, bool IsDone) + { + OrderArray.Append(Orders); + + if(IsDone) + { + OnSuccess(OrderArray); + } + }, OnFailure); +} + +void UMarketplace::GetFloorOrder(const int64 ChainID, const FString& ContractAddress, + const FSeqCollectiblesFilter& Filter, const TSuccessCallback& OnSuccess, + const FFailureCallback& OnFailure) +{ + const FString Endpoint = "GetFloorOrder"; + const FSeqGetFloorOrderArgs Args = FSeqGetFloorOrderArgs{ContractAddress, Filter, FSeqMarketplacePage::Empty()}; + HTTPPost(ChainID, Endpoint, BuildArgs(Args), [this, OnSuccess](const FString& Content) + { + const FSeqGetOrderReturn Response = this->BuildResponse(Content); + OnSuccess(Response.Collectible); + }, OnFailure); +} + + +// HELPER FUNCTIONS +void UMarketplace::ListAllCollectibleListingsWithLowestPriceListingsFirstHelper( + const int64 ChainID, + const FString& ContractAddress, + const FSeqCollectiblesFilter& Filter, + const FSeqMarketplacePage& Page, + TFunction, bool)> OnSuccess, + const FFailureCallback& OnFailure) +{ + ListCollectibleListingsWithLowestPriceListingsFirst(ChainID, ContractAddress, Filter, Page, [ChainID, ContractAddress, Filter, this, OnSuccess, OnFailure](const FSeqListCollectiblesReturn& CollectiblesReturn) + { + if (CollectiblesReturn.Page.More) + { + // Call the next page + ListAllCollectibleListingsWithLowestPriceListingsFirstHelper(ChainID, ContractAddress, Filter, CollectiblesReturn.Page, OnSuccess, OnFailure); + OnSuccess(CollectiblesReturn.CollectibleOrders, false); + } + else + { + OnSuccess(CollectiblesReturn.CollectibleOrders, true); + } + }, OnFailure); +} + +void UMarketplace::ListAllCollectibleOffersWithHighestPricedOfferFirstHelper( + const int64 ChainID, + const FString& ContractAddress, + const FSeqCollectiblesFilter& Filter, + const FSeqMarketplacePage& Page, + TFunction, bool)> OnSuccess, + const FFailureCallback& OnFailure) +{ + ListCollectibleOffersWithHighestPricedOfferFirst(ChainID, ContractAddress, Filter, Page, [ChainID, ContractAddress, Filter, this, OnSuccess, OnFailure](const FSeqListCollectiblesReturn& CollectiblesReturn) + { + + if (CollectiblesReturn.Page.More) + { + // Call the next page + ListAllCollectibleOffersWithHighestPricedOfferFirstHelper(ChainID, ContractAddress, Filter, CollectiblesReturn.Page, OnSuccess, OnFailure); + OnSuccess(CollectiblesReturn.CollectibleOrders, false); + } + else + { + OnSuccess(CollectiblesReturn.CollectibleOrders, true); + } + }, OnFailure); +} + +void UMarketplace::GetCollectibleOrder(const int64 ChainID, const FString& Endpoint, const FSeqGetCollectibleOrderArgs& Args, TSuccessCallback OnSuccess, + const FFailureCallback& OnFailure) +{ + HTTPPost(ChainID, Endpoint, BuildArgs(Args), [this, OnSuccess](const FString& Content) + { + const FSeqGetCollectibleOrderReturn Response = this->BuildResponse(Content); + OnSuccess(Response.Order); + }, OnFailure); +} + +void UMarketplace::ListAllListingsForCollectibleHelper(const int64 ChainID, const FString& ContractAddress, + const FString& TokenID, const FSeqCollectiblesFilter& Filter, const FSeqMarketplacePage& Page, + TFunction, bool)> OnSuccess, const FFailureCallback& OnFailure) +{ + ListListingsForCollectible(ChainID, ContractAddress, TokenID, Filter, Page, [ChainID, ContractAddress, Filter, TokenID, this, OnSuccess, OnFailure](const FSeqListCollectibleListingsReturn& CollectiblesReturn) + { + + if (CollectiblesReturn.Page.More) + { + // Call the next page + ListAllListingsForCollectibleHelper(ChainID, ContractAddress, TokenID, Filter, CollectiblesReturn.Page, OnSuccess, OnFailure); + OnSuccess(CollectiblesReturn.Listings, false); + } + else + { + OnSuccess(CollectiblesReturn.Listings, true); + } + }, OnFailure); +} + +void UMarketplace::ListAllOffersForCollectibleHelper(const int64 ChainID, const FString& ContractAddress, + const FString& TokenID, const FSeqCollectiblesFilter& Filter, const FSeqMarketplacePage& Page, + TFunction, bool)> OnSuccess, const FFailureCallback& OnFailure) +{ + ListOffersForCollectible(ChainID, ContractAddress, TokenID, Filter, Page, [ChainID, ContractAddress, Filter, TokenID, this, OnSuccess, OnFailure](const FSeqListCollectibleOffersReturn& CollectiblesReturn) + { + + if (CollectiblesReturn.Page.More) + { + // Call the next page + ListAllOffersForCollectibleHelper(ChainID, ContractAddress, TokenID, Filter, CollectiblesReturn.Page, OnSuccess, OnFailure); + OnSuccess(CollectiblesReturn.Offers, false); + } + else + { + OnSuccess(CollectiblesReturn.Offers, true); + } + }, OnFailure); +} diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Marketplace/Marketplace.h b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Marketplace/Marketplace.h deleted file mode 100644 index 9db028253..000000000 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Marketplace/Marketplace.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. - -#pragma once - -#include "CoreMinimal.h" -#include "Util/Async.h" -#include "Marketplace/Structs/Struct_Data.h" -#include "Marketplace.generated.h" - -UCLASS() -class SEQUENCEPLUGIN_API UMarketplace : public UObject -{ - GENERATED_BODY() - -private: - - const FString PATH = "/rpc/Marketplace/"; - - //private functions - - /* - Creates the URL from a given chainID and endpoint - */ - FString Url(const int64& ChainID, const FString& EndPoint) const; - - /* - Returns the host name - */ - static FString HostName(int64 ChainID); - -public: - /* - Used to send an HTTPPost req to a the sequence app - @return the content of the post response - */ - void HTTPPost(const int64& ChainID, const FString& Endpoint, const FString& Args, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const; - - - //public functions - - /* - Here we take in text and convert it to a Struct of type T if possible - @return a Struct of type T - - NOTE: Because unreal doesn't support nested TArrays and TMaps I had to use special implementations - for some data structures inorder for them to parse properly - */ - template < typename T > T BuildResponse(FString Text); - - /* - Here we take in a struct and convert it straight into a json object String - @Param (T) Struct_in the struct we are converting to a json object string - @Return the JSON Object String - */ - template < typename T> FString BuildArgs(T StructIn); - - UMarketplace(); - - void GetCollectiblesWithLowestListings(const int64 ChainID, const FSeqGetCollectiblesWithLowestListingsArgs& Args, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); - - - -}; - diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Marketplace/Sardine/SardineCheckout.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Marketplace/Sardine/SardineCheckout.cpp new file mode 100644 index 000000000..8d4db2351 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Marketplace/Sardine/SardineCheckout.cpp @@ -0,0 +1,614 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + + +#include "Marketplace/Sardine/SardineCheckout.h" + +#include "ConfigFetcher.h" +#include "HttpModule.h" +#include "Checkout/SequenceCheckout.h" +#include "Checkout/Structs/TransactionStep.h" +#include "Interfaces/IHttpResponse.h" +#include "Marketplace/Marketplace.h" +#include "Marketplace/Sardine/Structs/SardineEnabledTokensResponse.h" +#include "Marketplace/Sardine/Structs/SardineGetNFTCheckoutTokenResponse.h" +#include "Marketplace/Sardine/Structs/SardineGetQuoteArgs.h" +#include "Marketplace/Sardine/Structs/SardineGetQuoteResponse.h" +#include "Marketplace/Sardine/Structs/SardineSupportedFiatCurrenciesResponse.h" +#include "Marketplace/Sardine/Structs/SardineSupportedRegionsResponse.h" +#include "Marketplace/Sardine/Structs/SardineSupportedTokensResponse.h" +#include "Marketplace/Sardine/Structs/SardineTokenResponse.h" +#include "Types/ERC20.h" +#include "Types/SaleDetails.h" +#include "Util/Log.h" + +TArray PaymentMethods { + PaymentMethod_Us_Debit, + PaymentMethod_Us_Credit, + PaymentMethod_International_Debit, + PaymentMethod_International_Credit, + PaymentMethod_Ach +}; + +USardineCheckout::USardineCheckout() +{ + const TOptional WalletOptional = USequenceWallet::Get(); + if (WalletOptional.IsSet() && WalletOptional.GetValue()) + { + _wallet = WalletOptional.GetValue(); + } +} + +FString USardineCheckout::Url(const FString& EndPoint) const +{ + return _baseUrl + "/" + EndPoint; +} + +void USardineCheckout::GetPaymentDetails(FString PaymentToken, TSuccessCallback> OnSuccess, const FFailureCallback& OnFailure) +{ + if (PaymentToken == FAddress::New().ToHex()) + { + FString PaymentTokenSymbol = "POL"; + long PaymentTokenDecimals = 18; + OnSuccess(TTuple(PaymentTokenSymbol, PaymentTokenDecimals)); + } + else + { + OnSuccess(TTuple("USDC", 6)); // TODO: Use commented logic once ABI decoding is fixed + + // UERC20* PaymentTokenContract = NewObject(); + // PaymentTokenContract->Initialize(PaymentToken); + // FContractCall SymbolCall = PaymentTokenContract->MakeSymbolTransaction(); + // _wallet->Call(SymbolCall, [this, PaymentTokenContract, OnSuccess, OnFailure](FUnsizedData Data) + // { + // FString PaymentTokenSymbol = UTF8ToString(Data); + // FContractCall DecimalsCall = PaymentTokenContract->MakeDecimalsTransaction(); + // _wallet->Call(DecimalsCall, [this, PaymentTokenSymbol, OnSuccess](FUnsizedData Data) + // { + // long PaymentTokenDecimals = FCString::Atoi64(*UTF8ToString(Data)); + // OnSuccess(TTuple(PaymentTokenSymbol, PaymentTokenDecimals)); + // }, OnFailure); + // }, OnFailure); + } +} + +void USardineCheckout::GetSaleDetails(const FContractCall& SaleDetailsCall, long& Amount, long TokenID, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure) +{ + _wallet->Call(SaleDetailsCall, [this, Amount, TokenID, OnSuccess, OnFailure](FUnsizedData Data) + { + FSaleDetails SaleDetails; + SaleDetails.Initialize(Data); + + if (Amount > SaleDetails.SupplyCap) + { + SaleDetails.Amount = SaleDetails.SupplyCap; + } + else + { + SaleDetails.Amount = Amount; + } + if (SaleDetails.StartTimeLong > FDateTime::UtcNow().ToUnixTimestamp()) + { + OnFailure(FSequenceError(RequestFail, FString::Printf(TEXT("Token id %d is not yet available for sale"), (int) TokenID))); + } + if (SaleDetails.EndTimeLong < FDateTime::UtcNow().ToUnixTimestamp()) + { + OnFailure(FSequenceError(RequestFail, FString::Printf(TEXT("Token id %d is no longer available for sale"), (int) TokenID))); + } + + OnSuccess(SaleDetails); + }, OnFailure); +} + + +void USardineCheckout::SardineGetNFTCheckoutToken(const FSardineGetNFTCheckoutTokenArgs& Args, + TSuccessCallback OnSuccess, const FFailureCallback& OnFailure) +{ + if(Args.TokenAddress == FAddress::New().ToHex()) + { + OnFailure(FSequenceError(InvalidArgument, "Sardine doesn't support native currency checkout; please choose a different payment token")); + return; + } + + HTTPPost("SardineGetNFTCheckoutToken", BuildArgs(Args), [this, OnSuccess](const FString& Content) + { + const FSardineGetNFTCheckoutTokenResponse Response = this->BuildResponse(Content); + OnSuccess(Response.Checkout); + }, OnFailure); +} + +void USardineCheckout::SardineGetNFTCheckoutTokenSendRequest(int64 ChainId, FSeqCollectibleOrder Order, + FString RecipientAddress, FString MarketplaceContractAddress, long Quantity, FString PriceSymbol, FString CallData, + TSuccessCallback OnSuccess, const FFailureCallback& OnFailure) +{ + const FSardineGetNFTCheckoutTokenArgs Args { + "", + 3600, + FSardinePaymentMethodTypeConfig { + PaymentMethods, + PaymentMethod_Us_Debit + }, + Order.TokenMetadata.name, + Order.TokenMetadata.image, + USequenceSupport::GetNetworkNameForUrl(ChainId), + RecipientAddress, + MarketplaceContractAddress, + "calldata_execution", + "smart_contract", + Order.Order.TokenId, + Quantity, + Order.Order.QuantityDecimals, + Order.Order.PriceAmount, + Order.Order.PriceCurrencyAddress, + PriceSymbol, + Order.Order.PriceDecimals, + CallData, + }; + + FString Endpoint = "SardineGetNFTCheckoutToken"; + HTTPPost(Endpoint, BuildArgs(Args), [this, OnSuccess](const FString& Content) + { + const FSardineGetNFTCheckoutTokenResponse Response = this->BuildResponse(Content); + OnSuccess(Response.Checkout); + }, OnFailure); +} + +void USardineCheckout::HTTPPost(const FString& Endpoint, const FString& Args, + const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const +{ + const FString RequestURL = this->Url(Endpoint); + + const TSharedRef HTTP_Post_Req = FHttpModule::Get().CreateRequest(); + + FString AccessKey = UConfigFetcher::GetConfigVar("ProjectAccessKey"); + if (AccessKey.IsEmpty()) + { + UE_LOG(LogTemp, Error, TEXT("AccessKey is empty! Failed to set HTTP header.")); + return; + } + + HTTP_Post_Req->SetVerb("POST"); + HTTP_Post_Req->SetHeader(TEXT("Content-Type"), TEXT("application/json")); + HTTP_Post_Req->SetHeader(TEXT("Accept"), TEXT("application/json")); + + + HTTP_Post_Req->SetHeader(TEXT("X-Access-Key"), *AccessKey); + HTTP_Post_Req->SetTimeout(30); + HTTP_Post_Req->SetURL(RequestURL); + HTTP_Post_Req->SetContentAsString(Args); + + FString CurlCommand = FString::Printf( + TEXT("curl -X %s \"%s\" -H \"Content-Type: application/json\" -H \"Accept: application/json\" -H \"X-Access-Key: %s\" --data \"%s\""), + *HTTP_Post_Req->GetVerb(), + *HTTP_Post_Req->GetURL(), + *HTTP_Post_Req->GetHeader("X-Access-Key"), + *FString(UTF8_TO_TCHAR(HTTP_Post_Req->GetContent().GetData())).Replace(TEXT("\""), TEXT("\\\"")) + ); + + UE_LOG(LogTemp, Warning, TEXT("curl command: %s"), *CurlCommand); + // SEQ_LOG_EDITOR(Log, TEXT("%s"), *CurlCommand); + + + HTTP_Post_Req->OnProcessRequestComplete().BindLambda([OnSuccess, OnFailure](const FHttpRequestPtr& Request, FHttpResponsePtr Response, const bool bWasSuccessful) + { + if (bWasSuccessful) + { + const FString Content = Response->GetContentAsString(); + UE_LOG(LogTemp, Display, TEXT("Response: %s"), *Content); + OnSuccess(Content); + } + else + { + if (Request.IsValid() && Response.IsValid()) + { + const FString ErrorMessage = Response->GetContentAsString(); + UE_LOG(LogTemp, Error, TEXT("Request failed: %s"), *ErrorMessage); + OnFailure(FSequenceError(RequestFail, "Request failed: " + ErrorMessage)); + } + else + { + UE_LOG(LogTemp, Error, TEXT("Request failed: Invalid Request Pointer")); + OnFailure(FSequenceError(RequestFail, "Request failed: Invalid Request Pointer")); + } + } + }); + + // Process the request + HTTP_Post_Req->ProcessRequest(); +} + +void USardineCheckout::CheckSardineWhiteListStatus(FString Address, TSuccessCallback OnSuccess, + const FFailureCallback& OnFailure) +{ + const FString Endpoint = "SardineGetNFTCheckoutToken"; + + FString CheckWhiteListStatusUrl = Url(Endpoint); + FString ReferenceId = "sequence-unity-sardine-whitelist-check"; + FString Name = "whitelist-check"; + FString ImageUrl = "https://www.sequence.market/images/placeholder.png"; + int64 ChainID = _wallet->GetNetworkId(); + FString Platform = "calldata_execution"; + FString ExecutionType = "smart_contract"; + FString BlockchainNFTId = "42"; + uint Quantity = 1; + uint Decimals = 0; + FString TokenAmount = "1000000"; + FString TokenAddress = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; + FString TokenSymbol = "USDC"; + uint TokenDecimals = 6; + FString CallData = "0x1"; + + FSardinePaymentMethodTypeConfig PaymentConfig { + PaymentMethods, + ESardinePaymentMethod::PaymentMethod_Us_Debit + }; + + FSardineGetNFTCheckoutTokenArgs Args { + ReferenceId, + 3600, + PaymentConfig, + Name, + ImageUrl, + USequenceSupport::GetNetworkName(ChainID), + FAddress::New().ToHex(), + Address, + Platform, + ExecutionType, + BlockchainNFTId, + Quantity, + Decimals, + TokenAmount, + TokenAddress, + TokenSymbol, + TokenDecimals, + CallData + }; + + HTTPPost(Endpoint, BuildArgs(Args), [this, OnSuccess](const FString& Content) + { + OnSuccess(true); + }, OnFailure); +} + +void USardineCheckout::SardineGetQuote(TSuccessCallback OnSuccess, const FFailureCallback& OnFailure, FString WalletAddress, FSardineToken Token, u_long Amount, ESardinePaymentType PaymentType, + TOptional QuotedCurrency, ESardineQuoteType QuoteType) +{ + const FString Endpoint = "SardineGetQuote"; + + FSardineGetQuoteArgs Args { + Token.AssetSymbol, + Token.Network, + Amount, + QuotedCurrency.IsSet() ? QuotedCurrency->CurrencySymbol : "", + PaymentType, + QuoteType, + WalletAddress + }; + + HTTPPost(Endpoint, BuildArgs(Args), [this, OnSuccess](const FString& Content) + { + const FSardineGetQuoteResponse Response = this->BuildResponse(Content); + OnSuccess(Response.Quote); + }, OnFailure); +} + +void USardineCheckout::SardineGetClientToken(TSuccessCallback OnSuccess, const FFailureCallback& OnFailure) +{ + const FString Endpoint = "SardineGetClientToken"; + HTTPPost(Endpoint, "", [this, OnSuccess](const FString& Content) + { + const FSardineTokenResponse Response = this->BuildResponse(Content); + OnSuccess(Response.Token); + }, OnFailure); +} + +void USardineCheckout::OnRamp(const FString& ClientToken) +{ + FString URL = CheckoutURL(ClientToken); + FString * ErrorPtr = nullptr; + FPlatformProcess::LaunchURL(*URL,TEXT(""),ErrorPtr); + if (ErrorPtr) + { + UE_LOG(LogTemp,Error,TEXT("Browser LaunchError: %s"), **ErrorPtr); + } +} + +void USardineCheckout::SardineGetNFTCheckoutToken(int64 ChainId, const FString& WalletAddress, TArray Orders, long Quantity, + FString RecipientAddress, TArray AdditionalFee, FString MarketPlaceContractAddress, + TSuccessCallback OnSuccess, const FFailureCallback& OnFailure) +{ + if (RecipientAddress.IsEmpty()) + { + RecipientAddress = WalletAddress; + } + + if(Orders.Num() < 1) + { + OnFailure(FSequenceError(InvalidArgument, "Orders must contain at least one collectible")); + return; + } + + FSeqCollectibleOrder Order = Orders[0]; + + if(Order.Order.PriceCurrencyAddress == FAddress::New().ToHex()) + { + OnFailure(FSequenceError(InvalidArgument, "Sardine doesn't support native currency checkout; please choose a different payment token")); + return; + } + + FString PriceSymbol = USequenceSupport::GetNetworkSymbol(ChainId); + + const USequenceCheckout* Checkout = NewObject(); + + TArray BuyOrders; + for(FSeqCollectibleOrder CollectibleOrder : Orders) + BuyOrders.Push(CollectibleOrder.Order); + + Checkout->GenerateBuyTransaction(WalletAddress, BuyOrders, Quantity, AdditionalFee[0], EWalletKind::Unknown, + ([this, OnSuccess, ChainId, RecipientAddress, MarketPlaceContractAddress, Quantity, PriceSymbol, Order, OnFailure](const FGenerateTransactionResponse& Response) + { + const FTransactionStep Step = FTransactionStep::ExtractBuyStep(Response.Steps); + + if(Order.Order.PriceCurrencyAddress != FAddress::New().ToHex()) + { + // TODO: The following call will not work currently, so we will use USDC temporarily + // UERC20* PaymentTokenContract = NewObject(); + // PaymentTokenContract->Initialize(Order.Order.PriceCurrencyAddress); + // FContractCall SymbolCall = PaymentTokenContract->MakeSymbolTransaction(); + // _wallet->Call(SymbolCall, [this, OnSuccess, OnFailure, ChainId, Order, RecipientAddress, MarketPlaceContractAddress, Quantity, Step](FUnsizedData Data) + // { + // FString PaymentTokenSymbol = UTF8ToString(Data); + // SardineGetNFTCheckoutTokenSendRequest(ChainId, Order, RecipientAddress, MarketPlaceContractAddress, Quantity, PaymentTokenSymbol, Step.Data, + // OnSuccess, OnFailure); + // }, OnFailure); + + + SardineGetNFTCheckoutTokenSendRequest(ChainId, Order, RecipientAddress, MarketPlaceContractAddress, Quantity, "USDC", Step.Data, + OnSuccess, OnFailure); + } else + { + SardineGetNFTCheckoutTokenSendRequest(ChainId, Order, RecipientAddress, MarketPlaceContractAddress, Quantity, Order.Order.PriceCurrencyAddress, Step.Data, + OnSuccess, OnFailure); + } + + }), OnFailure); +} + + +void USardineCheckout::SardineGetNFTCheckoutToken(int64 ChainId, UERC1155SaleContract* SaleContract, FString CollectionAddress, + long TokenID, long Amount, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure, + FString RecipientAddress, TArray data, TArray Proof) +{ + FString RecipientAddressToUse = RecipientAddress; + if (RecipientAddressToUse.IsEmpty()) + { + RecipientAddressToUse = _wallet->GetWalletAddress(); + } + + if(Amount < 1) + { + OnFailure(FSequenceError(InvalidArgument, "Amount must be greater than 0")); + return; + } + + // set provider url to appropriate node gateway url for given chain + _wallet->UpdateProviderURL(ChainId); + + FString PaymentToken = SaleContract->PaymentToken; + + GetPaymentDetails(PaymentToken, [this, PaymentToken, SaleContract, CollectionAddress, TokenID, ChainId, RecipientAddress, &Amount, Proof, OnSuccess, OnFailure](TTuple PaymentDetails) + { + FString PaymentTokenSymbol = PaymentDetails.Get<0>(); + long PaymentTokenDecimals = PaymentDetails.Get<1>(); + + UMarketplace* Marketplace = NewObject(); + Marketplace->GetCollectible(ChainId, CollectionAddress, FString::FromInt(TokenID), + [this, SaleContract, TokenID, ChainId, RecipientAddress, Amount, PaymentToken, PaymentTokenSymbol, PaymentTokenDecimals, Proof, OnSuccess, OnFailure](const FSeqTokenMetaData& TokenMetaData) + { + FContractCall SaleDetailsCall = SaleContract->GetTokenSaleDetails(TokenID); + TSuccessCallback OnGetSaleDetailsSuccess = [this, TokenID, Amount, SaleContract, RecipientAddress, Proof, TokenMetaData, ChainId, PaymentToken, PaymentTokenSymbol, PaymentTokenDecimals, OnSuccess, OnFailure](FSaleDetails SaleDetails) + { + TArray TokenIds { (int32)TokenID }; + TArray Amounts { (int32)Amount }; + + FString CallData = SaleContract->MakePurchaseTransaction(RecipientAddress, TokenIds, Amounts, Proof).data; + + FSardinePaymentMethodTypeConfig PaymentConfig { + PaymentMethods, + PaymentMethod_Us_Debit + }; + + FSardineGetNFTCheckoutTokenArgs Args { + "", + 3600, + PaymentConfig, + TokenMetaData.name, + TokenMetaData.image, + USequenceSupport::GetNetworkNameForUrl(ChainId), + RecipientAddress, + SaleContract->ContractAddress, + "calldata_execution", + "smart_contract", + FString::FromInt(TokenID), + SaleDetails.Amount, + (uint)TokenMetaData.decimals, + FString::FromInt(SaleDetails.Cost), + PaymentToken, + PaymentTokenSymbol, + PaymentTokenDecimals, + CallData + }; + + SardineGetNFTCheckoutToken(Args, OnSuccess, OnFailure); + }; + + FSaleDetails MockSaleDetails { + "", + 20000, + 9999999999, + 1723058097, + 2448832492, + Amount, + TArray() + }; + + OnGetSaleDetailsSuccess(MockSaleDetails); + // TODO: Use helper below instead + // GetSaleDetails(SaleDetailsCall, Amount, TokenID, OnGetSaleDetailsSuccess, OnFailure); + }, OnFailure); + }, OnFailure); +} + +void USardineCheckout::SardineGetNFTCheckoutToken(int64 ChainID, UERC721SaleContract* SaleContract, FString CollectionAddress, + long TokenID, long Amount, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure, + FString RecipientAddress, TArray data, TArray Proof) +{ + if (RecipientAddress.IsEmpty()) + { + RecipientAddress = _wallet->GetWalletAddress(); + } + + if (Amount < 1) + { + OnFailure(FSequenceError(InvalidArgument, "Amount must be greater than 0")); + return; + } + + // set provider url to appropriate node gateway url for given chain + _wallet->UpdateProviderURL(ChainID); + + UMarketplace* Marketplace = NewObject(); + Marketplace->GetCollectible(ChainID, CollectionAddress, FString::FromInt(TokenID),[this, SaleContract, RecipientAddress, Amount, TokenID, Proof, ChainID, OnSuccess, OnFailure](const FSeqTokenMetaData& TokenMetaData) + { + FContractCall SaleDetailsCall = SaleContract->GetSaleDetails(); + TSuccessCallback OnGetSaleDetailsSuccess = [this, SaleContract, RecipientAddress, Amount, Proof, TokenMetaData, ChainID, TokenID, OnSuccess, OnFailure](FSaleDetails SaleDetails) + { + FString PaymentToken = SaleDetails.PaymentToken; + if (PaymentToken == FAddress::New().ToHex()) + { + OnFailure(FSequenceError(InvalidArgument, "Sardine checkout does not support native currency checkout; please choose an sales contract with a different payment token")); + } + + GetPaymentDetails(PaymentToken, [this, SaleContract, RecipientAddress, Amount, Proof, TokenMetaData, ChainID, TokenID, SaleDetails, PaymentToken, OnSuccess, OnFailure](TTuple PaymentDetails) + { + FString CallData = SaleContract->MakePurchaseTransaction(RecipientAddress, Amount, Proof).data; + + FSardinePaymentMethodTypeConfig PaymentConfig { + PaymentMethods, + PaymentMethod_Us_Debit + }; + + FSardineGetNFTCheckoutTokenArgs Args { + "", + 3600, + PaymentConfig, + TokenMetaData.name, + TokenMetaData.image, + USequenceSupport::GetNetworkNameForUrl(ChainID), + RecipientAddress, + SaleContract->ContractAddress, + "calldata_execution", + "smart_contract", + FString::FromInt(TokenID), + SaleDetails.Amount, + (uint)TokenMetaData.decimals, + FString::FromInt(SaleDetails.Cost), + PaymentToken, + PaymentDetails.Get<0>(), + PaymentDetails.Get<1>(), + CallData + }; + + SardineGetNFTCheckoutToken(Args, OnSuccess, OnFailure); + }, OnFailure); + }; + + FSaleDetails MockSaleDetails { + "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", + 0, + 10000, + 1723058097, + 2448832492, + Amount, + TArray() + }; + + OnGetSaleDetailsSuccess(MockSaleDetails); + + // TODO: Use helper below instead: + // GetSaleDetails(SaleDetailsCall, Amount, TokenID, , OnFailure); + }, OnFailure); +} + +void USardineCheckout::SardineGetNFTCheckoutOrderStatus(FString OrderID, TSuccessCallback OnSuccess, + const FFailureCallback& OnFailure) +{ + //TODO: This needs to be finished +} + + +void USardineCheckout::SardineGetSupportedRegions(TSuccessCallback> OnSuccess, + const FFailureCallback& OnFailure) +{ + const FString Endpoint = "SardineGetSupportedRegions"; + HTTPPost(Endpoint, "", [this, OnSuccess](const FString& Content) + { + const FSardineSupportedRegionsResponse Response = this->BuildResponse(Content); + OnSuccess(Response.Regions); + }, OnFailure); +} + +void USardineCheckout::SardineGetSupportedFiatCurrencies(TSuccessCallback> OnSuccess, + const FFailureCallback& OnFailure) +{ + const FString Endpoint = "SardineGetSupportedFiatCurrencies"; + HTTPPost(Endpoint, "", [this, OnSuccess](const FString& Content) + { + const FSardineSupportedFiatCurrenciesResponse Response = this->BuildResponse(Content); + OnSuccess(Response.Tokens); + }, OnFailure); +} + +void USardineCheckout::SardineGetSupportedTokens(TSuccessCallback> OnSuccess, + const FFailureCallback& OnFailure) +{ + const FString Endpoint = "SardineGetSupportedTokens"; + HTTPPost(Endpoint, "", [this, OnSuccess](const FString& Content) + { + const FSardineSupportedTokensResponse Response = this->BuildResponse(Content); + OnSuccess(Response.Tokens); + }, OnFailure); +} + +void USardineCheckout::SardineGetEnabledTokens(TSuccessCallback> OnSuccess, + const FFailureCallback& OnFailure) +{ + const FString Endpoint = "SardineGetEnabledTokens"; + HTTPPost(Endpoint, "", [this, OnSuccess](const FString& Content) + { + const FSardineEnabledTokensResponse Response = this->BuildResponse(Content); + OnSuccess(Response.Tokens); + }, OnFailure); +} + +FString USardineCheckout::CheckoutURL(FString ClientToken) +{ + return _baseCheckoutUrl + ClientToken + _sardineCheckoutUrlSuffix; +} + +FString USardineCheckout::CheckoutURL(FSardineNFTCheckout Token) +{ + return CheckoutURL(Token.Token); +} + +void USardineCheckout::Checkout(FSardineNFTCheckout Token) +{ + FString URL = CheckoutURL(Token); + FString * ErrorPtr = nullptr; + FPlatformProcess::LaunchURL(*URL,TEXT(""),ErrorPtr); + if (ErrorPtr) + { + UE_LOG(LogTemp,Error,TEXT("Browser LaunchError: %s"), **ErrorPtr); + } +} + + diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Marketplace/Sardine/Structs/SardineGetQuoteArgs.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Marketplace/Sardine/Structs/SardineGetQuoteArgs.cpp new file mode 100644 index 000000000..49d4dc7e5 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Marketplace/Sardine/Structs/SardineGetQuoteArgs.cpp @@ -0,0 +1,4 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + + +#include "Marketplace/Sardine/Structs/SardineGetQuoteArgs.h" diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Provider.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Provider.cpp index a1ab35efc..6a8a2f71c 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Provider.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Provider.cpp @@ -1,5 +1,7 @@ // Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. #include "Provider.h" + +#include "ConfigFetcher.h" #include "Eth/Crypto.h" #include "Eth/EthTransaction.h" #include "Types/BinaryData.h" @@ -7,6 +9,7 @@ #include "Util/JsonBuilder.h" #include "RequestHandler.h" #include "Types/Header.h" +#include "Util/SequenceSupport.h" void UProvider::Init(const FString& UrlIn) { @@ -25,6 +28,11 @@ void UProvider::UpdateUrl(const FString& UrlIn) this->Url = UrlIn; } +void UProvider::UpdateUrl(int64 ChainID) +{ + this->Url = _baseURL + USequenceSupport::GetNetworkNameForUrl(ChainID) + "/" + UConfigFetcher::GetConfigVar(UConfigFetcher::ProjectAccessKey); +} + void UProvider::BlockByNumberHelper(const FString& Number, const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure) { const FString Content = FJsonBuilder().ToPtr() @@ -386,12 +394,39 @@ void UProvider::Call(const FContractCall& ContractCall, const EBlockTag Number, return CallHelper(ContractCall, ConvertString(UEnum::GetValueAsString(Number)), OnSuccess, OnFailure); } +void UProvider::Call(const FContractCall& ContractCall, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) +{ + return CallHelper(ContractCall, OnSuccess, OnFailure); +} + void UProvider::NonViewCall(FEthTransaction Transaction, const FPrivateKey& PrivateKey, const int ChainID, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) { const FUnsizedData SignedTransaction = Transaction.GetSignedTransaction(PrivateKey, ChainID); return SendRawTransaction("0x" + SignedTransaction.ToHex(), OnSuccess, OnFailure); } +void UProvider::CallHelper(FContractCall ContractCall, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) +{ + const FString Content = RPCBuilder("eth_call").ToPtr() + ->AddArray("params").ToPtr() + ->AddValue(ContractCall.GetJson()) + ->EndArray() + ->ToString(); + + const FString MyUrl = this->Url; + this->SendRPCAndExtract(Url, Content, OnSuccess, [MyUrl](const FString& Response) + { + TResult StringResult = Make(MyUrl)->ExtractStringResult(Response); + + if(!StringResult.HasError()) + { + return TResult(MakeValue(HexStringToBinary(StringResult.GetValue()))); + } + + return TResult(MakeError(FSequenceError(ResponseParseError, ""))); + }, OnFailure); +} + void UProvider::CallHelper(FContractCall ContractCall, const FString& Number, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) { const FString Content = RPCBuilder("eth_call").ToPtr() diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Provider.h b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Provider.h index 6872ac1f9..82e7b8c76 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Provider.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Provider.h @@ -22,17 +22,22 @@ class SEQUENCEPLUGIN_API UProvider : public URPCCaller { GENERATED_BODY() private: + const FString _prodURL = "https://nodes.sequence.app/"; + const FString _devURL = "https://dev-nodes.sequence.app/"; + const FString _baseURL = _prodURL; FString Url; //helpers void BlockByNumberHelper(const FString& Number, const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure); void HeaderByNumberHelper(const FString& Number, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); void NonceAtHelper(const FString& Number, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); + void CallHelper(FContractCall ContractCall, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure); void CallHelper(FContractCall ContractCall, const FString& Number, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure); void Init(const FString& UrlIn); public: static UProvider* Make(const FString& UrlIn); void UpdateUrl(const FString& UrlIn); + void UpdateUrl(int64 ChainID); void BlockByNumber(const uint64 Number, const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure); void BlockByNumber(const EBlockTag Tag, const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure); void BlockByHash(const FHash256& Hash, const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure); @@ -62,5 +67,6 @@ class SEQUENCEPLUGIN_API UProvider : public URPCCaller void Call(const FContractCall& ContractCall, const uint64 Number, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure); void Call(const FContractCall& ContractCall, const EBlockTag Number, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure); + void Call(const FContractCall& ContractCall, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure); void NonViewCall(FEthTransaction Transaction, const FPrivateKey& PrivateKey, const int ChainID, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure); }; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/ResponseSignatureValidator.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/ResponseSignatureValidator.cpp index ed19aeb2b..5b6fbad72 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/ResponseSignatureValidator.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/ResponseSignatureValidator.cpp @@ -18,18 +18,22 @@ void UResponseSignatureValidator::LoadPublicKey() if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid()) { + // Extract the key values const TArray> Keys = JsonObject->GetArrayField("keys"); const TSharedPtr Key = Keys[0]->AsObject(); FString ExponentStr = Key->GetStringField("e"); FString ModulusStr = Key->GetStringField("n"); + // Decode the Base64 URL values TArray ExponentBytes = Base64UrlDecode(ExponentStr); TArray ModulusBytes = Base64UrlDecode(ModulusStr); + // Convert to OpenSSL BIGNUM format BIGNUM* ExponentBN = BN_bin2bn(ExponentBytes.GetData(), ExponentBytes.Num(), NULL); BIGNUM* ModulusBN = BN_bin2bn(ModulusBytes.GetData(), ModulusBytes.Num(), NULL); + // Create the RSA key structure WaasPublicKey = RSA_new(); RSA_set0_key(WaasPublicKey, ModulusBN, ExponentBN, NULL); @@ -47,6 +51,7 @@ TArray UResponseSignatureValidator::Base64UrlDecode(const FString& Input) FString Output = Input; Output = Output.Replace(TEXT("-"), TEXT("+")).Replace(TEXT("_"), TEXT("/")); + // Adjust for padding while (Output.Len() % 4 != 0) { Output.AppendChar('='); @@ -64,20 +69,23 @@ FString UResponseSignatureValidator::GetValue(const FString& HeaderItem) { return HeaderItem.Mid(FirstColon + 1, LastColon - FirstColon - 1).TrimStartAndEnd(); } - return FString(); + return FString(); // Return empty if no valid value found. } + bool UResponseSignatureValidator::ValidateResponseSignature(const FHttpResponsePtr& Response) { if (!Response.IsValid()) { tamperedResponseSignatureFound = true; - return false; + return false; // Invalid response } + // Extract headers const FString ContentDigestHeader = Response->GetHeader(TEXT("content-digest")); const FString SignatureHeader = Response->GetHeader(TEXT("signature")); const FString SignatureInputHeader = Response->GetHeader(TEXT("signature-input")); - + + // Validate that headers are present if (ContentDigestHeader.IsEmpty()) { UE_LOG(LogTemp, Error, TEXT("ContentDigestHeader is empty.")); @@ -103,11 +111,14 @@ bool UResponseSignatureValidator::ValidateResponseSignature(const FHttpResponseP FString CleanContentDigestHeader = ContentDigestHeader; const FString Prefix = TEXT("sha-256="); if (CleanContentDigestHeader.StartsWith(Prefix)) + { CleanContentDigestHeader = CleanContentDigestHeader.RightChop(Prefix.Len()); + } CleanContentDigestHeader.RemoveAt(0); CleanContentDigestHeader.RemoveAt(CleanContentDigestHeader.Len() - 1); + // Decode the Content-Digest header from Base64 TArray DecodedDigest; if (!FBase64::Decode(CleanContentDigestHeader, DecodedDigest)) @@ -117,8 +128,10 @@ bool UResponseSignatureValidator::ValidateResponseSignature(const FHttpResponseP return false; } + // Compute the SHA-256 hash of the response content Sha256Hash ComputedHash = Sha256().getHash(ResponseContent.GetData(), ResponseContent.Num()); + // Convert the computed hash to a Base64 string TArray HashBytes = TArray(ComputedHash.value, ComputedHash.HASH_LEN); FString ExpectedDigestBase64 = FBase64::Encode(HashBytes); @@ -129,19 +142,23 @@ bool UResponseSignatureValidator::ValidateResponseSignature(const FHttpResponseP return false; } + // Construct the signature base + // Parse the signature value from the header FString Signature = GetValue(SignatureHeader); if (Signature.IsEmpty()) { UE_LOG(LogTemp, Error, TEXT("Failed to parse Signature header.")); - tamperedResponseSignatureFound = true; return false; } + // Remove the "sig=" prefix from the SignatureInput header FString SignatureInputValue = SignatureInputHeader.Replace(TEXT("sig="), TEXT("")); + // Construct the SignatureBase string FString SignatureBase = FString::Printf(TEXT("\"content-digest\": sha-256=:%s:\n\"@signature-params\": %s"), *CleanContentDigestHeader, *SignatureInputValue); + // Here, you can log or return the SignatureBase if needed UE_LOG(LogTemp, Log, TEXT("Signature Base: %s"), *SignatureBase); return VerifySignature(SignatureBase, Signature); @@ -149,44 +166,51 @@ bool UResponseSignatureValidator::ValidateResponseSignature(const FHttpResponseP bool UResponseSignatureValidator::VerifySignature(const FString& SignatureBase, const FString& Signature) { + // Convert signature from Base64 to byte array TArray SignatureBytes; if (!FBase64::Decode(Signature, SignatureBytes)) { UE_LOG(LogTemp, Error, TEXT("Failed to decode signature from Base64")); tamperedResponseSignatureFound = true; - return false; + return false; // Return false on failure } + // Convert SignatureBase (the data to verify) to byte array (UTF-8 encoding) TArray DataBytes; FTCHARToUTF8 Converter(*SignatureBase); DataBytes.Append((uint8*)Converter.Get(), Converter.Length()); + // Verify the signature using the loaded RSA public key EVP_PKEY* PublicKey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(PublicKey, WaasPublicKey); + EVP_PKEY_assign_RSA(PublicKey, WaasPublicKey); // WaasPublicKey is the RSA key EVP_MD_CTX* mdCtx = EVP_MD_CTX_new(); EVP_PKEY_CTX* pkeyCtx = nullptr; + // Initialize signature verification if (EVP_DigestVerifyInit(mdCtx, &pkeyCtx, EVP_sha256(), nullptr, PublicKey) <= 0) { UE_LOG(LogTemp, Error, TEXT("Failed to initialize signature verification")); EVP_MD_CTX_free(mdCtx); EVP_PKEY_free(PublicKey); tamperedResponseSignatureFound = true; - return false; + return false; // Return false on failure } + // Update with data to verify if (EVP_DigestVerifyUpdate(mdCtx, DataBytes.GetData(), DataBytes.Num()) <= 0) { UE_LOG(LogTemp, Error, TEXT("Failed to update signature verification with data")); EVP_MD_CTX_free(mdCtx); EVP_PKEY_free(PublicKey); tamperedResponseSignatureFound = true; - return false; + return false; // Return false on failure } + // Perform the actual verification int result = EVP_DigestVerifyFinal(mdCtx, SignatureBytes.GetData(), SignatureBytes.Num()); + // Clean up OpenSSL structures EVP_MD_CTX_free(mdCtx); EVP_PKEY_free(PublicKey); @@ -194,14 +218,19 @@ bool UResponseSignatureValidator::VerifySignature(const FString& SignatureBase, { UE_LOG(LogTemp, Error, TEXT("Signature is invalid")); tamperedResponseSignatureFound = true; - return false; + return false; // Return false if signature verification fails } + // If everything was successful UE_LOG(LogTemp, Log, TEXT("Signature is valid")); - return true; + return true; // Return true if verification is successful } bool UResponseSignatureValidator::HasFoundTamperedResponse() { return tamperedResponseSignatureFound; } + +//l2am+8M1yDQUrezN2FqVJfMKsngtsv6p9Rvp11Ies0NMYd9lFcoQbqOCdEXklRT4eymVC4iFhUI4I4wimjOTopDptwfyQy8Fyo9tei0CqfnQejdIdIcGDaz6ncn68uow82jQTOuaEjkEHuxnQSRd46KrJQRdvHx7oL9koCxCThISb8JVgiOn7FdS2ZJ4XkU9WpBseL5FLiQW6M3PP9+77WaRJ+5MvVukAva6dblRdx497fB5TUbZsZzMh/duU+M2NkNebCpMmEFgOHsRmMRWSkKHwGhzFycNqiwyxrMOmdludz+Gpi9ZCoaiWuzb1ZC7gvhMCsxWtXc9oG5iv5U3hA== + +//"content-digest": sha-256=:g2r98q/9/5HDXq3LaiqNXmHaPQfruwSgefdPzt7uwlg=:"@signature-params": ("content-digest"); created = 1728998376; keyid = "nWh-_3nQ1lnhhI1ZSQTQmw"; alg = "rsa-v1_5-sha256" diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/ResponseSignatureValidator.h b/Plugins/SequencePlugin/Source/SequencePlugin/Private/ResponseSignatureValidator.h index 74b2fde64..1d9f849ce 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/ResponseSignatureValidator.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/ResponseSignatureValidator.h @@ -49,3 +49,7 @@ class SEQUENCEPLUGIN_API UResponseSignatureValidator : public UObject FString GetValue(const FString& HeaderItem); }; + + +//UResponseSignatureValidator + diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Sequence/SequenceAPI.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Sequence/SequenceAPI.cpp index 3b0490cb3..6cea4fe77 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Sequence/SequenceAPI.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Sequence/SequenceAPI.cpp @@ -308,6 +308,15 @@ void USequenceWallet::UpdateProviderURL(const FString& Url) const } } +void USequenceWallet::UpdateProviderURL(int64 ChainID) const +{ + if (this->Provider) + { + this->Provider->UpdateUrl(ChainID); + } +} + + void USequenceWallet::SignMessage(const FString& Message, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const { if (this->SequenceRPCManager) @@ -477,6 +486,71 @@ void USequenceWallet::SendTransaction(const TArray& Transactio } } +void USequenceWallet::GetLinkedWallets(const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const +{ + const FString& WalletAddress = this->GetWalletAddress(); + const FString& MessageToSign = "parent wallet with address " + WalletAddress; + + const TSuccessCallback OnSignatureSuccess = [this, WalletAddress, MessageToSign, OnSuccess, OnFailure](FSeqSignMessageResponse_Response SignatureResponse) + { + if (this->SequenceRPCManager) + { + const FString& ChainId = this->Credentials.GetNetworkString(); + FSeqLinkedWalletRequest Request; + Request.SignatureChainId = ChainId; + Request.ParentWalletAddress = WalletAddress; + Request.ParentWalletMessage = MessageToSign; + Request.ParentWalletSignature = SignatureResponse.Data.Signature; + + this->SequenceRPCManager->GetLinkedWallets(Request, OnSuccess, OnFailure); + } + else + { + OnFailure(FSequenceError(RequestFail, "SequenceRPCManager is not available.")); + } + }; + + const TFunction OnSignatureFailure = [OnFailure](FString Data, FSequenceError Err) + { + OnFailure(FSequenceError(RequestFail, "Error Parsing Response: " + Err.Message)); + }; + + this->SignMessage(MessageToSign, OnSignatureSuccess, OnFailure); +} + +void USequenceWallet::RemoveLinkedWallet(const FString& LinkedWalletAddress, const TFunction& OnSuccess, const FFailureCallback& OnFailure) const +{ + const FString& WalletAddress = this->GetWalletAddress(); + const FString& MessageToSign = "parent wallet with address " + WalletAddress + LinkedWalletAddress; + + const TSuccessCallback OnSignatureSuccess = [this, LinkedWalletAddress, WalletAddress, MessageToSign, OnSuccess, OnFailure](FSeqSignMessageResponse_Response SignatureResponse) + { + if (this->SequenceRPCManager) + { + const FString& ChainId = this->Credentials.GetNetworkString(); + FSeqLinkedWalletRequest Request; + Request.SignatureChainId = ChainId; + Request.ParentWalletAddress = WalletAddress; + Request.ParentWalletMessage = MessageToSign; + Request.ParentWalletSignature = SignatureResponse.Data.Signature; + Request.LinkedWalletAddress = LinkedWalletAddress; + + this->SequenceRPCManager->RemoveLinkedWallet(Request, OnSuccess, OnFailure); + } + else + { + OnFailure(FSequenceError(RequestFail, "SequenceRPCManager is not available.")); + } + }; + + const TFunction OnSignatureFailure = [OnFailure](FString Data, FSequenceError Err) + { + OnFailure(FSequenceError(RequestFail, "Error Parsing Response: " + Err.Message)); + }; + + this->SignMessage(MessageToSign, OnSignatureSuccess, OnFailure); +} + //Indexer Calls void USequenceWallet::Ping(const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const @@ -685,6 +759,14 @@ void USequenceWallet::Call(const FContractCall& ContractCall, EBlockTag Number, } } +void USequenceWallet::Call(const FContractCall& ContractCall, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const +{ + if (this->Provider) + { + this->Provider->Call(ContractCall,OnSuccess,OnFailure); + } +} + void USequenceWallet::NonViewCall(const FEthTransaction& Transaction, const FPrivateKey& PrivateKey, int ChainID, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const { if (this->Provider) diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/SequenceAuthenticator.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/SequenceAuthenticator.cpp index b51c38f0f..2df9441a1 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/SequenceAuthenticator.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/SequenceAuthenticator.cpp @@ -920,4 +920,4 @@ FStoredCredentials_BE USequenceAuthenticator::GetStoredCredentials() const FCredentials_BE* Credentials = &CredData; const bool IsValid = this->GetStoredCredentials(Credentials); return FStoredCredentials_BE(IsValid, *Credentials); -} +} \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/SequenceRPCManager.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/SequenceRPCManager.cpp index 604ec1303..511fdffe1 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/SequenceRPCManager.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/SequenceRPCManager.cpp @@ -13,6 +13,7 @@ #include "Sequence/SequenceAPI.h" #include "Sequence/SequenceAuthResponseIntent.h" #include "Misc/DateTime.h" +#include "Util/Log.h" template FString USequenceRPCManager::GenerateIntent(T Data, TOptional CurrentTime) const { @@ -41,6 +42,8 @@ void USequenceRPCManager::SequenceRPC(const FString& Url, const FString& Content { UResponseSignatureValidator& RPCValidator = *Validator; + SEQ_LOG_EDITOR(Display, TEXT("%s - %s"), *Url, *Content); + NewObject() ->PrepareRequest() ->WithUrl(Url) @@ -55,12 +58,15 @@ void USequenceRPCManager::SequenceRPC(const FString& Url, const FString& Content void USequenceRPCManager::SequenceRPC(const FString& Url, const FString& Content, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const { + SEQ_LOG_EDITOR(Display, TEXT("%s - %s"), *Url, *Content); + NewObject() ->PrepareRequest() ->WithUrl(Url) ->WithHeader("Content-type", "application/json") ->WithHeader("Accept", "application/json") ->WithHeader("X-Access-Key", this->Cached_ProjectAccessKey) + ->WithHeader("Accept-Signature", "sig=()") ->WithVerb("POST") ->WithContentAsString(Content) ->ProcessAndThen(OnSuccess, OnFailure); @@ -71,31 +77,36 @@ void USequenceRPCManager::SendIntent(const FString& Url, TFunctionSequenceRPC(Url, ContentGenerator(TOptional()), [this, Url, ContentGenerator, OnSuccess, OnFailure](FHttpResponsePtr Response) { - UE_LOG(LogTemp, Display, TEXT("SUCCESS")); - UE_LOG(LogTemp, Display, TEXT("CONTENT")); - FString Content = UTF8ToString(FUnsizedData(Response.Get()->GetContent())); - UE_LOG(LogTemp, Display, TEXT("%s"), *Content); + const FString Content = UTF8ToString(FUnsizedData(Response.Get()->GetContent())); + const int32 Code = Response.Get()->GetResponseCode(); + + SEQ_LOG_EDITOR(Display, TEXT("%d %s"), Code, *Content); - if(Content.Contains("intent is invalid: intent expired") || Content.Contains("intent is invalid: intent issued in the future")) + OnSuccess(Content); + }, [this, Url, ContentGenerator, OnSuccess, OnFailure](const FSequenceError& Error) + { + const FString Content = Error.Response->GetContentAsString(); + const int32 Code = Error.Response->GetResponseCode(); + SEQ_LOG_EDITOR(Error, TEXT("%d %s"), Code, *Content); + + if (!Content.Contains("intent is invalid: intent expired") && + !Content.Contains("intent is invalid: intent issued in the future")) { - FString Date = Response->GetHeader("Date"); - FDateTime Time; - bool IsParsed = FDateTime::ParseHttpDate(Date, Time); - - if(!IsParsed) - { - OnFailure(FSequenceError(FailedToParseIntentTime, "Failed to parse intent time " + Date)); - return; - } - - UE_LOG(LogTemp, Display, TEXT("Resending intent with date %i"), Time.ToUnixTimestamp()); - this->SequenceRPC(Url, ContentGenerator(TOptional(Time.ToUnixTimestamp())), OnSuccess, OnFailure); + OnFailure(Error); + return; } - else + + FDateTime Time; + const FString Date = Error.Response->GetHeader("Date"); + if(!FDateTime::ParseHttpDate(Date, Time)) { - OnSuccess(Content); + OnFailure(FSequenceError(FailedToParseIntentTime, Error.Response, "Failed to parse intent time " + Date)); + return; } - }, OnFailure); + + UE_LOG(LogTemp, Display, TEXT("Resending intent with date %i"), Time.ToUnixTimestamp()); + this->SequenceRPC(Url, ContentGenerator(TOptional(Time.ToUnixTimestamp())), OnSuccess, OnFailure); + }); } FString USequenceRPCManager::BuildGetFeeOptionsIntent(const FCredentials_BE& Credentials, const TArray& Transactions, TOptional CurrentTime) const @@ -952,6 +963,33 @@ void USequenceRPCManager::ForceOpenSessionInUse(const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const +{ + const TSuccessCallback OnResponse = [this, OnSuccess](const FString& OnResponse) + { + const FSeqLinkedWalletsResponse LinkedWallets = USequenceSupport::JSONStringToStruct(OnResponse); + OnSuccess(LinkedWallets); + }; + + this->SendIntent(this->BuildAPIUrl("GetLinkedWallets"),[this, Request](const TOptional& CurrentTime) + { + return USequenceSupport::StructToString(Request); + }, OnResponse, OnFailure); +} + +void USequenceRPCManager::RemoveLinkedWallet(const FSeqLinkedWalletRequest& Request, const TFunction& OnSuccess, const FFailureCallback& OnFailure) const +{ + const TSuccessCallback OnResponse = [this, OnSuccess](const FString& OnResponse) + { + OnSuccess(); + }; + + this->SendIntent(this->BuildAPIUrl("RemoveLinkedWallet"),[this, Request](const TOptional& CurrentTime) + { + return USequenceSupport::StructToString(Request); + }, OnResponse, OnFailure); +} + void USequenceRPCManager::FederateEmailSession(const FString& WalletIn, const FString& CodeIn, const TFunction& OnSuccess, const FFailureCallback& OnFailure) { this->UpdateWithStoredSessionWallet(); @@ -1145,4 +1183,4 @@ FTimespan USequenceRPCManager::GetTimeShiftFromResponse(const FString& DateHeade UE_LOG(LogTemp, Warning, TEXT("Failed to parse server time from date header: %s"), *DateHeader); return FTimespan::Zero(); -} +} \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/SequenceRPCManager.h b/Plugins/SequencePlugin/Source/SequencePlugin/Private/SequenceRPCManager.h index a00c09059..f69bf1bde 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/SequenceRPCManager.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/SequenceRPCManager.h @@ -49,7 +49,7 @@ class SEQUENCEPLUGIN_API USequenceRPCManager : public UObject */ bool PreserveSessionWallet = false; - inline const static FString WaaSVersion = FString(TEXT("1.0.0 (Unreal 1.5.1)")); + inline const static FString WaaSVersion = FString(TEXT("1.0.0 (Unreal 1.6.0)")); inline const static FString WaaSAuthenticatorIntentsUrlPath = TEXT("/rpc/WaasAuthenticator/SendIntent"); inline const static FString WaaSAuthenticatorRegisterUrlPath = TEXT("/rpc/WaasAuthenticator/RegisterSession"); @@ -276,6 +276,20 @@ class SEQUENCEPLUGIN_API USequenceRPCManager : public UObject * @param OnFailure Fires if there's an Authentication Issue */ void ForceOpenSessionInUse(const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure); + + /** + * GetLinkedWallets + * @param OnSuccess + * @param OnFailure + */ + void GetLinkedWallets(const FSeqLinkedWalletRequest& Request, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const; + + /** + * GetLinkedWallets + * @param OnSuccess + * @param OnFailure + */ + void RemoveLinkedWallet(const FSeqLinkedWalletRequest& Request, const TFunction& OnSuccess, const FFailureCallback& OnFailure) const; //Auth Calls// @@ -292,4 +306,4 @@ class SEQUENCEPLUGIN_API USequenceRPCManager : public UObject //Federation Calls// //RPC Calls// -}; +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Tests/MarketplaceCheckoutTests.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Tests/MarketplaceCheckoutTests.cpp new file mode 100644 index 000000000..c670c3ce4 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Tests/MarketplaceCheckoutTests.cpp @@ -0,0 +1,110 @@ +#include "MarketplaceCheckoutTests.h" + + +void FMarketplaceCheckoutTests::SubmitStepsAsTransaction(const TArray& Steps, USequenceWallet Wallet) +{ + if (Steps.IsEmpty()) + { + UE_LOG(LogTemp,Display,TEXT("Transaction Steps Is EMPTY")); + return; + } + + +} + +void FMarketplaceCheckoutTests::SeedWalletAndCreateListing(USequenceWallet Wallet, FString Address, + FString CurrencyToken) +{ +} + +void FMarketplaceCheckoutTests::FetchListingAndBuy(FString Address, USequenceWallet Wallet, int32 Retries, + const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure) +{ +} + +void FMarketplaceCheckoutTests::FetchListings(FString Collection, int64 ChainId, FSeqCollectiblesFilter Filter, + const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure) +{ +} + +void FMarketplaceCheckoutTests::FetchOfferAndSell(FString CollectionAddress, USequenceWallet Wallet, int32 Retries, + const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure) +{ +} + +void FMarketplaceCheckoutTests::FetchOffers(FString Collection, int64 ChainId, + const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure) +{ +} + +FSeqOrder FMarketplaceCheckoutTests::FindOrderCreatedByWallet(const FString& WalletAddress, + TArray CollectibleOrders) +{ + for (auto [TokenMetadata, Order] : CollectibleOrders) + { + if (Order.CreatedBy == WalletAddress) + { + return Order; + } + } + + return FSeqOrder(); +} + +void FMarketplaceCheckoutTests::FetchListingsForCollectible(FString Collection, FString TokenId, int64 ChainId, + FSeqCollectiblesFilter Filter, const TSuccessCallback>& OnSuccess, + const FFailureCallback& OnFailure) +{ +} + +// Public + +void FMarketplaceCheckoutTests::TestGetCheckoutOptions_Marketplace(int64 Amount) +{ +} + +void FMarketplaceCheckoutTests::TestGetCheckoutOptions_PrimarySale_Erc1155(TArray TokenIds, + TArray Amounts, FString ExpectedException) +{ +} + +void FMarketplaceCheckoutTests::TestGetCheckoutOptions_PrimarySale_Erc721(FString TokenId, int64 Amount, + FString ExpectedException) +{ +} + +void FMarketplaceCheckoutTests::TestGenerateBuyTransaction(int64 Amount) +{ +} + +void FMarketplaceCheckoutTests::TestGenerateSellTransaction(int64 Amount) +{ +} + +void FMarketplaceCheckoutTests::TestGenerateListingTransaction(int64 Amount) +{ +} + +void FMarketplaceCheckoutTests::TestGenerateOfferTransaction(int64 Amount) +{ +} + +void FMarketplaceCheckoutTests::TestGenerateOfferTransaction_NativeCurrency() +{ +} + +void FMarketplaceCheckoutTests::TestCreateListingAndBuyIt() +{ +} + +void FMarketplaceCheckoutTests::TestCreateOfferAndSellIt() +{ +} + +void FMarketplaceCheckoutTests::TestCancelOrder() +{ +} + +void FMarketplaceCheckoutTests::TestCreateListingAndBuyWithNativeCurrency() +{ +} diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Tests/MarketplaceCheckoutTests.h b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Tests/MarketplaceCheckoutTests.h new file mode 100644 index 000000000..ef3c9138b --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Tests/MarketplaceCheckoutTests.h @@ -0,0 +1,33 @@ +#pragma once +#include "Checkout/Structs/TransactionStep.h" +#include "Marketplace/Structs/SeqCollectibleOrder.h" +#include "Marketplace/Structs/SeqCollectiblesFilter.h" +#include "Sequence/SequenceAPI.h" + +class FMarketplaceCheckoutTests +{ + static void SubmitStepsAsTransaction(const TArray& Steps, USequenceWallet Wallet); + static void SeedWalletAndCreateListing(USequenceWallet Wallet, FString Address, FString CurrencyToken); + static void FetchListingAndBuy(FString Address, USequenceWallet Wallet, int32 Retries, const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure); + static void FetchListings(FString Collection, int64 ChainId, FSeqCollectiblesFilter Filter, const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure); + static void FetchOfferAndSell(FString CollectionAddress, USequenceWallet Wallet, int32 Retries, const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure); + static void FetchOffers(FString Collection, int64 ChainId, const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure); + static FSeqOrder FindOrderCreatedByWallet(const FString& WalletAddress, TArray CollectibleOrders); + static void FetchListingsForCollectible(FString Collection, FString TokenId, int64 ChainId, FSeqCollectiblesFilter Filter, const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure); + +public: + const FString TestWalletAddress = "0xD2eFbb2f18bfE3D265b26D2ACe83400A65335a07"; + + static void TestGetCheckoutOptions_Marketplace(int64 Amount); + static void TestGetCheckoutOptions_PrimarySale_Erc1155(TArray TokenIds, TArray Amounts, FString ExpectedException); + static void TestGetCheckoutOptions_PrimarySale_Erc721(FString TokenId, int64 Amount, FString ExpectedException); + static void TestGenerateBuyTransaction(int64 Amount); + static void TestGenerateSellTransaction(int64 Amount); + static void TestGenerateListingTransaction(int64 Amount); + static void TestGenerateOfferTransaction(int64 Amount); + static void TestGenerateOfferTransaction_NativeCurrency(); + static void TestCreateListingAndBuyIt(); + static void TestCreateOfferAndSellIt(); + static void TestCancelOrder(); + static void TestCreateListingAndBuyWithNativeCurrency(); +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Tests/TestSequenceAPI.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Tests/TestSequenceAPI.cpp index d410a5371..44bf9902b 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Tests/TestSequenceAPI.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Tests/TestSequenceAPI.cpp @@ -4,8 +4,12 @@ #include "Sequence/SequenceAPI.h" #include "SequenceAuthenticator.h" #include "ABI/ABI.h" +#include "Marketplace/Marketplace.h" +#include "Marketplace/Structs/SeqCollectibleOrder.h" +#include "Marketplace/Structs/SeqCollectiblesFilter.h" #include "Native/NativeOAuth.h" + /* * testing stack based implementation for memory faults */ @@ -462,3 +466,203 @@ void SequenceAPITest::TestLoadTransakUrl() Api->OpenTransakLink(); } } + +void SequenceAPITest::ListCurrencies(TFunction OnSuccess, + TFunction OnFailure) +{ + UMarketplace* Marketplace = NewObject(); + USequenceSupport* Support = NewObject(); + + Marketplace->ListCurrencies(Support->GetNetworkId(PolygonChain), [OnSuccess](FSeqListCurrenciesReturn Response) + { + FString Currencies = "Currencies: \n"; + + for(FSeqCurrency Currency : Response.Currencies) + { + Currencies += USequenceSupport::StructToString(Currency) + "\n"; + } + + OnSuccess(Currencies); + }, [OnFailure](FSequenceError Error) + { + OnFailure("Error: " + Error.Message, Error); + }); +} + +void SequenceAPITest::ListAllCollectibleListingsWithLowestPriceListingsFirst(TFunction OnSuccess, + TFunction OnFailure) +{ + UMarketplace* Marketplace = NewObject(); + USequenceSupport* Support = NewObject(); + + Marketplace->ListAllCollectibleListingsWithLowestPriceListingsFirst( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x44b3f42e2BF34F62868Ff9e9dAb7C2F807ba97Cb", + FSeqCollectiblesFilter::Empty(), + [OnSuccess](TArray Orders) { + OnSuccess("Orders: " + FString::FromInt(Orders.Num())); + }, + [OnFailure](FSequenceError Error) { + OnFailure("Error: " + Error.Message, Error); + } + ); +} + +void SequenceAPITest::ListAllCollectibleOffersWithHighestPricedOfferFirst(TFunction OnSuccess, + TFunction OnFailure) +{ + UMarketplace* Marketplace = NewObject(); + USequenceSupport* Support = NewObject(); + + Marketplace->ListAllCollectibleListingsWithLowestPriceListingsFirst( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x5e4bfd71236a21299d43f508dbb76cb7d0fd4e50", + FSeqCollectiblesFilter::Empty(), + [OnSuccess](TArray Orders) { + OnSuccess("Orders: " + FString::FromInt(Orders.Num())); + }, + [OnFailure](FSequenceError Error) { + OnFailure("Error: " + Error.Message, Error); + } + ); +} + +void SequenceAPITest::GetLowestPriceOfferForCollectible(TFunction OnSuccess, + TFunction OnFailure) +{ + UMarketplace* Marketplace = NewObject(); + USequenceSupport* Support = NewObject(); + + Marketplace->GetLowestPriceOfferForCollectible( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x079294e6ffec16234578c672fa3fbfd4b6c48640", + "1", + FSeqCollectiblesFilter::Empty(), + [OnSuccess](FSeqCollectibleOrder Order) { + OnSuccess("Order: " + Order.Order.OrderId); + }, + [OnFailure](FSequenceError Error) { + OnFailure("Error: " + Error.Message, Error); + } + ); +} + +void SequenceAPITest::GetHighestPriceOfferForCollectible(TFunction OnSuccess, + TFunction OnFailure) +{ + UMarketplace* Marketplace = NewObject(); + USequenceSupport* Support = NewObject(); + + Marketplace->GetHighestPriceOfferForCollectible( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x079294e6ffec16234578c672fa3fbfd4b6c48640", + "1", + FSeqCollectiblesFilter::Empty(), + [OnSuccess](FSeqCollectibleOrder Order) { + OnSuccess("Order: " + Order.Order.OrderId); + }, + [OnFailure](FSequenceError Error) { + OnFailure("Error: " + Error.Message, Error); + } + ); +} + +void SequenceAPITest::GetLowestPriceListingForCollectible(TFunction OnSuccess, + TFunction OnFailure) +{ + UMarketplace* Marketplace = NewObject(); + USequenceSupport* Support = NewObject(); + + Marketplace->GetLowestPriceListingForCollectible( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x079294e6ffec16234578c672fa3fbfd4b6c48640", + "1", + FSeqCollectiblesFilter::Empty(), + [OnSuccess](FSeqCollectibleOrder Order) { + OnSuccess("Order: " + Order.Order.OrderId); + }, + [OnFailure](FSequenceError Error) { + OnFailure("Error: " + Error.Message, Error); + } + ); +} + +void SequenceAPITest::GetHighestPriceListingForCollectible(TFunction OnSuccess, + TFunction OnFailure) +{ + UMarketplace* Marketplace = NewObject(); + USequenceSupport* Support = NewObject(); + + Marketplace->GetLowestPriceListingForCollectible( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x079294e6ffec16234578c672fa3fbfd4b6c48640", + "1", + FSeqCollectiblesFilter::Empty(), + [OnSuccess](FSeqCollectibleOrder Order) { + OnSuccess("Order: " + Order.Order.OrderId); + }, + [OnFailure](FSequenceError Error) { + OnFailure("Error: " + Error.Message, Error); + } + ); +} + +void SequenceAPITest::ListAllListingsForCollectible(TFunction OnSuccess, + TFunction OnFailure) +{ + UMarketplace* Marketplace = NewObject(); + USequenceSupport* Support = NewObject(); + + Marketplace->ListAllListingsForCollectible( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x079294e6ffec16234578c672fa3fbfd4b6c48640", + "1", + FSeqCollectiblesFilter::Empty(), + [OnSuccess](TArray Orders) { + OnSuccess("Orders: " + FString::FromInt(Orders.Num())); + }, + [OnFailure](FSequenceError Error) { + OnFailure("Error: " + Error.Message, Error); + } + ); +} + +void SequenceAPITest::ListAllOffersForCollectible(TFunction OnSuccess, + TFunction OnFailure) +{ + UMarketplace* Marketplace = NewObject(); + USequenceSupport* Support = NewObject(); + + Marketplace->ListAllOffersForCollectible( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x079294e6ffec16234578c672fa3fbfd4b6c48640", + "1", + FSeqCollectiblesFilter::Empty(), + [OnSuccess](TArray Orders) { + OnSuccess("Orders: " + FString::FromInt(Orders.Num())); + }, + [OnFailure](FSequenceError Error) { + OnFailure("Error: " + Error.Message, Error); + } + ); +} + +void SequenceAPITest::GetFloorOrder(TFunction OnSuccess, + TFunction OnFailure) +{ + UMarketplace* Marketplace = NewObject(); + USequenceSupport* Support = NewObject(); + + Marketplace->GetFloorOrder( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x44b3f42e2BF34F62868Ff9e9dAb7C2F807ba97Cb", + FSeqCollectiblesFilter::Empty(), + [OnSuccess](FSeqCollectibleOrder Order) { + OnSuccess("Order: %s" + Order.Order.OrderId); + }, + [OnFailure](FSequenceError Error) { + OnFailure("Error: " + Error.Message, Error); + } + ); +} + diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Tests/TestSequenceAPI.h b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Tests/TestSequenceAPI.h index 7c390d63f..566e38b4d 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Tests/TestSequenceAPI.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Tests/TestSequenceAPI.h @@ -21,4 +21,17 @@ class SequenceAPITest static void GetUnfilteredFeeOptions(TFunction OnSuccess, TFunction OnFailure); static void GetSupportedCountries(const TSuccessCallback>& OnSuccess, const FFailureCallback& OnFailure); static void TestLoadTransakUrl(); + + // Market + static void ListCurrencies(TFunction OnSuccess, TFunction OnFailure); + static void ListAllCollectibleListingsWithLowestPriceListingsFirst(TFunction OnSuccess, TFunction OnFailure); + static void ListAllCollectibleOffersWithHighestPricedOfferFirst(TFunction OnSuccess, TFunction OnFailure); + static void GetLowestPriceOfferForCollectible(TFunction OnSuccess, TFunction OnFailure); + static void GetHighestPriceOfferForCollectible(TFunction OnSuccess, TFunction OnFailure); + static void GetLowestPriceListingForCollectible(TFunction OnSuccess, TFunction OnFailure); + static void GetHighestPriceListingForCollectible(TFunction OnSuccess, TFunction OnFailure); + static void ListAllListingsForCollectible(TFunction OnSuccess, TFunction OnFailure); + static void ListAllOffersForCollectible(TFunction OnSuccess, TFunction OnFailure); + static void GetFloorOrder(TFunction OnSuccess, TFunction OnFailure); + }; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/ERC1155SaleContract.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/ERC1155SaleContract.cpp index 6618d7e25..aa867a80d 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/ERC1155SaleContract.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/ERC1155SaleContract.cpp @@ -14,6 +14,15 @@ UERC1155SaleContract::UERC1155SaleContract(FString ContractAddress, FString Paym this->Data = Data; } +void UERC1155SaleContract::Initialize(FString _ContractAddress, FString _PaymentToken, int32 _MaxTotal, FString _Data) +{ + this->ContractAddress = _ContractAddress; + this->PaymentToken = _PaymentToken; + this->MaxTotal = _MaxTotal; + this->Data = _Data; +} + + FRawTransaction UERC1155SaleContract::MakePurchaseTransaction(const FString& ToAddress, const TArray& TokenIds, const TArray& Amounts, const TArray& Proof) { FString FunctionSignature = "mint(address,uint256[],uint256[],bytes,address,uint256,bytes32[])"; @@ -89,7 +98,7 @@ FContractCall UERC1155SaleContract::GetPaymentToken() FContractCall CallData; CallData.Data = TOptional(EncodedData.ToHex()); - CallData.To = FAddress::From(ContractAddress); + CallData.To = FAddress::From(ContractAddress.Mid(2, ContractAddress.Len())); return CallData; } @@ -102,7 +111,23 @@ FContractCall UERC1155SaleContract::GetGlobalSaleDetails() FContractCall CallData; CallData.Data = TOptional(EncodedData.ToHex()); - CallData.To = FAddress::From(ContractAddress); + CallData.To = FAddress::From(ContractAddress.Mid(2, ContractAddress.Len())); + + return CallData; +} + +FContractCall UERC1155SaleContract::GetTokenSaleDetails(long TokenID) +{ + FString FunctionSignature = "tokenSaleDetails(uint256)"; + TFixedABIData* TokenIDData = new TFixedABIData(ABI::Int32(TokenID)); + + TArray Arr; + Arr.Add(TokenIDData); + FUnsizedData EncodedData = ABI::Encode(FunctionSignature, Arr); + + FContractCall CallData; + CallData.Data = TOptional(EncodedData.ToHex()); + CallData.To = FAddress::From(ContractAddress.Mid(2, ContractAddress.Len())); return CallData; } diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/ERC20.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/ERC20.cpp index a675583ed..805e3d9a5 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/ERC20.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/ERC20.cpp @@ -1,5 +1,6 @@ #include "Types/ERC20.h" #include "ABI/ABI.h" +#include "Util/Log.h" UERC20::UERC20() { @@ -10,6 +11,11 @@ UERC20::UERC20(FString ContractAddress) this->ContractAddress = ContractAddress; } +void UERC20::Initialize(FString _contractAddress) +{ + this->ContractAddress = _contractAddress; +} + FRawTransaction UERC20::MakeGrantRoleTransaction(const FString& role,const FString& ToAddress) { FString FunctionSignature = "grantRole(bytes32,address)"; @@ -116,3 +122,35 @@ FRawTransaction UERC20::MakeBurnTransaction(const int32 Amount) return T; } + +FContractCall UERC20::MakeSymbolTransaction() +{ + FString FunctionSignature = "symbol()"; + TArray> Arr; + TOptional EncodedData = ABI::Encode(FunctionSignature, Arr); + FContractCall T; + + if (!EncodedData.IsSet()) + { + SEQ_LOG(Display, TEXT("Encoded data is invalid")); + return T; + } + + T.To = FAddress::From(ContractAddress.Mid(2, ContractAddress.Len())); + T.Data = TOptional(EncodedData.GetValue().ToHex()); + + return T; +} + +FContractCall UERC20::MakeDecimalsTransaction() +{ + FString FunctionSignature = "decimals()"; + TArray Arr; + FUnsizedData EncodedData = ABI::Encode(FunctionSignature, Arr); + + FContractCall T; + T.To = FAddress::From(ContractAddress); + T.Data = TOptional(EncodedData.ToHex()); + + return T; +} diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/ERC721SaleContract.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/ERC721SaleContract.cpp index 181667ac0..9d2a985ed 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/ERC721SaleContract.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/ERC721SaleContract.cpp @@ -65,6 +65,13 @@ FRawTransaction UERC721SaleContract::MakePurchaseTransaction(const FString& ToAd return T; } +void UERC721SaleContract::Initialize(FString _ContractAddress, FString _PaymentToken, int32 _MaxTotal, FString _Data) +{ + ContractAddress = _ContractAddress; + PaymentToken = _PaymentToken; + MaxTotal = _MaxTotal; + Data = _Data; +} FContractCall UERC721SaleContract::GetSaleDetails() { @@ -74,7 +81,7 @@ FContractCall UERC721SaleContract::GetSaleDetails() FContractCall CallData; CallData.Data = TOptional(EncodedData.ToHex()); - CallData.To = FAddress::From(ContractAddress); + CallData.To = FAddress::From(ContractAddress.Mid(2, ContractAddress.Len())); return CallData; } \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/SaleDetails.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/SaleDetails.cpp new file mode 100644 index 000000000..8459d2b30 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Types/SaleDetails.cpp @@ -0,0 +1,11 @@ +#include "Types/SaleDetails.h" + +void FSaleDetails::Initialize(FUnsizedData Data) +{ + // unpack unsized data into usable fields + Cost = 20000; + SupplyCap = 9999999999999; + StartTimeLong = 1723058097; + EndTimeLong = 2448832492; +} + diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/JsonBuilder.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/JsonBuilder.cpp index 8f2892282..e3c0481e4 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/JsonBuilder.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/JsonBuilder.cpp @@ -52,7 +52,6 @@ FJsonArray FJsonBuilder::AddArray(FString Name) FString FJsonBuilder::ToString() const { - auto x = 3; return FString("{") + StringValue + FString("}"); } diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/Log.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/Log.cpp index 5ad012182..3ec651fa8 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/Log.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/Log.cpp @@ -1,6 +1,6 @@ // Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. -#include "Log.h" +#include "Util/Log.h" DEFINE_LOG_CATEGORY(LogSequence); DEFINE_LOG_CATEGORY(LogSequenceEditor); diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/SequenceSupport.cpp b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/SequenceSupport.cpp index 093efe6f7..047d96c8a 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/SequenceSupport.cpp +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/SequenceSupport.cpp @@ -29,6 +29,17 @@ FString USequenceSupport::GetNetworkName(const ENetwork NetworkIn) return TEXT(""); } +ENetwork USequenceSupport::GetNetworkFromId(const int64 NetworkIdIn) +{ + if (NetworkIdToEnumMap.Contains(NetworkIdIn)) + { + return *NetworkIdToEnumMap.Find(NetworkIdIn); + } + + UE_LOG(LogTemp, Warning, TEXT("Network not found for Id: %lld"), NetworkIdIn); + return Ethereum; +} + FString USequenceSupport::GetNetworkNameForUrl(const int64 NetworkIdIn) { if (NetworkIdToUrlMap.Contains(NetworkIdIn)) @@ -39,6 +50,21 @@ FString USequenceSupport::GetNetworkNameForUrl(const int64 NetworkIdIn) return TEXT(""); } +FString USequenceSupport::GetNetworkSymbol(const ENetwork NetworkIn) +{ + if (NetworkEnumToSymbolMap.Contains(NetworkIn)) + { + return *NetworkEnumToSymbolMap.Find(NetworkIn); + } + UE_LOG(LogTemp, Warning, TEXT("Name not found for Id: %lld"), NetworkIn); + return TEXT(""); +} + +FString USequenceSupport::GetNetworkSymbol(const int64 NetworkIn) +{ + return GetNetworkSymbol(GetNetworkFromId(NetworkIn)); +} + bool USequenceSupport::IsNetworkIdSupported(const int64 NetworkIdIn) { return NetworkIdToNameMap.Contains(NetworkIdIn); diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Enums/CheckoutOptions.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Enums/CheckoutOptions.h new file mode 100644 index 000000000..b189d8913 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Enums/CheckoutOptions.h @@ -0,0 +1,11 @@ +#pragma once + +UENUM(Blueprintable) +enum class ECheckoutOptions : uint8 +{ + CryptoPurchase UMETA(DisplayName = "CryptoPurchase"), + SwapAndPay UMETA(DisplayName = "SwapAndPay"), + SardineCheckout UMETA(DisplayName = "SardineCheckout"), + TransferFundsViaQR UMETA(DisplayName = "TransferFundsViaQR"), + TransakOnramp UMETA(DisplayName = "TransakOnramp") +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Enums/StepType.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Enums/StepType.h new file mode 100644 index 000000000..ca0f2800a --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Enums/StepType.h @@ -0,0 +1,42 @@ +#pragma once +#include "StepType.generated.h" + +ENUM_RANGE_BY_COUNT(EStepType, 8) +UENUM(Blueprintable) +enum class EStepType : uint8 +{ + Unknown UMETA(DisplayName = "unknown"), + TokenApproval UMETA(DisplayName = "tokenApproval"), + Buy UMETA(DisplayName = "buy"), + Sell UMETA(DisplayName = "sell"), + CreateListing UMETA(DisplayName = "createListing"), + CreateOffer UMETA(DisplayName = "createOffer"), + SignEip712 UMETA(DisplayName = "signEIP712"), + SignEip191 UMETA(DisplayName = "signEIP191"), +}; + +UCLASS() +class SEQUENCEPLUGIN_API UStepType : public UObject +{ + GENERATED_BODY() + +public: + static EStepType GetStepTypeFromString(const FString& StepTypeString) + { + FText EnumDisplayText = FText::FromString(""); + for (const EStepType Val : TEnumRange()) + { + UEnum::GetDisplayValueAsText(Val, EnumDisplayText); + + if (UEnum::GetValueAsString(Val).Equals(StepTypeString) || EnumDisplayText.ToString().Equals(StepTypeString)) + { + return Val; + } + } + + // Fallback if nothing is found + constexpr EStepType StepType{ EStepType::Unknown }; + return StepType; + } +}; + diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/SequenceCheckout.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/SequenceCheckout.h new file mode 100644 index 000000000..17b832d83 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/SequenceCheckout.h @@ -0,0 +1,71 @@ +#pragma once +#include "Errors.h" +#include "Checkout/Structs/AdditionalFee.h" +#include "Checkout/Structs/CheckoutOptionsMarketplaceOrder.h" +#include "Checkout/Structs/GenerateTransactionResponse.h" +#include "Checkout/Structs/GetCheckoutOptionsResponse.h" +#include "Marketplace/Marketplace.h" +#include "Sequence/SequenceAPI.h" +#include "Sequence/Wallet_Enums.h" +#include "Structs/OrderData.h" + +#include "SequenceCheckout.generated.h" + +UDELEGATE(BlueprintAuthorityOnly) +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnGetCheckoutOptionsResponseSuccess, FGetCheckoutOptionsResponse, Response); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnGenerateTransactionResponseSuccess, FGenerateTransactionResponse, Response); + +UDELEGATE(BlueprintAuthorityOnly) +DECLARE_DYNAMIC_DELEGATE(FOnCheckoutFailure); + +UCLASS() +class SEQUENCEPLUGIN_API USequenceCheckout : public UObject +{ + GENERATED_BODY() + +private: + int64 ChainID; + + const FString Path = "/rpc/Marketplace/"; + + FString Url(const int64& TargetChainID,const FString& EndPoint) const; + static FString HostName(int64 TargetChainID); + void HTTPPost(const int64& TargetChainID,const FString& Endpoint,const FString& Args, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const; + static TArray AssembleOrderData(TArray Orders, int64 amount); + void GenerateBuyTransaction(const FString& WalletAddress, const TArray OrderDatas, FString CollectionContractAddress, EMarketplaceKind + MarketplaceKind, const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, TSuccessCallback + OnSuccess, FFailureCallback OnFailure) const; + +public: + // Constructor + USequenceCheckout(); + explicit USequenceCheckout(const int64& InChainID); + + template < typename T> FString BuildArgs(T StructIn) const; + + template < typename T > T BuildResponse(FString Text) const; + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void SetChainID(const int64& InChainID); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GetCheckoutOptions(const FString& WalletAddress, const TArray& Orders, int64 AdditionalFeeBps, FOnGetCheckoutOptionsResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GetCheckoutOptionsByOrders(const FString& WalletAddress, const TArray& Orders, const int64 AdditionalFeeBps, FOnGetCheckoutOptionsResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure)const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GenerateBuyTransaction(const FString& WalletAddress, const FSeqOrder& Order, const int64 Amount, const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; + void GenerateBuyTransaction(const FString& WalletAddress, const FSeqOrder& Order, const int64 Amount, const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, TSuccessCallback OnSuccess, FFailureCallback OnFailure) const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GenerateBuyTransactionMultipleOrders(const FString& WalletAddress, const TArray Orders, const int64 Amount, const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; + void GenerateBuyTransaction(const FString& WalletAddress, const TArray Orders, const int64 Amount, const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, TSuccessCallback OnSuccess, FFailureCallback OnFailure) const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GenerateSellTransaction(const FString& WalletAddress, const FSeqOrder& Order, const int64 Amount, const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GenerateListingTransaction(const FString& WalletAddress, const FString& CollectionAddress, const FString& TokenId, int64 Amount, EContractType ContractType, const FString& CurrencyTokenAddress, int64 PricePerToken, FDateTime Expiry, EOrderbookKind OrderbookKind, const EWalletKind WalletKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GenerateOfferTransaction(const FString& WalletAddress, const FString& CollectionAddress, const FString& TokenId, int64 Amount, EContractType ContractType, const FString& CurrencyTokenAddress, int64 PricePerToken, FDateTime Expiry, EOrderbookKind OrderbookKind, const EWalletKind WalletKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GenerateCancelTransaction(const FString& WalletAddress, const FString& CollectionAddress, const FString& OrderId, EMarketplaceKind MarketplaceKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GenerateCancelTransactionByOrder(const FString& WalletAddress, const FString& CollectionAddress, const FSeqOrder& Order, const EMarketplaceKind MarketplaceKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/AdditionalFee.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/AdditionalFee.h new file mode 100644 index 000000000..3ed3edbbf --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/AdditionalFee.h @@ -0,0 +1,37 @@ +#pragma once + +#include "AdditionalFee.Generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FAdditionalFee +{ + GENERATED_USTRUCT_BODY() +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Amount; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Receiver; + + FAdditionalFee() + { + } + + FAdditionalFee(FString Amount, FString Receiver) + { + this->Amount = Amount; + this->Receiver = Receiver; + } + + bool customGetter = true; + FString GetArgs() const + { + FString ReturnArgs = "{"; + + ReturnArgs += "\"amount\":\"" + Amount + "\","; + ReturnArgs += "\"receiver\":\"" + Receiver + "\""; + + ReturnArgs.Append("}"); // Close the JSON object + + return ReturnArgs; + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/CheckoutOptionsMarketplaceOrder.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/CheckoutOptionsMarketplaceOrder.h new file mode 100644 index 000000000..81dbee2f1 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/CheckoutOptionsMarketplaceOrder.h @@ -0,0 +1,46 @@ +#pragma once +#include "Marketplace/Marketplace_Enums.h" + +#include "CheckoutOptionsMarketplaceOrder.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FCheckoutOptionsMarketplaceOrder +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString ContractAddress; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString OrderId; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + TEnumAsByte Marketplace; + + FCheckoutOptionsMarketplaceOrder() + { + this->ContractAddress = ""; + this->OrderId = ""; + this->Marketplace = EMarketplaceKind::UNKNOWN_MK; + } + + FCheckoutOptionsMarketplaceOrder(FString ContractAddress, FString OrderId, const EMarketplaceKind Marketplace) + { + this->ContractAddress = ContractAddress; + this->OrderId = OrderId; + this->Marketplace = Marketplace; + } + + bool customGetter = true; + FString GetArgs() const + { + FString ReturnArgs = "{"; + + ReturnArgs += "\"contractAddress\":\"" + ContractAddress + "\","; + ReturnArgs += "\"orderId\":\"" + OrderId + "\","; + ReturnArgs += "\"marketplace\":\"" + UEnum::GetValueAsString(Marketplace) + "\""; + + ReturnArgs.Append("}"); // Close the JSON object + + return ReturnArgs; + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/CreateReq.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/CreateReq.h new file mode 100644 index 000000000..2656466f0 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/CreateReq.h @@ -0,0 +1,64 @@ +#pragma once + +#include "CreateReq.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FCreateReq +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString TokenId; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Quantity; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Expiry; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString CurrencyAddress; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString PricePerToken; + + FCreateReq() + { + this->TokenId = ""; + this->Quantity = ""; + this->Expiry = ""; + this->CurrencyAddress = ""; + this->PricePerToken = ""; + } + + FCreateReq(FString TokenId, FString Quantity, FString Expiry, FString CurrencyAddress, FString PricePerToken) + { + this->TokenId = TokenId; + this->Quantity = Quantity; + this->Expiry = Expiry; + this->CurrencyAddress = CurrencyAddress; + this->PricePerToken = PricePerToken; + } + + bool customGetter = true; + FString GetArgs() const + { + FString ReturnArgs = "{"; + + ReturnArgs += "\"tokenId\":\"" + TokenId + "\","; + ReturnArgs += "\"quantity\":\"" + Quantity + "\","; + ReturnArgs += "\"expiry\":\"" + Expiry + "\","; + ReturnArgs += "\"currencyAddress\":\"" + CurrencyAddress + "\","; + ReturnArgs += "\"pricePerToken\":\"" + PricePerToken + "\""; + + ReturnArgs.Append("}"); // Close the JSON object + + return ReturnArgs; + } + + void Setup(FJsonObject& JSON_In) + { + TokenId = JSON_In.GetStringField(TEXT("tokenId")); + Quantity = JSON_In.GetStringField(TEXT("quantity")); + Expiry = JSON_In.GetStringField(TEXT("expiry")); + CurrencyAddress = JSON_In.GetStringField(TEXT("currencyAddress")); + PricePerToken = JSON_In.GetStringField(TEXT("pricePerToken")); + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/Domain.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/Domain.h new file mode 100644 index 000000000..5f273d077 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/Domain.h @@ -0,0 +1,78 @@ +#pragma once + +#include "Domain.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FDomain +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Name; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Version; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + int64 ChainId; + // Chain enum? + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString VerifyingContract; + + FDomain() + { + this->Name = ""; + this->Version = ""; + this->ChainId = 0; + this->VerifyingContract = ""; + } + + FDomain(FString Name, FString Version, const uint64 ChainId, FString VerifyingContract) + { + this->Name = Name; + this->Version = Version; + this->ChainId = ChainId; + this->VerifyingContract = VerifyingContract; + } + + bool customGetter = true; + FString GetArgs() const + { + FString ReturnArgs = "{"; + + ReturnArgs += "\"name\":\"" + Name + "\","; + ReturnArgs += "\"version\":\"" + Version + "\","; + ReturnArgs += "\"chainId\":\"" + FString::Printf(TEXT("%lld"), ChainId) + "\","; + ReturnArgs += "\"verifyingContract\":\"" + VerifyingContract + "\""; + + + ReturnArgs.Append("}"); // Close the JSON object + + return ReturnArgs; + } + + void Setup(const FJsonObject& JSON_In) + { + FString ReturnStringValue; + int64 ReturnIntegerValue; + + if (JSON_In.TryGetStringField(TEXT("name"), ReturnStringValue)) + { + this->Name = ReturnStringValue; + } + + if (JSON_In.TryGetStringField(TEXT("version"), ReturnStringValue)) + { + this->Version = ReturnStringValue; + } + + if (JSON_In.TryGetNumberField(TEXT("chainId"), ReturnIntegerValue)) + { + this->ChainId = ReturnIntegerValue; + } + + if (JSON_In.TryGetStringField(TEXT("verifyingContract"), ReturnStringValue)) + { + this->VerifyingContract = ReturnStringValue; + } + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateBuyTransaction.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateBuyTransaction.h new file mode 100644 index 000000000..e06facd82 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateBuyTransaction.h @@ -0,0 +1,103 @@ +#pragma once +#include "AdditionalFee.h" +#include "OrderData.h" +#include "Marketplace/Marketplace_Enums.h" +#include "Sequence/Wallet_Enums.h" + +#include "GenerateBuyTransaction.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FGenerateBuyTransaction +{ + GENERATED_USTRUCT_BODY() + +private: + FString GetOrdersDataArgs() const + { + FString OrdersDataArgs = ""; + + for (uint16 i = 0; i < OrdersData.Num(); i++) + { + if (i < OrdersData.Num() - 1) + { + OrdersDataArgs += OrdersData[i].GetArgs() + ","; + } + else + { + OrdersDataArgs += OrdersData[i].GetArgs(); + } + } + + return OrdersDataArgs; + } + + FString GetAdditionalFeesArgs() const + { + FString AdditionalFeesArgs = ""; + + for (uint16 i = 0; i < AdditionalFees.Num(); i++) + { + if (i < OrdersData.Num() - 1) + { + AdditionalFeesArgs += AdditionalFees[i].GetArgs() + ","; + } + else + { + AdditionalFeesArgs += AdditionalFees[i].GetArgs(); + } + } + + return AdditionalFeesArgs; + } + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString CollectionAddress; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Buyer; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + TEnumAsByte Marketplace; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + TArray OrdersData; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + TArray AdditionalFees; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + EWalletKind WalletType; + + FGenerateBuyTransaction() + { + this->CollectionAddress = ""; + this->Buyer = ""; + this->Marketplace = EMarketplaceKind::SEQUENCE_MARKETPLACE_V2; + this->OrdersData = TArray(); + this->AdditionalFees = TArray(); + this->WalletType = EWalletKind::Unknown; + } + + FGenerateBuyTransaction(FString CollectionAddress, FString Buyer, const EMarketplaceKind Marketplace, const TArray& OrdersData, const TArray& AdditionalFees, const EWalletKind WalletType) + { + this->CollectionAddress = CollectionAddress; + this->Buyer = Buyer; + this->Marketplace = Marketplace; + this->OrdersData = OrdersData; + this->AdditionalFees = AdditionalFees; + this->WalletType = WalletType; + } + + bool customGetter = true; + FString GetArgs() const + { + FString ReturnArgs = "{"; + + ReturnArgs += "\"collectionAddress\":\"" + CollectionAddress + "\","; + ReturnArgs += "\"buyer\":\"" + Buyer + "\","; + ReturnArgs += "\"marketplace\":\"" + UEnum::GetValueAsString(Marketplace) + "\","; + ReturnArgs += "\"OrdersData\":[" + GetOrdersDataArgs() + "],"; + ReturnArgs += "\"AdditionalFees\":[" + GetAdditionalFeesArgs() + "],"; + ReturnArgs += "\"WalletType\":\"" + UEnum::GetValueAsString(WalletType) + "\""; + + ReturnArgs.Append("}"); // Close the JSON object + + return ReturnArgs; + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateCancelTransactionRequest.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateCancelTransactionRequest.h new file mode 100644 index 000000000..e3a8058f9 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateCancelTransactionRequest.h @@ -0,0 +1,51 @@ +#pragma once +#include "Marketplace/Marketplace_Enums.h" + +#include "GenerateCancelTransactionRequest.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FGenerateCancelTransactionRequest +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString CollectionAddress; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Maker; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + TEnumAsByte Marketplace; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString OrderId; + + FGenerateCancelTransactionRequest() + { + this->CollectionAddress = ""; + this->Maker = ""; + this->Marketplace = UNKNOWN_MK; + this->OrderId = ""; + } + + FGenerateCancelTransactionRequest(FString CollectionAddress, FString Maker, EMarketplaceKind Marketplace, FString OrderId) + { + this->CollectionAddress = CollectionAddress; + this->Maker = Maker; + this->Marketplace = Marketplace; + this->OrderId = OrderId; + } + + bool customGetter = true; + FString GetArgs() const + { + FString ReturnArgs = "{"; + + ReturnArgs += "\"collectionAddress\":\"" + CollectionAddress + "\","; + ReturnArgs += "\"maker\":\"" + Maker + "\","; + ReturnArgs += "\"marketplace\":\"" + UEnum::GetValueAsString(Marketplace) + "\","; + ReturnArgs += "\"orderId\":\"" + OrderId + "\""; + + ReturnArgs.Append("}"); // Close the JSON object + + return ReturnArgs; + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateListingTransactionArgs.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateListingTransactionArgs.h new file mode 100644 index 000000000..2a4674e66 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateListingTransactionArgs.h @@ -0,0 +1,64 @@ +#pragma once +#include "CreateReq.h" +#include "Indexer/Indexer_Enums.h" +#include "Marketplace/Marketplace_Enums.h" +#include "Sequence/Wallet_Enums.h" + +#include "GenerateListingTransactionArgs.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FGenerateListingTransactionArgs +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString CollectionAddress; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Owner; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + TEnumAsByte ContractType; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + EOrderbookKind Orderbook; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FCreateReq Listing; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + EWalletKind WalletType; + + FGenerateListingTransactionArgs() + { + this->CollectionAddress = ""; + this->Owner = ""; + this->ContractType = UNKOWN_CT; + this->Orderbook = EOrderbookKind::Unknown; + this->Listing = FCreateReq(); + this->WalletType = EWalletKind::Sequence; + } + + FGenerateListingTransactionArgs(FString CollectionAddress, FString Owner, EContractType ContractType, EOrderbookKind OrderbookKind, FCreateReq Listing, EWalletKind WalletType) + { + this->CollectionAddress = CollectionAddress; + this->Owner = Owner; + this->ContractType = ContractType; + this->Orderbook = OrderbookKind; + this->Listing = Listing; + this->WalletType = WalletType; + } + + bool customGetter = true; + FString GetArgs() const + { + FString ReturnArgs = "{"; + + ReturnArgs += "\"collectionAddress\":\"" + CollectionAddress + "\","; + ReturnArgs += "\"owner\":\"" + Owner + "\","; + ReturnArgs += "\"contractType\":\"" + UEnum::GetValueAsString(ContractType) + "\","; + ReturnArgs += "\"orderbook\":\"" + UMarketplaceEnumsExtensions::AsString(Orderbook) + "\","; + ReturnArgs += "\"listing\":" + Listing.GetArgs() + ","; + ReturnArgs += "\"walletType\":\"" + UMarketplaceWalletKindExtensions::AsString(WalletType) + "\""; + + ReturnArgs.Append("}");// Close the JSON object + + return ReturnArgs; + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateOfferTransactionArgs.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateOfferTransactionArgs.h new file mode 100644 index 000000000..1f1139713 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateOfferTransactionArgs.h @@ -0,0 +1,64 @@ +#pragma once +#include "CreateReq.h" +#include "Indexer/Indexer_Enums.h" +#include "Marketplace/Marketplace_Enums.h" +#include "Sequence/Wallet_Enums.h" + +#include "GenerateOfferTransactionArgs.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FGenerateOfferTransactionArgs +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString CollectionAddress; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Maker; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + TEnumAsByte ContractType; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + EOrderbookKind Orderbook; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FCreateReq Offer; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + EWalletKind WalletType; + + FGenerateOfferTransactionArgs() + { + this->CollectionAddress = ""; + this->Maker = ""; + this->ContractType = EContractType::UNKOWN_CT; + this->Orderbook = EOrderbookKind::Unknown; + this->Offer = FCreateReq(); + this->WalletType = EWalletKind::Sequence; + } + + FGenerateOfferTransactionArgs(FString CollectionAddress, FString Maker, const EContractType ContractType, const EOrderbookKind Orderbook, const FCreateReq& Offer, const EWalletKind WalletType) + { + this->CollectionAddress = CollectionAddress; + this->Maker = Maker; + this->ContractType = ContractType; + this->Orderbook = Orderbook; + this->Offer = Offer; + this->WalletType = WalletType; + } + + bool customGetter = true; + FString GetArgs() const + { + FString ReturnArgs = "{"; + + ReturnArgs += "\"collectionAddress\":\"" + CollectionAddress + "\","; + ReturnArgs += "\"maker\":\"" + Maker + "\","; + ReturnArgs += "\"contractType\":\"" + UEnum::GetValueAsString(ContractType) + "\","; + ReturnArgs += "\"orderbook\":\"" + UEnum::GetValueAsString(Orderbook) + "\","; + ReturnArgs += "\"offer\":\"" + Offer.GetArgs() + "\","; + ReturnArgs += "\"WalletType\":\"" + UEnum::GetValueAsString(WalletType) + "\""; + + ReturnArgs.Append("}"); // Close the JSON object + + return ReturnArgs; + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateSellTransaction.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateSellTransaction.h new file mode 100644 index 000000000..156a5a1ce --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateSellTransaction.h @@ -0,0 +1,103 @@ +#pragma once +#include "AdditionalFee.h" +#include "OrderData.h" +#include "Marketplace/Marketplace_Enums.h" +#include "Sequence/Wallet_Enums.h" + +#include "GenerateSellTransaction.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FGenerateSellTransaction +{ + GENERATED_USTRUCT_BODY() + +private: + FString GetOrdersDataArgs() const + { + FString OrdersDataArgs = ""; + + for (uint16 i = 0; i < OrdersData.Num(); i++) + { + if (i < OrdersData.Num() - 1) + { + OrdersDataArgs += OrdersData[i].GetArgs() + ","; + } + else + { + OrdersDataArgs += OrdersData[i].GetArgs(); + } + } + + return OrdersDataArgs; + } + + FString GetAdditionalFeesArgs() const + { + FString AdditionalFeesArgs = ""; + + for (uint16 i = 0; i < AdditionalFees.Num(); i++) + { + if (i < OrdersData.Num() - 1) + { + AdditionalFeesArgs += AdditionalFees[i].GetArgs() + ","; + } + else + { + AdditionalFeesArgs += AdditionalFees[i].GetArgs(); + } + } + + return AdditionalFeesArgs; + } + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString CollectionAddress; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Seller; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + TEnumAsByte Marketplace; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + TArray OrdersData; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + TArray AdditionalFees; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + EWalletKind WalletType; + + FGenerateSellTransaction() + { + this->CollectionAddress = ""; + this->Seller = ""; + this->Marketplace = EMarketplaceKind::SEQUENCE_MARKETPLACE_V2; + this->OrdersData = TArray(); + this->AdditionalFees = TArray(); + this->WalletType = EWalletKind::Unknown; + } + + FGenerateSellTransaction(FString CollectionAddress, FString Seller, const EMarketplaceKind Marketplace, const TArray& OrdersData, const TArray& AdditionalFees, const EWalletKind WalletType) + { + this->CollectionAddress = CollectionAddress; + this->Seller = Seller; + this->Marketplace = Marketplace; + this->OrdersData = OrdersData; + this->AdditionalFees = AdditionalFees; + this->WalletType = WalletType; + } + + bool customGetter = true; + FString GetArgs() const + { + FString ReturnArgs = "{"; + + ReturnArgs += "\"collectionAddress\":\"" + CollectionAddress + "\","; + ReturnArgs += "\"seller\":\"" + Seller + "\","; + ReturnArgs += "\"marketplace\":\"" + UEnum::GetValueAsString(Marketplace) + "\","; + ReturnArgs += "\"OrdersData\":[" + GetOrdersDataArgs() + "],"; + ReturnArgs += "\"AdditionalFees\":[" + GetAdditionalFeesArgs() + "],"; + ReturnArgs += "\"WalletType\":\"" + UEnum::GetValueAsString(WalletType) + "\""; + + ReturnArgs.Append("}"); // Close the JSON object + + return ReturnArgs; + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateTransactionResponse.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateTransactionResponse.h new file mode 100644 index 000000000..337aefb3c --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GenerateTransactionResponse.h @@ -0,0 +1,71 @@ +#pragma once +#include "TransactionStep.h" +#include "Util/SequenceSupport.h" + +#include "GenerateTransactionResponse.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FGenerateTransactionResponse +{ + GENERATED_USTRUCT_BODY() + +private: + FString GetEachStepArg() + { + FString StepArgs = ""; + + for (uint16 StepIndex = 0; StepIndex < Steps.Num(); StepIndex++) + { + if (StepIndex < Steps.Num() - 1) + { + StepArgs += Steps[StepIndex].GetArgs() + ","; + } + else + { + StepArgs += Steps[StepIndex].GetArgs(); + } + } + + return StepArgs; + } + + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + TArray Steps; + + FGenerateTransactionResponse() + { + this->Steps = TArray(); + } + + FGenerateTransactionResponse(const TArray& Steps) + { + this->Steps = Steps; + } + + bool customConstructor = false; + + void Construct(FJsonObject JSON_In) + { + } + + void Setup(const FJsonObject& JSON_In) + { + if (JSON_In.HasField(TEXT("steps"))) + { + const TArray>& StepsArray = JSON_In.GetArrayField(TEXT("steps")); + Steps.Empty(); + for (int32 i = 0; i < StepsArray.Num(); ++i) + { + if (const TSharedPtr StepValue = StepsArray[i]; StepValue->Type == EJson::Object) + { + FTransactionStep Step; + TSharedPtr StepJsonObject = StepValue->AsObject();//USequenceSupport::JsonStringToObject(StepValue->AsString()); + Step.Setup(*StepJsonObject); + Steps.Add(Step); + } + } + } + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GetCheckoutOptionsArgs.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GetCheckoutOptionsArgs.h new file mode 100644 index 000000000..11f0bf291 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GetCheckoutOptionsArgs.h @@ -0,0 +1,66 @@ +#pragma once +#include "CheckoutOptionsMarketplaceOrder.h" + +#include "GetCheckoutOptionsArgs.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FGetCheckoutOptionsArgs +{ + GENERATED_USTRUCT_BODY() + +private: + FString GetOrdersDataArgs() const + { + FString OrdersDataArgs = ""; + + for (uint16 i = 0; i < Orders.Num(); i++) + { + if (i < Orders.Num() - 1) + { + OrdersDataArgs += Orders[i].GetArgs() + ","; + } + else + { + OrdersDataArgs += Orders[i].GetArgs(); + } + } + + return OrdersDataArgs; + } + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString WalletAddress; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + TArray Orders; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + int64 AdditionalFee; + + FGetCheckoutOptionsArgs() + { + this->WalletAddress = ""; + this->Orders = TArray(); + this->AdditionalFee = 0; + } + + FGetCheckoutOptionsArgs(FString WalletAddress, const TArray& Orders, const int64 AdditionalFee) + { + this->WalletAddress = WalletAddress; + this->Orders = Orders; + this->AdditionalFee = AdditionalFee; + } + + bool customGetter = true; + FString GetArgs() const + { + FString ReturnArgs = "{"; + + ReturnArgs += "\"walletAddress\":\"" + WalletAddress + "\","; + ReturnArgs += "\"orders\":[" + GetOrdersDataArgs() + "],"; + ReturnArgs += "\"additionalFee\":\"" + FString::Printf(TEXT("%lld"), AdditionalFee) + "\""; + + ReturnArgs.Append("}"); // Close the JSON object + + return ReturnArgs; + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GetCheckoutOptionsResponse.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GetCheckoutOptionsResponse.h new file mode 100644 index 000000000..0de2cfe0d --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/GetCheckoutOptionsResponse.h @@ -0,0 +1,38 @@ +#pragma once +#include "Checkout/Enums/CheckoutOptions.h" + +#include "GetCheckoutOptionsResponse.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FGetCheckoutOptionsResponse +{ + GENERATED_USTRUCT_BODY() + + public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + ECheckoutOptions Options; + + FGetCheckoutOptionsResponse() + { + this->Options = ECheckoutOptions::CryptoPurchase; + } + + FGetCheckoutOptionsResponse(const ECheckoutOptions Options) + { + this->Options = Options; + } + + bool customConstructor = false; + + void Construct(FJsonObject JSON_In) + { + } + + void Setup(const FJsonObject& JSON_In) + { + if (JSON_In.HasField(TEXT("options"))) + { + this->Options = static_cast(JSON_In.GetIntegerField(TEXT("options"))); + } + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/OrderData.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/OrderData.h new file mode 100644 index 000000000..619afe1b0 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/OrderData.h @@ -0,0 +1,40 @@ +#pragma once + +#include "OrderData.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FOrderData +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString OrderId; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Quantity; + + FOrderData() + { + OrderId = ""; + Quantity = ""; + } + + FOrderData(FString OrderId, FString Quantity) + { + this->OrderId = OrderId; + this->Quantity = Quantity; + } + + bool customGetter = true; + FString GetArgs() const + { + FString ReturnArgs = "{"; + + ReturnArgs += "\"orderId\":\"" + OrderId + "\","; + ReturnArgs += "\"quantity\":\"" + Quantity + "\""; + + ReturnArgs.Append("}"); // Close the JSON object + + return ReturnArgs; + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/PostRequest.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/PostRequest.h new file mode 100644 index 000000000..191326b2c --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/PostRequest.h @@ -0,0 +1,63 @@ +#pragma once + +#include "PostRequest.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FPostRequest +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString EndPoint; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Method; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Body; + + FPostRequest() + { + EndPoint = ""; + Method = ""; + Body = ""; + } + + FPostRequest(FString EndPoint, FString Method, FString Body) + { + this->EndPoint = EndPoint; + this->Method = Method; + this->Body = Body; + } + + bool customGetter = true; + FString GetArgs() const + { + FString ReturnArgs = "{"; + + ReturnArgs += "\"endPoint\":\"" + EndPoint + "\","; + ReturnArgs += "\"method\":\"" + Method + "\","; + ReturnArgs += "\"body\":\"" + Body + "\""; + + ReturnArgs.Append("}"); // Close the JSON object + + return ReturnArgs; + } + + void Setup(const FJsonObject& JSON_In) + { + if (FString ReturnEndPointString; JSON_In.TryGetStringField(TEXT("endPoint"), ReturnEndPointString)) + { + EndPoint = ReturnEndPointString; + } + + if (FString ReturnMethodString; JSON_In.TryGetStringField(TEXT("method"), ReturnMethodString)) + { + Method = ReturnMethodString; + } + + if (FString ReturnBodyString; JSON_In.TryGetStringField(TEXT("body"), ReturnBodyString)) + { + Body = ReturnBodyString; + } + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/TransactionSignature.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/TransactionSignature.h new file mode 100644 index 000000000..b0fa4f917 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/TransactionSignature.h @@ -0,0 +1,85 @@ +#pragma once +#include "Domain.h" +#include "Util/SequenceSupport.h" + +#include "TransactionSignature.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FTransactionSignature +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FDomain Domain; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Types; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString PrimaryType; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Value; + + FTransactionSignature() + { + Domain = FDomain(); + Types = ""; + PrimaryType = ""; + Value = ""; + } + + FTransactionSignature(const FDomain& Domain, FString Types, FString PrimaryType, FString Value) + { + this->Domain = Domain; + this->Types = Types; + this->PrimaryType = PrimaryType; + this->Value = Value; + } + + bool customGetter = true; + FString GetArgs() const + { + FString ReturnArgs = "{"; + + ReturnArgs += "\"domain\":" + Domain.GetArgs() + ","; + ReturnArgs += "\"types\":\"" + Types + "\","; + ReturnArgs += "\"primaryType\":\"" + PrimaryType + "\","; + ReturnArgs += "\"value\":\"" + Value + "\""; + + + ReturnArgs.Append("}"); // Close the JSON object + + return ReturnArgs; + } + + void Setup(const FJsonObject& JSON_In) + { + // Setup Domain + if (JSON_In.HasField(TEXT("domain"))) + { + const TSharedPtr DomainValue = JSON_In.TryGetField(TEXT("domain")); + if (DomainValue != nullptr) + { + const TSharedPtr DomainJsonObject = DomainValue->AsObject(); //USequenceSupport::JsonStringToObject(DomainValue->AsString()); + if (DomainJsonObject != nullptr) + { + Domain.Setup(*DomainJsonObject); + } + } + } + + if (FString ReturnTypesString; JSON_In.TryGetStringField(TEXT("types"), ReturnTypesString)) + { + Types = ReturnTypesString; + } + + if (FString ReturnPrimaryTypeString; JSON_In.TryGetStringField(TEXT("primaryType"), ReturnPrimaryTypeString)) + { + PrimaryType = ReturnPrimaryTypeString; + } + + if (FString ReturnValueString; JSON_In.TryGetStringField(TEXT("value"), ReturnValueString)) + { + Value = ReturnValueString; + } + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/TransactionStep.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/TransactionStep.h new file mode 100644 index 000000000..afc9aeac0 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Checkout/Structs/TransactionStep.h @@ -0,0 +1,138 @@ +#pragma once +#include "PostRequest.h" +#include "TransactionSignature.h" +#include "Checkout/Enums/StepType.h" +#include "Sequence/SequenceAPI.h" +#include "Sequence/Transactions.h" +#include "Util/SequenceSupport.h" + +#include "TransactionStep.generated.h" + +UDELEGATE(BlueprintAuthorityOnly) +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnGetSequenceTransactionResponseSuccess, FSeqTransactionResponse_Data, Response); +DECLARE_DYNAMIC_DELEGATE(FOnGetSeqTransactionFailure); + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FTransactionStep +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(BlueprintReadWrite, EditAnywhere) + EStepType Id; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Data; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString To; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Value; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FTransactionSignature Signature; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FPostRequest Post; + + FTransactionStep() + { + this->Id = EStepType::Unknown; + this->Data = ""; + this->To = ""; + this->Value = ""; + this->Signature = FTransactionSignature(); + this->Post = FPostRequest(); + } + + FTransactionStep(const EStepType Id, FString Data, FString To, FString Value, const FTransactionSignature& Signature, const FPostRequest& Post) + { + this->Id = Id; + this->Data = Data; + this->To = To; + this->Value = Value; + this->Signature = Signature; + this->Post = Post; + } + + bool customGetter = true; + FString GetArgs() const + { + FString ReturnArgs = "{"; + + ReturnArgs += "\"id\":\"" + UEnum::GetValueAsString(Id) + "\","; + ReturnArgs += "\"data\":\"" + Data + "\","; + ReturnArgs += "\"to\":\"" + To + "\","; + ReturnArgs += "\"value\":\"" + Value + "\","; + ReturnArgs += "\"signature\":" + Signature.GetArgs() + ","; + ReturnArgs += "\"post\":" + Post.GetArgs(); + + ReturnArgs.Append("}"); // Close the JSON object + + return ReturnArgs; + } + + void Setup(const FJsonObject& JSON_In) + { + if (JSON_In.TryGetField(TEXT("id"))) + { + Id = UStepType::GetStepTypeFromString(JSON_In.GetStringField(TEXT("id"))); + } + + Data = JSON_In.GetStringField(TEXT("data")); + To = JSON_In.GetStringField(TEXT("to")); + Value = JSON_In.GetStringField(TEXT("value")); + // Setup Signature + if (JSON_In.HasField(TEXT("signature"))) + { + const TSharedPtr SignatureValue = JSON_In.TryGetField(TEXT("signature")); + if (SignatureValue != nullptr) + { + TSharedPtr SignatureJsonObject = SignatureValue->AsObject(); + Signature.Setup(*SignatureJsonObject); + } + } + // Setup Post Request + if (JSON_In.HasField(TEXT("post"))) + { + const TSharedPtr PostRequestValue = JSON_In.TryGetField(TEXT("post")); + + if (PostRequestValue != nullptr) + { + TSharedPtr PostRequestJsonObject = PostRequestValue->AsObject(); + Post.Setup(*PostRequestJsonObject); + } + } + } + + static TArray AsTransactionArray(const TArray& Steps) + { + if (Steps.IsEmpty()) + { + UE_LOG(LogTemp, Error, TEXT("Steps cannot be null or empty")); + } + + TArray Transactions; + Transactions.Reserve(Steps.Num()); + for (int i = 0; i < Steps.Num(); i++) + { + Transactions[i] = TUnion( + FRawTransaction(Steps[i].To, Steps[i].Value, Steps[i].Data)); + } + + return Transactions; + } + + static FTransactionStep ExtractBuyStep(const TArray& Steps) + { + FTransactionStep Result; + + const int64 Length = Steps.Num(); + for (int i = 0; i < Length; i++) + { + if (Steps[i].Id == EStepType::Buy) + { + Result = Steps[i]; + break; + } + } + + return Result; + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Errors.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Errors.h index 1d3cb83dd..e487439e3 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Errors.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Errors.h @@ -1,5 +1,6 @@ // Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. #pragma once +#include "Http.h" #include "Templates/ValueOrError.h" #include "Containers/UnrealString.h" @@ -20,9 +21,11 @@ enum EErrorType class SEQUENCEPLUGIN_API FSequenceError { public: - FSequenceError(EErrorType Type, FString Message); + FSequenceError(EErrorType Type, const FString& Message); + FSequenceError(EErrorType Type, const FHttpResponsePtr& Response, const FString& Message); + FHttpResponsePtr Response; FString Message; EErrorType Type; }; -template using TResult = TValueOrError; +template using TResult = TValueOrError; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Indexer/Structs/SeqTokenMetaData.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Indexer/Structs/SeqTokenMetaData.h index 319d8c194..1a8eb0827 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Indexer/Structs/SeqTokenMetaData.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Indexer/Structs/SeqTokenMetaData.h @@ -97,7 +97,7 @@ struct SEQUENCEPLUGIN_API FSeqTokenMetaData */ void Setup(FJsonObject json_in) {//the json object we expect here will be a mirror of what is above EXCEPT we will be snipping out what we need! - + FString tokenIdString; if (json_in.TryGetStringField(TEXT("tokenId"), tokenIdString)) { diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Integrators/SardineCheckoutBP.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Integrators/SardineCheckoutBP.h new file mode 100644 index 000000000..d598d5d04 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Integrators/SardineCheckoutBP.h @@ -0,0 +1,84 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Checkout/SequenceCheckout.h" +#include "Subsystems/GameInstanceSubsystem.h" +#include "Sequence/SequenceResponseIntent.h" +#include "Marketplace/Sardine/SardineCheckout.h" +#include "SardineCheckoutBP.generated.h" + +UDELEGATE(BlueprintAuthorityOnly) +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnCheckSardineWhiteListStatus, bool, Response); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnSardineGetQuote, FSardineQuote, Response); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnSardineGetClientToken, FString, Response); +DECLARE_DYNAMIC_DELEGATE(FOnRampAsync); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnSardineGetNFTCheckoutToken, FSardineNFTCheckout, Response); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnSardineGetNFTCheckoutOrderStatus, FSardineOrder, Response); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnSardineGetSupportedRegions, TArray, Response); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnSardineGetSupportedFiatCurrencies, TArray, Response); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnSardineGetSupportedTokens, TArray, Response); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnSardineGetEnabledTokens, TArray, Response); + +UDELEGATE(BlueprintAuthorityOnly) +DECLARE_DYNAMIC_DELEGATE(FOnSardineCheckoutFailure); + +UCLASS() +class SEQUENCEPLUGIN_API USardineCheckoutBP : public UGameInstanceSubsystem +{ + GENERATED_BODY() + + USardineCheckout* SardineCheckout; + +public: + USardineCheckoutBP(); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void CheckSardineWhiteListStatus(FString Address, FOnCheckSardineWhiteListStatus OnSuccess, FOnSardineCheckoutFailure OnFailure); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void SardineGetQuote(FOnSardineGetQuote OnSuccess, FOnSardineCheckoutFailure OnFailure, FString WalletAddress, FSardineToken Token, int Amount, FSardineFiatCurrency QuotedCurrency, ESardinePaymentType PaymentType = Credit, ESardineQuoteType QuoteType = Buy); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void SardineGetClientToken(FOnSardineGetClientToken OnSuccess, FOnSardineCheckoutFailure OnFailure); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void OnRamp(const FString& ClientToken); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void SardineGetNFTCheckoutTokenOrders(int64 ChainId, const FString& WalletAddress, TArray Orders, int Quantity, FString RecipientAddress, TArray + AdditionalFee, FString MarketPlaceContractAddress, FOnSardineGetNFTCheckoutToken OnSuccess, FOnSardineCheckoutFailure OnFailure); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void SardineGetNFTCheckoutTokenERC1155(int64 ChainId, UERC1155SaleContract* SaleContract, FString CollectionAddress, int TokenID, int Amount, + FOnSardineGetNFTCheckoutToken OnSuccess, FOnSardineCheckoutFailure OnFailure, + TArray data, TArray Proof, FString RecipientAddress = ""); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void SardineGetNFTCheckoutTokenERC721(int64 ChainID, UERC721SaleContract* SaleContract, FString CollectionAddress, int TokenID, + int Amount, FOnSardineGetNFTCheckoutToken OnSuccess, FOnSardineCheckoutFailure OnFailure, FString RecipientAddress, TArray data , TArray Proof); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void SardineGetNFTCheckoutOrderStatus(FString OrderID, FOnSardineGetNFTCheckoutOrderStatus OnSuccess, FOnSardineCheckoutFailure OnFailure); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void SardineGetSupportedRegions(FOnSardineGetSupportedRegions OnSuccess, FOnSardineCheckoutFailure OnFailure); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void SardineGetSupportedFiatCurrencies(FOnSardineGetSupportedFiatCurrencies OnSuccess, FOnSardineCheckoutFailure OnFailure); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void SardineGetSupportedTokens(FOnSardineGetSupportedTokens OnSuccess, FOnSardineCheckoutFailure OnFailure); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void SardineGetEnabledTokens(FOnSardineGetEnabledTokens OnSuccess, FOnSardineCheckoutFailure OnFailure); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + FString CheckoutURL(FString ClientToken); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + FString CheckoutURLFromToken(FSardineNFTCheckout Token); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void Checkout(FSardineNFTCheckout Token); + +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Integrators/SequenceCheckoutBP.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Integrators/SequenceCheckoutBP.h new file mode 100644 index 000000000..4ced473d1 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Integrators/SequenceCheckoutBP.h @@ -0,0 +1,46 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Checkout/SequenceCheckout.h" +#include "Subsystems/GameInstanceSubsystem.h" +#include "Sequence/SequenceResponseIntent.h" +#include "SequenceCheckoutBP.generated.h" + +UCLASS() +class SEQUENCEPLUGIN_API USequenceCheckoutBP : public UGameInstanceSubsystem +{ + GENERATED_BODY() + + virtual void Initialize(FSubsystemCollectionBase& Collection) override; + virtual void Deinitialize() override; + +public: + USequenceCheckoutBP(); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void SetChainID(const int64& InChainID); + + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GetCheckoutOptions(const FString& WalletAddress, const TArray& Orders, int64 AdditionalFeeBps, FOnGetCheckoutOptionsResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GetCheckoutOptionsByOrders(const FString& WalletAddress, const TArray& Orders, const int64 AdditionalFeeBps, FOnGetCheckoutOptionsResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure)const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GenerateBuyTransaction(const FString& WalletAddress, const FSeqOrder& Order, const int64 Amount, const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GenerateSellTransaction(const FString& WalletAddress, const FSeqOrder& Order, const int64 Amount, const FAdditionalFee& AdditionalFee, const EWalletKind WalletKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GenerateListingTransaction(const FString& WalletAddress, const FString& CollectionAddress, const FString& TokenId, int64 Amount, EContractType ContractType, const FString& CurrencyTokenAddress, int64 PricePerToken, FDateTime Expiry, EOrderbookKind OrderbookKind, const EWalletKind WalletKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GenerateOfferTransaction(const FString& WalletAddress, const FString& CollectionAddress, const FString& TokenId, int64 Amount, EContractType ContractType, const FString& CurrencyTokenAddress, int64 PricePerToken, FDateTime Expiry, EOrderbookKind OrderbookKind, const EWalletKind WalletKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GenerateCancelTransaction(const FString& WalletAddress, const FString& CollectionAddress, const FString& OrderId, EMarketplaceKind MarketplaceKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + void GenerateCancelTransactionByOrder(const FString& WalletAddress, const FString& CollectionAddress, const FSeqOrder& Order, const EMarketplaceKind MarketplaceKind, FOnGenerateTransactionResponseSuccess OnSuccess, FOnCheckoutFailure OnFailure) const; + UFUNCTION(BlueprintCallable, Category = "Checkout") + UTransactions* StepsToTransactions(const TArray& Steps); + +private: + USequenceCheckout* Checkout; + + UTransactions* CreateTransaction(); +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Integrators/SequenceMarketplaceBP.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Integrators/SequenceMarketplaceBP.h index 494aab26a..77ebc4469 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Integrators/SequenceMarketplaceBP.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Integrators/SequenceMarketplaceBP.h @@ -3,9 +3,22 @@ #include "CoreMinimal.h" #include "Marketplace/Marketplace.h" #include "Subsystems/GameInstanceSubsystem.h" +#include "Marketplace/Structs/SeqListCollectibleListingsArgs.h" #include "SequenceMarketplaceBP.generated.h" -DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnGetCollectiblesWithLowestListings, bool, Status, const int64, ChainId, FSeqGetCollectiblesWithLowestListingsReturn, Response); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnGetCollectiblesWithLowestListingsFirst, bool, Status, const int64, ChainId, FSeqListCollectiblesReturn, Response); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnGetAllCollectiblesWithLowestListingsFirst, bool, Status, const int64, ChainId, TArray, Response); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnGetCollectiblesWithHighestPricedOffersFirst, bool, Status, const int64, ChainId, FSeqListCollectiblesReturn, Response); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnGetAllCollectiblesWithHighestPricedOffersFirst, bool, Status, const int64, ChainId, TArray, Response); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnGetLowestPriceOfferForCollectible, bool, Status, const int64, ChainId, FSeqCollectibleOrder, Response); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnGetHighestPriceOfferForCollectible, bool, Status, const int64, ChainId, FSeqCollectibleOrder, Response); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnGetLowestPriceListingForCollectible, bool, Status, const int64, ChainId, FSeqCollectibleOrder, Response); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnGetHighestPriceListingForCollectible, bool, Status, const int64, ChainId, FSeqCollectibleOrder, Response); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnListListingsForCollectible, bool, Status, const int64, ChainId, FSeqListCollectibleListingsReturn, Response); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnListAllListingsForCollectible, bool, Status, const int64, ChainId, TArray, Response); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnListOffersForCollectible, bool, Status, const int64, ChainId, FSeqListCollectibleOffersReturn, Response); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnListAllOffersForCollectible, bool, Status, const int64, ChainId, TArray, Response); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnGetFloorOrder, bool, Status, const int64, ChainId, FSeqCollectibleOrder, Response); UCLASS(Blueprintable) class SEQUENCEPLUGIN_API USequenceMarketplaceBP : public UGameInstanceSubsystem @@ -15,16 +28,100 @@ class SEQUENCEPLUGIN_API USequenceMarketplaceBP : public UGameInstanceSubsystem public: USequenceMarketplaceBP(); + UPROPERTY(BlueprintAssignable, Category = "0xSequence SDK - Events") - FOnGetCollectiblesWithLowestListings CollectiblesWithLowestListingsResponse; + FOnGetCollectiblesWithLowestListingsFirst CollectiblesWithLowestListingsResponse; + UFUNCTION(BlueprintCallable, Category = "0xSequence SDK - Functions") + void GetCollectiblesWithLowestListingsFirstAsync(const int64 ChainId, const FSeqListCollectiblesArgs& Args); + + UPROPERTY(BlueprintAssignable, Category = "0xSequence SDK - Events") + FOnGetAllCollectiblesWithLowestListingsFirst AllCollectiblesWithLowestListingsResponse; UFUNCTION(BlueprintCallable, Category = "0xSequence SDK - Functions") - void GetGetCollectiblesWithLowestListingsAsync(const int64 ChainId, const FSeqGetCollectiblesWithLowestListingsArgs& Args); + void GetAllCollectiblesWithLowestListingsFirstAsync(const int64 ChainId, const FSeqListCollectiblesArgs& Args); -private: + UPROPERTY(BlueprintAssignable, Category = "0xSequence SDK - Events") + FOnGetCollectiblesWithHighestPricedOffersFirst CollectiblesWithHighestListingsResponse; + + UFUNCTION(BlueprintCallable, Category = "0xSequence SDK - Functions") + void GetCollectiblesWithHighestPricedOffersFirstAsync(const int64 ChainId, const FSeqListCollectiblesArgs& Args); + + UPROPERTY(BlueprintAssignable, Category = "0xSequence SDK - Events") + FOnGetAllCollectiblesWithHighestPricedOffersFirst AllCollectiblesWithHighestPricedOffersResponse; + + UFUNCTION(BlueprintCallable, Category = "0xSequence SDK - Functions") + void GetAllCollectiblesWithHighestPricedOffersFirstAsync(const int64 ChainId, const FSeqListCollectiblesArgs& Args); + + UPROPERTY(BlueprintAssignable, Category = "0xSequence SDK - Events") + FOnGetLowestPriceOfferForCollectible GetLowestPriceOfferForCollectibleResponse; + + UFUNCTION(BlueprintCallable, Category = "0xSequence SDK - Functions") + void GetLowestPriceOfferForCollectibleAsync(const int64 ChainId, const FSeqGetCollectibleOrderArgs& Args); + + UPROPERTY(BlueprintAssignable, Category = "0xSequence SDK - Events") + FOnGetHighestPriceOfferForCollectible GetHighestPriceOfferForCollectibleResponse; + + UFUNCTION(BlueprintCallable, Category = "0xSequence SDK - Functions") + void GetHighestPriceOfferForCollectibleAsync(const int64 ChainId, const FSeqGetCollectibleOrderArgs& Args); + + UPROPERTY(BlueprintAssignable, Category = "0xSequence SDK - Events") + FOnGetLowestPriceListingForCollectible GetLowestPriceListingForCollectibleResponse; + + UFUNCTION(BlueprintCallable, Category = "0xSequence SDK - Functions") + void GetLowestPriceListingForCollectibleAsync(const int64 ChainId, const FSeqGetCollectibleOrderArgs& Args); + + UPROPERTY(BlueprintAssignable, Category = "0xSequence SDK - Events") + FOnGetHighestPriceListingForCollectible GetHighestPriceListingForCollectibleResponse; + + UFUNCTION(BlueprintCallable, Category = "0xSequence SDK - Functions") + void GetHighestPriceListingForCollectibleAsync(const int64 ChainId, const FSeqGetCollectibleOrderArgs& Args); + + UPROPERTY(BlueprintAssignable, Category = "0xSequence SDK - Events") + FOnListListingsForCollectible FOnListListingsForCollectibleResponse; + + UFUNCTION(BlueprintCallable, Category = "0xSequence SDK - Functions") + void ListListingsForCollectibleAsync(const int64 ChainId, const FSeqListCollectibleListingsArgs& Args); + + UPROPERTY(BlueprintAssignable, Category = "0xSequence SDK - Events") + FOnListAllListingsForCollectible FOnListAllListingsForCollectibleResponse; + + UFUNCTION(BlueprintCallable, Category = "0xSequence SDK - Functions") + void ListAllListingsForCollectibleAsync(const int64 ChainId, const FSeqListCollectibleListingsArgs& Args); + + UPROPERTY(BlueprintAssignable, Category = "0xSequence SDK - Events") + FOnListOffersForCollectible FOnListOffersForCollectibleResponse; + + UFUNCTION(BlueprintCallable, Category = "0xSequence SDK - Functions") + void ListOffersForCollectibleAsync(const int64 ChainId, const FSeqListCollectibleListingsArgs& Args); + + UPROPERTY(BlueprintAssignable, Category = "0xSequence SDK - Events") + FOnListAllOffersForCollectible FOnListAllOffersForCollectibleResponse; + + UFUNCTION(BlueprintCallable, Category = "0xSequence SDK - Functions") + void ListAllOffersForCollectibleAsync(const int64 ChainId, const FSeqListCollectibleListingsArgs& Args); + + UPROPERTY(BlueprintAssignable, Category = "0xSequence SDK - Events") + FOnGetFloorOrder FOnGetFloorOrderResponse; + UFUNCTION(BlueprintCallable, Category = "0xSequence SDK - Functions") + void GetFloorOrderAsync(const int64 ChainId, const FSeqListCollectiblesArgs& Args); + + +private: UMarketplace* Marketplace; - void CallCollectiblesWithLowestListingsReceived(const bool Status, const int64 ChainId, const FSeqGetCollectiblesWithLowestListingsReturn& Response); + void CallCollectiblesWithLowestListingsFirstReceived(const bool Status, const int64 ChainId, const FSeqListCollectiblesReturn& Response); + void CallAllCollectiblesWithLowestListingsFirstReceived(const bool Status, const int64 ChainId, const TArray& Response); + void CallCollectiblesWithHighestPricedOffersFirstReceived(const bool Status, const int64 ChainId, const FSeqListCollectiblesReturn& Response); + void CallAllCollectiblesWithHighestPricedOffersFirstReceived(const bool Status, const int64 ChainId, const TArray& Response); + void CallLowestPriceOfferForCollectibleReceived(const bool Status, const int64 ChainId, const FSeqCollectibleOrder& Response); + void CallHighestPriceOfferForCollectibleReceived(const bool Status, const int64 ChainId, const FSeqCollectibleOrder& Response); + void CallLowestPriceListingForCollectibleReceived(const bool Status, const int64 ChainId, const FSeqCollectibleOrder& Response); + void CallHighestPriceListingForCollectibleReceived(const bool Status, const int64 ChainId, const FSeqCollectibleOrder& Response); + void CallListListingsForCollectibleReceived(const bool Status, const int64 ChainId, const FSeqListCollectibleListingsReturn& Response); + void CallListAllListingsForCollectibleReceived(const bool Status, const int64 ChainId, const TArray& Response); + void CallListOffersForCollectibleReceived(const bool Status, const int64 ChainId, const FSeqListCollectibleOffersReturn& Response); + void CallListAllOffersForCollectibleReceived(const bool Status, const int64 ChainId, const TArray& Response); + void CallGetFloorOrderReceived(const bool Status, const int64 ChainId, const FSeqCollectibleOrder& Response); }; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Marketplace.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Marketplace.h new file mode 100644 index 000000000..51e199fbe --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Marketplace.h @@ -0,0 +1,232 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Util/Async.h" +#include "Marketplace/Structs/Struct_Data.h" +#include "Structs/SeqGetCollectibleOrderArgs.h" +#include "Structs/SeqListCollectibleListingsReturn.h" +#include "Structs/SeqListCollectibleOffersReturn.h" +#include "Structs/SeqListCurrenciesReturn.h" +#include "Marketplace.generated.h" + +UCLASS() +class SEQUENCEPLUGIN_API UMarketplace : public UObject +{ + GENERATED_BODY() + +private: + + const FString PATH = "/rpc/Marketplace/"; + + TArray OrderArray; + + //private functions + + /* + Creates the URL from a given chainID and endpoint + */ + FString Url(const int64& ChainID, const FString& EndPoint) const; + + /* + Returns the host name + */ + static FString HostName(int64 ChainID); + + // HELPERS + void ListAllCollectibleListingsWithLowestPriceListingsFirstHelper(const int64 ChainID, const FString& ContractAddress, const FSeqCollectiblesFilter& Filter, const FSeqMarketplacePage& Page, TFunction, bool)> OnSuccess, const FFailureCallback& OnFailure); + void ListAllCollectibleOffersWithHighestPricedOfferFirstHelper(const int64 ChainID, const FString& ContractAddress, const FSeqCollectiblesFilter& Filter, const FSeqMarketplacePage& Page, TFunction, bool)> OnSuccess, const FFailureCallback& OnFailure); + void GetCollectibleOrder(int64 ChainID, const FString& Endpoint, const FSeqGetCollectibleOrderArgs& Args, + TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); + void ListAllListingsForCollectibleHelper(const int64 ChainID, const FString& ContractAddress, const FString& TokenID, const FSeqCollectiblesFilter& Filter, const FSeqMarketplacePage& Page, TFunction, bool)> OnSuccess, const FFailureCallback& OnFailure); + void ListAllOffersForCollectibleHelper(const int64 ChainID, const FString& ContractAddress, const FString& TokenID, const FSeqCollectiblesFilter& Filter, const FSeqMarketplacePage& Page, TFunction, bool)> OnSuccess, const FFailureCallback& OnFailure); +public: + /* + Used to send an HTTPPost req to a the sequence app + @return the content of the post response + */ + void HTTPPost(const int64& ChainID, const FString& Endpoint, const FString& Args, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const; + + + //public functions + + /* + Here we take in text and convert it to a Struct of type T if possible + @return a Struct of type T + + NOTE: Because unreal doesn't support nested TArrays and TMaps I had to use special implementations + for some data structures inorder for them to parse properly + */ + template < typename T > T BuildResponse(FString Text); + + /* + Here we take in a struct and convert it straight into a json object String + @Param (T) Struct_in the struct we are converting to a json object string + @Return the JSON Object String + */ + template < typename T> FString BuildArgs(T StructIn); + + UMarketplace(); + + /** + * Lists the marketplace currencies + * @param ChainID the id of the chain + * @param OnSuccess handler for success, takes in a FSeqListCurrenciesReturn + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void ListCurrencies(const int64 ChainID, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); + + /** + * Lists collectible listings with the lowest price listings first + * @param ChainID the id of the chain + * @param ContractAddress the address of the contract + * @param Filter the filter to apply + * @param Page the page to apply + * @param OnSuccess handler for success, takes in a FSeqListCollectiblesReturn + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void ListCollectibleListingsWithLowestPriceListingsFirst(const int64 ChainID, const FString& ContractAddress, const FSeqCollectiblesFilter& Filter, const FSeqMarketplacePage& Page, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); + + /** + * Lists all collectible listings with the lowest price listings first + * @param ChainID the id of the chain + * @param ContractAddress the address of the contract + * @param Filter the filter to apply + * @param OnSuccess handler for success, takes in a TArray of FSeqCollectibleOrder + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void ListAllCollectibleListingsWithLowestPriceListingsFirst(const int64 ChainID, const FString& ContractAddress, const FSeqCollectiblesFilter& Filter, TSuccessCallback> OnSuccess, const FFailureCallback& OnFailure); + + /** + * List collectible offers with the highest priced offer first + * @param ChainID the id of the chain + * @param ContractAddress the address of the contract + * @param Filter the filter to apply + * @param Page the page to apply + * @param OnSuccess handler for success, takes in a FSeqListCollectiblesReturn + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void ListCollectibleOffersWithHighestPricedOfferFirst(const int64 ChainID, const FString& ContractAddress, const FSeqCollectiblesFilter& Filter, const FSeqMarketplacePage& Page, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); + + /** + * Lists all collectible offers with the highest priced offer first + * @param ChainID the id of the chain + * @param ContractAddress the address of the contract + * @param Filter the filter to apply + * @param OnSuccess handler for success, takes in a TArray of FSeqCollectibleOrder + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void ListAllCollectibleOffersWithHighestPricedOfferFirst(const int64 ChainID, const FString& ContractAddress, const FSeqCollectiblesFilter& Filter, TSuccessCallback> OnSuccess, const FFailureCallback& OnFailure); + + /** + * Gets the meta data for a collectible + * @param ChainID the id of the chain + * @param ContractAddress the address of the contract + * @param TokenId the id of the token + * @param OnSuccess handler for success, takes in a FSeqTokenMetaData + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void GetCollectible(const int64 ChainID, const FString& ContractAddress, const FString& TokenId, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); + + /** + * Gets the lowest price offer for a collectible + * @param ChainID the id of the chain + * @param ContractAddress the address of the contract + * @param TokenID the id of the token + * @param Filter the filter to apply + * @param OnSuccess handler for success, takes in a FSeqCollectibleOrder + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void GetLowestPriceOfferForCollectible(const int64 ChainID, const FString& ContractAddress, const FString& TokenID, const FSeqCollectiblesFilter& Filter, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure); + + /** + * Gets the highest price offer for a collectible + * @param ChainID the id of the chain + * @param ContractAddress the address of the contract + * @param TokenID the id of the token + * @param Filter the filter to apply + * @param OnSuccess handler for success, takes in a FSeqCollectibleOrder + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void GetHighestPriceOfferForCollectible(const int64 ChainID, const FString& ContractAddress, const FString& TokenID, const FSeqCollectiblesFilter& Filter, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure); + + /** + * Gets the lowest price listing for a collectible + * @param ChainID the id of the chain + * @param ContractAddress the address of the contract + * @param TokenID the id of the token + * @param Filter the filter to apply + * @param OnSuccess handler for success, takes in a FSeqCollectibleOrder + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void GetLowestPriceListingForCollectible(const int64 ChainID, const FString& ContractAddress, const FString& TokenID, const FSeqCollectiblesFilter& Filter, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure); + + /** + * Get the highest price listing for a collectible + * @param ChainID the id of the chain + * @param ContractAddress the address of the contract + * @param TokenID the id of the token + * @param Filter the filter to apply + * @param OnSuccess handler for success, takes in a FSeqCollectibleOrder + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void GetHighestPriceListingForCollectible(const int64 ChainID, const FString& ContractAddress, const FString& TokenID, const FSeqCollectiblesFilter& Filter, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure); + + /** + * Get listings for a collectible + * @param ChainID the id of the chain + * @param ContractAddress the address of the contract + * @param TokenID the id of the token + * @param Filter the filter to apply + * @param Page the page to apply + * @param OnSuccess handler for success, takes in a FSeqListCollectibleListingsReturn + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void ListListingsForCollectible(const int64 ChainID, const FString& ContractAddress, const FString& TokenID, const FSeqCollectiblesFilter& Filter, const FSeqMarketplacePage& Page, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); + + /** + * Get all listings for a collectible + * @param ChainID the id of the chain + * @param ContractAddress the address of the contract + * @param TokenID the id of the token + * @param Filter the filter to apply + * @param OnSuccess handler for success, takes in a TArray of FSeqCollectibleOrder + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void ListAllListingsForCollectible(const int64 ChainID, const FString& ContractAddress, const FString& TokenID, const FSeqCollectiblesFilter& Filter, TSuccessCallback> OnSuccess, const FFailureCallback& OnFailure); + + /** + * Get offers for a collectible + * @param ChainID the id of the chain + * @param ContractAddress the address of the contract + * @param TokenID the id of the token + * @param Filter the filter to apply + * @param Page the page to apply + * @param OnSuccess handler for success, takes in a FSeqListCollectibleOffersReturn + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void ListOffersForCollectible(const int64 ChainID, const FString& ContractAddress, const FString& TokenID, const FSeqCollectiblesFilter& Filter, const FSeqMarketplacePage& Page, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); + + /** + * Get all offers for a collectible + * @param ChainID the id of the chain + * @param ContractAddress the address of the contract + * @param TokenID the id of the token + * @param Filter the filter to apply + * @param OnSuccess handler for success, takes in a TArray of FSeqCollectibleOrder + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void ListAllOffersForCollectible(const int64 ChainID, const FString& ContractAddress, const FString& TokenID, const FSeqCollectiblesFilter& Filter, TSuccessCallback> OnSuccess, const FFailureCallback& OnFailure); + + /** + * Get the floor order for a collectible + * @param ChainID the id of the chain + * @param ContractAddress the address of the contract + * @param Filter the filter to apply + * @param OnSuccess handler for success, takes in a FSeqCollectibleOrder + * @param OnFailure handler for failure, takes in a FSequenceError + */ + void GetFloorOrder(const int64 ChainID, const FString& ContractAddress, const FSeqCollectiblesFilter& Filter, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure); +}; + diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Marketplace_Enums.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Marketplace_Enums.h index e0595f5ac..7bef5df48 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Marketplace_Enums.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Marketplace_Enums.h @@ -67,6 +67,19 @@ enum EOrderStatus FILLED UMETA(DisplayName = "Filled"), }; +UENUM(BlueprintType) +enum class EOrderbookKind : uint8 +{ + Unknown UMETA(DisplayName = "unknown"), + Sequence_Marketplace_V1 UMETA(DisplayName = "sequence_marketplace_v1"), + Sequence_Marketplace_V2 UMETA(DisplayName = "sequence_marketplace_v2"), + Blur UMETA(DisplayName = "blur"), + Opensea UMETA(DisplayName = "opensea"), + Looks_Rare UMETA(DisplayName = "looks_rare"), + Reservoir UMETA(DisplayName = "reservoir"), + X2Y2 UMETA(DisplayName = "x2y2") +}; + // PropertyType Extensions UCLASS() @@ -76,6 +89,32 @@ class UMarketplaceEnumsExtensions : public UObject public: + template + static FString AsString(EnumType EnumValue); + + template<> + FString AsString(const EOrderbookKind OrderbookKind) + { + switch (OrderbookKind) + { + case EOrderbookKind::Sequence_Marketplace_V1: + return FString("sequence_marketplace_v1"); + case EOrderbookKind::Sequence_Marketplace_V2: + return FString("sequence_marketplace_v2"); + case EOrderbookKind::Blur: + return FString("blur"); + case EOrderbookKind::Opensea: + return FString("opensea"); + case EOrderbookKind::Looks_Rare: + return FString("looks_rare"); + case EOrderbookKind::Reservoir: + return FString("reservoir"); + case EOrderbookKind::X2Y2: + return FString("x2y2"); + default: return FString("unknown"); + } + } + template static FString AsString(TEnumAsByte EnumValue); @@ -151,4 +190,4 @@ class UMarketplaceEnumsExtensions : public UObject } return StringArray; } -}; \ No newline at end of file +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/SardineCheckout.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/SardineCheckout.h new file mode 100644 index 000000000..7e4304a80 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/SardineCheckout.h @@ -0,0 +1,173 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Checkout/Structs/AdditionalFee.h" +#include "Marketplace/Structs/SeqCollectibleOrder.h" +#include "Sequence/SequenceAPI.h" +#include "Structs/SardineEnabledToken.h" +#include "Structs/SardineFiatCurrency.h" +#include "Structs/SardineGetNFTCheckoutTokenArgs.h" +#include "Structs/SardineGetQuoteArgs.h" +#include "Structs/SardineNFTCheckout.h" +#include "Structs/SardineOrder.h" +#include "Structs/SardinePaymentType.h" +#include "Structs/SardineQuote.h" +#include "Structs/SardineQuoteType.h" +#include "Structs/SardineRegion.h" +#include "Structs/SardineSupportedToken.h" +#include "Structs/SardineToken.h" +#include "Types/ERC1155SaleContract.h" +#include "Types/ERC721SaleContract.h" +#include "Types/SaleDetails.h" +#include "UObject/Object.h" +#include "Util/Async.h" +#include "SardineCheckout.generated.h" + +/** + * + */ +UCLASS() +class SEQUENCEPLUGIN_API USardineCheckout : public UObject +{ + GENERATED_BODY() + + const FString _sardineCheckoutUrl = + "https://sardine-checkout.sequence.info?api_url=https://sardine-api.sequence.info&client_token="; + + const FString _sardineSandboxCheckoutUrl = + "https://sardine-checkout-sandbox.sequence.info?api_url=https://sardine-api-sandbox.sequence.info&client_token="; + + const FString _sardineCheckoutUrlSuffix = "&show_features=true"; + + const FString _devUrl = "https://dev-api.sequence.app/rpc/API"; + const FString _prodUrl = "https://api.sequence.app/rpc/API"; + FString _baseUrl = _devUrl; + FString _baseCheckoutUrl = _sardineCheckoutUrl; + + USequenceWallet* _wallet = nullptr; + + FString Url(const FString& EndPoint) const; + + void GetPaymentDetails(FString PaymentToken, TSuccessCallback> OnSuccess, const FFailureCallback& OnFailure); + + void GetSaleDetails(const FContractCall& SaleDetailsCall, long& Amount, long TokenID, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); + + void SardineGetNFTCheckoutToken(const FSardineGetNFTCheckoutTokenArgs& Args, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); + void SardineGetNFTCheckoutTokenSendRequest(int64 ChainId, FSeqCollectibleOrder Order, FString RecipientAddress, + FString MarketplaceContractAddress, long Quantity, FString PriceSymbol, FString CallData, + TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); + +public: + //public functions + USardineCheckout(); + USardineCheckout(ENetwork Chain); + + /* + Here we take in text and convert it to a Struct of type T if possible + @return a Struct of type T + + NOTE: Because unreal doesn't support nested TArrays and TMaps I had to use special implementations + for some data structures inorder for them to parse properly + */ + template < typename T > T BuildResponse(FString Text); + + /* + Here we take in a struct and convert it straight into a json object String + @Param (T) Struct_in the struct we are converting to a json object string + @Return the JSON Object String + */ + template < typename T> FString BuildArgs(T StructIn); + void HTTPPost(const FString& Endpoint, const FString& Args, const TSuccessCallback& OnSuccess, const FFailureCallback& + OnFailure) const; + + const FString SequenceMarketplaceV2Contract = "0xfdb42A198a932C8D3B506Ffa5e855bC4b348a712"; + + void CheckSardineWhiteListStatus(FString Address, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); + + void SardineGetQuote(TSuccessCallback OnSuccess, const FFailureCallback& OnFailure, FString WalletAddress, FSardineToken Token, u_long Amount, ESardinePaymentType PaymentType = Credit, + TOptional QuotedCurrency = TOptional(), + ESardineQuoteType QuoteType = Buy); + + void SardineGetClientToken(TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); + + void OnRamp(const FString& ClientToken); + + void OnRampAsync(FString ClientToken, TFunction OnSuccess, const FFailureCallback& OnFailure); + + void SardineGetNFTCheckoutToken(int64 ChainId, const FString& WalletAddress, TArray Orders, long Quantity, FString RecipientAddress, TArray + AdditionalFee, FString MarketPlaceContractAddress, TSuccessCallback OnSuccess, const + FFailureCallback& OnFailure); + + void SardineGetNFTCheckoutToken(int64 ChainId, UERC1155SaleContract* SaleContract, FString CollectionAddress, long TokenID, long Amount, + TSuccessCallback OnSuccess, const FFailureCallback& OnFailure, FString RecipientAddress = "", + TArray data = TArray(), TArray Proof = TArray()); + + void SardineGetNFTCheckoutToken(int64 ChainID, UERC721SaleContract* SaleContract, FString CollectionAddress, long TokenID, + long Amount, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure, + FString RecipientAddress = "", TArray data = TArray(),TArray Proof = TArray()); + + void SardineGetNFTCheckoutOrderStatus(FString OrderID, TSuccessCallback OnSuccess, const FFailureCallback& OnFailure); + + void SardineGetSupportedRegions(TSuccessCallback> OnSuccess, const FFailureCallback& OnFailure); + + void SardineGetSupportedFiatCurrencies(TSuccessCallback> OnSuccess, const FFailureCallback& OnFailure); + + void SardineGetSupportedTokens(TSuccessCallback> OnSuccess, const FFailureCallback& OnFailure); + + void SardineGetEnabledTokens(TSuccessCallback> OnSuccess, const FFailureCallback& OnFailure); + + FString CheckoutURL(FString ClientToken); + + FString CheckoutURL(FSardineNFTCheckout Token); + + void Checkout(FSardineNFTCheckout Token); +}; + +template < typename T> FString USardineCheckout::BuildArgs(T StructIn) +{ + FString Result = "[FAILED TO PARSE]"; + if (StructIn.customGetter) + { + Result = StructIn.GetArgs(); + } + else + { + if (!FJsonObjectConverter::UStructToJsonObjectString(StructIn, Result)) + { + UE_LOG(LogTemp, Display, TEXT("Failed to convert specified UStruct to a json object\n")); + } + } + return Result; +} + +//generic +template T USardineCheckout::BuildResponse(const FString Text) +{ + //Take the FString and convert it to a JSON object first! + TSharedPtr JSON_Step; + //Then take the json object we make and convert it to a USTRUCT of type T then we return that! + T Ret_Struct; + + if (!FJsonSerializer::Deserialize(TJsonReaderFactory<>::Create(Text), JSON_Step)) + { + UE_LOG(LogTemp, Display, TEXT("Failed to convert String: %s to Json object"), *Text); + return T(); + } + //this next line with throw an exception in null is used as an entry in json attributes! we need to remove null entries + if (Ret_Struct.customConstructor) + {//use the custom constructor! + Ret_Struct.construct(*JSON_Step.Get()); + } + else + {//use unreal parsing! + if (!FJsonObjectConverter::JsonObjectToUStruct(JSON_Step.ToSharedRef(), &Ret_Struct)) + { + UE_LOG(LogTemp, Display, TEXT("Failed to convert Json Object: %s to USTRUCT of type T"), *Text); + return T(); + } + } + Ret_Struct.Setup(*JSON_Step.Get());//now for the edge cases we will manually inject the data where it needs to be! + return Ret_Struct; +} \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineEnabledToken.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineEnabledToken.h new file mode 100644 index 000000000..12ab19d3e --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineEnabledToken.h @@ -0,0 +1,14 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardineToken.h" +#include "SardineEnabledToken.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineEnabledToken : public FSardineToken +{ + GENERATED_USTRUCT_BODY() + +public: + +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineEnabledTokensResponse.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineEnabledTokensResponse.h new file mode 100644 index 000000000..a63388223 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineEnabledTokensResponse.h @@ -0,0 +1,36 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#pragma once + +#include + +#include "CoreMinimal.h" +#include "SardineEnabledToken.h" +#include "SardinePaymentType.h" +#include "SardineQuote.h" +#include "Util/JsonBuilder.h" +#include "SardineQuoteType.h" +#include "UObject/Object.h" +#include "SardineEnabledTokensResponse.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineEnabledTokensResponse +{ + GENERATED_USTRUCT_BODY() + +public: + TArray Tokens; + + bool customConstructor = false; + + void construct(FJsonObject& json_in) {} + void Setup(FJsonObject& json_in) + { + for(TSharedPtr json : json_in.GetArrayField(TEXT("tokens"))) + { + FSardineEnabledToken Token; + Token.Setup(*json->AsObject()); + Tokens.Add(Token); + } + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineFiatCurrency.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineFiatCurrency.h new file mode 100644 index 000000000..e2d58e669 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineFiatCurrency.h @@ -0,0 +1,34 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardinePaymentOption.h" +#include "SardineFiatCurrency.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineFiatCurrency +{ + GENERATED_USTRUCT_BODY() + +public: + FString CurrencyCode; + FString Name; + FString CurrencySymbol; + TArray PaymentOptions; + TArray SupportedCountries; + + void Setup(FJsonObject& json_in) + { + json_in.TryGetStringField(TEXT("currencyCode"), CurrencyCode); + json_in.TryGetStringField(TEXT("name"), Name); + json_in.TryGetStringField(TEXT("currencySymbol"), CurrencySymbol); + + for(TSharedPtr Option : json_in.GetArrayField(TEXT("paymentOptions"))) + { + FSardinePaymentOption PaymentOption; + PaymentOption.Setup(*Option->AsObject()); + PaymentOptions.Add(PaymentOption); + } + + json_in.TryGetStringArrayField(TEXT("supportedCountries"), SupportedCountries); + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineGetNFTCheckoutTokenArgs.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineGetNFTCheckoutTokenArgs.h new file mode 100644 index 000000000..a9b71354e --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineGetNFTCheckoutTokenArgs.h @@ -0,0 +1,67 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#pragma once + +#include + +#include "CoreMinimal.h" +#include "SardinePaymentMethodTypeConfig.h" +#include "SardinePaymentType.h" +#include "Util/JsonBuilder.h" +#include "SardineQuoteType.h" +#include "UObject/Object.h" +#include "SardineGetNFTCheckoutTokenArgs.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineGetNFTCheckoutTokenArgs +{ + GENERATED_USTRUCT_BODY() + +public: + FString ReferenceId; + uint ExpiresIn; + FSardinePaymentMethodTypeConfig PaymentMethodTypeConfig; + FString Name; + FString ImageUrl; + FString Network; + FString RecipientAddress; + FString ContractAddress; + FString Platform; + FString ExecutionType; + FString BlockchainNftId; + long Quantity; + long Decimals; + FString TokenAmount; + FString TokenAddress; + FString TokenSymbol; + long TokenDecimals; + FString CallData; + + bool customGetter = true; + + FString GetArgs() + { + FJsonBuilder Builder; + + Builder.AddString(TEXT("name"), Name == "" ? "Placeholder" : Name); + Builder.AddString(TEXT("imageUrl"), ImageUrl == "" ? "https://dev-metadata.sequence.app/projects/1010/collections/394/tokens/1/image.webp" : ImageUrl); + Builder.AddString(TEXT("network"), Network); + Builder.AddString(TEXT("recipientAddress"), RecipientAddress); + Builder.AddString(TEXT("blockchainNftId"), BlockchainNftId); + Builder.AddString(TEXT("contractAddress"), ContractAddress); + Builder.AddInt(TEXT("decimals"), Decimals); + Builder.AddInt(TEXT("quantity"), Quantity); + Builder.AddString(TEXT("tokenAmount"), TokenAmount); + Builder.AddString(TEXT("tokenAddress"), TokenAddress); + Builder.AddString(TEXT("tokenSymbol"), TokenSymbol); + Builder.AddInt(TEXT("tokenDecimals"), TokenDecimals); + Builder.AddString(TEXT("callData"), CallData); + Builder.AddString(TEXT("platform"), Platform); + + // Builder.AddInt(TEXT("expiresIn"), ExpiresIn); + // Builder.AddString(TEXT("referenceId"), ReferenceId); + + FString Params = "{\"params\":" + Builder.ToString() + "}"; + return Params; + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineGetNFTCheckoutTokenResponse.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineGetNFTCheckoutTokenResponse.h new file mode 100644 index 000000000..c69ed0da4 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineGetNFTCheckoutTokenResponse.h @@ -0,0 +1,28 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#pragma once + +#include + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "SardineNFTCheckout.h" +#include "SardineGetNFTCheckoutTokenResponse.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineGetNFTCheckoutTokenResponse +{ + GENERATED_USTRUCT_BODY() + +public: + FSardineNFTCheckout Checkout; + + bool customConstructor = false; + + void construct(FJsonObject& json_in) {} + void Setup(FJsonObject& json_in) + { + const auto CheckoutObject = json_in.GetObjectField(TEXT("resp")); + Checkout.Setup(*CheckoutObject); + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineGetQuoteArgs.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineGetQuoteArgs.h new file mode 100644 index 000000000..23fcc27c6 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineGetQuoteArgs.h @@ -0,0 +1,47 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#pragma once + +#include + +#include "CoreMinimal.h" +#include "SardinePaymentType.h" +#include "Util/JsonBuilder.h" +#include "SardineQuoteType.h" +#include "UObject/Object.h" +#include "SardineGetQuoteArgs.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineGetQuoteArgs +{ + GENERATED_USTRUCT_BODY() + +private: + inline static const FString DefaultCurrency = "USD"; + +public: + FString AssetType; + FString Network; + u_long Total; + FString Currency; + ESardinePaymentType PaymentType; + ESardineQuoteType QuoteType; + FString WalletAddress; + + bool customGetter = true; + + FString GetArgs() + { + FJsonBuilder Builder; + + Builder.AddString(TEXT("assetType"), AssetType); + Builder.AddString(TEXT("network"), Network); + Builder.AddField(TEXT("total"), FString::SanitizeFloat(Total)); + Builder.AddString(TEXT("currency"), Currency == "" ? DefaultCurrency : Currency); + Builder.AddString(TEXT("paymentType"), UEnum::GetValueAsString(PaymentType).ToLower()); + Builder.AddString(TEXT("quoteType"), UEnum::GetValueAsString(QuoteType).ToLower()); + Builder.AddString(TEXT("walletAddress"), WalletAddress); + + return Builder.ToString(); + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineGetQuoteResponse.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineGetQuoteResponse.h new file mode 100644 index 000000000..871f02dbf --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineGetQuoteResponse.h @@ -0,0 +1,31 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#pragma once + +#include + +#include "CoreMinimal.h" +#include "SardinePaymentType.h" +#include "SardineQuote.h" +#include "Util/JsonBuilder.h" +#include "SardineQuoteType.h" +#include "UObject/Object.h" +#include "SardineGetQuoteResponse.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineGetQuoteResponse +{ + GENERATED_USTRUCT_BODY() + +public: + FSardineQuote Quote; + + bool customConstructor = false; + + void construct(FJsonObject& json_in) {} + void Setup(FJsonObject& json_in) + { + const auto QuoteObject = json_in.GetObjectField(TEXT("quote")); + Quote.Setup(*QuoteObject); + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineNFTCheckout.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineNFTCheckout.h new file mode 100644 index 000000000..5759d1067 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineNFTCheckout.h @@ -0,0 +1,25 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardineNFTCheckout.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineNFTCheckout +{ + GENERATED_USTRUCT_BODY() + +public: + FString Token; + FString ExpiresAt; + FString OrderID; + + bool customConstructor = false; + + void construct(FJsonObject& json_in) {} + void Setup(FJsonObject& json_in) + { + Token = json_in.GetStringField(TEXT("token")); + ExpiresAt = json_in.GetStringField(TEXT("expiresAt")); + OrderID = json_in.GetStringField(TEXT("orderID")); + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineOrder.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineOrder.h new file mode 100644 index 000000000..f9c9031af --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineOrder.h @@ -0,0 +1,33 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardineOrder.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineOrder +{ + GENERATED_USTRUCT_BODY() + +public: + FString ID; + FString CreatedAt; + FString ReferenceID; + FString Status; + FString FiatCurrency; + double FiatExchangeRateUSD; + FString TransactionID; + FString ExpiresAt; + double Total; + double SubTotal; + double TransactionFee; + double NetworkFee; + FString PaymentCurrency; + FString PaymentMethodType; + FString TransactionType; + FString Name; + int Price; + FString ImageURL; + FString ContractAddress; + FString TransactionHash; + FString RecipientAddress; +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardinePaymentMethod.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardinePaymentMethod.h new file mode 100644 index 000000000..126595f6d --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardinePaymentMethod.h @@ -0,0 +1,14 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardinePaymentMethod.generated.h" + +UENUM(BlueprintType) +enum ESardinePaymentMethod +{ + PaymentMethod_Us_Debit UMETA(DisplayName = "US_DEBIT"), + PaymentMethod_Us_Credit UMETA(DisplayName = "US_CREDIT"), + PaymentMethod_International_Debit UMETA(DisplayName = "INTERNATIONAL_DEBIT"), + PaymentMethod_International_Credit UMETA(DisplayName = "INTERNATIONAL_CREDIT"), + PaymentMethod_Ach UMETA(DisplayName = "ACH"), +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardinePaymentMethodTypeConfig.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardinePaymentMethodTypeConfig.h new file mode 100644 index 000000000..672aa346a --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardinePaymentMethodTypeConfig.h @@ -0,0 +1,33 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardinePaymentMethod.h" +#include "Util/JsonBuilder.h" +#include "SardinePaymentMethodTypeConfig.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardinePaymentMethodTypeConfig +{ + GENERATED_USTRUCT_BODY() + +public: + TArray Enabled; + ESardinePaymentMethod DefaultPaymentMethod; + + bool customGetter = true; + + FString GetArgs() + { + FJsonBuilder Builder; + + FJsonArray Array = Builder.AddArray("enabled"); + for(const ESardinePaymentMethod Method : Enabled) + { + Array.AddString(UEnum::GetValueAsString(Method).ToLower()); + } + Builder = *Array.EndArray(); + Builder.AddString(TEXT("defaultPaymentMethod"), UEnum::GetValueAsString(DefaultPaymentMethod).ToLower()); + + return Builder.ToString(); + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardinePaymentOption.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardinePaymentOption.h new file mode 100644 index 000000000..b0473bf47 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardinePaymentOption.h @@ -0,0 +1,36 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardinePaymentOption.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardinePaymentOption +{ + GENERATED_USTRUCT_BODY() + +public: + FString Name; + double DailyLimit; + double WeeklyLimit; + double MonthlyLimit; + double MaxAmount; + double MinAmount; + TArray SubTypes; + FString Type; + FString SubType; + FString ProcessingTime; + + void Setup(FJsonObject& json_in) + { + json_in.TryGetStringField(TEXT("name"), Name); + json_in.TryGetNumberField(TEXT("dailyLimit"), DailyLimit); + json_in.TryGetNumberField(TEXT("weeklyLimit"), WeeklyLimit); + json_in.TryGetNumberField(TEXT("monthlyLimit"), MonthlyLimit); + json_in.TryGetNumberField(TEXT("maxAmount"), MaxAmount); + json_in.TryGetNumberField(TEXT("minAmount"), MinAmount); + json_in.TryGetStringArrayField(TEXT("subTypes"), SubTypes); + json_in.TryGetStringField(TEXT("type"), Type); + json_in.TryGetStringField(TEXT("subType"), SubType); + json_in.TryGetStringField(TEXT("processingTime"), ProcessingTime); + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardinePaymentType.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardinePaymentType.h new file mode 100644 index 000000000..72a74942a --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardinePaymentType.h @@ -0,0 +1,15 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardinePaymentType.generated.h" + +UENUM(BlueprintType) +enum ESardinePaymentType +{ + Ach UMETA(DisplayName = "ACH"), + Debit UMETA(DisplayName = "DEBIT"), + Credit UMETA(DisplayName = "CREDIT"), + Us_Debit UMETA(DisplayName = "US_DEBIT"), + International_Debit UMETA(DisplayName = "INTERNATIONAL_DEBIT"), + International_Credit UMETA(DisplayName = "INTERNATIONAL_CREDIT"), +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineQuote.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineQuote.h new file mode 100644 index 000000000..1b11f6f69 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineQuote.h @@ -0,0 +1,46 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardineQuote.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineQuote +{ + GENERATED_USTRUCT_BODY() + +public: + double Quantity; + FString Network; + FString AssetType; + double Total; + FString Currency; + FString ExpiresAt; + FString PaymentType; + double Price; + double SubTotal; + double TransactionFee; + double NetworkFee; + bool HighNetworkFee; + double MinTransactionValue; + double MaxTransactionValue; + FString LiquidityProvider; + + void Setup(FJsonObject& json_in) + { + Quantity = json_in.GetNumberField(TEXT("quantity")); + Network = json_in.GetStringField(TEXT("network")); + AssetType = json_in.GetStringField(TEXT("assetType")); + Total = json_in.GetNumberField(TEXT("total")); + Currency = json_in.GetStringField(TEXT("currency")); + ExpiresAt = json_in.GetStringField(TEXT("expiresAt")); + PaymentType = json_in.GetStringField(TEXT("paymentType")); + Price = json_in.GetNumberField(TEXT("price")); + SubTotal = json_in.GetNumberField(TEXT("subTotal")); + TransactionFee = json_in.GetNumberField(TEXT("transactionFee")); + NetworkFee = json_in.GetNumberField(TEXT("networkFee")); + HighNetworkFee = json_in.GetBoolField(TEXT("highNetworkFee")); + MinTransactionValue = json_in.GetNumberField(TEXT("minTransactionValue")); + MaxTransactionValue = json_in.GetNumberField(TEXT("maxTransactionValue")); + LiquidityProvider = json_in.GetStringField(TEXT("liquidityProvider")); + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineQuoteType.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineQuoteType.h new file mode 100644 index 000000000..39de89e1f --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineQuoteType.h @@ -0,0 +1,11 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardineQuoteType.generated.h" + +UENUM(BlueprintType) +enum ESardineQuoteType +{ + Buy UMETA(DisplayName = "BUY"), + Sell UMETA(DisplayName = "SELL"), +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineRegion.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineRegion.h new file mode 100644 index 000000000..57cd416f5 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineRegion.h @@ -0,0 +1,52 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardineRegionPaymentMethod.h" +#include "SardineRegionState.h" +#include "SardineRegion.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineRegion +{ + GENERATED_USTRUCT_BODY() + +public: + FString CountryCode; + bool IsAllowedOnRamp; + bool IsAllowedOnNFT; + TArray IsBasicKycRequired; + TArray IsSSNRequired; + FString Name; + FString CurrencyCode; + bool IsPayrollSupported; + TArray SupportedDocuments; + TArray PaymentMethods; + TArray States; + + void Setup(FJsonObject& json_in) + { + json_in.TryGetStringField(TEXT("countryCode"), CountryCode); + json_in.TryGetBoolField(TEXT("isAllowedOnRamp"), IsAllowedOnRamp); + json_in.TryGetBoolField(TEXT("isAllowedOnNFT"), IsAllowedOnNFT); + json_in.TryGetStringArrayField(TEXT("isBasicKycRequired"), IsBasicKycRequired); + json_in.TryGetStringArrayField(TEXT("isSSNRequired"), IsSSNRequired); + json_in.TryGetStringField(TEXT("name"), Name); + json_in.TryGetStringField(TEXT("currencyCode"), CurrencyCode); + json_in.TryGetBoolField(TEXT("isPayrollSupported"), IsPayrollSupported); + json_in.TryGetStringArrayField(TEXT("supportedDocuments"), SupportedDocuments); + + for(TSharedPtr Method : json_in.GetArrayField(TEXT("paymentMethods"))) + { + FSardineRegionPaymentMethod PaymentMethod; + PaymentMethod.Setup(*Method->AsObject()); + PaymentMethods.Add(PaymentMethod); + } + + for(TSharedPtr State : json_in.GetArrayField(TEXT("states"))) + { + FSardineRegionState RegionState; + RegionState.Setup(*State->AsObject()); + States.Add(RegionState); + } + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineRegionPaymentMethod.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineRegionPaymentMethod.h new file mode 100644 index 000000000..ccc2d60d6 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineRegionPaymentMethod.h @@ -0,0 +1,28 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardineRegionPaymentMethod.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineRegionPaymentMethod +{ + GENERATED_USTRUCT_BODY() + +public: + FString Name; + bool IsAllowedOnRamp; + bool IsAllowedOnNFT; + TArray SubTypes; + FString Type; + FString SubType; + + void Setup(FJsonObject& json_in) + { + json_in.TryGetStringField(TEXT("name"), Name); + json_in.TryGetBoolField(TEXT("isAllowedOnRamp"), IsAllowedOnRamp); + json_in.TryGetBoolField(TEXT("isAllowedOnNFT"), IsAllowedOnNFT); + json_in.TryGetStringArrayField(TEXT("subTypes"), SubTypes); + json_in.TryGetStringField(TEXT("type"), Type); + json_in.TryGetStringField(TEXT("subType"), SubType); + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineRegionState.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineRegionState.h new file mode 100644 index 000000000..a89db5205 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineRegionState.h @@ -0,0 +1,25 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardineRegionPaymentMethod.h" +#include "SardineRegionState.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineRegionState +{ + GENERATED_USTRUCT_BODY() + +public: + FString Code; + FString Name; + bool IsAllowedOnRamp; + bool IsAllowedOnNFT; + + void Setup(FJsonObject& json_in) + { + json_in.TryGetStringField(TEXT("code"), Code); + json_in.TryGetStringField(TEXT("name"), Name); + json_in.TryGetBoolField(TEXT("isAllowedOnRamp"), IsAllowedOnRamp); + json_in.TryGetBoolField(TEXT("isAllowedOnNFT"), IsAllowedOnNFT); + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineSupportedFiatCurrenciesResponse.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineSupportedFiatCurrenciesResponse.h new file mode 100644 index 000000000..086f2e0c0 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineSupportedFiatCurrenciesResponse.h @@ -0,0 +1,38 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#pragma once + +#include + +#include "CoreMinimal.h" +#include "SardineEnabledToken.h" +#include "SardineFiatCurrency.h" +#include "SardinePaymentType.h" +#include "SardineQuote.h" +#include "Util/JsonBuilder.h" +#include "SardineQuoteType.h" +#include "SardineSupportedToken.h" +#include "UObject/Object.h" +#include "SardineSupportedFiatCurrenciesResponse.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineSupportedFiatCurrenciesResponse +{ + GENERATED_USTRUCT_BODY() + +public: + TArray Tokens; + + bool customConstructor = false; + + void construct(FJsonObject& json_in) {} + void Setup(FJsonObject& json_in) + { + for(TSharedPtr json : json_in.GetArrayField(TEXT("tokens"))) + { + FSardineFiatCurrency Currency; + Currency.Setup(*json->AsObject()); + Tokens.Add(Currency); + } + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineSupportedRegionsResponse.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineSupportedRegionsResponse.h new file mode 100644 index 000000000..013aeea3b --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineSupportedRegionsResponse.h @@ -0,0 +1,38 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#pragma once + +#include + +#include "CoreMinimal.h" +#include "SardineEnabledToken.h" +#include "SardinePaymentType.h" +#include "SardineQuote.h" +#include "Util/JsonBuilder.h" +#include "SardineQuoteType.h" +#include "SardineRegion.h" +#include "SardineSupportedToken.h" +#include "UObject/Object.h" +#include "SardineSupportedRegionsResponse.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineSupportedRegionsResponse +{ + GENERATED_USTRUCT_BODY() + +public: + TArray Regions; + + bool customConstructor = false; + + void construct(FJsonObject& json_in) {} + void Setup(FJsonObject& json_in) + { + for(TSharedPtr json : json_in.GetArrayField(TEXT("regions"))) + { + FSardineRegion Token; + Token.Setup(*json->AsObject()); + Regions.Add(Token); + } + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineSupportedToken.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineSupportedToken.h new file mode 100644 index 000000000..7d4f5c1da --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineSupportedToken.h @@ -0,0 +1,14 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardineToken.h" +#include "SardineSupportedToken.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineSupportedToken : public FSardineToken +{ + GENERATED_USTRUCT_BODY() + +public: + +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineSupportedTokensResponse.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineSupportedTokensResponse.h new file mode 100644 index 000000000..29cd31c19 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineSupportedTokensResponse.h @@ -0,0 +1,37 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#pragma once + +#include + +#include "CoreMinimal.h" +#include "SardineEnabledToken.h" +#include "SardinePaymentType.h" +#include "SardineQuote.h" +#include "Util/JsonBuilder.h" +#include "SardineQuoteType.h" +#include "SardineSupportedToken.h" +#include "UObject/Object.h" +#include "SardineSupportedTokensResponse.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineSupportedTokensResponse +{ + GENERATED_USTRUCT_BODY() + +public: + TArray Tokens; + + bool customConstructor = false; + + void construct(FJsonObject& json_in) {} + void Setup(FJsonObject& json_in) + { + for(TSharedPtr json : json_in.GetArrayField(TEXT("tokens"))) + { + FSardineSupportedToken Token; + Token.Setup(*json->AsObject()); + Tokens.Add(Token); + } + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineToken.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineToken.h new file mode 100644 index 000000000..73b51a5be --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineToken.h @@ -0,0 +1,30 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SardineToken.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineToken +{ + GENERATED_USTRUCT_BODY() + +public: + FString Network; + FString AssetSymbol; + FString AssetName; + FString ChainID; + FString TokenName; + FString Token; + FString TokenAddress; + + void Setup(FJsonObject& json_in) + { + json_in.TryGetStringField(TEXT("network"), Network); + json_in.TryGetStringField(TEXT("assetSymbol"), AssetSymbol); + json_in.TryGetStringField(TEXT("assetName"), AssetName); + json_in.TryGetStringField(TEXT("chainID"), ChainID); + json_in.TryGetStringField(TEXT("tokenName"), TokenName); + json_in.TryGetStringField(TEXT("token"), Token); + json_in.TryGetStringField(TEXT("tokenAddress"), TokenAddress); + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineTokenResponse.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineTokenResponse.h new file mode 100644 index 000000000..12f85db84 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Sardine/Structs/SardineTokenResponse.h @@ -0,0 +1,27 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#pragma once + +#include + +#include "CoreMinimal.h" +#include "SardineSupportedToken.h" +#include "UObject/Object.h" +#include "SardineTokenResponse.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSardineTokenResponse +{ + GENERATED_USTRUCT_BODY() + +public: + FString Token; + + bool customConstructor = false; + + void construct(FJsonObject& json_in) {} + void Setup(FJsonObject& json_in) + { + Token = json_in.GetStringField(TEXT("token")); + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqCollectibleOrder.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqCollectibleOrder.h index e8344bb80..e39a7bdb9 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqCollectibleOrder.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqCollectibleOrder.h @@ -12,7 +12,6 @@ struct SEQUENCEPLUGIN_API FSeqCollectibleOrder GENERATED_USTRUCT_BODY() public: - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Order") FSeqTokenMetaData TokenMetadata; @@ -32,6 +31,8 @@ struct SEQUENCEPLUGIN_API FSeqCollectibleOrder void Setup(FJsonObject json_in) { + UE_LOG(LogTemp, Warning, TEXT("seq collectible setup start")); + const TSharedPtr* item; if (json_in.TryGetObjectField(TEXT("metadata"), item)) { @@ -43,5 +44,7 @@ struct SEQUENCEPLUGIN_API FSeqCollectibleOrder { Order.Setup(*orderItem->Get()); } + + UE_LOG(LogTemp, Warning, TEXT("seq collectible setup done")); } }; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqCollectiblesFilter.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqCollectiblesFilter.h index fbef9f125..2f0eb9e8e 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqCollectiblesFilter.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqCollectiblesFilter.h @@ -37,6 +37,11 @@ struct SEQUENCEPLUGIN_API FSeqCollectiblesFilter UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") TArray OrdersNotCreatedBy; + static FSeqCollectiblesFilter Empty() + { + return FSeqCollectiblesFilter{}; + } + bool ContainsData() { // Check for valid data in the properties diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqCurrency.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqCurrency.h new file mode 100644 index 000000000..07c24031f --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqCurrency.h @@ -0,0 +1,21 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SeqCurrency.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSeqCurrency +{ + GENERATED_USTRUCT_BODY() + +public: + // Properties + UPROPERTY(EditAnywhere, BlueprintReadWrite) + int ID; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + int ChainID; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FString ContractAddress; +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectibleArgs.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectibleArgs.h new file mode 100644 index 000000000..a6e8a5bf8 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectibleArgs.h @@ -0,0 +1,33 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SeqCollectiblesFilter.h" +#include "SeqMarketplacePage.h" +#include "Util/JsonBuilder.h" +#include "SeqGetCollectibleArgs.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSeqGetCollectibleArgs +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FString ContractAddress; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FString TokenId; + + bool customGetter = true; + + FString GetArgs() + { + FJsonBuilder Builder; + + Builder.AddString("contractAddress", ContractAddress); + Builder.AddString("tokenId", TokenId); + + return Builder.ToString(); + } + +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectibleOrderArgs.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectibleOrderArgs.h new file mode 100644 index 000000000..8734491d4 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectibleOrderArgs.h @@ -0,0 +1,39 @@ +#pragma once + +#include "Util/JsonBuilder.h" +#include "SeqCollectiblesFilter.h" +#include "SeqGetCollectibleOrderArgs.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSeqGetCollectibleOrderArgs +{ + GENERATED_USTRUCT_BODY() + + public: + // Properties + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FString ContractAddress; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FString TokenID; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FSeqCollectiblesFilter Filter; + + bool customGetter = true; + + FString GetArgs() + { + FJsonBuilder Builder; + + Builder.AddString("contractAddress", ContractAddress); + Builder.AddString("tokenID", TokenID); + + if (Filter.ContainsData()) + {// Check if the Filter has data and append its args if it does + Builder.AddField("filter", Filter.GetArgs()); + } + + return Builder.ToString(); + } +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectibleOrderReturn.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectibleOrderReturn.h new file mode 100644 index 000000000..4216bbb27 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectibleOrderReturn.h @@ -0,0 +1,21 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SeqCollectibleOrder.h" +#include "SeqCurrency.h" +#include "SeqGetCollectibleOrderReturn.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSeqGetCollectibleOrderReturn +{ + GENERATED_USTRUCT_BODY() + +public: + bool customConstructor = false;//used to tell buildresponse whether or not to use a custom constructor OR the unreal one! + void construct(FJsonObject json_in) {};//dummy construct for templating + void Setup(FJsonObject json_in) {};//dummy method to allow for templating in build response! + + // Properties + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Order") + FSeqCollectibleOrder Order; +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectibleReturn.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectibleReturn.h new file mode 100644 index 000000000..25c290a19 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectibleReturn.h @@ -0,0 +1,28 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SeqCollectibleOrder.h" +#include "SeqCurrency.h" +#include "SeqGetCollectibleReturn.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSeqGetCollectibleReturn +{ + GENERATED_USTRUCT_BODY() + +public: + bool customConstructor = false;//used to tell buildresponse whether or not to use a custom constructor OR the unreal one! + void construct(FJsonObject json_in) {};//dummy construct for templating + void Setup(FJsonObject json_in) + { + const TSharedPtr* obj; + if(json_in.TryGetObjectField(TEXT("metadata"), obj)) + { + MetaData.Setup(*obj->Get()); + } + }; + + // Properties + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Order") + FSeqTokenMetaData MetaData; +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectiblesWithLowestListingsArgs.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetFloorOrderArgs.h similarity index 62% rename from Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectiblesWithLowestListingsArgs.h rename to Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetFloorOrderArgs.h index de4c11894..e88efd84c 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectiblesWithLowestListingsArgs.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetFloorOrderArgs.h @@ -3,15 +3,15 @@ #include "CoreMinimal.h" #include "SeqCollectiblesFilter.h" #include "SeqMarketplacePage.h" -#include "SeqGetCollectiblesWithLowestListingsArgs.generated.h" +#include "Util/JsonBuilder.h" +#include "SeqGetFloorOrderArgs.generated.h" USTRUCT(BlueprintType) -struct SEQUENCEPLUGIN_API FSeqGetCollectiblesWithLowestListingsArgs +struct SEQUENCEPLUGIN_API FSeqGetFloorOrderArgs { GENERATED_USTRUCT_BODY() public: - // Properties UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") FString ContractAddress; @@ -25,26 +25,22 @@ struct SEQUENCEPLUGIN_API FSeqGetCollectiblesWithLowestListingsArgs FString GetArgs() { - FString ret = "{"; + FJsonBuilder Builder; - ret += "\"contractAddress\":\"" + ContractAddress + "\""; + Builder.AddString("contractAddress", ContractAddress); if (Filter.ContainsData()) {// Check if the Filter has data and append its args if it does - ret.Append(",\"filter\":"); - ret.Append(Filter.GetArgs()); + Builder.AddField("filter", Filter.GetArgs()); } // Check if the Page has data and append its args if it does if (Page.ContainsData()) { - ret.Append(",\"page\":"); - ret.Append(Page.GetArgs()); + Builder.AddString("page", Page.GetArgs()); } - ret.Append("}"); // Close the JSON object - return ret; - + return Builder.ToString(); } }; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetOrderReturn.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetOrderReturn.h new file mode 100644 index 000000000..a072b42c2 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetOrderReturn.h @@ -0,0 +1,21 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SeqCollectibleOrder.h" +#include "Util/JsonBuilder.h" +#include "SeqMarketplacePage.h" +#include "SeqGetOrderReturn.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSeqGetOrderReturn +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FSeqCollectibleOrder Collectible; + + bool customConstructor = false;//used to tell buildresponse whether or not to use a custom constructor OR the unreal one! + void construct(FJsonObject json_in) {};//dummy construct for templating + void Setup(FJsonObject json_in) {};//dummy method to allow for templating in build response! +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectibleListingsArgs.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectibleListingsArgs.h new file mode 100644 index 000000000..6937e8d90 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectibleListingsArgs.h @@ -0,0 +1,50 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SeqCollectiblesFilter.h" +#include "SeqMarketplacePage.h" +#include "Util/JsonBuilder.h" +#include "SeqListCollectibleListingsArgs.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSeqListCollectibleListingsArgs +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FString ContractAddress; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FString TokenID; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FSeqCollectiblesFilter Filter; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FSeqMarketplacePage Page; + + bool customGetter = true; + + FString GetArgs() + { + FJsonBuilder Builder; + + Builder.AddString("contractAddress", ContractAddress); + Builder.AddString("tokenID", TokenID); + + if (Filter.ContainsData()) + {// Check if the Filter has data and append its args if it does + Builder.AddField("filter", Filter.GetArgs()); + } + + // Check if the Page has data and append its args if it does + if (Page.ContainsData()) + { + Builder.AddString("page", Page.GetArgs()); + } + + return Builder.ToString(); + } + +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectibleListingsReturn.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectibleListingsReturn.h new file mode 100644 index 000000000..9bf8ae57e --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectibleListingsReturn.h @@ -0,0 +1,74 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SeqCollectibleOrder.h" +#include "SeqMarketplacePage.h" +#include "SeqListCollectibleListingsReturn.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSeqListCollectibleListingsReturn +{ + GENERATED_USTRUCT_BODY() + +public: + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + TArray Listings; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FSeqMarketplacePage Page; + + bool customConstructor = false; // Flag to determine the constructor used + + // Dummy constructor method to maintain consistency + void construct(FJsonObject json_in) {} + + /* + * Returns a JSON Object for arguments / testing purposes + */ + TSharedPtr GetJson() + { + TSharedPtr ret = MakeShareable(new FJsonObject); + + // Convert Page object to JSON + ret->SetObjectField("page", Page.GetJson()); + + // Convert CollectibleOrders array to JSON + TArray> collectibleOrdersList; + for (FSeqCollectibleOrder order : Listings) + { + collectibleOrdersList.Add(order.GetJson()); + } + + // Set the collectible orders as a simple string array in JSON + ret->SetStringField("listings", USequenceSupport::JsonObjListToSimpleString(collectibleOrdersList)); + return ret; + } + + /* + * Handles edge cases with Unreal's JSON parsing + //*/ + void Setup(FJsonObject json_in) + { + const TArray>* lst; + if (json_in.TryGetArrayField(TEXT("listings"), lst)) + { + Listings.SetNum(lst->Num()); + + for (int32 i = 0; i < lst->Num(); i++) + { + TSharedPtr item = (*lst)[i]; + + if (item.IsValid()) + { + TSharedPtr itemObj = item->AsObject(); + Listings[i].Setup(*itemObj); + } + } + } + else + { + UE_LOG(LogTemp, Warning, TEXT("No collectibles field found in the GetCollectiblesWithLowestListings response.")); + } + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectibleOffersReturn.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectibleOffersReturn.h new file mode 100644 index 000000000..ea00762a4 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectibleOffersReturn.h @@ -0,0 +1,74 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SeqCollectibleOrder.h" +#include "SeqMarketplacePage.h" +#include "SeqListCollectibleOffersReturn.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSeqListCollectibleOffersReturn +{ + GENERATED_USTRUCT_BODY() + +public: + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + TArray Offers; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FSeqMarketplacePage Page; + + bool customConstructor = false; // Flag to determine the constructor used + + // Dummy constructor method to maintain consistency + void construct(FJsonObject json_in) {} + + /* + * Returns a JSON Object for arguments / testing purposes + */ + TSharedPtr GetJson() + { + TSharedPtr ret = MakeShareable(new FJsonObject); + + // Convert Page object to JSON + ret->SetObjectField("page", Page.GetJson()); + + // Convert CollectibleOrders array to JSON + TArray> collectibleOrdersList; + for (FSeqCollectibleOrder order : Offers) + { + collectibleOrdersList.Add(order.GetJson()); + } + + // Set the collectible orders as a simple string array in JSON + ret->SetStringField("listings", USequenceSupport::JsonObjListToSimpleString(collectibleOrdersList)); + return ret; + } + + /* + * Handles edge cases with Unreal's JSON parsing + //*/ + void Setup(FJsonObject json_in) + { + const TArray>* lst; + if (json_in.TryGetArrayField(TEXT("offers"), lst)) + { + Offers.SetNum(lst->Num()); + + for (int32 i = 0; i < lst->Num(); i++) + { + TSharedPtr item = (*lst)[i]; + + if (item.IsValid()) + { + TSharedPtr itemObj = item->AsObject(); + Offers[i].Setup(*itemObj); + } + } + } + else + { + UE_LOG(LogTemp, Warning, TEXT("No collectibles field found in the GetCollectibleOffers response.")); + } + } +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectiblesArgs.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectiblesArgs.h new file mode 100644 index 000000000..d2ff72808 --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectiblesArgs.h @@ -0,0 +1,51 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SeqCollectiblesFilter.h" +#include "SeqMarketplacePage.h" +#include "Util/JsonBuilder.h" +#include "SeqListCollectiblesArgs.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSeqListCollectiblesArgs +{ + GENERATED_USTRUCT_BODY() + +public: + // Properties + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + TEnumAsByte Side; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FString ContractAddress; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FSeqCollectiblesFilter Filter; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collectibles") + FSeqMarketplacePage Page; + + bool customGetter = true; + + FString GetArgs() + { + FJsonBuilder Builder; + + Builder.AddString("side", UEnum::GetValueAsString(Side).ToLower()); + Builder.AddString("contractAddress", ContractAddress); + + if (Filter.ContainsData()) + {// Check if the Filter has data and append its args if it does + Builder.AddField("filter", Filter.GetArgs()); + } + + // Check if the Page has data and append its args if it does + if (Page.ContainsData()) + { + Builder.AddString("page", Page.GetArgs()); + } + + return Builder.ToString(); + } + +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectiblesWithLowestListingsReturn.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectiblesReturn.h similarity index 94% rename from Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectiblesWithLowestListingsReturn.h rename to Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectiblesReturn.h index 19863ef3c..f00c01457 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqGetCollectiblesWithLowestListingsReturn.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCollectiblesReturn.h @@ -3,10 +3,10 @@ #include "CoreMinimal.h" #include "SeqCollectibleOrder.h" #include "SeqMarketplacePage.h" -#include "SeqGetCollectiblesWithLowestListingsReturn.generated.h" +#include "SeqListCollectiblesReturn.generated.h" USTRUCT(BlueprintType) -struct SEQUENCEPLUGIN_API FSeqGetCollectiblesWithLowestListingsReturn +struct SEQUENCEPLUGIN_API FSeqListCollectiblesReturn { GENERATED_USTRUCT_BODY() diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCurrenciesReturn.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCurrenciesReturn.h new file mode 100644 index 000000000..06f5e1ede --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqListCurrenciesReturn.h @@ -0,0 +1,20 @@ +#pragma once + +#include "CoreMinimal.h" +#include "SeqCurrency.h" +#include "SeqListCurrenciesReturn.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSeqListCurrenciesReturn +{ + GENERATED_USTRUCT_BODY() + +public: + bool customConstructor = false;//used to tell buildresponse whether or not to use a custom constructor OR the unreal one! + void construct(FJsonObject json_in) {};//dummy construct for templating + void Setup(FJsonObject json_in) {};//dummy method to allow for templating in build response! + + // Properties + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Page") + TArray Currencies; +}; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqMarketplacePage.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqMarketplacePage.h index b4894ca4f..9c65c493e 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqMarketplacePage.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqMarketplacePage.h @@ -33,6 +33,11 @@ struct SEQUENCEPLUGIN_API FSeqMarketplacePage UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Page") bool More; + static FSeqMarketplacePage Empty() + { + return FSeqMarketplacePage{}; + } + bool ContainsData() { bool ret = false;//assume nothing & look for true states! diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqOrder.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqOrder.h index b99c9bde8..f3a18b9dc 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqOrder.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/SeqOrder.h @@ -196,10 +196,11 @@ struct SEQUENCEPLUGIN_API FSeqOrder TSharedPtr feeValue = feeBreakdownArray[i]; if (feeValue->Type == EJson::Object) { - FSeqFeeBreakdown fee; - TSharedPtr feeJsonObject = USequenceSupport::JsonStringToObject(feeValue->AsString()); - fee.Setup(*feeJsonObject); - FeeBreakdown.Add(fee); + FSeqFeeBreakdown fee; + fee.Setup(*feeValue->AsObject()); + FeeBreakdown.Add(fee); + + UE_LOG(LogTemp, Warning, TEXT("fee setup")); } } } diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/Struct_Data.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/Struct_Data.h index e3dab820b..4d0536e73 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/Struct_Data.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Marketplace/Structs/Struct_Data.h @@ -1,8 +1,8 @@ #pragma once #include "Marketplace/Marketplace_Enums.h" -#include "SeqGetCollectiblesWithLowestListingsArgs.h" -#include "SeqGetCollectiblesWithLowestListingsReturn.h" +#include "SeqListCollectiblesArgs.h" +#include "SeqListCollectiblesReturn.h" #include "SeqCollectiblesFilter.h" #include "SeqPropertyFilter.h" #include "SeqMarketplaceSortBy.h" diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Sequence/SequenceAPI.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Sequence/SequenceAPI.h index a0901ddc2..009948de2 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Sequence/SequenceAPI.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Sequence/SequenceAPI.h @@ -138,6 +138,12 @@ class SEQUENCEPLUGIN_API USequenceWallet : public UGameInstanceSubsystem */ void UpdateProviderURL(const FString& Url) const; + /** + * Allows you to update the provider URL to a node gateway url given the chainID + * @param ChainID ID for chain you want the node gateway to be associated with + */ + void UpdateProviderURL(int64 ChainID) const; + /** * Allows you to update the set network for the SequenceWallet * @param NewNetwork New network you wish to use @@ -310,6 +316,16 @@ class SEQUENCEPLUGIN_API USequenceWallet : public UGameInstanceSubsystem */ void GetTransactionHistory(const FSeqGetTransactionHistoryArgs& Args, const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const; + /* + Get Linked Wallets + */ + void GetLinkedWallets(const TSuccessCallback& OnSuccess, const FFailureCallback& OnFailure) const; + + /* + Remove a Linked Wallet + */ + void RemoveLinkedWallet(const FString& LinkedWalletAddress, const TFunction& OnSuccess, const FFailureCallback& OnFailure) const; + //Provider calls void BlockByNumber(uint64 Number, const TFunction)>& OnSuccess, @@ -349,6 +365,9 @@ class SEQUENCEPLUGIN_API USequenceWallet : public UGameInstanceSubsystem void Call(const FContractCall& ContractCall, EBlockTag Number, const TFunction& OnSuccess, const TFunction& OnFailure) const; + + void Call(const FContractCall& ContractCall, const TFunction& OnSuccess, + const TFunction& OnFailure) const; void NonViewCall(const FEthTransaction& Transaction, const FPrivateKey& PrivateKey, int ChainID, const TFunction& OnSuccess, const TFunction& OnFailure) const; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Sequence/SequenceResponseIntent.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Sequence/SequenceResponseIntent.h index bd5ef2d2c..1acb80ac0 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Sequence/SequenceResponseIntent.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Sequence/SequenceResponseIntent.h @@ -538,6 +538,59 @@ struct SEQUENCEPLUGIN_API FSeqIdTokenResponse } }; +// Wallet Linking + +USTRUCT(Blueprintable) +struct SEQUENCEPLUGIN_API FSeqLinkedWalletRequest +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, meta = (JsonFieldName = "signatureChainId")) + FString SignatureChainId = ""; + + UPROPERTY(BlueprintReadWrite, meta = (JsonFieldName = "parentWalletAddress")) + FString ParentWalletAddress = ""; + + UPROPERTY(BlueprintReadWrite, meta = (JsonFieldName = "parentWalletMessage")) + FString ParentWalletMessage = ""; + + UPROPERTY(BlueprintReadWrite, meta = (JsonFieldName = "parentWalletSignature")) + FString ParentWalletSignature = ""; + + UPROPERTY(BlueprintReadWrite, meta = (JsonFieldName = "linkedWalletAddress")) + FString LinkedWalletAddress = ""; +}; + +USTRUCT(Blueprintable) +struct SEQUENCEPLUGIN_API FSeqLinkedWallet +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, meta = (JsonFieldName = "id")) + int64 Id = 0; + + UPROPERTY(BlueprintReadWrite, meta = (JsonFieldName = "walletType")) + FString WalletType = ""; + + UPROPERTY(BlueprintReadWrite, meta = (JsonFieldName = "walletAddress")) + FString WalletAddress = ""; + + UPROPERTY(BlueprintReadWrite, meta = (JsonFieldName = "linkedWalletAddress")) + FString LinkedWalletAddress = ""; + + UPROPERTY(BlueprintReadWrite, meta = (JsonFieldName = "createdAt")) + FString CreatedAt = ""; +}; + +USTRUCT(Blueprintable) +struct SEQUENCEPLUGIN_API FSeqLinkedWalletsResponse +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, meta = (JsonFieldName = "linkedWallets")) + TArray LinkedWallets; +}; + //Validate Signature// diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Sequence/Wallet_Enums.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Sequence/Wallet_Enums.h new file mode 100644 index 000000000..0451c5dae --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Sequence/Wallet_Enums.h @@ -0,0 +1,45 @@ +#pragma once +#include "SequenceAPI.h" + +#include "Wallet_Enums.generated.h" + +UENUM(BlueprintType) +enum class EWalletKind : uint8 +{ + Unknown UMETA(DisplayName = "unknown"), + Sequence UMETA(DisplayName = "sequence") +}; + +// PropertyType Extensions +UCLASS() +class UMarketplaceWalletKindExtensions : public UObject +{ + GENERATED_BODY() + +public: + template + static EWalletKind GetWalletKind(WalletType) + { + if (std::is_same_v) + { + return EWalletKind::Sequence; + } + + return EWalletKind::Unknown; + } + + template + static FString AsString(EnumType EnumValue); + + template<> + FString AsString(const EWalletKind OrderbookKind) + { + switch (OrderbookKind) + { + case EWalletKind::Sequence: + return FString("sequence"); + default: return FString("unknown"); + } + } + +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/ERC1155SaleContract.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/ERC1155SaleContract.h index 17b824b0e..74e106e8f 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/ERC1155SaleContract.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/ERC1155SaleContract.h @@ -31,10 +31,11 @@ class SEQUENCEPLUGIN_API UERC1155SaleContract : public UObject UFUNCTION(BlueprintCallable, Category = "ERC1155 Sale") FRawTransaction MakePurchaseTransaction(const FString& ToAddress, const TArray& TokenIds, const TArray& Amounts, const TArray& Proof); - + void Initialize(FString _ContractAddress, FString _PaymentToken, int32 _MaxTotal, FString _Data); + FContractCall GetPaymentToken(); FContractCall GetGlobalSaleDetails(); - + FContractCall GetTokenSaleDetails(long TokenID); }; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/ERC20.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/ERC20.h index 895aaff87..86baca228 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/ERC20.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/ERC20.h @@ -1,6 +1,7 @@ #pragma once #include "CoreMinimal.h" +#include "ContractCall.h" #include "UObject/Object.h" #include "Sequence/Transactions.h" #include "ERC20.generated.h" @@ -17,6 +18,8 @@ class SEQUENCEPLUGIN_API UERC20 : public UObject UERC20(FString ContractAddress); + void Initialize(FString ContractAddress); + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn = true), Category = "ERC20") FString ContractAddress; @@ -31,5 +34,9 @@ class SEQUENCEPLUGIN_API UERC20 : public UObject UFUNCTION(BlueprintCallable, Category = "ERC20") FRawTransaction MakeBurnTransaction(const int32 Amount); + + FContractCall MakeSymbolTransaction(); + + FContractCall MakeDecimalsTransaction(); }; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/ERC721SaleContract.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/ERC721SaleContract.h index 2a85a1dc2..3f8c77e2b 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/ERC721SaleContract.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/ERC721SaleContract.h @@ -32,6 +32,8 @@ class SEQUENCEPLUGIN_API UERC721SaleContract : public UObject UFUNCTION(BlueprintCallable, Category = "ERC721 Sale") FRawTransaction MakePurchaseTransaction(const FString& ToAddress, const int32& Amount, const TArray& Proof); + void Initialize(FString _ContractAddress, FString _PaymentToken, int32 _MaxTotal, FString _Data); + FContractCall GetSaleDetails(); }; \ No newline at end of file diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/SaleDetails.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/SaleDetails.h new file mode 100644 index 000000000..5fec1d20c --- /dev/null +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Types/SaleDetails.h @@ -0,0 +1,21 @@ +#pragma once + +#include "BinaryData.h" +#include "SaleDetails.generated.h" + +USTRUCT(BlueprintType) +struct SEQUENCEPLUGIN_API FSaleDetails +{ + GENERATED_USTRUCT_BODY() + +public: + FString PaymentToken; + long Cost; + long SupplyCap; + long StartTimeLong; + long EndTimeLong; + long Amount; + TArray MerkleRoot; + + void Initialize(FUnsizedData Data); +}; diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/HexUtility.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Util/HexUtility.h similarity index 100% rename from Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/HexUtility.h rename to Plugins/SequencePlugin/Source/SequencePlugin/Public/Util/HexUtility.h diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/JsonBuilder.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Util/JsonBuilder.h similarity index 100% rename from Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/JsonBuilder.h rename to Plugins/SequencePlugin/Source/SequencePlugin/Public/Util/JsonBuilder.h diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/Log.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Util/Log.h similarity index 100% rename from Plugins/SequencePlugin/Source/SequencePlugin/Private/Util/Log.h rename to Plugins/SequencePlugin/Source/SequencePlugin/Public/Util/Log.h diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Util/SequenceSupport.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Util/SequenceSupport.h index 36e3a8e6a..27701889b 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Util/SequenceSupport.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Util/SequenceSupport.h @@ -56,6 +56,7 @@ class SEQUENCEPLUGIN_API USequenceSupport : public UObject FIdName(56,TEXT("bsc")), FIdName(100,TEXT("gnosis")), FIdName(137,TEXT("polygon")), + FIdName(273,TEXT("xr1")), FIdName(1101,TEXT("polygon-zkevm")), FIdName(1284,TEXT("moonbeam")), FIdName(1868,TEXT("soneium")), @@ -68,6 +69,7 @@ class SEQUENCEPLUGIN_API USequenceSupport : public UObject FIdName(33139,TEXT("apechain")), FIdName(42161,TEXT("arbitrum")), FIdName(42170,TEXT("arbitrum-nova")), + FIdName(42793,TEXT("etherlink")), FIdName(43114,TEXT("avalanche")), FIdName(81457,TEXT("blast")), FIdName(660279,TEXT("xai")), @@ -87,6 +89,7 @@ class SEQUENCEPLUGIN_API USequenceSupport : public UObject FIdName(62850,TEXT("laos-sigma-testnet")), FIdName(80002,TEXT("amoy")), FIdName(84532,TEXT("base-sepolia")), + FIdName(128123,TEXT("etherlink-testnet")), FIdName(421614,TEXT("arbitrum-sepolia")), FIdName(11155111,TEXT("sepolia")), FIdName(11155420,TEXT("optimism-sepolia")), @@ -118,6 +121,8 @@ class SEQUENCEPLUGIN_API USequenceSupport : public UObject FIdName(1868,TEXT("Soneium")), FIdName(40,TEXT("Telos")), FIdName(1284,TEXT("Moonbeam")), + FIdName(42793, TEXT("Etherlink")), + FIdName(273, TEXT("XR1")), FIdName(13473,TEXT("Immutable Testnet")), FIdName(97,TEXT("BNB Smart Chain Testnet")), @@ -140,6 +145,7 @@ class SEQUENCEPLUGIN_API USequenceSupport : public UObject FIdName(7672,TEXT("Root Network Porcini Testnet")), FIdName(41,TEXT("Telos Testnet")), FIdName(1287,TEXT("Moonbase Alpha")), + FIdName(128123,TEXT("Etherlink Testnet")), }; static inline TMap NetworkNameToIdMap = { @@ -165,6 +171,8 @@ class SEQUENCEPLUGIN_API USequenceSupport : public UObject FNameId(TEXT("soneium"),1868), FNameId(TEXT("telos"),40), FNameId(TEXT("moonbeam"),1284), + FNameId(TEXT("etherlink"),42793), + FNameId(TEXT("xr1"),273), FNameId(TEXT("immutable-testnet"),13473), FNameId(TEXT("bnbsmartchaintestnet"),97), @@ -187,6 +195,57 @@ class SEQUENCEPLUGIN_API USequenceSupport : public UObject FNameId(TEXT("rootnet-porcini"),7672), FNameId(TEXT("telos-testnet"), 41), FNameId(TEXT("moonbase-alpha"),1287), + FNameId(TEXT("etherlink-testnet"),128123), + }; + + static inline TMap NetworkIdToEnumMap = { + {1, ENetwork::Ethereum}, + {13371, ENetwork::Immutable}, + {1482601649, ENetwork::SkaleNebula}, + {10, ENetwork::Optimism}, + {56, ENetwork::BNBSmartChain}, + {100, ENetwork::GnosisChain}, + {137, ENetwork::PolygonChain}, + {1101, ENetwork::PolygonZkEVM}, + {8333, ENetwork::B3}, + {8453, ENetwork::Base}, + {19011, ENetwork::OasysHomeverse}, + {33139, ENetwork::APEChain}, + {42161, ENetwork::ArbitrumOne}, + {42170, ENetwork::ArbitrumNova}, + {43114, ENetwork::Avalanche}, + {81457, ENetwork::Blast}, + {660279, ENetwork::Xai}, + {6283, ENetwork::LAOS}, + {7668, ENetwork::Root}, + {1868, ENetwork::Soneium}, + {40, ENetwork::Telos}, + {1284, ENetwork::Moonbeam}, + {42793, ENetwork::Etherlink}, + {273, ENetwork::XR1}, + + {13473, ENetwork::ImmutableTestnet}, + {97, ENetwork::BNBSmartChainTestnet}, + {1946, ENetwork::SoneiumMinatoTestnet}, + {1993, ENetwork::B3Sepolia}, + {2730, ENetwork::XRSepolia}, + {33111, ENetwork::APEChainTestnet}, + {40875, ENetwork::OasysHomeverseTestnet}, + {43113, ENetwork::AvalancheTestnet}, + {80002, ENetwork::PolygonAmoy}, + {84532, ENetwork::BaseSepolia}, + {421614, ENetwork::ArbitrumSepolia}, + {11155111, ENetwork::Sepolia}, + {11155420, ENetwork::OptimismSepolia}, + {21000000, ENetwork::TOYTestnet}, + {37084624, ENetwork::SKALENebulaGamingHubTestnet}, + {168587773, ENetwork::BlastSepolia}, + {37714555429, ENetwork::XaiSepolia}, + {62850, ENetwork::LAOSSigma}, + {7672, ENetwork::RootPorcini}, + {41, ENetwork::TelosTestnet}, + {1287, ENetwork::MoonbaseAlpha}, + {128123, ENetwork::EtherlinkTestnet}, }; static inline TMap NetworkEnumToIdMap = { @@ -212,6 +271,8 @@ class SEQUENCEPLUGIN_API USequenceSupport : public UObject {ENetwork::Soneium, 1868}, {ENetwork::Telos, 40}, {ENetwork::Moonbeam, 1284}, + {ENetwork::Etherlink, 42793}, + {ENetwork::XR1, 273}, {ENetwork::ImmutableTestnet, 13473}, {ENetwork::BNBSmartChainTestnet, 97}, @@ -234,6 +295,7 @@ class SEQUENCEPLUGIN_API USequenceSupport : public UObject {ENetwork::RootPorcini, 7672}, {ENetwork::TelosTestnet, 41}, {ENetwork::MoonbaseAlpha, 1287}, + {ENetwork::EtherlinkTestnet, 128123}, }; static inline TMap NetworkEnumToNameMap = { @@ -259,6 +321,8 @@ class SEQUENCEPLUGIN_API USequenceSupport : public UObject {ENetwork::Soneium, TEXT("Soneium")}, {ENetwork::Telos, TEXT("Telos")}, {ENetwork::Moonbeam, TEXT("Moonbeam")}, + {ENetwork::Etherlink, TEXT("Etherlink")}, + {ENetwork::XR1, TEXT("XR1")}, {ENetwork::ImmutableTestnet, TEXT("Immutable Testnet")}, {ENetwork::BNBSmartChainTestnet, TEXT("BNB Smart Chain Testnet")}, @@ -281,6 +345,57 @@ class SEQUENCEPLUGIN_API USequenceSupport : public UObject {ENetwork::RootPorcini, TEXT("Root Network Porcini Testnet")}, {ENetwork::TelosTestnet, TEXT("Telos Testnet")}, {ENetwork::MoonbaseAlpha, TEXT("Moonbase Alpha")}, + {ENetwork::EtherlinkTestnet, TEXT("Etherlink Testnet")}, + }; + + static inline TMap NetworkEnumToSymbolMap = { + {ENetwork::Ethereum, TEXT("ETH")}, + {ENetwork::Immutable, TEXT("IMX")}, + {ENetwork::SkaleNebula, TEXT("sFUEL")}, + {ENetwork::Optimism, TEXT("OP")}, + {ENetwork::BNBSmartChain, TEXT("BNB")}, + {ENetwork::GnosisChain, TEXT("xDai")}, + {ENetwork::PolygonChain, TEXT("POL")}, + {ENetwork::PolygonZkEVM, TEXT("POL")}, + {ENetwork::B3, TEXT("ETH")}, + {ENetwork::Base, TEXT("ETH")}, + {ENetwork::OasysHomeverse, TEXT("OAS")}, + {ENetwork::APEChain, TEXT("APE")}, + {ENetwork::ArbitrumOne, TEXT("AETH")}, + {ENetwork::ArbitrumNova, TEXT("AETH")}, + {ENetwork::Avalanche, TEXT("AVAX")}, + {ENetwork::Blast, TEXT("ETH")}, + {ENetwork::Xai, TEXT("XAI")}, + {ENetwork::LAOS, TEXT("LAOS")}, + {ENetwork::Root, TEXT("XRP")}, + {ENetwork::Soneium, TEXT("ETH")}, + {ENetwork::Telos, TEXT("TLOS")}, + {ENetwork::Moonbeam, TEXT("GLMR")}, + {ENetwork::Etherlink, TEXT("XTZ")}, + {ENetwork::XR1, TEXT("XR1")}, + + {ENetwork::ImmutableTestnet, TEXT("IMX")}, + {ENetwork::BNBSmartChainTestnet, TEXT("BNB")}, + {ENetwork::SoneiumMinatoTestnet, TEXT("ETH")}, + {ENetwork::B3Sepolia, TEXT("ETH")}, + {ENetwork::XRSepolia, TEXT("tXR")}, + {ENetwork::APEChainTestnet, TEXT("APE")}, + {ENetwork::OasysHomeverseTestnet, TEXT("OAS")}, + {ENetwork::AvalancheTestnet, TEXT("AVAX")}, + {ENetwork::PolygonAmoy, TEXT("POL")}, + {ENetwork::BaseSepolia, TEXT("ETH")}, + {ENetwork::ArbitrumSepolia, TEXT("AETH")}, + {ENetwork::Sepolia, TEXT("Sepolia")}, + {ENetwork::OptimismSepolia, TEXT("OP")}, + {ENetwork::TOYTestnet, TEXT("TOY")}, + {ENetwork::SKALENebulaGamingHubTestnet, TEXT("sFUEL")}, + {ENetwork::BlastSepolia, TEXT("ETH")}, + {ENetwork::XaiSepolia, TEXT("sXAI")}, + {ENetwork::LAOSSigma, TEXT("SIGMA")}, + {ENetwork::RootPorcini, TEXT("XRP")}, + {ENetwork::TelosTestnet, TEXT("TLOS")}, + {ENetwork::MoonbaseAlpha, TEXT("DEV")}, + {ENetwork::EtherlinkTestnet, TEXT("XTZ")}, }; public: @@ -294,9 +409,14 @@ class SEQUENCEPLUGIN_API USequenceSupport : public UObject static FString GetNetworkName(const ENetwork NetworkIn); + static ENetwork GetNetworkFromId(const int64 NetworkIdIn); static FString GetNetworkNameForUrl(const int64 NetworkIdIn); + static FString GetNetworkSymbol(const ENetwork NetworkIn); + + static FString GetNetworkSymbol(const int64 NetworkIn); + static bool IsNetworkIdSupported(const int64 NetworkIdIn); /** diff --git a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Util/Structs/BE_Enums.h b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Util/Structs/BE_Enums.h index dcb9979b6..a5e026022 100644 --- a/Plugins/SequencePlugin/Source/SequencePlugin/Public/Util/Structs/BE_Enums.h +++ b/Plugins/SequencePlugin/Source/SequencePlugin/Public/Util/Structs/BE_Enums.h @@ -38,6 +38,8 @@ enum ENetwork Soneium UMETA(DisplayName = "Soneium"), Telos UMETA(DisplayName = "Telos"), Moonbeam UMETA(DisplayName = "Moonbeam"), + Etherlink UMETA(DisplayName = "Etherlink"), + XR1 UMETA(DisplayName = "XR1"), ImmutableTestnet UMETA(DisplayName = "Immutable Testnet"), BNBSmartChainTestnet UMETA(DisplayName = "BNB Smart Chain Testnet"), @@ -60,4 +62,5 @@ enum ENetwork RootPorcini UMETA(DisplayName = "Root Network Porcini Testnet"), TelosTestnet UMETA(DisplayName = "Telos Testnet"), MoonbaseAlpha UMETA(DisplayName = "Moonbase Alpha"), + EtherlinkTestnet UMETA(DisplayName = "Etherlink Testnet"), }; \ No newline at end of file diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/Helpers/IndexerEndToEndTestsCommon.h b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/Helpers/IndexerEndToEndTestsCommon.h index 68b991e54..73d0dc918 100644 --- a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/Helpers/IndexerEndToEndTestsCommon.h +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/Helpers/IndexerEndToEndTestsCommon.h @@ -4,7 +4,7 @@ #include "CoreMinimal.h" -namespace IndexerEndToEndTestsCommon +namespace MarketplaceEndToEndTestsCommon { const FString TestAddress = TEXT("0x8e3E38fe7367dd3b52D1e281E4e8400447C8d8B9"); // From the Sequence Docs - this address has a fair amount of tokens held on Polygon and works great for our test cases const int64 PolygonNetworkId = 137; diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetEtherBalanceTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetEtherBalanceTest.cpp index cfc5ca547..38d838606 100644 --- a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetEtherBalanceTest.cpp +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetEtherBalanceTest.cpp @@ -39,8 +39,8 @@ void FIndexerGetEtherBalanceTest::GetTests(TArray& OutBeautifiedNames, bool FIndexerGetEtherBalanceTest::RunTest(const FString& Parameters) { - const int64 PolygonNetworkId = IndexerEndToEndTestsCommon::PolygonNetworkId; - const FString& TestAddress = IndexerEndToEndTestsCommon::TestAddress; + const int64 PolygonNetworkId = MarketplaceEndToEndTestsCommon::PolygonNetworkId; + const FString& TestAddress = MarketplaceEndToEndTestsCommon::TestAddress; UIndexerRequestsTestData * IndexerRequestsTestData = UIndexerRequestsTestData::Make(1); const TSuccessCallback GenericSuccess = [this, IndexerRequestsTestData, TestAddress](const FSeqEtherBalance& Balance) diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenBalanceTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenBalanceTest.cpp index 5d6ef564d..775c6a790 100644 --- a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenBalanceTest.cpp +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenBalanceTest.cpp @@ -2,6 +2,7 @@ #include "CoreMinimal.h" #include "Helpers/IndexerEndToEndTestsCommon.h" +#include "Helpers/IndexerRequestsTestData.h" #include "Misc/AutomationTest.h" #include "Util/Async.h" #include "Util/SequenceSupport.h" @@ -39,8 +40,8 @@ void FIndexerGetTokenBalancesTest::GetTests(TArray& OutBeautifiedNames, bool FIndexerGetTokenBalancesTest::RunTest(const FString& Parameters) { - const int64 PolygonNetworkId = IndexerEndToEndTestsCommon::PolygonNetworkId; - const FString& TestAddress = IndexerEndToEndTestsCommon::TestAddress; + const int64 PolygonNetworkId = MarketplaceEndToEndTestsCommon::PolygonNetworkId; + const FString& TestAddress = MarketplaceEndToEndTestsCommon::TestAddress; UIndexerRequestsTestData * IndexerRequestsTestData = UIndexerRequestsTestData::Make(1); const TSuccessCallback GenericSuccess = [this, IndexerRequestsTestData](const FSeqGetTokenBalancesReturn& TokenBalances) diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenBalancesAsMapTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenBalancesAsMapTest.cpp index 33a3f05be..045f6c089 100644 --- a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenBalancesAsMapTest.cpp +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenBalancesAsMapTest.cpp @@ -39,8 +39,8 @@ void FIndexerGetTokenBalancesOrganizedInMapTest::GetTests(TArray& OutBe bool FIndexerGetTokenBalancesOrganizedInMapTest::RunTest(const FString& Parameters) { - const int64 PolygonNetworkId = IndexerEndToEndTestsCommon::PolygonNetworkId; - const FString& TestAddress = IndexerEndToEndTestsCommon::TestAddress; + const int64 PolygonNetworkId = MarketplaceEndToEndTestsCommon::PolygonNetworkId; + const FString& TestAddress = MarketplaceEndToEndTestsCommon::TestAddress; UIndexerRequestsTestData * IndexerRequestsTestData = UIndexerRequestsTestData::Make(1); const TSuccessCallback GenericSuccess = [this, IndexerRequestsTestData](const FSeqGetTokenBalancesReturn& TokenBalances) diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenSuppliesMapTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenSuppliesMapTest.cpp index 8b5cf876f..ae8639c4e 100644 --- a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenSuppliesMapTest.cpp +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenSuppliesMapTest.cpp @@ -36,12 +36,12 @@ void FIndexerGetTokenSuppliesMapTest::GetTests(TArray& OutBeautifiedNam bool FIndexerGetTokenSuppliesMapTest::RunTest(const FString& Parameters) { - const int64 PolygonNetworkId = IndexerEndToEndTestsCommon::PolygonNetworkId; + const int64 PolygonNetworkId = MarketplaceEndToEndTestsCommon::PolygonNetworkId; UIndexerRequestsTestData* IndexerRequestsTestData = UIndexerRequestsTestData::Make(1); - const FString UsdcAddress = IndexerEndToEndTestsCommon::TestContractAddress_USDC; - const FString WmaticAddress = IndexerEndToEndTestsCommon::TestContractAddress_WMATIC; - const FString SkyweaverAddress = IndexerEndToEndTestsCommon::TestContractAddress_Skyweaver; + const FString UsdcAddress = MarketplaceEndToEndTestsCommon::TestContractAddress_USDC; + const FString WmaticAddress = MarketplaceEndToEndTestsCommon::TestContractAddress_WMATIC; + const FString SkyweaverAddress = MarketplaceEndToEndTestsCommon::TestContractAddress_Skyweaver; const FString SkyweaverTokenId1 = "68657"; const FString SkyweaverTokenId2 = "66669"; const FString SkyweaverTokenId3 = "66668"; diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenSuppliesTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenSuppliesTest.cpp index 14a99fe06..07a1bbaad 100644 --- a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenSuppliesTest.cpp +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTokenSuppliesTest.cpp @@ -39,8 +39,8 @@ void FIndexerGetTokenSuppliesTest::GetTests(TArray& OutBeautifiedNames, bool FIndexerGetTokenSuppliesTest::RunTest(const FString& Parameters) { - const int64 PolygonNetworkId = IndexerEndToEndTestsCommon::PolygonNetworkId; - const FString TestAddress = IndexerEndToEndTestsCommon::TestContractAddress_Skyweaver; + const int64 PolygonNetworkId = MarketplaceEndToEndTestsCommon::PolygonNetworkId; + const FString TestAddress = MarketplaceEndToEndTestsCommon::TestContractAddress_Skyweaver; UIndexerRequestsTestData * IndexerRequestsTestData = UIndexerRequestsTestData::Make(1); const TSuccessCallback GenericSuccess = [this, IndexerRequestsTestData](const FSeqGetTokenSuppliesReturn& TokenSupplies) diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTransactionHistoryTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTransactionHistoryTest.cpp index f043c34ea..0ab6bd7d7 100644 --- a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTransactionHistoryTest.cpp +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerGetTransactionHistoryTest.cpp @@ -36,8 +36,8 @@ void FIndexerGetTransactionHistoryTest::GetTests(TArray& OutBeautifiedN bool FIndexerGetTransactionHistoryTest::RunTest(const FString& Parameters) { - const int64 PolygonNetworkId = IndexerEndToEndTestsCommon::PolygonNetworkId; - const FString TestAddress = IndexerEndToEndTestsCommon::TestAddress; + const int64 PolygonNetworkId = MarketplaceEndToEndTestsCommon::PolygonNetworkId; + const FString TestAddress = MarketplaceEndToEndTestsCommon::TestAddress; UIndexerRequestsTestData* IndexerRequestsTestData = UIndexerRequestsTestData::Make(1); const TSuccessCallback GenericSuccess = [this, IndexerRequestsTestData](const FSeqGetTransactionHistoryReturn& History) diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerPingTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerPingTest.cpp index 7a864ad1f..1f8c9a3ae 100644 --- a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerPingTest.cpp +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerPingTest.cpp @@ -6,6 +6,7 @@ #include "Util/SequenceSupport.h" #include "IndexerEndToEndTests/Helpers/IndexerRequestsTestData.h" #include "Helpers/BatchTestBuilder.h" // Include the BatchTestBuilder header +#include "Helpers/IndexerRequestsTestData.h" IMPLEMENT_COMPLEX_AUTOMATION_TEST(FIndexerPingTest, "SequencePlugin.EndToEnd.IndexerTests.PingTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerVersionTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerVersionTest.cpp index 719d525dc..7dfeda953 100644 --- a/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerVersionTest.cpp +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/IndexerEndToEndTests/IndexerVersionTest.cpp @@ -6,6 +6,7 @@ #include "Util/SequenceSupport.h" #include "IndexerEndToEndTests/Helpers/IndexerRequestsTestData.h" #include "Helpers/BatchTestBuilder.h" // Include the BatchTestBuilder header +#include "Helpers/IndexerRequestsTestData.h" IMPLEMENT_COMPLEX_AUTOMATION_TEST(FIndexerVersionTest, "SequencePlugin.EndToEnd.IndexerTests.VersionTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetFloorOrderTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetFloorOrderTest.cpp new file mode 100644 index 000000000..29bd7ae7c --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetFloorOrderTest.cpp @@ -0,0 +1,83 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#include + +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "SequencePlugin/Public/Sequence/SequenceAPI.h" +#include "Engine/World.h" +#include "Helpers/MarketplaceRequestsTestData.h" +#include "Marketplace/Marketplace.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "JsonObjectConverter.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FGetFloorOrderTest, "SequencePlugin.EndToEnd.MarketplaceTests.GetFloorOrder", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter | EAutomationTestFlags::ClientContext) + +/* Latent command used to poll off main thread to see if our requests are done */ +DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER(FGetFloorOrderTestIsDone, const UMarketplaceRequestsTestData *, MarketPlaceRequestsTestData, FAutomationTestBase *, FGetFloorOrderTest); + +bool FGetFloorOrderTestIsDone::Update() +{ + while(this->MarketPlaceRequestsTestData->GetPendingRequests() > 0) + { + return false; + } + + if (this->MarketPlaceRequestsTestData->GetAllRequestsSuccessful()) + { + FGetFloorOrderTest->AddInfo(TEXT("GetFloorOrderTest request completed")); + } + else + { + FGetFloorOrderTest->AddError(FString::Printf(TEXT("GetFloorOrderTest request failed"))); + } + + return true; +} + +void FGetFloorOrderTest::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("Get Floor Order Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FGetFloorOrderTest::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Testing Get Floor Order")); + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + USequenceSupport* Support = NewObject(); + + UMarketplaceRequestsTestData* MarketplaceTestData = UMarketplaceRequestsTestData::Make(1); + + const TSuccessCallback GenericSuccess = [this, MarketplaceTestData](FSeqCollectibleOrder Order) + { + AddInfo(FString::Printf(TEXT("ID: %s. Remaining tests: %d"), *Order.Order.OrderId, MarketplaceTestData->DecrementPendingRequests())); + }; + + const FFailureCallback GenericFailure = [this, MarketplaceTestData](const FSequenceError& Error) + { + const FString Message = "Get Floor Order Failure"; + AddError(FString::Printf(TEXT("%s with error: %s. Remaining tests: %d"), + *Message, + *Error.Message, + MarketplaceTestData->DecrementPendingRequests())); + MarketplaceTestData->RequestFailed(); + }; + + MarketplaceTestData->GetMarketplace()->GetFloorOrder( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x44b3f42e2BF34F62868Ff9e9dAb7C2F807ba97Cb", + FSeqCollectiblesFilter::Empty(), + GenericSuccess, + GenericFailure + ); + + ADD_LATENT_AUTOMATION_COMMAND(FGetFloorOrderTestIsDone(MarketplaceTestData, this)); + return true; + })); + return true; +} \ No newline at end of file diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetHighestPriceListingForCollectibleTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetHighestPriceListingForCollectibleTest.cpp new file mode 100644 index 000000000..7e22b66c3 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetHighestPriceListingForCollectibleTest.cpp @@ -0,0 +1,82 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "SequencePlugin/Public/Sequence/SequenceAPI.h" +#include "Engine/World.h" +#include "Helpers/MarketplaceRequestsTestData.h" +#include "Marketplace/Marketplace.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "JsonObjectConverter.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FGetHighestPriceListingForCollectibleTest, "SequencePlugin.EndToEnd.MarketplaceTests.GetHighestPriceListingForCollectibleTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter | EAutomationTestFlags::ClientContext) + +/* Latent command used to poll off main thread to see if our requests are done */ +DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER(FGetHighestPriceListingForCollectibleTestIsDone, const UMarketplaceRequestsTestData *, MarketPlaceRequestsTestData, FAutomationTestBase *, FGetHighestPriceListingForCollectibleTest); + +bool FGetHighestPriceListingForCollectibleTestIsDone::Update() +{ + while(this->MarketPlaceRequestsTestData->GetPendingRequests() > 0) + { + return false; + } + + if (this->MarketPlaceRequestsTestData->GetAllRequestsSuccessful()) + { + FGetHighestPriceListingForCollectibleTest->AddInfo(TEXT("GetFloorOrderTest request completed")); + } + else + { + FGetHighestPriceListingForCollectibleTest->AddError(FString::Printf(TEXT("GetFloorOrderTest request failed"))); + } + + return true; +} + +void FGetHighestPriceListingForCollectibleTest::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("Get Highest Price Listing For Collectible Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FGetHighestPriceListingForCollectibleTest::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Testing Get Highest Price Listing For Collectible")); + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + USequenceSupport* Support = NewObject(); + + UMarketplaceRequestsTestData* MarketplaceTestData = UMarketplaceRequestsTestData::Make(1); + + const TSuccessCallback GenericSuccess = [this, MarketplaceTestData](FSeqCollectibleOrder Order) + { + AddInfo(FString::Printf(TEXT("%s. Remaining tests: %d"), *Order.Order.OrderId, MarketplaceTestData->DecrementPendingRequests())); + }; + + const FFailureCallback GenericFailure = [this, MarketplaceTestData](const FSequenceError& Error) + { + const FString Message = "Get Highest Price Listing For Collectible Failure"; + AddError(FString::Printf(TEXT("%s with error: %s. Remaining tests: %d"), + *Message, + *Error.Message, + MarketplaceTestData->DecrementPendingRequests())); + MarketplaceTestData->RequestFailed(); + }; + + MarketplaceTestData->GetMarketplace()->GetHighestPriceListingForCollectible( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x079294e6ffec16234578c672fa3fbfd4b6c48640", + "1", + FSeqCollectiblesFilter::Empty(), + GenericSuccess, + GenericFailure + ); + + ADD_LATENT_AUTOMATION_COMMAND(FGetHighestPriceListingForCollectibleTestIsDone(MarketplaceTestData, this)); + return true; + })); + return true; +} \ No newline at end of file diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetHighestPriceOfferForCollectibleTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetHighestPriceOfferForCollectibleTest.cpp new file mode 100644 index 000000000..01b74523f --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetHighestPriceOfferForCollectibleTest.cpp @@ -0,0 +1,82 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "SequencePlugin/Public/Sequence/SequenceAPI.h" +#include "Engine/World.h" +#include "Helpers/MarketplaceRequestsTestData.h" +#include "Marketplace/Marketplace.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "JsonObjectConverter.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FGetHighestPriceOfferForCollectibleTest, "SequencePlugin.EndToEnd.MarketplaceTests.GetHighestPriceOfferForCollectibleTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter | EAutomationTestFlags::ClientContext) + +/* Latent command used to poll off main thread to see if our requests are done */ +DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER(FGetHighestPriceOfferForCollectibleTestIsDone, const UMarketplaceRequestsTestData *, MarketPlaceRequestsTestData, FAutomationTestBase *, FGetHighestPriceOfferForCollectibleTest); + +bool FGetHighestPriceOfferForCollectibleTestIsDone::Update() +{ + while(this->MarketPlaceRequestsTestData->GetPendingRequests() > 0) + { + return false; + } + + if (this->MarketPlaceRequestsTestData->GetAllRequestsSuccessful()) + { + FGetHighestPriceOfferForCollectibleTest->AddInfo(TEXT("GetFloorOrderTest request completed")); + } + else + { + FGetHighestPriceOfferForCollectibleTest->AddError(FString::Printf(TEXT("GetFloorOrderTest request failed"))); + } + + return true; +} + +void FGetHighestPriceOfferForCollectibleTest::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("Get Highest Price Offer For Collectible Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FGetHighestPriceOfferForCollectibleTest::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Testing Get Highest Price Offer For Collectible")); + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + USequenceSupport* Support = NewObject(); + + UMarketplaceRequestsTestData* MarketplaceTestData = UMarketplaceRequestsTestData::Make(1); + + const TSuccessCallback GenericSuccess = [this, MarketplaceTestData](FSeqCollectibleOrder Order) + { + AddInfo(FString::Printf(TEXT("%s. Remaining tests: %d"), *Order.Order.OrderId, MarketplaceTestData->DecrementPendingRequests())); + }; + + const FFailureCallback GenericFailure = [this, MarketplaceTestData](const FSequenceError& Error) + { + const FString Message = "Get Highest Price Offer For Collectible Failure"; + AddError(FString::Printf(TEXT("%s with error: %s. Remaining tests: %d"), + *Message, + *Error.Message, + MarketplaceTestData->DecrementPendingRequests())); + MarketplaceTestData->RequestFailed(); + }; + + MarketplaceTestData->GetMarketplace()->GetHighestPriceOfferForCollectible( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x079294e6ffec16234578c672fa3fbfd4b6c48640", + "1", + FSeqCollectiblesFilter::Empty(), + GenericSuccess, + GenericFailure + ); + + ADD_LATENT_AUTOMATION_COMMAND(FGetHighestPriceOfferForCollectibleTestIsDone(MarketplaceTestData, this)); + return true; + })); + return true; +} \ No newline at end of file diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetLowestPriceListingForCollectibleTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetLowestPriceListingForCollectibleTest.cpp new file mode 100644 index 000000000..868330f08 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetLowestPriceListingForCollectibleTest.cpp @@ -0,0 +1,82 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "SequencePlugin/Public/Sequence/SequenceAPI.h" +#include "Engine/World.h" +#include "Helpers/MarketplaceRequestsTestData.h" +#include "Marketplace/Marketplace.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "JsonObjectConverter.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FGetLowestPriceListingForCollectibleTest, "SequencePlugin.EndToEnd.MarketplaceTests.GetLowestPriceListingForCollectibleTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter | EAutomationTestFlags::ClientContext) + +/* Latent command used to poll off main thread to see if our requests are done */ +DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER(FGetLowestPriceListingForCollectibleTestIsDone, const UMarketplaceRequestsTestData *, MarketPlaceRequestsTestData, FAutomationTestBase *, FGetLowestPriceListingForCollectibleTest); + +bool FGetLowestPriceListingForCollectibleTestIsDone::Update() +{ + while(this->MarketPlaceRequestsTestData->GetPendingRequests() > 0) + { + return false; + } + + if (this->MarketPlaceRequestsTestData->GetAllRequestsSuccessful()) + { + FGetLowestPriceListingForCollectibleTest->AddInfo(TEXT("GetFloorOrderTest request completed")); + } + else + { + FGetLowestPriceListingForCollectibleTest->AddError(FString::Printf(TEXT("GetFloorOrderTest request failed"))); + } + + return true; +} + +void FGetLowestPriceListingForCollectibleTest::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("Get Lowest Price Listing For Collectible Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FGetLowestPriceListingForCollectibleTest::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Testing Get Lowest Price Listing For Collectible")); + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + USequenceSupport* Support = NewObject(); + + UMarketplaceRequestsTestData* MarketplaceTestData = UMarketplaceRequestsTestData::Make(1); + + const TSuccessCallback GenericSuccess = [this, MarketplaceTestData](FSeqCollectibleOrder Order) + { + AddInfo(FString::Printf(TEXT("%s. Remaining tests: %d"), *Order.Order.OrderId, MarketplaceTestData->DecrementPendingRequests())); + }; + + const FFailureCallback GenericFailure = [this, MarketplaceTestData](const FSequenceError& Error) + { + const FString Message = "Get Lowest Price Listing For Collectible Failure"; + AddError(FString::Printf(TEXT("%s with error: %s. Remaining tests: %d"), + *Message, + *Error.Message, + MarketplaceTestData->DecrementPendingRequests())); + MarketplaceTestData->RequestFailed(); + }; + + MarketplaceTestData->GetMarketplace()->GetLowestPriceListingForCollectible( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x079294e6ffec16234578c672fa3fbfd4b6c48640", + "1", + FSeqCollectiblesFilter::Empty(), + GenericSuccess, + GenericFailure + ); + + ADD_LATENT_AUTOMATION_COMMAND(FGetLowestPriceListingForCollectibleTestIsDone(MarketplaceTestData, this)); + return true; + })); + return true; +} \ No newline at end of file diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetLowestPriceOfferForCollectibleTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetLowestPriceOfferForCollectibleTest.cpp new file mode 100644 index 000000000..9242ea6e1 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/GetLowestPriceOfferForCollectibleTest.cpp @@ -0,0 +1,83 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "SequencePlugin/Public/Sequence/SequenceAPI.h" +#include "Engine/World.h" +#include "Helpers/MarketplaceRequestsTestData.h" +#include "Marketplace/Marketplace.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "JsonObjectConverter.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FGetLowestPriceOfferForCollectibleTest, "SequencePlugin.EndToEnd.MarketplaceTests.GetLowestPriceOfferForCollectibleTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter | EAutomationTestFlags::ClientContext) + +/* Latent command used to poll off main thread to see if our requests are done */ +DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER(FGetLowestPriceOfferForCollectibleTestIsDone, const UMarketplaceRequestsTestData *, MarketPlaceRequestsTestData, FAutomationTestBase *, FGetLowestPriceOfferForCollectibleTest); + +bool FGetLowestPriceOfferForCollectibleTestIsDone::Update() +{ + while(this->MarketPlaceRequestsTestData->GetPendingRequests() > 0) + { + return false; + } + + if (this->MarketPlaceRequestsTestData->GetAllRequestsSuccessful()) + { + FGetLowestPriceOfferForCollectibleTest->AddInfo(TEXT("GetFloorOrderTest request completed")); + } + else + { + FGetLowestPriceOfferForCollectibleTest->AddError(FString::Printf(TEXT("GetFloorOrderTest request failed"))); + } + + return true; +} + + +void FGetLowestPriceOfferForCollectibleTest::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("Get Lowest Price Offer For Collectible Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FGetLowestPriceOfferForCollectibleTest::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Testing Get Lowest Price Offer For Collectible")); + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + USequenceSupport* Support = NewObject(); + + UMarketplaceRequestsTestData* MarketplaceTestData = UMarketplaceRequestsTestData::Make(1); + + const TSuccessCallback GenericSuccess = [this, MarketplaceTestData](FSeqCollectibleOrder Order) + { + AddInfo(FString::Printf(TEXT("%s. Remaining tests: %d"), *Order.Order.OrderId, MarketplaceTestData->DecrementPendingRequests())); + }; + + const FFailureCallback GenericFailure = [this, MarketplaceTestData](const FSequenceError& Error) + { + const FString Message = "Get Lowest Price Offer For Collectible Failure"; + AddError(FString::Printf(TEXT("%s with error: %s. Remaining tests: %d"), + *Message, + *Error.Message, + MarketplaceTestData->DecrementPendingRequests())); + MarketplaceTestData->RequestFailed(); + }; + + MarketplaceTestData->GetMarketplace()->GetLowestPriceOfferForCollectible( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x079294e6ffec16234578c672fa3fbfd4b6c48640", + "1", + FSeqCollectiblesFilter::Empty(), + GenericSuccess, + GenericFailure + ); + + ADD_LATENT_AUTOMATION_COMMAND(FGetLowestPriceOfferForCollectibleTestIsDone(MarketplaceTestData, this)); + return true; + })); + return true; +} \ No newline at end of file diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/Helpers/BatchTestBuilder.h b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/Helpers/BatchTestBuilder.h new file mode 100644 index 000000000..f5966f042 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/Helpers/BatchTestBuilder.h @@ -0,0 +1,37 @@ +#pragma once + +class FBatchTestBuilder +{ +public: + FBatchTestBuilder(int32 InBatchSize, int32 InTotalItems) + : BatchSize(InBatchSize), TotalItems(InTotalItems), StartIndex(0), EndIndex(FMath::Min(BatchSize - 1, TotalItems - 1)) + { + } + + bool CanBuildBatch() const + { + return StartIndex < TotalItems; + } + + void BuildNextBatch() + { + StartIndex += BatchSize; + EndIndex = FMath::Min((StartIndex + BatchSize - 1), TotalItems - 1); + } + + int32 GetStartIndex() const + { + return StartIndex; + } + + int32 GetEndIndex() const + { + return EndIndex; + } + +private: + int32 BatchSize; + int32 TotalItems; + int32 StartIndex; + int32 EndIndex; +}; \ No newline at end of file diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/Helpers/IndexerEndToEndTestsCommon.h b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/Helpers/IndexerEndToEndTestsCommon.h new file mode 100644 index 000000000..a76dc9dbf --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/Helpers/IndexerEndToEndTestsCommon.h @@ -0,0 +1,10 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#pragma once + +#include "CoreMinimal.h" + +namespace MarketplaceEndToEndTestsCommon +{ + const int64 PolygonNetworkId = 137; +} \ No newline at end of file diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/Helpers/MarketplaceRequestsTestData.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/Helpers/MarketplaceRequestsTestData.cpp new file mode 100644 index 000000000..b34a88a9b --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/Helpers/MarketplaceRequestsTestData.cpp @@ -0,0 +1,53 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#include "MarketplaceRequestsTestData.h" +#include "SequencePlugin/Private/Indexer/Indexer.h" + +UMarketplaceRequestsTestData * UMarketplaceRequestsTestData::Make(const int32 PendingRequestsIn) +{ + UMarketplaceRequestsTestData * IndexerRequestsTestData = NewObject(); + IndexerRequestsTestData->PendingRequests = PendingRequestsIn; + IndexerRequestsTestData->Marketplace = NewObject(); + return IndexerRequestsTestData; +} + +int32 UMarketplaceRequestsTestData::DecrementPendingRequests() +{ + if (this->PendingRequests > 0) + { + this->PendingRequests -= 1; + this->RequestsComplete += 1; + } + + return this->PendingRequests; +} + +int32 UMarketplaceRequestsTestData::GetPendingRequests() const +{ + return this->PendingRequests; +} + +int32 UMarketplaceRequestsTestData::GetRequestsComplete() const +{ + return this->RequestsComplete; +} + +void UMarketplaceRequestsTestData::RequestFailed() +{ + this->bAllRequestsSuccessful = false; +} + +bool UMarketplaceRequestsTestData::GetAllRequestsSuccessful() const +{ + return this->bAllRequestsSuccessful; +} + +bool UMarketplaceRequestsTestData::TestDone() const +{ + return this->PendingRequests == 0; +} + +UMarketplace * UMarketplaceRequestsTestData::GetMarketplace() const +{ + return this->Marketplace; +} diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/Helpers/MarketplaceRequestsTestData.h b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/Helpers/MarketplaceRequestsTestData.h new file mode 100644 index 000000000..576f463d1 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/Helpers/MarketplaceRequestsTestData.h @@ -0,0 +1,67 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Marketplace/Marketplace.h" +#include "SequencePlugin/Private/Indexer/Indexer.h" +#include "MarketplaceRequestsTestData.generated.h" + +/** + * Used to track Async data for UIndexer tests that involve multiple chains + */ +UCLASS() +class UMarketplaceRequestsTestData : public UObject +{ + GENERATED_BODY() + + UPROPERTY() + int32 RequestsComplete = 0; + + UPROPERTY() + int32 PendingRequests = 0; + + UPROPERTY() + bool bAllRequestsSuccessful = true; + + UPROPERTY() + UMarketplace * Marketplace; + +public: + + /** + * Builds a UIndexerRequestsTestData UObject & Initializes it + * @param PendingRequestsIn The PendingRequests count we initialize with + * @return The Initialized UIndexerVersionTestData UObject + */ + static UMarketplaceRequestsTestData * Make(const int32 PendingRequestsIn); + + /** + * Decrements PendingRequests & returns it, Also increments RequestsComplete + * @return The post decremented PendingRequests int32 + */ + int32 DecrementPendingRequests(); + + /** + * Returns PendingRequests + * @return PendingRequests + */ + int32 GetPendingRequests() const; + + /** + * Returns RequestsComplete + * @return RequestsComplete + */ + int32 GetRequestsComplete() const; + + /** + * Sets bAllRequestsSuccessful to false + */ + void RequestFailed(); + + bool GetAllRequestsSuccessful() const; + + bool TestDone() const; + + UMarketplace * GetMarketplace() const; +}; diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListAllCollectibleListingsWithLowestPriceListingsFirstTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListAllCollectibleListingsWithLowestPriceListingsFirstTest.cpp new file mode 100644 index 000000000..cdf6ecb6e --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListAllCollectibleListingsWithLowestPriceListingsFirstTest.cpp @@ -0,0 +1,97 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "SequencePlugin/Public/Sequence/SequenceAPI.h" +#include "Engine/World.h" +#include "Helpers/MarketplaceRequestsTestData.h" +#include "Marketplace/Marketplace.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "JsonObjectConverter.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FListAllCollectibleListingsWithLowestPriceListingsFirstTest, "SequencePlugin.EndToEnd.MarketplaceTests.ListAllCollectibleListingsWithLowestPriceListingsFirstTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter | EAutomationTestFlags::ClientContext) + +/* Latent command used to poll off main thread to see if our requests are done */ +DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER(FListAllCollectibleListingsWithLowestPriceListingsFirstTestIsDone, const UMarketplaceRequestsTestData *, MarketPlaceRequestsTestData, FAutomationTestBase *, FListAllCollectibleListingsWithLowestPriceListingsFirstTest); + +bool FListAllCollectibleListingsWithLowestPriceListingsFirstTestIsDone::Update() +{ + while(this->MarketPlaceRequestsTestData->GetPendingRequests() > 0) + { + return false; + } + + if (this->MarketPlaceRequestsTestData->GetAllRequestsSuccessful()) + { + FListAllCollectibleListingsWithLowestPriceListingsFirstTest->AddInfo(TEXT("GetFloorOrderTest request completed")); + } + else + { + FListAllCollectibleListingsWithLowestPriceListingsFirstTest->AddError(FString::Printf(TEXT("GetFloorOrderTest request failed"))); + } + + return true; +} + +void FListAllCollectibleListingsWithLowestPriceListingsFirstTest::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("List All Collectible Listings With Lowest Price Listings First Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FListAllCollectibleListingsWithLowestPriceListingsFirstTest::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Testing List All Collectible Listings With Lowest Price Listings First Test")); + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + USequenceSupport* Support = NewObject(); + + UMarketplaceRequestsTestData* MarketplaceTestData = UMarketplaceRequestsTestData::Make(1); + + const TSuccessCallback> GenericSuccess = [this, MarketplaceTestData](TArray Orders) + { + if(Orders.Num() == 0) + { + const FString Message = "List All Collectible Listings With Lowest Price Listings First Test Failure"; + AddError(FString::Printf(TEXT("%s returned no currencies. Remaining tests: %d"), + *Message, + MarketplaceTestData->DecrementPendingRequests())); + MarketplaceTestData->RequestFailed(); + } + else + { + FString Message; + for(FSeqCollectibleOrder Order : Orders) + { + Message += USequenceSupport::StructToString(Order) + "\n"; + } + AddInfo(FString::Printf(TEXT("%s. Remaining tests: %d"), *Message, MarketplaceTestData->DecrementPendingRequests())); + } + }; + + const FFailureCallback GenericFailure = [this, MarketplaceTestData](const FSequenceError& Error) + { + const FString Message = "List All Collectible Listings With Lowest Price Listings First Test Failure"; + AddError(FString::Printf(TEXT("%s with error: %s. Remaining tests: %d"), + *Message, + *Error.Message, + MarketplaceTestData->DecrementPendingRequests())); + MarketplaceTestData->RequestFailed(); + }; + + MarketplaceTestData->GetMarketplace()->ListAllCollectibleListingsWithLowestPriceListingsFirst( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x44b3f42e2BF34F62868Ff9e9dAb7C2F807ba97Cb", + FSeqCollectiblesFilter::Empty(), + GenericSuccess, + GenericFailure + ); + + ADD_LATENT_AUTOMATION_COMMAND(FListAllCollectibleListingsWithLowestPriceListingsFirstTestIsDone(MarketplaceTestData, this)); + return true; + })); + return true; +} \ No newline at end of file diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListAllCollectibleOffersWithHighestPricedOfferFirst.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListAllCollectibleOffersWithHighestPricedOfferFirst.cpp new file mode 100644 index 000000000..b8bb1dc6d --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListAllCollectibleOffersWithHighestPricedOfferFirst.cpp @@ -0,0 +1,97 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "SequencePlugin/Public/Sequence/SequenceAPI.h" +#include "Engine/World.h" +#include "Helpers/MarketplaceRequestsTestData.h" +#include "Marketplace/Marketplace.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "JsonObjectConverter.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FListCollectibleOffersWithHighestPricedOfferFirst, "SequencePlugin.EndToEnd.MarketplaceTests.ListCollectibleOffersWithHighestPricedOfferFirst", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter | EAutomationTestFlags::ClientContext) + +/* Latent command used to poll off main thread to see if our requests are done */ +DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER(FListCollectibleOffersWithHighestPricedOfferFirstIsDone, const UMarketplaceRequestsTestData *, MarketPlaceRequestsTestData, FAutomationTestBase *, FListCollectibleOffersWithHighestPricedOfferFirst); + +bool FListCollectibleOffersWithHighestPricedOfferFirstIsDone::Update() +{ + while(this->MarketPlaceRequestsTestData->GetPendingRequests() > 0) + { + return false; + } + + if (this->MarketPlaceRequestsTestData->GetAllRequestsSuccessful()) + { + FListCollectibleOffersWithHighestPricedOfferFirst->AddInfo(TEXT("GetFloorOrderTest request completed")); + } + else + { + FListCollectibleOffersWithHighestPricedOfferFirst->AddError(FString::Printf(TEXT("GetFloorOrderTest request failed"))); + } + + return true; +} + +void FListCollectibleOffersWithHighestPricedOfferFirst::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("List All Collectible Listings With Lowest Price Listings First Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FListCollectibleOffersWithHighestPricedOfferFirst::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Testing List All Collectible Listings With Highest Priced Offer First")); + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + USequenceSupport* Support = NewObject(); + + UMarketplaceRequestsTestData* MarketplaceTestData = UMarketplaceRequestsTestData::Make(1); + + const TSuccessCallback> GenericSuccess = [this, MarketplaceTestData](TArray Orders) + { + if(Orders.Num() == 0) + { + const FString Message = "List All Collectible Listings With Highest Priced Offer First Failure"; + AddError(FString::Printf(TEXT("%s returned no currencies. Remaining tests: %d"), + *Message, + MarketplaceTestData->DecrementPendingRequests())); + MarketplaceTestData->RequestFailed(); + } + else + { + FString Message; + for(FSeqCollectibleOrder Order : Orders) + { + Message += USequenceSupport::StructToString(Order) + "\n"; + } + AddInfo(FString::Printf(TEXT("%s. Remaining tests: %d"), *Message, MarketplaceTestData->DecrementPendingRequests())); + } + }; + + const FFailureCallback GenericFailure = [this, MarketplaceTestData](const FSequenceError& Error) + { + const FString Message = "List All Collectible Listings With Highest Priced Offer First Failure"; + AddError(FString::Printf(TEXT("%s with error: %s. Remaining tests: %d"), + *Message, + *Error.Message, + MarketplaceTestData->DecrementPendingRequests())); + MarketplaceTestData->RequestFailed(); + }; + + MarketplaceTestData->GetMarketplace()->ListAllCollectibleOffersWithHighestPricedOfferFirst( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x5e4bfd71236a21299d43f508dbb76cb7d0fd4e50", + FSeqCollectiblesFilter::Empty(), + GenericSuccess, + GenericFailure + ); + + ADD_LATENT_AUTOMATION_COMMAND(FListCollectibleOffersWithHighestPricedOfferFirstIsDone(MarketplaceTestData, this)); + return true; + })); + return true; +} \ No newline at end of file diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListAllListingsForCollectibleTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListAllListingsForCollectibleTest.cpp new file mode 100644 index 000000000..70c6560f4 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListAllListingsForCollectibleTest.cpp @@ -0,0 +1,100 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#include + +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "SequencePlugin/Public/Sequence/SequenceAPI.h" +#include "Engine/World.h" +#include "Helpers/MarketplaceRequestsTestData.h" +#include "Marketplace/Marketplace.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "JsonObjectConverter.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FListAllListingsForCollectible, "SequencePlugin.EndToEnd.MarketplaceTests.ListAllListingsForCollectible", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter | EAutomationTestFlags::ClientContext) + +/* Latent command used to poll off main thread to see if our requests are done */ +DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER(FListAllListingsForCollectibleIsDone, const UMarketplaceRequestsTestData *, MarketPlaceRequestsTestData, FAutomationTestBase *, FListAllListingsForCollectible); + +bool FListAllListingsForCollectibleIsDone::Update() +{ + while(this->MarketPlaceRequestsTestData->GetPendingRequests() > 0) + { + return false; + } + + if (this->MarketPlaceRequestsTestData->GetAllRequestsSuccessful()) + { + FListAllListingsForCollectible->AddInfo(TEXT("GetFloorOrderTest request completed")); + } + else + { + FListAllListingsForCollectible->AddError(FString::Printf(TEXT("GetFloorOrderTest request failed"))); + } + + return true; +} + +void FListAllListingsForCollectible::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("List All Collectible Listings With Lowest Price Listings First Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FListAllListingsForCollectible::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Testing List All Listings For Collectible")); + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + USequenceSupport* Support = NewObject(); + + UMarketplaceRequestsTestData* MarketplaceTestData = UMarketplaceRequestsTestData::Make(1); + + const TSuccessCallback> GenericSuccess = [this, MarketplaceTestData](TArray Orders) + { + if(Orders.Num() == 0) + { + const FString Message = "List All Listings For Collectible Failure"; + AddError(FString::Printf(TEXT("%s returned no currencies. Remaining tests: %d"), + *Message, + MarketplaceTestData->DecrementPendingRequests())); + MarketplaceTestData->RequestFailed(); + } + else + { + FString Message; + for(FSeqCollectibleOrder Order : Orders) + { + Message += USequenceSupport::StructToString(Order) + "\n"; + } + AddInfo(FString::Printf(TEXT("%s. Remaining tests: %d"), *Message, MarketplaceTestData->DecrementPendingRequests())); + } + }; + + const FFailureCallback GenericFailure = [this, MarketplaceTestData](const FSequenceError& Error) + { + const FString Message = "List All Listings For Collectible Failure"; + AddError(FString::Printf(TEXT("%s with error: %s. Remaining tests: %d"), + *Message, + *Error.Message, + MarketplaceTestData->DecrementPendingRequests())); + MarketplaceTestData->RequestFailed(); + }; + + MarketplaceTestData->GetMarketplace()->ListAllListingsForCollectible( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x079294e6ffec16234578c672fa3fbfd4b6c48640", + "1", + FSeqCollectiblesFilter::Empty(), + GenericSuccess, + GenericFailure + ); + + ADD_LATENT_AUTOMATION_COMMAND(FListAllListingsForCollectibleIsDone(MarketplaceTestData, this)); + return true; + })); + return true; +} \ No newline at end of file diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListAllOffersForCollectibleTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListAllOffersForCollectibleTest.cpp new file mode 100644 index 000000000..61b269e74 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListAllOffersForCollectibleTest.cpp @@ -0,0 +1,100 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#include + +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "SequencePlugin/Public/Sequence/SequenceAPI.h" +#include "Engine/World.h" +#include "Helpers/MarketplaceRequestsTestData.h" +#include "Marketplace/Marketplace.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "JsonObjectConverter.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FListAllOffersForCollectibleTest, "SequencePlugin.EndToEnd.MarketplaceTests.ListAllOffersForCollectible", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter | EAutomationTestFlags::ClientContext) + +/* Latent command used to poll off main thread to see if our requests are done */ +DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER(FListAllOffersForCollectibleTestIsDone, const UMarketplaceRequestsTestData *, MarketPlaceRequestsTestData, FAutomationTestBase *, FListAllOffersForCollectibleTest); + +bool FListAllOffersForCollectibleTestIsDone::Update() +{ + while(this->MarketPlaceRequestsTestData->GetPendingRequests() > 0) + { + return false; + } + + if (this->MarketPlaceRequestsTestData->GetAllRequestsSuccessful()) + { + FListAllOffersForCollectibleTest->AddInfo(TEXT("GetFloorOrderTest request completed")); + } + else + { + FListAllOffersForCollectibleTest->AddError(FString::Printf(TEXT("GetFloorOrderTest request failed"))); + } + + return true; +} + +void FListAllOffersForCollectibleTest::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("List All Offers For Collectible Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FListAllOffersForCollectibleTest::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Testing List All Offers For Collectible")); + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + USequenceSupport* Support = NewObject(); + + UMarketplaceRequestsTestData* MarketplaceTestData = UMarketplaceRequestsTestData::Make(1); + + const TSuccessCallback> GenericSuccess = [this, MarketplaceTestData](TArray Orders) + { + if(Orders.Num() == 0) + { + const FString Message = "List All Listings For Collectible Failure"; + AddError(FString::Printf(TEXT("%s had no offers. Remaining tests: %d"), + *Message, + MarketplaceTestData->DecrementPendingRequests())); + MarketplaceTestData->RequestFailed(); + } + else + { + FString Message; + for(FSeqCollectibleOrder Order : Orders) + { + Message += USequenceSupport::StructToString(Order) + "\n"; + } + AddInfo(FString::Printf(TEXT("%s. Remaining tests: %d"), *Message, MarketplaceTestData->DecrementPendingRequests())); + } + }; + + const FFailureCallback GenericFailure = [this, MarketplaceTestData](const FSequenceError& Error) + { + const FString Message = "List All Listings For Collectible Failure"; + AddError(FString::Printf(TEXT("%s with error: %s. Remaining tests: %d"), + *Message, + *Error.Message, + MarketplaceTestData->DecrementPendingRequests())); + MarketplaceTestData->RequestFailed(); + }; + + MarketplaceTestData->GetMarketplace()->ListAllOffersForCollectible( + Support->GetNetworkId(ENetwork::PolygonChain), + "0x079294e6ffec16234578c672fa3fbfd4b6c48640", + "1", + FSeqCollectiblesFilter::Empty(), + GenericSuccess, + GenericFailure + ); + + ADD_LATENT_AUTOMATION_COMMAND(FListAllOffersForCollectibleTestIsDone(MarketplaceTestData, this)); + return true; + })); + return true; +} \ No newline at end of file diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListCurrenciesTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListCurrenciesTest.cpp new file mode 100644 index 000000000..26205eaca --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/MarketplaceEndToEndTests/ListCurrenciesTest.cpp @@ -0,0 +1,86 @@ +// Copyright 2024 Horizon Blockchain Games Inc. All rights reserved. + +#include "JsonObjectConverter.h" +#include "CoreMinimal.h" +#include "SequencePlugin/Public/Sequence/SequenceAPI.h" +#include "Engine/World.h" +#include "Helpers/MarketplaceRequestsTestData.h" +#include "Marketplace/Marketplace.h" +#include "Misc/AutomationTest.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FListCurrenciesTest, "SequencePlugin.EndToEnd.MarketplaceTests.ListCurrenciesTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter | EAutomationTestFlags::ClientContext) + +/* Latent command used to poll off main thread to see if our requests are done */ +DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER(FListCurrenciesTestIsDone, const UMarketplaceRequestsTestData *, MarketPlaceRequestsTestData, FAutomationTestBase *, FListCurrenciesTest); + +bool FListCurrenciesTestIsDone::Update() +{ + while(this->MarketPlaceRequestsTestData->GetPendingRequests() > 0) + { + return false; + } + + if (this->MarketPlaceRequestsTestData->GetAllRequestsSuccessful()) + { + FListCurrenciesTest->AddInfo(TEXT("GetFloorOrderTest request completed")); + } + else + { + FListCurrenciesTest->AddError(FString::Printf(TEXT("GetFloorOrderTest request failed"))); + } + + return true; +} + +void FListCurrenciesTest::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("List Currencies Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FListCurrenciesTest::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Testing List Currencies")); + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + UMarketplace* Marketplace = NewObject(); + USequenceSupport* Support = NewObject(); + + UMarketplaceRequestsTestData* MarketplaceTestData = UMarketplaceRequestsTestData::Make(1); + + const TSuccessCallback GenericSuccess = [this, MarketplaceTestData](const FString Message) + { + AddInfo(FString::Printf(TEXT("%s. Remaining pings: %d"), *Message, MarketplaceTestData->DecrementPendingRequests())); + }; + + const FFailureCallback GenericFailure = [this, MarketplaceTestData](const FSequenceError& Error) + { + const FString Message = "List currencies Failure"; + AddError(FString::Printf(TEXT("%s with error: %s. Remaining tests: %d"), + *Message, + *Error.Message, + MarketplaceTestData->DecrementPendingRequests())); + MarketplaceTestData->RequestFailed(); + }; + + Marketplace->ListCurrencies(Support->GetNetworkId(PolygonChain), [this, MarketplaceTestData, GenericSuccess](FSeqListCurrenciesReturn Response) + { + FString Currencies = "Currencies: \n"; + + for(FSeqCurrency Currency : Response.Currencies) + { + Currencies += USequenceSupport::StructToString(Currency) + "\n"; + } + + GenericSuccess(Currencies); + }, GenericFailure); + + ADD_LATENT_AUTOMATION_COMMAND(FListCurrenciesTestIsDone(MarketplaceTestData, this)); + return true; + })); + return true; +} \ No newline at end of file diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineERC1155CheckoutTokenTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineERC1155CheckoutTokenTest.cpp new file mode 100644 index 000000000..c60588011 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineERC1155CheckoutTokenTest.cpp @@ -0,0 +1,80 @@ +#include "SardineERC1155CheckoutTokenTest.h" +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "Engine/World.h" +#include "Marketplace/Sardine/SardineCheckout.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "Util/Async.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FSardineERC1155CheckoutTokenTest, "SequencePlugin.EndToEnd.SardineTests.ERC1155CheckoutTokenTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) + +void FSardineERC1155CheckoutTokenTest::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("Sardine ERC1155 Checkout Token Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FSardineERC1155CheckoutTokenTest::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Starting Sardine ERC1155 Checkout Token Test")); + + // Start PIE + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + + // Wait for PIE to initialize + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + + // Run the actual test + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + USardineERC1155CheckoutTokenTestHelper* TestHelper = NewObject(); + TestHelper->ParentTest = this; + TestHelper->RunTest(); + + ADD_LATENT_AUTOMATION_COMMAND(FWaitForERC1155CheckoutToken(TestHelper)); + return true; + })); + return true; +} + +void USardineERC1155CheckoutTokenTestHelper::RunTest() +{ + Checkout = NewObject(); + + // mock data + int64 ChainID = 137; + UERC1155SaleContract* SaleContract = NewObject(); + SaleContract->Initialize("0xe65b75eb7c58ffc0bf0e671d64d0e1c6cd0d3e5b", "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", 99999, ""); + + FString CollectionAddress = "0xdeb398f41ccd290ee5114df7e498cf04fac916cb"; + long TokenID = 1; + long Amount = 1; + FString RecipientAddress = "0x9886910Faec24328FE8104a300e5D08FF0B5675b"; + TArray Proof; + TArray Data; + Proof.Empty(); + Data.Empty(); + + const TSuccessCallback GetNFTCheckoutTokenSuccess = [this](const FSardineNFTCheckout& Token) + { + bTestComplete = true; + const FString Message = "Sardine NFT Checkout Token request succeeded with token"; + ParentTest->AddInfo(FString::Printf(TEXT("%s: %s"), *Message, *Token.Token)); + }; + + const FFailureCallback GetNFTCheckoutTokenFailure = [this](const FSequenceError& Error) + { + bTestComplete = true; + const FString Message = "Request Failure"; + ParentTest->AddError(FString::Printf(TEXT("%s: %s."), *Message, *Error.Message)); + }; + + Checkout->SardineGetNFTCheckoutToken(ChainID, SaleContract, CollectionAddress, TokenID, Amount, + GetNFTCheckoutTokenSuccess, GetNFTCheckoutTokenFailure, RecipientAddress, Data, Proof); +} + +bool FWaitForERC1155CheckoutToken::Update() +{ + return TestHelper->IsTestComplete(); +} diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineERC1155CheckoutTokenTest.h b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineERC1155CheckoutTokenTest.h new file mode 100644 index 000000000..ded30c2cb --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineERC1155CheckoutTokenTest.h @@ -0,0 +1,24 @@ +#pragma once +#include "Marketplace/Sardine/SardineCheckout.h" + +#include "SardineERC1155CheckoutTokenTest.generated.h" + +class FSardineERC1155CheckoutTokenTest; + +UCLASS() +class USardineERC1155CheckoutTokenTestHelper : public UObject +{ + GENERATED_BODY() + +public: + void RunTest(); + bool IsTestComplete() const { return bTestComplete; } + + FSardineERC1155CheckoutTokenTest* ParentTest; + +private: + bool bTestComplete = false; + USardineCheckout* Checkout = nullptr; +}; + +DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER(FWaitForERC1155CheckoutToken, USardineERC1155CheckoutTokenTestHelper*, TestHelper); diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineERC721CheckoutTokenTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineERC721CheckoutTokenTest.cpp new file mode 100644 index 000000000..9d97e1241 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineERC721CheckoutTokenTest.cpp @@ -0,0 +1,80 @@ +#include "SardineERC721CheckoutTokenTest.h" +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "Engine/World.h" +#include "Marketplace/Sardine/SardineCheckout.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "Util/Async.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FSardineERC721CheckoutTokenTest, "SequencePlugin.EndToEnd.SardineTests.ERC721CheckoutTokenTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) + +void FSardineERC721CheckoutTokenTest::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("Sardine ERC721 Checkout Token Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FSardineERC721CheckoutTokenTest::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Starting Sardine ERC721 Checkout Token Test")); + + // Start PIE + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + + // Wait for PIE to initialize + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + + // Run the actual test + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + USardineERC721CheckoutTokenTestHelper* TestHelper = NewObject(); + TestHelper->ParentTest = this; + TestHelper->RunTest(); + + ADD_LATENT_AUTOMATION_COMMAND(FWaitForERC721CheckoutToken(TestHelper)); + return true; + })); + return true; +} + +void USardineERC721CheckoutTokenTestHelper::RunTest() +{ + Checkout = NewObject(); + + // mock data + int64 ChainID = 137; + UERC721SaleContract* SaleContract = NewObject(); + SaleContract->Initialize("0xa3834cf6a4a620469fca67c7c7be4b840e2d27c0", "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", 99999, ""); + + FString CollectionAddress = "0x36feb83e1f52180aca9ada43ec1797aa7406a2bd"; + long TokenID = 1; + long Amount = 1; + FString RecipientAddress = "0x9886910Faec24328FE8104a300e5D08FF0B5675b"; + TArray Proof; + TArray Data; + Proof.Empty(); + Data.Empty(); + + const TSuccessCallback GetNFTCheckoutTokenSuccess = [this](const FSardineNFTCheckout& Token) + { + bTestComplete = true; + const FString Message = "Sardine NFT Checkout Token request succeeded with token"; + ParentTest->AddInfo(FString::Printf(TEXT("%s: %s"), *Message, *Token.Token)); + }; + + const FFailureCallback GetNFTCheckoutTokenFailure = [this](const FSequenceError& Error) + { + bTestComplete = true; + const FString Message = "Request Failure"; + ParentTest->AddError(FString::Printf(TEXT("%s: %s."), *Message, *Error.Message)); + }; + + Checkout->SardineGetNFTCheckoutToken(ChainID, SaleContract, CollectionAddress, TokenID, Amount, + GetNFTCheckoutTokenSuccess, GetNFTCheckoutTokenFailure, RecipientAddress, Data, Proof); +} + +bool FWaitForERC721CheckoutToken::Update() +{ + return TestHelper->IsTestComplete(); +} diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineERC721CheckoutTokenTest.h b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineERC721CheckoutTokenTest.h new file mode 100644 index 000000000..bd1144a18 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineERC721CheckoutTokenTest.h @@ -0,0 +1,24 @@ +#pragma once +#include "Marketplace/Sardine/SardineCheckout.h" + +#include "SardineERC721CheckoutTokenTest.generated.h" + +class FSardineERC721CheckoutTokenTest; + +UCLASS() +class USardineERC721CheckoutTokenTestHelper : public UObject +{ + GENERATED_BODY() + +public: + void RunTest(); + bool IsTestComplete() const { return bTestComplete; } + + FSardineERC721CheckoutTokenTest* ParentTest; + +private: + bool bTestComplete = false; + USardineCheckout* Checkout = nullptr; +}; + +DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER(FWaitForERC721CheckoutToken, USardineERC721CheckoutTokenTestHelper*, TestHelper); diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetClientTokenTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetClientTokenTest.cpp new file mode 100644 index 000000000..826847100 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetClientTokenTest.cpp @@ -0,0 +1,65 @@ +#include "SardineGetClientTokenTest.h" +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "Engine/World.h" +#include "Marketplace/Sardine/SardineCheckout.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "Util/Async.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FSardineGetClientTokenTest, "SequencePlugin.EndToEnd.SardineTests.GetClientTokenTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) + +void FSardineGetClientTokenTest::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("Sardine Get Client Token Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FSardineGetClientTokenTest::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Starting Sardine Get Client Token Test")); + + // Start PIE + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + + // Wait for PIE to initialize + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + + // Run the actual test + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + USardineGetClientTokenTestHelper* TestHelper = NewObject(); + TestHelper->ParentTest = this; + TestHelper->RunTest(); + + ADD_LATENT_AUTOMATION_COMMAND(FWaitForGetClientTokenToComplete(TestHelper)); + return true; + })); + return true; +} + +void USardineGetClientTokenTestHelper::RunTest() +{ + Checkout = NewObject(); + + const TSuccessCallback GetClientTokenSuccess = [this](const FString& Token) + { + bTestComplete = true; + const FString Message = "SardineGetClientToken request succeeded with token"; + ParentTest->AddInfo(FString::Printf(TEXT("%s: %s"), *Message, *Token)); + }; + + const FFailureCallback GetClientTokenFailure = [this](const FSequenceError& Error) + { + bTestComplete = true; + const FString Message = "Request Failure"; + ParentTest->AddError(FString::Printf(TEXT("%s: %s."), *Message, *Error.Message)); + }; + + Checkout->SardineGetClientToken(GetClientTokenSuccess, GetClientTokenFailure); +} + +bool FWaitForGetClientTokenToComplete::Update() +{ + return TestHelper->IsTestComplete(); +} diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetClientTokenTest.h b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetClientTokenTest.h new file mode 100644 index 000000000..9c19f1859 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetClientTokenTest.h @@ -0,0 +1,24 @@ +#pragma once +#include "Marketplace/Sardine/SardineCheckout.h" + +#include "SardineGetClientTokenTest.generated.h" + +class FSardineGetClientTokenTest; + +UCLASS() +class USardineGetClientTokenTestHelper : public UObject +{ + GENERATED_BODY() + +public: + void RunTest(); + bool IsTestComplete() const { return bTestComplete; } + + FSardineGetClientTokenTest* ParentTest; + +private: + bool bTestComplete = false; + USardineCheckout* Checkout = nullptr; +}; + +DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER(FWaitForGetClientTokenToComplete, USardineGetClientTokenTestHelper*, TestHelper); diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetSupportedFiatCurrenciesTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetSupportedFiatCurrenciesTest.cpp new file mode 100644 index 000000000..5c1efabf1 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetSupportedFiatCurrenciesTest.cpp @@ -0,0 +1,69 @@ +#include "SardineGetSupportedFiatCurrenciesTest.h" +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "Engine/World.h" +#include "Marketplace/Sardine/SardineCheckout.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "Util/Async.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FSardineGetSupportedFiatCurrenciesTest, "SequencePlugin.EndToEnd.SardineTests.GetSupportedFiatCurrenciesTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) + +void FSardineGetSupportedFiatCurrenciesTest::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("Sardine Get Supported Fiat Currencies Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FSardineGetSupportedFiatCurrenciesTest::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Starting Sardine Get Supported Fiat Currencies Test")); + + // Start PIE + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + + // Wait for PIE to initialize + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + + // Run the actual test + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + USardineGetSupportedFiatCurrenciesTestHelper* TestHelper = NewObject(); + TestHelper->ParentTest = this; + TestHelper->RunTest(); + + ADD_LATENT_AUTOMATION_COMMAND(FWaitForGetSupportedFiatCurrenciesToComplete(TestHelper)); + return true; + })); + return true; +} + +void USardineGetSupportedFiatCurrenciesTestHelper::RunTest() +{ + Checkout = NewObject(); + + const TSuccessCallback> GetSupportedFiatCurrenciesSuccess = [this](const TArray& Currencies) + { + bTestComplete = true; + const FString Message = "SardineGetSupportedFiatCurrencies request succeeded with currencies:"; + ParentTest->AddInfo(Message); + for (const FSardineFiatCurrency& Currency : Currencies) + { + ParentTest->AddInfo(FString::Printf(TEXT("%s: %s."), *Currency.CurrencyCode, *Currency.Name)); + } + }; + + const FFailureCallback GenericFailure = [this](const FSequenceError& Error) + { + bTestComplete = true; + const FString Message = "Request Failure"; + ParentTest->AddError(FString::Printf(TEXT("%s: %s."), *Message, *Error.Message)); + }; + + Checkout->SardineGetSupportedFiatCurrencies(GetSupportedFiatCurrenciesSuccess, GenericFailure); +} + +bool FWaitForGetSupportedFiatCurrenciesToComplete::Update() +{ + return TestHelper->IsTestComplete(); +} diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetSupportedFiatCurrenciesTest.h b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetSupportedFiatCurrenciesTest.h new file mode 100644 index 000000000..64ed8937d --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetSupportedFiatCurrenciesTest.h @@ -0,0 +1,24 @@ +#pragma once +#include "Marketplace/Sardine/SardineCheckout.h" + +#include "SardineGetSupportedFiatCurrenciesTest.generated.h" + +class FSardineGetSupportedFiatCurrenciesTest; + +UCLASS() +class USardineGetSupportedFiatCurrenciesTestHelper : public UObject +{ + GENERATED_BODY() + +public: + void RunTest(); + bool IsTestComplete() const { return bTestComplete; } + + FSardineGetSupportedFiatCurrenciesTest* ParentTest; + +private: + bool bTestComplete = false; + USardineCheckout* Checkout = nullptr; +}; + +DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER(FWaitForGetSupportedFiatCurrenciesToComplete, USardineGetSupportedFiatCurrenciesTestHelper*, TestHelper); diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetSupportedRegionsTest.cpp b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetSupportedRegionsTest.cpp new file mode 100644 index 000000000..c85ffda00 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetSupportedRegionsTest.cpp @@ -0,0 +1,69 @@ +#include "SardineGetSupportedRegionsTest.h" +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "Engine/World.h" +#include "Marketplace/Sardine/SardineCheckout.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "Util/Async.h" + +IMPLEMENT_COMPLEX_AUTOMATION_TEST(FSardineGetSupportedRegionsTest, "SequencePlugin.EndToEnd.SardineTests.GetSupportedRegionsTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) + +void FSardineGetSupportedRegionsTest::GetTests(TArray& OutBeautifiedNames, TArray& OutTestCommands) const +{ + OutBeautifiedNames.Add(TEXT("Sardine Get Supported Regions Test")); + OutTestCommands.Add(TEXT("")); +} + +bool FSardineGetSupportedRegionsTest::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("Starting Sardine Get Supported Regions Test")); + + // Start PIE + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(true)); + + // Wait for PIE to initialize + ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.0f)); + + // Run the actual test + ADD_LATENT_AUTOMATION_COMMAND(FFunctionLatentCommand([this]() + { + USardineGetSupportedRegionsTestHelper* TestHelper = NewObject(); + TestHelper->ParentTest = this; + TestHelper->RunTest(); + + ADD_LATENT_AUTOMATION_COMMAND(FWaitForGetSupportedRegionsToComplete(TestHelper)); + return true; + })); + return true; +} + +void USardineGetSupportedRegionsTestHelper::RunTest() +{ + Checkout = NewObject(); + + const TSuccessCallback> GetSupportedRegionsSuccess = [this](const TArray& Regions) + { + bTestComplete = true; + const FString Message = "SardineGetSupportedRegions request succeeded with regions:"; + ParentTest->AddInfo(Message); + for (const FSardineRegion& Region : Regions) + { + ParentTest->AddInfo(FString::Printf(TEXT("%s: %s."), *Region.CountryCode, *Region.Name)); + } + }; + + const FFailureCallback GenericFailure = [this](const FSequenceError& Error) + { + bTestComplete = true; + const FString Message = "Request Failure"; + ParentTest->AddError(FString::Printf(TEXT("%s: %s."), *Message, *Error.Message)); + }; + + Checkout->SardineGetSupportedRegions(GetSupportedRegionsSuccess, GenericFailure); +} + +bool FWaitForGetSupportedRegionsToComplete::Update() +{ + return TestHelper->IsTestComplete(); +} diff --git a/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetSupportedRegionsTest.h b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetSupportedRegionsTest.h new file mode 100644 index 000000000..a782eaba4 --- /dev/null +++ b/Plugins/SequenceTests/Source/SequenceTests/Private/SardineTests/SardineGetSupportedRegionsTest.h @@ -0,0 +1,24 @@ +#pragma once +#include "Marketplace/Sardine/SardineCheckout.h" + +#include "SardineGetSupportedRegionsTest.generated.h" + +class FSardineGetSupportedRegionsTest; + +UCLASS() +class USardineGetSupportedRegionsTestHelper : public UObject +{ + GENERATED_BODY() + +public: + void RunTest(); + bool IsTestComplete() const { return bTestComplete; } + + FSardineGetSupportedRegionsTest* ParentTest; + +private: + bool bTestComplete = false; + USardineCheckout* Checkout = nullptr; +}; + +DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER(FWaitForGetSupportedRegionsToComplete, USardineGetSupportedRegionsTestHelper*, TestHelper); diff --git a/Plugins/SequenceTests/Source/SequenceTests/SequenceTests.Build.cs b/Plugins/SequenceTests/Source/SequenceTests/SequenceTests.Build.cs index 21613ca7c..f56ee3481 100644 --- a/Plugins/SequenceTests/Source/SequenceTests/SequenceTests.Build.cs +++ b/Plugins/SequenceTests/Source/SequenceTests/SequenceTests.Build.cs @@ -36,6 +36,8 @@ public SequenceTests(ReadOnlyTargetRules Target) : base(Target) { "CoreUObject", "Engine", + "Json", + "JsonUtilities", "Slate", "SlateCore", "SequencePlugin", diff --git a/SequenceUnreal.uproject b/SequenceUnreal.uproject index db1f5ce4c..6bf7e86e6 100644 --- a/SequenceUnreal.uproject +++ b/SequenceUnreal.uproject @@ -1,6 +1,6 @@ { "FileVersion": 3, - "EngineAssociation": "5.4", + "EngineAssociation": "5.5", "Category": "", "Description": "", "Modules": [