diff --git a/src/UnitySampleProject/Assets/ExternalDependencyManager.meta b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime.meta similarity index 77% rename from src/UnitySampleProject/Assets/ExternalDependencyManager.meta rename to Packages/io.chainsafe.web3-unity.hyperplay/Runtime.meta index 11c988c51..0c74a21f0 100644 --- a/src/UnitySampleProject/Assets/ExternalDependencyManager.meta +++ b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: b68b274307aa0f4489642aa55b200874 +guid: b570d148b322940459375542e91ef7af folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/src/UnitySampleProject/Assets/ExternalDependencyManager/Editor.meta b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Libraries.meta similarity index 77% rename from src/UnitySampleProject/Assets/ExternalDependencyManager/Editor.meta rename to Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Libraries.meta index e5123a164..ad8be91f0 100644 --- a/src/UnitySampleProject/Assets/ExternalDependencyManager/Editor.meta +++ b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Libraries.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: d939ba36a37c8274897ea497cd5dc8fc +guid: 6aa4f545932270b48acdc4de1df73b2d folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/src/UnitySampleProject/Assets/ExternalDependencyManager/Editor/1.2.179.meta b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Scripts.meta similarity index 77% rename from src/UnitySampleProject/Assets/ExternalDependencyManager/Editor/1.2.179.meta rename to Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Scripts.meta index e9466dade..91e399dbf 100644 --- a/src/UnitySampleProject/Assets/ExternalDependencyManager/Editor/1.2.179.meta +++ b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Scripts.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 066c254a3621598429e298b41d522cc8 +guid: 541b8003286f5264ca1ed22079546a3b folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Scripts/HyperPlayWeb3.cs b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Scripts/HyperPlayWeb3.cs new file mode 100644 index 000000000..a6f0b9074 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Scripts/HyperPlayWeb3.cs @@ -0,0 +1,31 @@ +using System.Threading.Tasks; +using ChainSafe.Gaming.Evm.JsonRpc; +using ChainSafe.Gaming.UnityPackage; +using ChainSafe.Gaming.Web3.Build; +using ChainSafe.Gaming.Web3.Unity; + +namespace ChainSafe.Gaming.HyperPlay +{ + /// + /// Helper class to build preconfigured Web3 clients for HyperPlay. + /// + public static class HyperPlayWeb3 + { + /// + /// Builds a lightweight Web3 client with basic HyperPlay functionality. + /// + /// Your HyperPlay config. + /// A lightweight version of Web3 client with basic HyperPlay functionality. + public static ValueTask BuildLightweightWeb3(IHyperPlayConfig config) + { + var projectConfig = ProjectConfigUtilities.Load(); + + return new Web3Builder(projectConfig).Configure(services => + { + services.UseUnityEnvironment(); + services.UseRpcProvider(); + services.UseHyperPlay(config); + }).LaunchAsync(); + } + } +} \ No newline at end of file diff --git a/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Scripts/HyperPlayWeb3.cs.meta b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Scripts/HyperPlayWeb3.cs.meta new file mode 100644 index 000000000..1318e4172 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Scripts/HyperPlayWeb3.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7fd38b3373d04c6408afb61a39c01a29 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/io.chainsafe.web3-unity.hyperplay.runtime.asmdef b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/io.chainsafe.web3-unity.hyperplay.runtime.asmdef new file mode 100644 index 000000000..6944e4657 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/io.chainsafe.web3-unity.hyperplay.runtime.asmdef @@ -0,0 +1,16 @@ +{ + "name": "io.chainsafe.web3-unity.hyperplay.runtime", + "rootNamespace": "ChainSafe.Gaming.HyperPlay", + "references": [ + "GUID:5426c6b788696eb4c88f4198b59839eb" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/io.chainsafe.web3-unity.hyperplay.runtime.asmdef.meta b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/io.chainsafe.web3-unity.hyperplay.runtime.asmdef.meta new file mode 100644 index 000000000..f7631ab52 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/io.chainsafe.web3-unity.hyperplay.runtime.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2de764c29718da4449911a17cfdde636 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/io.chainsafe.web3-unity.hyperplay/package.json b/Packages/io.chainsafe.web3-unity.hyperplay/package.json new file mode 100644 index 000000000..262bd237b --- /dev/null +++ b/Packages/io.chainsafe.web3-unity.hyperplay/package.json @@ -0,0 +1,33 @@ +{ + "name": "io.chainsafe.web3-unity.hyperplay", + "version": "1.0.0", + "displayName": "web3.unity SDK HyperPlay", + "description": "This package includes the integration of HyperPlay, which you can use with our Gaming SDK.", + "license": "LGPL-3.0-only", + "licensesUrl": "https://github.com/ChainSafe/web3.unity/blob/main/LICENSE", + "documentationUrl": "https://docs.gaming.chainsafe.io/", + "dependencies": { + "com.unity.nuget.newtonsoft-json": "3.0.2", + "io.chainsafe.web3-unity": "2.6.0" + }, + "keywords": [ + "web3", + "ethereum", + "evm", + "blockchain", + "nft", + "hyperplay" + ], + "author": { + "name": "ChainSafe Gaming", + "email": "bd@chainsafe.io", + "url": "https://gaming.chainsafe.io/" + }, + "samples": [ + { + "displayName": "HyperPlay Usage Sample", + "description": "Contains example of integration and usage of HyperPlay functionality.", + "path": "Samples~/Web3.Unity HyperPlay Samples" + } + ] +} \ No newline at end of file diff --git a/Packages/io.chainsafe.web3-unity.hyperplay/package.json.meta b/Packages/io.chainsafe.web3-unity.hyperplay/package.json.meta new file mode 100644 index 000000000..2829a4dde --- /dev/null +++ b/Packages/io.chainsafe.web3-unity.hyperplay/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3536bd3009300f64ca0dd11bfea1da39 +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/scripts/data/duplicate_samples.txt b/scripts/data/duplicate_samples.txt new file mode 100644 index 000000000..485699603 --- /dev/null +++ b/scripts/data/duplicate_samples.txt @@ -0,0 +1,5 @@ +src/UnitySampleProject/Assets/Samples/web3.unity SDK:Web3.Unity Samples:Packages/io.chainsafe.web3-unity/Samples~/Web3.Unity/ +src/UnitySampleProject/Assets/Samples/web3.unity SDK Web3Auth:Web3.Unity Web3Auth Samples:Packages/io.chainsafe.web3-unity.web3auth/Samples~/Web3.Unity Web3Auth/ +src/UnitySampleProject/Assets/Samples/web3.unity SDK Lootboxes:Chainlink Lootbox Sample:Packages/io.chainsafe.web3-unity.lootboxes/Samples~/Chainlink Lootbox Samples/ +src/UnitySampleProject/Assets/Samples/web3.unity SDK Ramp:Web3.Unity Ramp Samples:Packages/io.chainsafe.web3-unity.ramp/Samples~/Web3.Unity Ramp Samples/ +src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay:Web3.Unity HyperPlay Samples:Packages/io.chainsafe.web3-unity.hyperplay/Samples~/Web3.Unity HyperPlay Samples/ \ No newline at end of file diff --git a/scripts/data/published_dependencies.txt b/scripts/data/published_dependencies.txt index b2fdea8e8..95a06a814 100644 --- a/scripts/data/published_dependencies.txt +++ b/scripts/data/published_dependencies.txt @@ -1,2 +1,3 @@ -Packages/io.chainsafe.web3-unity/Runtime/Libraries/:ADRaffy.ENSNormalize;Nethereum.Model;BouncyCastle.Crypto;Nethereum.RLP;ChainSafe.Gaming.Debugging;Nethereum.RPC;ChainSafe.Gaming.Gelato;ChainSafe.Gaming.SygmaClient;Nethereum.Signer.EIP712;ChainSafe.Gaming.InProcessSigner;Nethereum.Signer;ChainSafe.Gaming.InProcessTransactionExecutor;Nethereum.Util;ChainSafe.Gaming.Unity.ThirdParty;Nethereum.Web3;ChainSafe.Gaming.Unity;System.Buffers;ChainSafe.Gaming.WalletConnect;System.Memory;ChainSafe.Gaming;System.Numerics.Vectors;Microsoft.Bcl.AsyncInterfaces;System.Reactive;Microsoft.Extensions.DependencyInjection.Abstractions;System.Runtime.CompilerServices.Unsafe;Microsoft.Extensions.DependencyInjection;System.Runtime.InteropServices.WindowsRuntime;Microsoft.Extensions.Logging.Abstractions;System.Security.Cryptography.Cng;Microsoft.IdentityModel.Abstractions;System.Text.Encodings.Web;Microsoft.IdentityModel.Logging;System.Text.Json;Microsoft.IdentityModel.Tokens;System.Threading.Channels;NBitcoin;System.Threading.Tasks.Extensions;Nethereum.ABI;WalletConnectSharp.Auth;Nethereum.Accounts;WalletConnectSharp.Common;WalletConnectSharp.Events;Nethereum.BlockchainProcessing;WalletConnectSharp.Core;Nethereum.Contracts;WalletConnectSharp.Crypto;Nethereum.Hex;Nethereum.JsonRpc.Client;WalletConnectSharp.Network.Websocket;Nethereum.JsonRpc.IpcClient;WalletConnectSharp.Network;Nethereum.JsonRpc.RpcClient;WalletConnectSharp.Sign;Nethereum.KeyStore;WalletConnectSharp.Storage;Nethereum.Merkle.Patricia;WalletConnectSharp.Web3Wallet;Nethereum.Merkle;Websocket.Client;Nethereum.Metamask;Nethereum.Siwe.Core;Nethereum.Siwe;Nethereum.UI;Nethereum.Unity.Metamask;Nethereum.Unity;ChainSafe.Gaming.MetaMask;ChainSafe.Gaming.MetaMask.Unity;ChainSafe.Gaming.InProcessTransactionExecutor.Unity;ChainSafe.Gaming.Marketplace;ChainSafe.Gaming.HyperPlay -Packages/io.chainsafe.web3-unity.lootboxes/Chainlink/Runtime/Libraries/:Chainsafe.Gaming.Chainlink;ChainSafe.Gaming.Lootboxes.Chainlink \ No newline at end of file +Packages/io.chainsafe.web3-unity/Runtime/Libraries/:ADRaffy.ENSNormalize;Nethereum.Model;BouncyCastle.Crypto;Nethereum.RLP;ChainSafe.Gaming.Debugging;Nethereum.RPC;ChainSafe.Gaming.Gelato;ChainSafe.Gaming.SygmaClient;Nethereum.Signer.EIP712;ChainSafe.Gaming.InProcessSigner;Nethereum.Signer;ChainSafe.Gaming.InProcessTransactionExecutor;Nethereum.Util;ChainSafe.Gaming.Unity.ThirdParty;Nethereum.Web3;ChainSafe.Gaming.Unity;System.Buffers;ChainSafe.Gaming.WalletConnect;System.Memory;ChainSafe.Gaming;System.Numerics.Vectors;Microsoft.Bcl.AsyncInterfaces;System.Reactive;Microsoft.Extensions.DependencyInjection.Abstractions;System.Runtime.CompilerServices.Unsafe;Microsoft.Extensions.DependencyInjection;System.Runtime.InteropServices.WindowsRuntime;Microsoft.Extensions.Logging.Abstractions;System.Security.Cryptography.Cng;Microsoft.IdentityModel.Abstractions;System.Text.Encodings.Web;Microsoft.IdentityModel.Logging;System.Text.Json;Microsoft.IdentityModel.Tokens;System.Threading.Channels;NBitcoin;System.Threading.Tasks.Extensions;Nethereum.ABI;WalletConnectSharp.Auth;Nethereum.Accounts;WalletConnectSharp.Common;WalletConnectSharp.Events;Nethereum.BlockchainProcessing;WalletConnectSharp.Core;Nethereum.Contracts;WalletConnectSharp.Crypto;Nethereum.Hex;Nethereum.JsonRpc.Client;WalletConnectSharp.Network.Websocket;Nethereum.JsonRpc.IpcClient;WalletConnectSharp.Network;Nethereum.JsonRpc.RpcClient;WalletConnectSharp.Sign;Nethereum.KeyStore;WalletConnectSharp.Storage;Nethereum.Merkle.Patricia;WalletConnectSharp.Web3Wallet;Nethereum.Merkle;Websocket.Client;Nethereum.Metamask;Nethereum.Siwe.Core;Nethereum.Siwe;Nethereum.UI;Nethereum.Unity.Metamask;Nethereum.Unity;ChainSafe.Gaming.MetaMask;ChainSafe.Gaming.MetaMask.Unity;ChainSafe.Gaming.InProcessTransactionExecutor.Unity;ChainSafe.Gaming.Marketplace +Packages/io.chainsafe.web3-unity.lootboxes/Chainlink/Runtime/Libraries/:Chainsafe.Gaming.Chainlink;ChainSafe.Gaming.Lootboxes.Chainlink +Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Libraries/:ChainSafe.Gaming.HyperPlay \ No newline at end of file diff --git a/src/ChainSafe.Gaming.HyperPlay/HyperPlayConfig.cs b/src/ChainSafe.Gaming.HyperPlay/HyperPlayConfig.cs new file mode 100644 index 000000000..eaf0ebd34 --- /dev/null +++ b/src/ChainSafe.Gaming.HyperPlay/HyperPlayConfig.cs @@ -0,0 +1,14 @@ +namespace ChainSafe.Gaming.HyperPlay +{ + /// + /// Config for a HyperPlay connection. + /// + public class HyperPlayConfig : IHyperPlayConfig + { + /// + /// Remember the HyperPlay session. + /// Like remember me for login. + /// + public bool RememberSession { get; set; } + } +} \ No newline at end of file diff --git a/src/ChainSafe.Gaming.HyperPlay/HyperPlayData.cs b/src/ChainSafe.Gaming.HyperPlay/HyperPlayData.cs new file mode 100644 index 000000000..4822f2748 --- /dev/null +++ b/src/ChainSafe.Gaming.HyperPlay/HyperPlayData.cs @@ -0,0 +1,20 @@ +using Newtonsoft.Json; + +namespace ChainSafe.Gaming.HyperPlay +{ + /// + /// Concrete implementation of . + /// + public class HyperPlayData : IHyperPlayData + { + [JsonIgnore] + public string StoragePath => "hyperplay-data.json"; + + [JsonIgnore] + public bool LoadOnInitialize => true; + + public bool RememberSession { get; set; } + + public string SavedAccount { get; set; } + } +} \ No newline at end of file diff --git a/src/ChainSafe.Gaming.HyperPlay/HyperPlayExtensions.cs b/src/ChainSafe.Gaming.HyperPlay/HyperPlayExtensions.cs index b71c3671d..f418b75a6 100644 --- a/src/ChainSafe.Gaming.HyperPlay/HyperPlayExtensions.cs +++ b/src/ChainSafe.Gaming.HyperPlay/HyperPlayExtensions.cs @@ -1,9 +1,12 @@ using ChainSafe.Gaming.Evm.Signers; +using ChainSafe.Gaming.LocalStorage; using ChainSafe.Gaming.Web3.Build; using ChainSafe.Gaming.Web3.Core; using ChainSafe.Gaming.Web3.Core.Evm; +using ChainSafe.Gaming.Web3.Core.Logout; using ChainSafe.Gaming.Web3.Evm.Wallet; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; namespace ChainSafe.Gaming.HyperPlay { @@ -13,13 +16,18 @@ public static class HyperPlayExtensions /// Binds implementation of as to Web3 as a service. /// /// Service collection to bind implementations to. + /// Config for connecting via HyperPlay. /// The same service collection that was passed in. This enables fluent style. - public static IWeb3ServiceCollection UseHyperPlay(this IWeb3ServiceCollection collection) + public static IWeb3ServiceCollection UseHyperPlay(this IWeb3ServiceCollection collection, IHyperPlayConfig config) { collection.AssertServiceNotBound(); collection.AddSingleton(); + collection.AddSingleton(); + + collection.Replace(ServiceDescriptor.Singleton(typeof(IHyperPlayConfig), config)); + return collection; } @@ -32,7 +40,7 @@ public static IWeb3ServiceCollection UseHyperPlaySigner(this IWeb3ServiceCollect { collection.AssertServiceNotBound(); - collection.AddSingleton(); + collection.AddSingleton(); return collection; } diff --git a/src/ChainSafe.Gaming.HyperPlay/HyperPlayProvider.cs b/src/ChainSafe.Gaming.HyperPlay/HyperPlayProvider.cs index 8cb8186ad..5e7774bdd 100644 --- a/src/ChainSafe.Gaming.HyperPlay/HyperPlayProvider.cs +++ b/src/ChainSafe.Gaming.HyperPlay/HyperPlayProvider.cs @@ -2,8 +2,11 @@ using System.Threading.Tasks; using ChainSafe.Gaming.Evm; using ChainSafe.Gaming.HyperPlay.Dto; +using ChainSafe.Gaming.LocalStorage; using ChainSafe.Gaming.Web3; +using ChainSafe.Gaming.Web3.Core; using ChainSafe.Gaming.Web3.Core.Debug; +using ChainSafe.Gaming.Web3.Core.Logout; using ChainSafe.Gaming.Web3.Environment; using ChainSafe.Gaming.Web3.Evm.Wallet; using Nethereum.Signer; @@ -18,18 +21,27 @@ namespace ChainSafe.Gaming.HyperPlay /// public class HyperPlayProvider : WalletProvider { + private readonly IHyperPlayConfig config; + private readonly IHyperPlayData data; + private readonly DataStorage dataStorage; private readonly IHttpClient httpClient; private readonly IChainConfig chainConfig; /// /// Initializes a new instance of the class. /// + /// Injected . + /// Injected . + /// Injected . /// HttpClient to make requests. /// ChainConfig to fetch chain data. /// Injected . - public HyperPlayProvider(IHttpClient httpClient, IChainConfig chainConfig, ChainRegistryProvider chainRegistryProvider) + public HyperPlayProvider(IHyperPlayConfig config, IHyperPlayData data, DataStorage dataStorage, IHttpClient httpClient, IChainConfig chainConfig, ChainRegistryProvider chainRegistryProvider) : base(chainRegistryProvider: chainRegistryProvider) { + this.config = config; + this.data = data; + this.dataStorage = dataStorage; this.httpClient = httpClient; this.chainConfig = chainConfig; } @@ -44,6 +56,12 @@ public override async Task Connect() string account = accounts[0].AssertIsPublicAddress(nameof(account)); + // Saved account exists. + if (data.RememberSession && data.SavedAccount == account) + { + return account; + } + string message = "Sign-in with Ethereum"; string hash = await Perform("personal_sign", message, account); @@ -63,12 +81,25 @@ public override async Task Connect() throw new Web3Exception("Fetched address does not match the signing address."); } + if (config.RememberSession) + { + data.RememberSession = true; + + data.SavedAccount = account; + + await dataStorage.Save(data); + } + return account; } public override Task Disconnect() { - // currently HyperPlay doesn't support disconnecting. + if (data.RememberSession) + { + dataStorage.Clear(data); + } + return Task.CompletedTask; } @@ -94,7 +125,7 @@ public override async Task Perform(string method, params object[] paramete }, }); - string response = (await httpClient.PostRaw("http://localhost:9680/rpc", body, "application/json")).Response; + string response = (await httpClient.PostRaw(config.Url, body, "application/json")).Response; // In case response is just a primitive type like string/number... // Deserializing it directly doesn't work. diff --git a/src/ChainSafe.Gaming.HyperPlay/HyperPlaySigner.cs b/src/ChainSafe.Gaming.HyperPlay/HyperPlaySigner.cs index fed910337..c829a54cd 100644 --- a/src/ChainSafe.Gaming.HyperPlay/HyperPlaySigner.cs +++ b/src/ChainSafe.Gaming.HyperPlay/HyperPlaySigner.cs @@ -2,6 +2,7 @@ using ChainSafe.Gaming.Evm.Signers; using ChainSafe.Gaming.Web3.Core; using ChainSafe.Gaming.Web3.Core.Evm; +using ChainSafe.Gaming.Web3.Core.Logout; using ChainSafe.Gaming.Web3.Evm.Wallet; namespace ChainSafe.Gaming.HyperPlay @@ -9,7 +10,7 @@ namespace ChainSafe.Gaming.HyperPlay /// /// Concrete implementation of via HyperPlay desktop client. /// - public class HyperPlaySigner : ISigner, ILifecycleParticipant + public class HyperPlaySigner : ISigner, ILifecycleParticipant, ILogoutHandler { private readonly IWalletProvider walletProvider; @@ -57,5 +58,10 @@ public ValueTask WillStopAsync() { return new ValueTask(Task.CompletedTask); } + + public async Task OnLogout() + { + await walletProvider.Disconnect(); + } } } \ No newline at end of file diff --git a/src/ChainSafe.Gaming.HyperPlay/IHyperPlayConfig.cs b/src/ChainSafe.Gaming.HyperPlay/IHyperPlayConfig.cs new file mode 100644 index 000000000..c1019e971 --- /dev/null +++ b/src/ChainSafe.Gaming.HyperPlay/IHyperPlayConfig.cs @@ -0,0 +1,18 @@ +namespace ChainSafe.Gaming.HyperPlay +{ + /// + /// Config for a HyperPlay connection. + /// + public interface IHyperPlayConfig + { + /// + /// Url for connecting to HyperPlay desktop client. + /// + public string Url => "http://localhost:9680/rpc"; + + /// + /// Remember a connected session. + /// + public bool RememberSession { get; set; } + } +} \ No newline at end of file diff --git a/src/ChainSafe.Gaming.HyperPlay/IHyperPlayData.cs b/src/ChainSafe.Gaming.HyperPlay/IHyperPlayData.cs new file mode 100644 index 000000000..c53dad351 --- /dev/null +++ b/src/ChainSafe.Gaming.HyperPlay/IHyperPlayData.cs @@ -0,0 +1,21 @@ +using ChainSafe.Gaming.LocalStorage; + +namespace ChainSafe.Gaming.HyperPlay +{ + /// + /// data for HyperPlay. + /// Persisted data for HyperPlay. + /// + public interface IHyperPlayData : IStorable + { + /// + /// Remember session from a previous connection. + /// + public bool RememberSession { get; set; } + + /// + /// Saved account from a previous session. + /// + public string SavedAccount { get; set; } + } +} \ No newline at end of file diff --git a/src/ChainSafe.Gaming/LocalStorage/DataStorage.cs b/src/ChainSafe.Gaming/LocalStorage/DataStorage.cs new file mode 100644 index 000000000..2a6d00e17 --- /dev/null +++ b/src/ChainSafe.Gaming/LocalStorage/DataStorage.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using ChainSafe.Gaming.Web3; +using ChainSafe.Gaming.Web3.Environment; +using Newtonsoft.Json; + +namespace ChainSafe.Gaming.LocalStorage +{ + /// + /// Default implementation of the component responsible for storage of persistent data. + /// + public class DataStorage + { + private readonly IEnumerable store; + private readonly IOperatingSystemMediator osMediator; + private readonly ILogWriter logWriter; + + /// + /// Initializes a new instance of the class. + /// + /// All injected . + /// Injected . + /// Injected . + public DataStorage(IEnumerable store, IOperatingSystemMediator osMediator, ILogWriter logWriter) + { + this.store = store; + this.osMediator = osMediator; + this.logWriter = logWriter; + } + + /// + /// Initialize all storable data. + /// + /// Awaitable task for Initialize operation. + public async Task Initialize() + { + foreach (var storable in store) + { + if (storable.LoadOnInitialize && Exists(AbsolutePath(storable.StoragePath))) + { + await Load(storable); + } + } + } + + /// + /// Save storable data to local storage. + /// + /// Storable data to be saved. + /// Create new file if file doesn't exist. + /// Type of Storable to be saved. Helps for serializing. + /// Awaitable Task for save operation. + public async Task Save(T storable, bool createFile = true) + where T : IStorable + { + var path = AbsolutePath(storable.StoragePath); + + if (!createFile && !Exists(path)) + { + return; + } + + try + { + var json = JsonConvert.SerializeObject(storable); + + await File.WriteAllTextAsync(path, json); + } + catch (Exception e) + { + logWriter.LogError($"Failed to save {storable.StoragePath} : {e.Message} : {e}"); + } + } + + /// + /// Load storable data from local storage. + /// + /// Storable data to be loaded. + /// Type of Storable to be loaded. Helps for deserializing. + /// Awaitable Task for load operation. + public async Task Load(T storable) + where T : IStorable + { + var path = AbsolutePath(storable.StoragePath); + + if (!Exists(path)) + { + logWriter.LogError($"Failed to load {storable.StoragePath} : File not found."); + + return; + } + + try + { + var json = await File.ReadAllTextAsync(path); + + JsonConvert.PopulateObject(json, storable); + } + catch + { + logWriter.LogError($"Local data file for {storable.StoragePath} is corrupted. Removing.."); + + File.Delete(path); + } + } + + /// + /// Clear storable data from local storage. + /// + /// Storable data to be cleared. + public void Clear(IStorable storable) + { + string path = AbsolutePath(storable.StoragePath); + + if (!Exists(path)) + { + logWriter.LogError($"Failed to clear {storable.StoragePath} : File not found."); + + return; + } + + File.Delete(path); + } + + private bool Exists(string path) + { + return File.Exists(path); + } + + private string AbsolutePath(string path) + { + return Path.Combine(osMediator.AppPersistentDataPath, path); + } + } +} \ No newline at end of file diff --git a/src/ChainSafe.Gaming/LocalStorage/IStorable.cs b/src/ChainSafe.Gaming/LocalStorage/IStorable.cs new file mode 100644 index 000000000..169453389 --- /dev/null +++ b/src/ChainSafe.Gaming/LocalStorage/IStorable.cs @@ -0,0 +1,18 @@ +namespace ChainSafe.Gaming.LocalStorage +{ + /// + /// Storable data for local storage. + /// + public interface IStorable + { + /// + /// Path to store the data. + /// + public string StoragePath { get; } + + /// + /// Load data on initialize. + /// + public bool LoadOnInitialize { get; } + } +} \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs b/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs index 37711f860..57958a8c2 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs @@ -3,7 +3,7 @@ using ChainSafe.Gaming.Evm; using ChainSafe.Gaming.Evm.Contracts; using ChainSafe.Gaming.Evm.Contracts.BuiltIn; -using ChainSafe.Gaming.Web3.Core; +using ChainSafe.Gaming.LocalStorage; using ChainSafe.Gaming.Web3.Core.Evm.EventPoller; using ChainSafe.Gaming.Web3.Core.Logout; using ChainSafe.Gaming.Web3.Environment; @@ -25,6 +25,7 @@ private Web3Builder() // Bind default services serviceCollection .UseEventPoller() + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() diff --git a/src/ChainSafe.Gaming/Web3/Core/Web3.cs b/src/ChainSafe.Gaming/Web3/Core/Web3.cs index 1e6d6db97..74bd4c340 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Web3.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Web3.cs @@ -5,6 +5,7 @@ using ChainSafe.Gaming.Evm.Contracts.BuiltIn; using ChainSafe.Gaming.Evm.Providers; using ChainSafe.Gaming.Evm.Signers; +using ChainSafe.Gaming.LocalStorage; using ChainSafe.Gaming.Web3.Core; using ChainSafe.Gaming.Web3.Core.Evm; using ChainSafe.Gaming.Web3.Core.Logout; @@ -24,6 +25,7 @@ public class Web3 : IAsyncDisposable private readonly ITransactionExecutor? transactionExecutor; private readonly IEvmEvents? events; private readonly ILogoutManager logoutManager; + private readonly DataStorage dataStorage; private bool initialized; private bool terminated; @@ -39,6 +41,7 @@ internal Web3(ServiceProvider serviceProvider) ProjectConfig = serviceProvider.GetRequiredService(); ChainConfig = serviceProvider.GetRequiredService(); logoutManager = this.serviceProvider.GetRequiredService(); + dataStorage = this.serviceProvider.GetRequiredService(); Erc20 = this.serviceProvider.GetRequiredService(); Erc721 = this.serviceProvider.GetRequiredService(); Erc1155 = this.serviceProvider.GetRequiredService(); @@ -108,6 +111,8 @@ async ValueTask IAsyncDisposable.DisposeAsync() internal async ValueTask InitializeAsync() { + await dataStorage.Initialize(); + foreach (var lifecycleParticipant in serviceProvider.GetServices()) { await lifecycleParticipant.WillStartAsync(); @@ -141,7 +146,7 @@ public async ValueTask TerminateAsync(bool logout = false) } } - serviceProvider.Dispose(); + await serviceProvider.DisposeAsync(); terminated = true; } diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay.meta b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay.meta new file mode 100644 index 000000000..e31cd1d39 --- /dev/null +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 75427b31abfe3df4cac0a541e61a77fd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0.meta b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0.meta new file mode 100644 index 000000000..2a6c792ca --- /dev/null +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9e3d4519bbfe0064b9144f4635cafd27 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample.meta b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample.meta new file mode 100644 index 000000000..2d377d24b --- /dev/null +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c08bb86b42cf5254096d24c0240b9027 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scenes.meta b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scenes.meta new file mode 100644 index 000000000..be3471699 --- /dev/null +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d14fc9e97141fe548bdeadfc8bfa5fb0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.5.0/Web3.Unity Samples/Scenes/SampleLogin - HyperPlay.unity b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scenes/SampleLogin - HyperPlay.unity similarity index 82% rename from src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.5.0/Web3.Unity Samples/Scenes/SampleLogin - HyperPlay.unity rename to src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scenes/SampleLogin - HyperPlay.unity index 7ad506231..33c6ecd11 100644 --- a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.5.0/Web3.Unity Samples/Scenes/SampleLogin - HyperPlay.unity +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scenes/SampleLogin - HyperPlay.unity @@ -326,6 +326,217 @@ MonoBehaviour: gelatoApiKey: 7MFQqyGS1Iui_e_MgmFW1BfbFeJ06g8nnL2oUTlIJug_ errorPopup: {fileID: 314965761} loginButton: {fileID: 2048731599} + rememberMeToggle: {fileID: 1755680257} +--- !u!1 &482586192 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 482586193} + - component: {fileID: 482586195} + - component: {fileID: 482586194} + m_Layer: 5 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &482586193 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 482586192} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 859742331} + m_Father: {fileID: 1755680255} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0.25, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -44, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &482586194 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 482586192} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 1 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &482586195 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 482586192} + m_CullTransparentMesh: 1 +--- !u!1 &669337707 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 669337708} + - component: {fileID: 669337710} + - component: {fileID: 669337709} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &669337708 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 669337707} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1755680255} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.25, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -75, y: 0} + m_SizeDelta: {x: -150, y: -30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &669337709 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 669337707} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Remember me + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: b137a8f4bbcdafc439306c89bed89215, type: 2} + m_sharedMaterial: {fileID: 7077468325371864899, guid: b137a8f4bbcdafc439306c89bed89215, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294111986 + m_fontColor: {r: 0.95, g: 0.95, b: 0.95, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 18 + m_fontSizeBase: 18 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 8 + m_fontSizeMax: 36 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &669337710 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 669337707} + m_CullTransparentMesh: 1 --- !u!1 &740974330 GameObject: m_ObjectHideFlags: 0 @@ -632,6 +843,81 @@ RectTransform: m_AnchoredPosition: {x: 0, y: -25} m_SizeDelta: {x: -50, y: -50} m_Pivot: {x: 0.5, y: 1} +--- !u!1 &859742330 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 859742331} + - component: {fileID: 859742333} + - component: {fileID: 859742332} + m_Layer: 5 + m_Name: Checkmark + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &859742331 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 859742330} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 482586193} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &859742332 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 859742330} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10901, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 0 + m_PreserveAspect: 1 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &859742333 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 859742330} + m_CullTransparentMesh: 1 --- !u!1 &893732502 GameObject: m_ObjectHideFlags: 0 @@ -755,6 +1041,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: - {fileID: 2048731596} + - {fileID: 1755680255} m_Father: {fileID: 740974331} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} @@ -1447,6 +1734,113 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1572088722} m_CullTransparentMesh: 1 +--- !u!1 &1755680254 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1755680255} + - component: {fileID: 1755680257} + - component: {fileID: 1755680256} + m_Layer: 5 + m_Name: Toggle - Remember Me + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1755680255 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1755680254} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 482586193} + - {fileID: 669337708} + m_Father: {fileID: 956735924} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1755680256 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1755680254} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: 50 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1755680257 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1755680254} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 482586194} + toggleTransition: 1 + graphic: {fileID: 859742332} + m_Group: {fileID: 0} + onValueChanged: + m_PersistentCalls: + m_Calls: [] + m_IsOn: 0 --- !u!1 &1812470005 GameObject: m_ObjectHideFlags: 0 diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.5.0/Web3.Unity Samples/Scenes/SampleLogin - HyperPlay.unity.meta b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scenes/SampleLogin - HyperPlay.unity.meta similarity index 100% rename from src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.5.0/Web3.Unity Samples/Scenes/SampleLogin - HyperPlay.unity.meta rename to src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scenes/SampleLogin - HyperPlay.unity.meta diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scripts.meta b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scripts.meta new file mode 100644 index 000000000..634ad428e --- /dev/null +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2d9c25322424d4f41a30626fdfd56e0e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scripts/HyperPlayLoginProvider.cs b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scripts/HyperPlayLoginProvider.cs new file mode 100644 index 000000000..7ccf6694d --- /dev/null +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scripts/HyperPlayLoginProvider.cs @@ -0,0 +1,57 @@ +using ChainSafe.Gaming.HyperPlay; +using ChainSafe.Gaming.UnityPackage.Common; +using ChainSafe.Gaming.Web3.Build; +using Microsoft.Extensions.DependencyInjection; +using Scenes; +using UnityEngine; +using UnityEngine.UI; + +/// +/// Login using HyperPlay desktop client. +/// +public class HyperPlayLoginProvider : LoginProvider, IWeb3BuilderServiceAdapter +{ + [SerializeField] private Button loginButton; + [SerializeField] private Toggle rememberMeToggle; + + private bool _storedSessionAvailable; + + protected override async void Initialize() + { + base.Initialize(); + + _storedSessionAvailable = false; + + await using (var lightWeb3 = await HyperPlayWeb3.BuildLightweightWeb3(new HyperPlayConfig())) + { + var data = lightWeb3.ServiceProvider.GetService(); + + _storedSessionAvailable = data.RememberSession; + } + + if (_storedSessionAvailable) // auto-login + { + Debug.Log("Proceeding with auto-login."); + + await TryLogin(); + } + + loginButton.onClick.AddListener(OnLoginClicked); + } + + public Web3Builder ConfigureServices(Web3Builder web3Builder) + { + return web3Builder.Configure(services => + { + services.UseHyperPlay(new HyperPlayConfig + { + RememberSession = rememberMeToggle.isOn || _storedSessionAvailable, + }).UseHyperPlaySigner().UseHyperPlayTransactionExecutor(); + }); + } + + private async void OnLoginClicked() + { + await TryLogin(); + } +} diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.5.0/Web3.Unity Samples/Scripts/Scenes/HyperPlayLoginProvider.cs.meta b/src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scripts/HyperPlayLoginProvider.cs.meta similarity index 100% rename from src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.5.0/Web3.Unity Samples/Scripts/Scenes/HyperPlayLoginProvider.cs.meta rename to src/UnitySampleProject/Assets/Samples/web3.unity SDK HyperPlay/1.0.0/HyperPlay Usage Sample/Scripts/HyperPlayLoginProvider.cs.meta diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.5.0/Web3.Unity Samples/Scripts/Scenes/HyperPlayLoginProvider.cs b/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.5.0/Web3.Unity Samples/Scripts/Scenes/HyperPlayLoginProvider.cs deleted file mode 100644 index c6230a0c0..000000000 --- a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.5.0/Web3.Unity Samples/Scripts/Scenes/HyperPlayLoginProvider.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using ChainSafe.Gaming.HyperPlay; -using ChainSafe.Gaming.UnityPackage.Common; -using ChainSafe.Gaming.WalletConnect; -using ChainSafe.Gaming.Web3.Build; -using Scenes; -using UnityEngine; -using UnityEngine.UI; - -/// -/// Login using HyperPlay desktop client. -/// -public class HyperPlayLoginProvider : LoginProvider, IWeb3BuilderServiceAdapter -{ - [SerializeField] private Button loginButton; - - protected override void Initialize() - { - base.Initialize(); - - loginButton.onClick.AddListener(OnLoginClicked); - } - - public Web3Builder ConfigureServices(Web3Builder web3Builder) - { - return web3Builder.Configure(services => - { - services.UseHyperPlay().UseHyperPlaySigner().UseHyperPlayTransactionExecutor(); - }); - } - - private async void OnLoginClicked() - { - await TryLogin(); - } -} diff --git a/src/UnitySampleProject/Packages/manifest.json b/src/UnitySampleProject/Packages/manifest.json index 154d659ff..c677282c4 100644 --- a/src/UnitySampleProject/Packages/manifest.json +++ b/src/UnitySampleProject/Packages/manifest.json @@ -9,9 +9,11 @@ "com.unity.textmeshpro": "3.0.6", "com.unity.timeline": "1.7.6", "com.unity.toolchain.macos-arm64-linux-x86_64": "2.0.0", + "com.unity.toolchain.win-x86_64-linux-x86_64": "2.0.9", "com.unity.ugui": "1.0.0", "com.unity.visualscripting": "1.9.4", "io.chainsafe.web3-unity": "file:../../../Packages/io.chainsafe.web3-unity", + "io.chainsafe.web3-unity.hyperplay": "file:../../../Packages/io.chainsafe.web3-unity.hyperplay", "io.chainsafe.web3-unity.lootboxes": "file:../../../Packages/io.chainsafe.web3-unity.lootboxes", "io.chainsafe.web3-unity.ramp": "file:../../../Packages/io.chainsafe.web3-unity.ramp", "io.chainsafe.web3-unity.web3auth": "file:../../../Packages/io.chainsafe.web3-unity.web3auth", diff --git a/src/UnitySampleProject/Packages/packages-lock.json b/src/UnitySampleProject/Packages/packages-lock.json index 24307719a..27ac78b2f 100644 --- a/src/UnitySampleProject/Packages/packages-lock.json +++ b/src/UnitySampleProject/Packages/packages-lock.json @@ -54,18 +54,18 @@ "url": "https://packages.unity.com" }, "com.unity.sysroot": { - "version": "2.0.7", + "version": "2.0.10", "depth": 1, "source": "registry", "dependencies": {}, "url": "https://packages.unity.com" }, "com.unity.sysroot.linux-x86_64": { - "version": "2.0.6", + "version": "2.0.9", "depth": 1, "source": "registry", "dependencies": { - "com.unity.sysroot": "2.0.7" + "com.unity.sysroot": "2.0.10" }, "url": "https://packages.unity.com" }, @@ -111,6 +111,16 @@ }, "url": "https://packages.unity.com" }, + "com.unity.toolchain.win-x86_64-linux-x86_64": { + "version": "2.0.9", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.sysroot": "2.0.10", + "com.unity.sysroot.linux-x86_64": "2.0.9" + }, + "url": "https://packages.unity.com" + }, "com.unity.ugui": { "version": "1.0.0", "depth": 0, @@ -139,6 +149,15 @@ "com.unity.textmeshpro": "3.0.6" } }, + "io.chainsafe.web3-unity.hyperplay": { + "version": "file:../../../Packages/io.chainsafe.web3-unity.hyperplay", + "depth": 0, + "source": "local", + "dependencies": { + "com.unity.nuget.newtonsoft-json": "3.0.2", + "io.chainsafe.web3-unity": "2.5.0" + } + }, "io.chainsafe.web3-unity.lootboxes": { "version": "file:../../../Packages/io.chainsafe.web3-unity.lootboxes", "depth": 0,