diff --git a/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Libraries/ChainSafe.Gaming.HyperPlay.dll b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Libraries/ChainSafe.Gaming.HyperPlay.dll index f1c65ef3c..81ef0a179 100644 Binary files a/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Libraries/ChainSafe.Gaming.HyperPlay.dll and b/Packages/io.chainsafe.web3-unity.hyperplay/Runtime/Libraries/ChainSafe.Gaming.HyperPlay.dll differ diff --git a/Packages/io.chainsafe.web3-unity.lootboxes/Chainlink/Runtime/Libraries/ChainSafe.Gaming.Lootboxes.Chainlink.dll b/Packages/io.chainsafe.web3-unity.lootboxes/Chainlink/Runtime/Libraries/ChainSafe.Gaming.Lootboxes.Chainlink.dll index 1a2f3fbaa..1a7f27878 100644 Binary files a/Packages/io.chainsafe.web3-unity.lootboxes/Chainlink/Runtime/Libraries/ChainSafe.Gaming.Lootboxes.Chainlink.dll and b/Packages/io.chainsafe.web3-unity.lootboxes/Chainlink/Runtime/Libraries/ChainSafe.Gaming.Lootboxes.Chainlink.dll differ diff --git a/Packages/io.chainsafe.web3-unity.lootboxes/Chainlink/Runtime/Libraries/Chainsafe.Gaming.Chainlink.dll b/Packages/io.chainsafe.web3-unity.lootboxes/Chainlink/Runtime/Libraries/Chainsafe.Gaming.Chainlink.dll index 8fecd65de..60ad9b627 100644 Binary files a/Packages/io.chainsafe.web3-unity.lootboxes/Chainlink/Runtime/Libraries/Chainsafe.Gaming.Chainlink.dll and b/Packages/io.chainsafe.web3-unity.lootboxes/Chainlink/Runtime/Libraries/Chainsafe.Gaming.Chainlink.dll differ diff --git a/Packages/io.chainsafe.web3-unity.mud/Runtime/Libraries/ChainSafe.Gaming.Mud.dll b/Packages/io.chainsafe.web3-unity.mud/Runtime/Libraries/ChainSafe.Gaming.Mud.dll index d789b51f9..8231a228d 100644 Binary files a/Packages/io.chainsafe.web3-unity.mud/Runtime/Libraries/ChainSafe.Gaming.Mud.dll and b/Packages/io.chainsafe.web3-unity.mud/Runtime/Libraries/ChainSafe.Gaming.Mud.dll differ diff --git a/Packages/io.chainsafe.web3-unity.web3auth/Runtime/WalletGUI/Scripts/Web3AuthWalletGUITokenManager.cs b/Packages/io.chainsafe.web3-unity.web3auth/Runtime/WalletGUI/Scripts/Web3AuthWalletGUITokenManager.cs index 875592232..dd40357c3 100644 --- a/Packages/io.chainsafe.web3-unity.web3auth/Runtime/WalletGUI/Scripts/Web3AuthWalletGUITokenManager.cs +++ b/Packages/io.chainsafe.web3-unity.web3auth/Runtime/WalletGUI/Scripts/Web3AuthWalletGUITokenManager.cs @@ -83,7 +83,7 @@ private async void SetTokens() customTokenDisplay.SetActive(false); } // Set native token - nativeTokenSymbolText.text = Web3Unity.Web3.ChainConfig.Symbol.ToUpper(); + nativeTokenSymbolText.text = Web3Unity.Web3.ChainConfig.NativeCurrency.Symbol.ToUpper(); var hexBalance = await Web3Unity.Web3.RpcProvider.GetBalance(Web3Unity.Web3.Signer.PublicAddress); var weiBalance = BigInteger.Parse(hexBalance.ToString()); decimal ethBalance = (decimal)weiBalance / (decimal)Math.Pow(10, 18); diff --git a/Packages/io.chainsafe.web3-unity.web3auth/Runtime/Web3AuthConnectionProvider.cs b/Packages/io.chainsafe.web3-unity.web3auth/Runtime/Web3AuthConnectionProvider.cs index d13277187..fba8abe9c 100644 --- a/Packages/io.chainsafe.web3-unity.web3auth/Runtime/Web3AuthConnectionProvider.cs +++ b/Packages/io.chainsafe.web3-unity.web3auth/Runtime/Web3AuthConnectionProvider.cs @@ -92,7 +92,7 @@ public override async Task Initialize(bool rememberSession) //1155 is a decimal number, we need to convert it to an integer InitWeb3Auth(clientId, new HexBigInteger(BigInteger.Parse(chainConfig.ChainId)).HexValue, - chainConfig.Rpc, chainConfig.Network, "", chainConfig.Symbol, "", network.ToString().ToLower(), Initialized, InitializeError); + chainConfig.Rpc, chainConfig.Network, "", chainConfig.NativeCurrency.Symbol, "", network.ToString().ToLower(), Initialized, InitializeError); await _initializeTcs.Task; } diff --git a/Packages/io.chainsafe.web3-unity/Editor/OpenPersistenDataPath.cs b/Packages/io.chainsafe.web3-unity/Editor/OpenPersistenDataPath.cs new file mode 100644 index 000000000..a280eb808 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Editor/OpenPersistenDataPath.cs @@ -0,0 +1,21 @@ +using UnityEditor; +using UnityEngine; +using System.IO; + +public class OpenPersistentDataPath +{ + [MenuItem("Edit/Open Persistent Data Path")] + private static void OpenPersistentDataPathFolder() + { + string path = Application.persistentDataPath; + + // Check if the directory exists + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + + // Open the folder in the file explorer + EditorUtility.RevealInFinder(path); + } +} \ No newline at end of file diff --git a/Packages/io.chainsafe.web3-unity/Editor/OpenPersistenDataPath.cs.meta b/Packages/io.chainsafe.web3-unity/Editor/OpenPersistenDataPath.cs.meta new file mode 100644 index 000000000..cf96c6d4b --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Editor/OpenPersistenDataPath.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e81dc37649c94b29bd15993aa11ecc7d +timeCreated: 1732802488 \ No newline at end of file diff --git a/Packages/io.chainsafe.web3-unity/Editor/Web3SettingsEditor.ChainSettings.cs b/Packages/io.chainsafe.web3-unity/Editor/Web3SettingsEditor.ChainSettings.cs index 041b372e3..8e4189ad1 100644 --- a/Packages/io.chainsafe.web3-unity/Editor/Web3SettingsEditor.ChainSettings.cs +++ b/Packages/io.chainsafe.web3-unity/Editor/Web3SettingsEditor.ChainSettings.cs @@ -1,9 +1,11 @@ using System; using System.Linq; using ChainSafe.Gaming; +using ChainSafe.Gaming.Web3; using UnityEditor; using UnityEditor.Experimental.GraphView; using UnityEngine; +using NativeCurrency = ChainSafe.Gaming.Web3.NativeCurrency; namespace ChainSafe.GamingSdk.Editor { @@ -85,7 +87,13 @@ public void OnGUI() chainConfig.Network = EditorGUILayout.TextField("Network", chainConfig.Network); chainConfig.ChainId = EditorGUILayout.TextField("Chain ID", chainConfig.ChainId); - chainConfig.Symbol = EditorGUILayout.TextField("Symbol", chainConfig.Symbol); + EditorGUILayout.LabelField("Native Currency", EditorStyles.boldLabel); + EditorGUI.indentLevel++; + // Draw fields for NativeCurrency + chainConfig.NativeCurrency.Name = EditorGUILayout.TextField("Name", chainConfig.NativeCurrency.Name); + chainConfig.NativeCurrency.Symbol = EditorGUILayout.TextField("Symbol", chainConfig.NativeCurrency.Symbol); + chainConfig.NativeCurrency.Decimals = EditorGUILayout.IntField("Decimals", chainConfig.NativeCurrency.Decimals); + EditorGUI.indentLevel--; chainConfig.BlockExplorerUrl = EditorGUILayout.TextField("Block Explorer", chainConfig.BlockExplorerUrl); GUI.enabled = true; @@ -195,7 +203,12 @@ private void UpdateServerMenuInfo(bool chainSwitched = false) { chainConfig.Network = chainPrototype.chain; chainConfig.ChainId = chainPrototype.chainId.ToString(); - chainConfig.Symbol = chainPrototype.nativeCurrency.symbol; + chainConfig.NativeCurrency = new NativeCurrency() + { + Name = chainPrototype.nativeCurrency.Name, + Symbol = chainPrototype.nativeCurrency.Symbol, + Decimals = chainPrototype.nativeCurrency.Decimals + }; if (chainPrototype.explorers != null) { chainConfig.BlockExplorerUrl = chainPrototype.explorers[0].url; diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Debugging.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Debugging.dll index da3ebd09b..042e4ebfc 100644 Binary files a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Debugging.dll and b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Debugging.dll differ diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Gelato.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Gelato.dll index eed487db5..adcb47440 100644 Binary files a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Gelato.dll and b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Gelato.dll differ diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.InProcessSigner.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.InProcessSigner.dll index 8fade8f60..dfa4afff6 100644 Binary files a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.InProcessSigner.dll and b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.InProcessSigner.dll differ diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.InProcessTransactionExecutor.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.InProcessTransactionExecutor.dll index 105810e93..f78e5de60 100644 Binary files a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.InProcessTransactionExecutor.dll and b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.InProcessTransactionExecutor.dll differ diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Marketplace.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Marketplace.dll index ceb57cbbd..9ff0efaa5 100644 Binary files a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Marketplace.dll and b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Marketplace.dll differ diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Reown.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Reown.dll index dc37c5fc3..695e646df 100644 Binary files a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Reown.dll and b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Reown.dll differ diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.SygmaClient.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.SygmaClient.dll index 0cb44a360..e11a1a857 100644 Binary files a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.SygmaClient.dll and b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.SygmaClient.dll differ diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.EthereumWindow.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.EthereumWindow.dll index faecc8d03..312b18c29 100644 Binary files a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.EthereumWindow.dll and b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.EthereumWindow.dll differ diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.MetaMask.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.MetaMask.dll index 9577dd66d..b58fb7314 100644 Binary files a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.MetaMask.dll and b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.MetaMask.dll differ diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.ThirdParty.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.ThirdParty.dll index 7f4f953bc..e47bb456b 100644 Binary files a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.ThirdParty.dll and b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.ThirdParty.dll differ diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.dll index bce890a82..d70affe2d 100644 Binary files a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.dll and b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.Unity.dll differ diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.dll index bdccc0526..1fadb3289 100644 Binary files a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.dll and b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.dll differ diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/System.Numerics.Vectors.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/System.Numerics.Vectors.dll index a808165ac..10205772c 100755 Binary files a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/System.Numerics.Vectors.dll and b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/System.Numerics.Vectors.dll differ diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ChainConfigEntry.cs b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ChainConfigEntry.cs index 72e21bd25..a07a9ea31 100644 --- a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ChainConfigEntry.cs +++ b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ChainConfigEntry.cs @@ -1,5 +1,6 @@ using System; using ChainSafe.Gaming.Web3; +using ChainSafe.Gaming.Web3.Core.Chains; using UnityEngine; namespace ChainSafe.Gaming @@ -10,13 +11,32 @@ public class ChainConfigEntry : IChainConfig private const string ChainIdDefault = "11155111"; private const string ChainDefault = "Sepolia"; private const string NetworkDefault = "Sepolia"; - private const string SymbolDefault = "Seth"; + + private static readonly NativeCurrencyUnityWrapper DefaultNativeCurrency = new() + { + Name = "Sepolia Ether", + Symbol = "ETH", + Decimals = 18 + }; + private const string RpcDefault = "https://rpc.sepolia.org"; private const string BlockExplorerUrlDefault = "https://sepolia.etherscan.io"; private const string WsDefault = ""; [field: SerializeField] public string ChainId { get; set; } - [field: SerializeField] public string Symbol { get; set; } + + public INativeCurrency NativeCurrency + { + get => nativeCurrency; + set => nativeCurrency = new NativeCurrencyUnityWrapper() + { + Name = value.Name, + Symbol = value.Symbol, + Decimals = value.Decimals + }; + } + + [SerializeField] private NativeCurrencyUnityWrapper nativeCurrency ; [field: SerializeField] public string Chain { get; set; } [field: SerializeField] public string Network { get; set; } [field: SerializeField] public string Rpc { get; set; } @@ -26,7 +46,7 @@ public class ChainConfigEntry : IChainConfig public static ChainConfigEntry Default => new() { ChainId = ChainIdDefault, - Symbol = SymbolDefault, + NativeCurrency = DefaultNativeCurrency, Chain = ChainDefault, Network = NetworkDefault, Rpc = RpcDefault, @@ -37,7 +57,7 @@ public class ChainConfigEntry : IChainConfig public static ChainConfigEntry Empty => new() { ChainId = string.Empty, - Symbol = string.Empty, + NativeCurrency = new NativeCurrencyUnityWrapper(), Chain = "Custom", Network = string.Empty, Rpc = string.Empty, @@ -45,4 +65,15 @@ public class ChainConfigEntry : IChainConfig Ws = string.Empty }; } + + /// + /// This is basically a wrapper for the INativeCurrency interface to allow for Unity serialization. + /// + [Serializable] + public class NativeCurrencyUnityWrapper : INativeCurrency + { + [field: SerializeField] public string Name { get; set; } = "Ether"; + [field: SerializeField] public string Symbol { get; set; } = "ETH"; + [field: SerializeField] public int Decimals { get; set; } = 18; + } } \ No newline at end of file diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/Model/ChainInfoModel.cs b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/Model/ChainInfoModel.cs index 63afdd884..20d9bbf09 100644 --- a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/Model/ChainInfoModel.cs +++ b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/Model/ChainInfoModel.cs @@ -1,10 +1,17 @@ using System.Collections.Generic; +using Newtonsoft.Json; namespace ChainSafe.Gaming.UnityPackage.Model { public struct NativeCurrency { - public string symbol { get; set; } + [JsonProperty(PropertyName = "symbol")] + public string Symbol { get; set; } + + [JsonProperty(PropertyName = "decimals")] + public int Decimals { get; set; } + [JsonProperty(PropertyName = "name")] + public string Name { get; set; } } public struct Explorer diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ProjectConfigUtilities.cs b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ProjectConfigUtilities.cs index 3dff368a3..a40b6366f 100644 --- a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ProjectConfigUtilities.cs +++ b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ProjectConfigUtilities.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; using ChainSafe.Gaming.Web3; +using ChainSafe.Gaming.Web3.Core.Chains; using UnityEngine; namespace ChainSafe.Gaming.UnityPackage @@ -39,7 +40,12 @@ public static Web3ConfigAsset Create(string projectId, string chainId, string ch ChainId = chainId, Chain = chain, Network = network, - Symbol = symbol, + NativeCurrency = new NativeCurrencyUnityWrapper() + { + Name = symbol, + Symbol = symbol, + Decimals = 18 + }, Rpc = rpc, Ws = ws, BlockExplorerUrl = blockExplorerUrl, @@ -91,7 +97,7 @@ public LocalhostChainConfig(string chainId, string symbol, string chain, string var localhostEndPoint = $"127.0.0.1:{port}"; ChainId = chainId; - Symbol = symbol; + NativeCurrency = new NativeCurrencyUnityWrapper(){ Symbol = symbol, Name = symbol, Decimals = 18 }; Chain = chain; Network = network; Rpc = $"http://{localhostEndPoint}"; @@ -100,7 +106,7 @@ public LocalhostChainConfig(string chainId, string symbol, string chain, string } public string ChainId { get; } - public string Symbol { get; } + public INativeCurrency NativeCurrency { get; } public string Chain { get; } public string Network { get; } public string Rpc { get; } diff --git a/scripts/lint.bat b/scripts/lint.bat index bbf2c9826..d74124bec 100644 --- a/scripts/lint.bat +++ b/scripts/lint.bat @@ -8,10 +8,5 @@ cd .. :: Run format command in project root dotnet format --verbosity=d --severity=warn ChainSafe.Gaming.sln --exclude /submodules -:: Navigate to the UnitySampleProject within src and run the format command -pushd .\src\UnitySampleProject -dotnet format --verbosity=d --severity=warn .\UnitySampleProject.sln -popd - :: Restore the original directory popd \ No newline at end of file diff --git a/src/ChainSafe.Gaming.Reown/Methods/WalletAddEthereumChain.cs b/src/ChainSafe.Gaming.Reown/Methods/WalletAddEthereumChain.cs new file mode 100644 index 000000000..a660b5a5c --- /dev/null +++ b/src/ChainSafe.Gaming.Reown/Methods/WalletAddEthereumChain.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using ChainSafe.Gaming.Evm.Network; +using Reown.Core.Common.Utils; +using Reown.Core.Network.Models; + +namespace ChainSafe.Gaming.Reown.Methods +{ + [RpcMethod("wallet_addEthereumChain")] + [RpcRequestOptions(Clock.ONE_MINUTE, 99993)] + public class WalletAddEthereumChain : List + { + public WalletAddEthereumChain(object[] chains) + : base(chains) + { + } + + public WalletAddEthereumChain() + { + } + } +} \ No newline at end of file diff --git a/src/ChainSafe.Gaming.Reown/ReownProvider.cs b/src/ChainSafe.Gaming.Reown/ReownProvider.cs index 3946d5d16..2dcada2b2 100644 --- a/src/ChainSafe.Gaming.Reown/ReownProvider.cs +++ b/src/ChainSafe.Gaming.Reown/ReownProvider.cs @@ -1,8 +1,12 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; +using System.Numerics; using System.Threading; using System.Threading.Tasks; +using ChainSafe.Gaming.Evm.Network; +using ChainSafe.Gaming.Evm.Providers; using ChainSafe.Gaming.Reown.Connection; using ChainSafe.Gaming.Reown.Methods; using ChainSafe.Gaming.Reown.Models; @@ -16,6 +20,7 @@ using ChainSafe.Gaming.Web3.Core.Operations; using ChainSafe.Gaming.Web3.Environment; using ChainSafe.Gaming.Web3.Evm.Wallet; +using Nethereum.Hex.HexTypes; using Nethereum.JsonRpc.Client.RpcMessages; using Newtonsoft.Json; using Reown.Core.Common.Logging; @@ -48,7 +53,7 @@ public class ReownProvider : WalletProvider, ILifecycleParticipant, IConnectionH private readonly Web3Environment environment; private readonly IChainConfigSet chainConfigSet; private readonly IOperationTracker operationTracker; - private readonly IMainThreadRunner mainThreadRunner; + private readonly IRpcProvider rpcProvider; private SessionStruct session; private bool connected; @@ -66,11 +71,11 @@ public ReownProvider( Web3Environment environment, ReownHttpClient reownHttpClient, IOperationTracker operationTracker, - IMainThreadRunner mainThreadRunner) + IRpcProvider rpcProvider) : base(environment, chainConfig, operationTracker) { this.operationTracker = operationTracker; - this.mainThreadRunner = mainThreadRunner; + this.rpcProvider = rpcProvider; this.chainConfigSet = chainConfigSet; this.environment = environment; analyticsClient = environment.AnalyticsClient; @@ -172,6 +177,7 @@ private async Task Initialize() "eth_sendTransaction", "eth_getTransactionByHash", "wallet_switchEthereumChain", + "wallet_addEthereumChain", "eth_blockNumber", }, Events = new[] @@ -234,8 +240,6 @@ public override async Task Connect() connected = true; - await CheckAndSwitchNetwork(); - return address; } catch (Exception e) @@ -247,43 +251,6 @@ public override async Task Connect() } } - private async Task CheckAndSwitchNetwork() - { - var chainId = ExtractChainIdFromAddress(); - if (chainId == $"{EvmNamespace}:{chainConfig.ChainId}") - { - return; - } - - const int maxSwitchAttempts = 3; - - for (var i = 0; ;) - { - var messageToUser = i == 0 - ? "Switching wallet network..." - : $"Switching wallet network (attempt {i + 1})..."; - - using (operationTracker.TrackOperation(messageToUser)) - { - try - { - await SwitchChain(chainConfig.ChainId); - UpdateSessionChainId(); - return; // success, exit loop - } - catch (ReownNetworkException) - { - if (++i >= maxSwitchAttempts) - { - throw; - } - - logWriter.Log("Attempted to switch the network, but was rejected. Trying again..."); - } - } - } - } - private void UpdateSessionChainId() { var defaultChain = session.Namespaces.Keys.FirstOrDefault(); @@ -589,6 +556,8 @@ async Task MakeRequest(bool sendChainId = true) return await MakeRequest(); case "wallet_switchEthereumChain": return await MakeRequest(false); + case "wallet_addEthereumChain": + return await MakeRequest(false); default: try { diff --git a/src/ChainSafe.Gaming.Unity.EthereumWindow/Dto/NativeCurrency.cs b/src/ChainSafe.Gaming.Unity.EthereumWindow/Dto/NativeCurrency.cs index 7267720bd..657403baf 100644 --- a/src/ChainSafe.Gaming.Unity.EthereumWindow/Dto/NativeCurrency.cs +++ b/src/ChainSafe.Gaming.Unity.EthereumWindow/Dto/NativeCurrency.cs @@ -7,11 +7,11 @@ namespace ChainSafe.Gaming.Unity.EthereumWindow.Dto /// public struct NativeCurrency { - public NativeCurrency(string symbol) + public NativeCurrency(string name, string symbol, int decimals) { - Name = symbol; + Name = name; Symbol = symbol; - Decimals = 18; + Decimals = decimals; } [JsonProperty("name")] diff --git a/src/ChainSafe.Gaming.Unity.EthereumWindow/EthereumWindowController.cs b/src/ChainSafe.Gaming.Unity.EthereumWindow/EthereumWindowController.cs index 0f45e4d64..d03bcdbe1 100644 --- a/src/ChainSafe.Gaming.Unity.EthereumWindow/EthereumWindowController.cs +++ b/src/ChainSafe.Gaming.Unity.EthereumWindow/EthereumWindowController.cs @@ -10,6 +10,7 @@ using Nethereum.JsonRpc.Client.RpcMessages; using Newtonsoft.Json; using UnityEngine; +using NativeCurrency = ChainSafe.Gaming.Unity.EthereumWindow.Dto.NativeCurrency; namespace ChainSafe.Gaming.Unity.EthereumWindow { @@ -142,7 +143,7 @@ private async Task WalletChain(IChainConfig chainConfig, ChainRegis Symbol = nativeCurrency.Symbol, Decimals = (int)nativeCurrency.Decimals, } - : new NativeCurrency(chainConfig.Symbol), + : new NativeCurrency(chainConfig.NativeCurrency.Name, chainConfig.NativeCurrency.Symbol, chainConfig.NativeCurrency.Decimals), }; } diff --git a/src/ChainSafe.Gaming/Web3/Core/Chains/ChainConfig.cs b/src/ChainSafe.Gaming/Web3/Core/Chains/ChainConfig.cs index 1db3033ce..58d035e5d 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Chains/ChainConfig.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Chains/ChainConfig.cs @@ -1,5 +1,7 @@ using System; +using ChainSafe.Gaming.Evm.Network; using ChainSafe.Gaming.Web3; +using ChainSafe.Gaming.Web3.Core.Chains; namespace ChainSafe.Gaming.NetCore { @@ -17,10 +19,9 @@ public class ChainConfig : IChainConfig public string ChainId { get; set; } /// - /// Implementation of - /// Chain currency symbol. + /// Implementation of . /// - public string Symbol { get; set; } + public INativeCurrency NativeCurrency { get; set; } /// /// Implementation of diff --git a/src/ChainSafe.Gaming/Web3/Core/Chains/ChainConfigExtensions.cs b/src/ChainSafe.Gaming/Web3/Core/Chains/ChainConfigExtensions.cs index 7eccd7f00..cd57b11b7 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Chains/ChainConfigExtensions.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Chains/ChainConfigExtensions.cs @@ -12,7 +12,7 @@ public static IChainConfig Clone(this IChainConfig chainConfig) ChainId = chainConfig.ChainId, Network = chainConfig.Network, Rpc = chainConfig.Rpc, - Symbol = chainConfig.Symbol, + NativeCurrency = chainConfig.NativeCurrency, BlockExplorerUrl = chainConfig.BlockExplorerUrl, Ws = chainConfig.Ws, }; diff --git a/src/ChainSafe.Gaming/Web3/Core/Chains/ChainManagerChainConfig.cs b/src/ChainSafe.Gaming/Web3/Core/Chains/ChainManagerChainConfig.cs index d46c5b385..816197ddc 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Chains/ChainManagerChainConfig.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Chains/ChainManagerChainConfig.cs @@ -13,7 +13,7 @@ public ChainManagerChainConfig(IChainManager chainManager) public string ChainId => CurrentConfig.ChainId; - public string Symbol => CurrentConfig.Symbol; + public INativeCurrency NativeCurrency => CurrentConfig.NativeCurrency; public string Chain => CurrentConfig.Chain; diff --git a/src/ChainSafe.Gaming/Web3/Core/Chains/IChainConfig.cs b/src/ChainSafe.Gaming/Web3/Core/Chains/IChainConfig.cs index 82edf0631..c0a8014e6 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Chains/IChainConfig.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Chains/IChainConfig.cs @@ -1,3 +1,6 @@ +using ChainSafe.Gaming.Evm.Network; +using ChainSafe.Gaming.Web3.Core.Chains; + namespace ChainSafe.Gaming.Web3 { /// @@ -13,7 +16,7 @@ public interface IChainConfig // TODO: double check these xml docs pls /// /// Token symbol ID. /// - public string Symbol { get; } + public INativeCurrency NativeCurrency { get; } /// /// The name of the chain to be used. Equals 'Ethereum' for Ethereum Mainnet. diff --git a/src/ChainSafe.Gaming/Web3/Core/Chains/INativeCurrency.cs b/src/ChainSafe.Gaming/Web3/Core/Chains/INativeCurrency.cs new file mode 100644 index 000000000..ccfc9560f --- /dev/null +++ b/src/ChainSafe.Gaming/Web3/Core/Chains/INativeCurrency.cs @@ -0,0 +1,11 @@ +namespace ChainSafe.Gaming.Web3.Core.Chains +{ + public interface INativeCurrency + { + string Name { get; set; } + + string Symbol { get; set; } + + int Decimals { get; set; } + } +} \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/Chains/NativeCurrency.cs b/src/ChainSafe.Gaming/Web3/Core/Chains/NativeCurrency.cs new file mode 100644 index 000000000..84e9a1408 --- /dev/null +++ b/src/ChainSafe.Gaming/Web3/Core/Chains/NativeCurrency.cs @@ -0,0 +1,17 @@ +using ChainSafe.Gaming.Web3.Core.Chains; + +namespace ChainSafe.Gaming.Web3 +{ + /// + /// This class is necessary in order to properly create a request when adding the new network to reown. + /// + [System.Serializable] + public class NativeCurrency : INativeCurrency + { + public string Name { get; set; } + + public string Symbol { get; set; } + + public int Decimals { get; set; } + } +} \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Evm/Wallet/IWalletProvider.cs b/src/ChainSafe.Gaming/Web3/Evm/Wallet/IWalletProvider.cs index 5b30f9bbb..cbb30c95b 100644 --- a/src/ChainSafe.Gaming/Web3/Evm/Wallet/IWalletProvider.cs +++ b/src/ChainSafe.Gaming/Web3/Evm/Wallet/IWalletProvider.cs @@ -21,5 +21,13 @@ public interface IWalletProvider : IRpcProvider Task Disconnect(); Task Request(string method, params object[] parameters); + + /// + /// Method that automatically adds a new network to the wallet if it's not present. + /// If the network is present, it prompts to switch to that network. + /// + /// Throwing exception if we fail to switch to the network. + /// Nothing. + Task AddNetworkIfNotExistInWallet(IChainConfig chainConfig = null); } } \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Evm/Wallet/WalletProvider.cs b/src/ChainSafe.Gaming/Web3/Evm/Wallet/WalletProvider.cs index 781b24598..b2f03a1e4 100644 --- a/src/ChainSafe.Gaming/Web3/Evm/Wallet/WalletProvider.cs +++ b/src/ChainSafe.Gaming/Web3/Evm/Wallet/WalletProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Numerics; using System.Threading.Tasks; using ChainSafe.Gaming.Evm.Providers; @@ -41,10 +42,7 @@ public async Task HandleChainSwitching() { try { - using (operationTracker.TrackOperation("Switching wallet network...")) - { - await SwitchChain(chainConfig.ChainId); - } + await SwitchChain(chainConfig); } catch (Exception ex) { @@ -52,16 +50,66 @@ public async Task HandleChainSwitching() } } - protected async Task SwitchChain(string chainId) + private async Task SwitchChain(IChainConfig chainId) + { + await AddNetworkIfNotExistInWallet(chainId); + } + + private async Task GetWalletChainId() + { + var rawHexChainId = await Request( + "eth_chainId"); + rawHexChainId = rawHexChainId.Replace("0x", string.Empty); + ulong number = Convert.ToUInt64(rawHexChainId, 16); + + return number.ToString(CultureInfo.InvariantCulture); + } + + public async Task AddNetworkIfNotExistInWallet(IChainConfig config = null) { - var str = $"{BigInteger.Parse(chainId):X}"; - str = str.TrimStart('0'); - var networkSwitchParams = new + var chainId = await GetWalletChainId(); + var chainConfig = config ?? this.chainConfig; + + // If we are already on the correct network, return. + if (chainId == chainConfig.ChainId) { - chainId = $"0x{str}", // Convert the Chain ID to hex format + return; + } + + var addChainParameters = new[] + { + new + { + chainId = "0x" + ulong.Parse(chainConfig.ChainId).ToString("X"), + chainName = chainConfig.Chain, + nativeCurrency = new + { + name = chainConfig.NativeCurrency.Name, + symbol = chainConfig.NativeCurrency.Symbol, + decimals = chainConfig.NativeCurrency.Decimals, + }, + rpcUrls = new[] { chainConfig.Rpc }, + blockExplorerUrls = new[] { chainConfig.BlockExplorerUrl }, + }, }; - await Request("wallet_switchEthereumChain", networkSwitchParams); + using (operationTracker.TrackOperation($"Adding or Switching the network to: {chainConfig.Chain}...")) + { + try + { + await AddChain(addChainParameters); + } + catch (Exception e) + { + logWriter.LogError($"Failed to add and switch to the network: {e.Message}"); + throw new InvalidOperationException("Failed to add or switch to the network.", e); + } + } + } + + protected async Task AddChain(object addChainParameters) + { + await Request("wallet_addEthereumChain", addChainParameters); } } } \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Evm/Wallet/WalletSigner.cs b/src/ChainSafe.Gaming/Web3/Evm/Wallet/WalletSigner.cs index cd81ed8f9..af9f11551 100644 --- a/src/ChainSafe.Gaming/Web3/Evm/Wallet/WalletSigner.cs +++ b/src/ChainSafe.Gaming/Web3/Evm/Wallet/WalletSigner.cs @@ -29,6 +29,8 @@ public virtual async ValueTask WillStartAsync() string address = await walletProvider.Connect(); PublicAddress = address.AssertIsPublicAddress(); + + await walletProvider.AddNetworkIfNotExistInWallet(); } public virtual async Task SignMessage(string message) diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK Lootboxes/3.0.6/Lootboxes Samples/Scripts/ChainlinkLootboxSampleLauncher.cs b/src/UnitySampleProject/Assets/Samples/web3.unity SDK Lootboxes/3.0.6/Lootboxes Samples/Scripts/ChainlinkLootboxSampleLauncher.cs index 367dcf027..14ed13825 100644 --- a/src/UnitySampleProject/Assets/Samples/web3.unity SDK Lootboxes/3.0.6/Lootboxes Samples/Scripts/ChainlinkLootboxSampleLauncher.cs +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK Lootboxes/3.0.6/Lootboxes Samples/Scripts/ChainlinkLootboxSampleLauncher.cs @@ -12,6 +12,7 @@ using ChainSafe.Gaming.Web3.Unity; using Microsoft.Extensions.DependencyInjection; using UnityEngine; +using NativeCurrency = ChainSafe.Gaming.Web3.NativeCurrency; namespace LootBoxes.Chainlink @@ -38,7 +39,12 @@ private class Web3Config : ICompleteProjectConfig ChainId = "31337", Chain = "Anvil", Network = "GoChain Testnet", - Symbol = "GO", + NativeCurrency = new NativeCurrency() + { + Name = "Go Ether", + Symbol = "GO", + Decimals = 18 + }, Rpc = $"http://127.0.0.1:8545", BlockExplorerUrl = "https://explorer.gochain.io/", } diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK Marketplace/3.0.6/Marketplace Samples/Scripts/UI_MarketplaceItem.cs b/src/UnitySampleProject/Assets/Samples/web3.unity SDK Marketplace/3.0.6/Marketplace Samples/Scripts/UI_MarketplaceItem.cs index 3b50b4c0b..ad73b7e01 100644 --- a/src/UnitySampleProject/Assets/Samples/web3.unity SDK Marketplace/3.0.6/Marketplace Samples/Scripts/UI_MarketplaceItem.cs +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK Marketplace/3.0.6/Marketplace Samples/Scripts/UI_MarketplaceItem.cs @@ -35,7 +35,7 @@ public async Task Initialize(MarketplaceItem model) itemId.text = "ID " + model.Token.Id; itemPrice.text = ((decimal)BigInteger.Parse(model.Price) / (decimal)BigInteger.Pow(10, 18)).ToString("0.############", - CultureInfo.InvariantCulture) + Web3Unity.Web3.ChainConfig.Symbol; + CultureInfo.InvariantCulture) + Web3Unity.Web3.ChainConfig.NativeCurrency.Symbol; button.onClick.AddListener(Purchase); } @@ -68,7 +68,7 @@ private async void Purchase() button.interactable = false; itemStatus.text = "Sold"; } - catch (ServiceNotBoundWeb3Exception _) + catch (ServiceNotBoundWeb3Exception) { Debug.LogError("You wanted to purchase an item and you don't have a wallet. Please connect the wallet to make a purchase"); Web3Unity.ConnectionScreen.Open(); diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/3.0.6/Web3.Unity Samples/Scenes/SampleMain.unity b/src/UnitySampleProject/Assets/Samples/web3.unity SDK/3.0.6/Web3.Unity Samples/Scenes/SampleMain.unity index f7d317da7..59fb3ff5d 100644 --- a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/3.0.6/Web3.Unity Samples/Scenes/SampleMain.unity +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK/3.0.6/Web3.Unity Samples/Scenes/SampleMain.unity @@ -1119,7 +1119,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: -0.000030517578, y: 0} + m_AnchoredPosition: {x: -0.000061035156, y: 0} m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0, y: 1} --- !u!114 &1703188665