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 e14a2d974..a584b04ee 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 5da81746b..35cd77561 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 ecc7e2df4..dc859690a 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/Editor/ABICSharpConverter.cs b/Packages/io.chainsafe.web3-unity/Editor/ABICSharpConverter.cs new file mode 100644 index 000000000..342b95a4e --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Editor/ABICSharpConverter.cs @@ -0,0 +1,496 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Text.RegularExpressions; +using Nethereum.ABI; +using Nethereum.ABI.ABIDeserialisation; +using Nethereum.ABI.FunctionEncoding.Attributes; +using Nethereum.ABI.Model; +using UnityEditor; +using UnityEngine; + +public class ABICSharpConverter : EditorWindow +{ + private string _abi; + private bool _abiIsValid; + private ContractABI _contractABI; + private string _contractName; + private DefaultAsset _targetFolder; + private Dictionary> _customClassDict; + + public Dictionary> CustomClassDict => _customClassDict; + + private static ABICSharpConverter _instance; + + public static ABICSharpConverter Instance + { + get + { + if (_instance == null) + _instance = GetWindow("ABI to C# Contract Converter"); + return _instance; + } + set => _instance = value; + } + + // UI rendering method + private void OnGUI() + { + var style = new GUIStyle(GUI.skin.label) { richText = true }; + + GUILayout.Space(10); + GUILayout.Label("ChainSafe ABI to C# Contract Converter", style); + GUILayout.Space(10); + + _contractName = EditorGUILayout.TextField("Contract Name", _contractName); + _targetFolder = (DefaultAsset)EditorGUILayout.ObjectField("Select Folder", _targetFolder, typeof(DefaultAsset), false); + + if (_targetFolder == null) + { + EditorGUILayout.HelpBox("No folder selected, please select a folder first", MessageType.Error); + return; + } + + EditorGUI.BeginChangeCheck(); + _abi = EditorGUILayout.TextField("ABI", _abi, EditorStyles.textArea, GUILayout.Height(200)); + if (EditorGUI.EndChangeCheck()) + _abiIsValid = IsValidAbi(_abi); + + if (!_abiIsValid) + { + EditorGUILayout.HelpBox("Invalid ABI", MessageType.Error); + return; + } + + if (string.IsNullOrEmpty(_contractName.Trim())) + { + EditorGUILayout.HelpBox("Contract Name cannot be empty", MessageType.Error); + return; + } + + if (Regex.IsMatch(_contractName, @"[^a-zA-Z0-9_]|(?<=^)[0-9]")) + { + EditorGUILayout.HelpBox("Contract name is invalid", MessageType.Error); + return; + } + + if (GUILayout.Button("Convert")) + { + ConvertAbiToCSharp(); + } + } + + [MenuItem("ChainSafe SDK/ABI to C# Contract Converter")] + public static void ShowWindow() + { + Instance = GetWindow("ABI to C# Contract Converter"); + } + + // Method to handle ABI conversion + private void ConvertAbiToCSharp() + { + _contractABI = ABIDeserialiserFactory.DeserialiseContractABI(_abi); + var text = Resources.Load("ABIContractClassTemplate").text; + var className = Regex.Replace(_contractName, @"[^a-zA-Z0-9_]|(?<=^)[0-9]", string.Empty); + + text = text.Replace("{CLASS_NAME}", className); + var minifiedJson = JsonDocument.Parse(_abi).RootElement.GetRawText(); + var escapedJson = minifiedJson.Replace("\"", "\\\""); + text = text.Replace("{CONTRACT_ABI}", escapedJson); + text = Regex.Replace(text, @"\s*\{CUSTOM_CLASSES\}", "\n\n" + ParseCustomClasses()); + text = Regex.Replace(text, @"\s*\{EVENT_CLASSES\}", "\n\n" + ParseEventClasses()); + text = Regex.Replace(text, @"\s*\{METHODS\}", "\n\n" + ParseMethods()); + text = Regex.Replace(text, @"\s*\{EVENT_SUBSCRIPTION\}", "\n\n" + ParseEventSubscription()); + text = Regex.Replace(text, @"\s*\{EVENT_UNSUBSCRIPTION\}", "\n\n" + ParseEventUnsubscription()); + var path = AssetDatabase.GetAssetPath(_targetFolder); + var fullPath = $"{path}/{className}.cs"; + File.WriteAllText(fullPath, text); + AssetDatabase.Refresh(); + } + + // Method to check if the ABI is valid + private bool IsValidAbi(string abi) + { + abi = abi.Trim(); + var contractABI = ABIDeserialiserFactory.DeserialiseContractABI(abi); + return !string.IsNullOrEmpty(abi) && (contractABI.Functions.Length > 0 || contractABI.Events.Length > 0 || contractABI.Errors.Length > 0); + } + + // Method to parse and extract custom classes + private string ParseCustomClasses() + { + var sb = new StringBuilder(); + _customClassDict = ExtractCustomClassesWithParams(); + + var customClassTemplate = Resources.Load("CustomClassTemplate").text; + var paramTemplate = Resources.Load("ParamTemplate").text; + + foreach (var key in _customClassDict.Keys) + { + var classStringBuilder = new StringBuilder(customClassTemplate); + classStringBuilder.Replace("{CLASSNAME}", key); + classStringBuilder.Replace("{PARAMETERS}", ParseParameters(_customClassDict[key], paramTemplate).ToString()); + sb.Append(classStringBuilder); + } + + return sb.ToString(); + } + + private Dictionary> ExtractCustomClassesWithParams() + { + var dict = new Dictionary>(); + + foreach (var functionABI in _contractABI.Functions) + { + foreach (var inputParameter in functionABI.InputParameters) ProcessParameter(inputParameter, dict); + foreach (var outputParameter in functionABI.OutputParameters) ProcessParameter(outputParameter, dict); + } + + foreach (var abiEvent in _contractABI.Events) + foreach (var inputParameter in abiEvent.InputParameters) ProcessParameter(inputParameter, dict); + return dict; + } + + private void ProcessParameter(Parameter parameter, Dictionary> dict) + { + switch (parameter.ABIType) + { + case TupleType tupleType: + ProcessTupleComponents(parameter, tupleType.Components, dict); + break; + case ArrayType { ElementType: TupleType elementTupleType }: + ProcessTupleComponents(parameter, elementTupleType.Components, dict, true); + break; + } + } + + private void ProcessTupleComponents(Parameter parameter, IReadOnlyList components, Dictionary> dict, bool isArray = false) + { + var className = parameter.InternalType.Split(".")[^1].RemoveFirstUnderscore().Capitalize(); + if (isArray) className = className.Replace("[]", ""); + + if (dict.ContainsKey(className)) + { + Debug.LogError("Trying to process the same class " + className + " multiple times. Skipping..."); + return; + } + + dict[className] = new List(); + + foreach (var component in components) + { + ProcessParameter(component, dict); + dict[className].Add(component); + } + } + + private StringBuilder ParseParameters(IList parameters, string paramTemplate) + { + var stringBuilder = new StringBuilder(); + for (var index = 0; index < parameters.Count; index++) + { + var param = parameters[index]; + var eventParamStringBuilder = new StringBuilder(paramTemplate); + eventParamStringBuilder.Replace("{TRUE_TYPE}", param.Type); + eventParamStringBuilder.Replace("{TRUE_NAME}", param.Name); + eventParamStringBuilder.Replace("{CSHARP_TYPE}", param.InternalType.ToCSharpType()); + eventParamStringBuilder.Replace("{CSHARP_NAME}", param.Name.RemoveFirstUnderscore().Capitalize()); + eventParamStringBuilder.Replace("{PARAM_ORDER}", index.ToString()); + eventParamStringBuilder.Replace("{PARAM_INDEXED}", param.Indexed.ToString().ToLowerInvariant()); + stringBuilder.Append(eventParamStringBuilder); + stringBuilder.Append("\n"); + } + + return stringBuilder; + } + + private string ParseMethods() + { + var functionTemplateBase = Resources.Load("FunctionTemplate").text; + var result = new StringBuilder(); + + foreach (var functionABI in _contractABI.Functions) + { + var functionNoTransactionReceipt = GenerateMethodWithFunctionABI(functionABI, functionTemplateBase, false); + var functionWithTransactionReceipt = ""; + if (!functionABI.Constant) + functionWithTransactionReceipt = GenerateMethodWithFunctionABI(functionABI, functionTemplateBase, true); + result.Append(functionNoTransactionReceipt); + result.Append("\n"); + result.Append(functionWithTransactionReceipt); + result.Append("\n\n"); + } + + return result.ToString(); + } + + private static string GenerateMethodWithFunctionABI(FunctionABI functionABI, string functionTemplateBase, bool useTransactionReceipt) + { + var functionStringBuilder = new StringBuilder(functionTemplateBase); + + ReplaceMethodName(functionStringBuilder, functionABI, useTransactionReceipt); + ReplaceInputParameters(functionStringBuilder, functionABI); + ReplaceContractMethodCall(functionStringBuilder, functionABI); + ReplaceReturnType(functionStringBuilder, functionABI, useTransactionReceipt); + ReplaceFunctionCall(functionStringBuilder, functionABI, useTransactionReceipt); + ReplaceInputParamNames(functionStringBuilder, functionABI); + ReplaceReturnStatement(functionStringBuilder, functionABI, useTransactionReceipt); + + return functionStringBuilder.ToString(); + } + + private static void ReplaceMethodName(StringBuilder functionStringBuilder, FunctionABI functionABI, bool useTransactionReceipt) + { + functionStringBuilder.Replace("{METHOD_NAME}", functionABI.Name.RemoveFirstUnderscore().Capitalize() + (useTransactionReceipt ? "WithReceipt" : "")); + } + + private static void ReplaceInputParameters(StringBuilder functionStringBuilder, FunctionABI functionABI) + { + functionStringBuilder.Replace("{INPUT_PARAMS}", string.Join(", ", functionABI.InputParameters.Select(x => $"{x.InternalType.ToCSharpType()} {(string.IsNullOrEmpty(x.Name.ReplaceReservedNames()) ? $"{x.InternalType}" : $"{x.Name.ReplaceReservedNames()}")}"))); + } + + private static void ReplaceContractMethodCall(StringBuilder functionStringBuilder, FunctionABI functionABI) + { + functionStringBuilder.Replace("{CONTRACT_METHOD_CALL}", functionABI.Name); + } + + private static void ReplaceReturnType(StringBuilder functionStringBuilder, FunctionABI functionABI, bool useTransactionReceipt) + { + if (useTransactionReceipt) + { + if (functionABI.OutputParameters.Length >= 1) + functionStringBuilder.Replace("{RETURN_TYPE}", "(" + string.Join(", ", functionABI.OutputParameters.Select(x => $"{x.InternalType.ToCSharpType()} {x.Name.ReplaceReservedNames()}")) + (functionABI.OutputParameters.Length != 0 ? ", " : "") + "TransactionReceipt receipt)"); + else + functionStringBuilder.Replace("{RETURN_TYPE}", "TransactionReceipt"); + } + else + { + if (functionABI.OutputParameters.Length > 1) + functionStringBuilder.Replace("{RETURN_TYPE}", "(" + string.Join(", ", functionABI.OutputParameters.Select(x => $"{x.InternalType.ToCSharpType()} {x.Name.ReplaceReservedNames()}")) + ")"); + else if (functionABI.OutputParameters.Length == 1) + functionStringBuilder.Replace("{RETURN_TYPE}", functionABI.OutputParameters[0].InternalType.ToCSharpType()); + else + functionStringBuilder.Replace("<{RETURN_TYPE}>", ""); + } + } + + private static void ReplaceFunctionCall(StringBuilder functionStringBuilder, FunctionABI functionABI, bool useTransactionReceipt) + { + var sb = new StringBuilder(); + + if (functionABI.Constant) + sb.Append("Call"); + else + sb.Append(useTransactionReceipt ? "SendWithReceipt" : "Send"); + if (functionABI.OutputParameters.Length == 1) + sb.Append($"<{functionABI.OutputParameters[0].InternalType.ToCSharpType()}>"); + functionStringBuilder.Replace("{FUNCTION_CALL}", sb.ToString()); + } + + private static void ReplaceInputParamNames(StringBuilder functionStringBuilder, FunctionABI functionABI) + { + functionStringBuilder.Replace("{INPUT_PARAM_NAMES}", string.Join(", ", functionABI.InputParameters.Select(x => x.Name.ReplaceReservedNames()))); + } + + private static void ReplaceReturnStatement(StringBuilder functionStringBuilder, FunctionABI functionABI, bool useTransactionReceipt) + { + var sb = new StringBuilder(); + + if (functionABI.OutputParameters.Length > 1) + { + sb.Append("("); + for (var i = 0; i < functionABI.OutputParameters.Length; i++) + { + sb.Append($"({functionABI.OutputParameters[i].Type.ToCSharpType()})response" + $"{(useTransactionReceipt ? ".response" : "")}[{i}]"); + if (i != functionABI.OutputParameters.Length - 1) sb.Append(", "); + } + sb.Append(useTransactionReceipt ? ", response.receipt)" : ")"); + } + else if (functionABI.OutputParameters.Length == 1) + { + if (useTransactionReceipt) sb.Append("("); + sb.Append($"response{(useTransactionReceipt ? ".response" : "")}"); + sb.Append(useTransactionReceipt ? ", response.receipt)" : ""); + } + + if (functionABI.OutputParameters.Length != 0) + functionStringBuilder.Replace("{RETURN_STATEMENT}", sb.ToString()); + else + functionStringBuilder.Replace("return {RETURN_STATEMENT};", useTransactionReceipt ? "return response.receipt;" : ""); + } + + private string ParseEventSubscription() + { + var sb = new StringBuilder(); + + foreach (var eventABI in _contractABI.Events) + { + var varName = eventABI.Name.RemoveFirstUnderscore().Capitalize(); + sb.Append($"\t\t\tvar filter{varName}Event = Event<{varName}EventDTO>.GetEventABI().CreateFilterInput();\n"); + var eventSubscription = new StringBuilder(Resources.Load("SubscriptionTemplate").text); + eventSubscription.Replace("{ETH_LOG_CLIENT_NAME}", $"event{varName}"); + eventSubscription.Replace("{FILTER}", $"filter{varName}Event"); + eventSubscription.Replace("{CLASS_DTO_NAME}", $"{varName}EventDTO"); + eventSubscription.Replace("{EVENT_NAME}", $"On{varName}"); + sb.Append(eventSubscription); + sb.Append("\n"); + } + + return sb.ToString(); + } + + private string ParseEventUnsubscription() + { + var sb = new StringBuilder(); + + foreach (var eventABI in _contractABI.Events) + { + var varName = eventABI.Name.RemoveFirstUnderscore().Capitalize(); + sb.Append($"\t\t\tawait event{varName}.UnsubscribeAsync();\n"); + sb.Append($"\t\t\tOn{varName} = null;\n"); + } + + return sb.ToString(); + } + + private string ParseEventClasses() + { + var sb = new StringBuilder(); + var eventTemplateBase = Resources.Load("EventTemplate").text; + var paramTemplate = Resources.Load("ParamTemplate").text; + + foreach (var eventABI in _contractABI.Events) + { + var eventStringBuilder = new StringBuilder(eventTemplateBase); + eventStringBuilder.Replace("{EVENT_NAME}", eventABI.Name); + eventStringBuilder.Replace("{EVENT_NAME_CSHARP}", eventABI.Name.RemoveFirstUnderscore().Capitalize()); + var stringBuilder = ParseParameters(eventABI.InputParameters, paramTemplate); + + eventStringBuilder.Replace("{EVENT_PARAMS}", stringBuilder.ToString()); + sb.Append(eventStringBuilder); + sb.Append("\n\n"); + sb.Replace("{EVENT_LOG_SUBSCRIPTION}", $"EthLogsObservableSubscription event{eventABI.Name.RemoveFirstUnderscore().Capitalize()};"); + sb.Replace("{EVENT_ACTION_SUBSCRIPTION}", $"public event Action<{eventABI.Name.RemoveFirstUnderscore().Capitalize()}EventDTO> On{eventABI.Name.RemoveFirstUnderscore().Capitalize()};"); + } + + return sb.ToString(); + } +} + +public static class ABIToCSHarpTypesExtension +{ + public static string ToCSharpType(this string parameter) + { + return parameter switch + { + "uint256" => "BigInteger", + "uint256[]" => "BigInteger[]", + "uint8" => "byte", + "uint8[]" => "byte[]", + "uint16" => "ushort", + "uint16[]" => "ushort[]", + "uint32" => "uint", + "uint32[]" => "uint[]", + "uint64" => "ulong", + "uint64[]" => "ulong[]", + "uint128" => "BigInteger", + "uint128[]" => "BigInteger[]", + "uint" => "BigInteger", // Alias for uint256 + "uint[]" => "BigInteger[]", + "int256" => "BigInteger", + "int256[]" => "BigInteger[]", + "int8" => "sbyte", + "int8[]" => "sbyte[]", + "int16" => "short", + "int16[]" => "short[]", + "int32" => "int", + "int32[]" => "int[]", + "int64" => "long", + "int64[]" => "long[]", + "int128" => "BigInteger", + "int128[]" => "BigInteger[]", + "int" => "BigInteger", // Alias for int256 + "int[]" => "BigInteger[]", + "address" => "string", + "address[]" => "string[]", + "bool" => "bool", + "bool[]" => "bool[]", + "string" => "string", + "string[]" => "string[]", + "bytes" => "byte[]", + "bytes[]" => "byte[][]", + "bytes1" => "byte[]", + "bytes2" => "byte[]", + "bytes3" => "byte[]", + "bytes4" => "byte[]", + "bytes5" => "byte[]", + "bytes6" => "byte[]", + "bytes7" => "byte[]", + "bytes8" => "byte[]", + "bytes9" => "byte[]", + "bytes10" => "byte[]", + "bytes11" => "byte[]", + "bytes12" => "byte[]", + "bytes13" => "byte[]", + "bytes14" => "byte[]", + "bytes15" => "byte[]", + "bytes16" => "byte[]", + "bytes17" => "byte[]", + "bytes18" => "byte[]", + "bytes19" => "byte[]", + "bytes20" => "byte[]", + "bytes21" => "byte[]", + "bytes22" => "byte[]", + "bytes23" => "byte[]", + "bytes24" => "byte[]", + "bytes25" => "byte[]", + "bytes26" => "byte[]", + "bytes27" => "byte[]", + "bytes28" => "byte[]", + "bytes29" => "byte[]", + "bytes30" => "byte[]", + "bytes31" => "byte[]", + "bytes32" => "byte[]", + _ => GetParameterTypeFromDictionary(parameter) + }; + } + + private static string GetParameterTypeFromDictionary(string parameter) + { + var dict = ABICSharpConverter.Instance.CustomClassDict; + var isArray = parameter.Contains("[]"); + var paramName = parameter.Split(".")[^1].RemoveFirstUnderscore().Capitalize().Replace("[]", ""); + if (!dict.ContainsKey(paramName)) + { + Debug.LogError("Can't find " + paramName + " in the dictionary"); + return "object"; + } + + return paramName + (isArray ? "[]" : ""); + } + + public static string Capitalize(this string str) + { + return string.IsNullOrEmpty(str) ? str : char.ToUpper(str[0]) + str[1..]; + } + + public static string RemoveFirstUnderscore(this string str) + { + return str[0] == '_' ? str[1..] : str; + } + + public static string ReplaceReservedNames(this string str) + { + return str switch + { + "operator" => "@operator", + "params" => "@params", + "event" => "@event", + "delegate" => "@delegate", + "object" => "@object", + _ => str + }; + } +} diff --git a/Packages/io.chainsafe.web3-unity/Editor/ABICSharpConverter.cs.meta b/Packages/io.chainsafe.web3-unity/Editor/ABICSharpConverter.cs.meta new file mode 100644 index 000000000..f729c6555 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Editor/ABICSharpConverter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7993de1fa7ccf4244a6d5af367d8dc2f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/io.chainsafe.web3-unity/Editor/ABIConverter.cs b/Packages/io.chainsafe.web3-unity/Editor/ABIConverter.cs index 4ac499058..30955c748 100644 --- a/Packages/io.chainsafe.web3-unity/Editor/ABIConverter.cs +++ b/Packages/io.chainsafe.web3-unity/Editor/ABIConverter.cs @@ -11,14 +11,14 @@ public class ABIWindow : EditorWindow Vector2 TextArea; // Where is the window menu located - [MenuItem("ChainSafe SDK/ABI Converter")] + [MenuItem("ChainSafe SDK/Generate ABI wrapper")] // Show our window public static void ShowWindow() { - GetWindow("ChainSafe ABI Converter"); + GetWindow("ChainSafe ABI Formatter"); } - + private void OnGUI() { @@ -28,7 +28,7 @@ private void OnGUI() // Window Header GUILayout.Space(10); - GUILayout.Label("ChainSafe ABI Converter", style); + GUILayout.Label("ChainSafe ABI Wrapper", style); GUILayout.Label("Copy/Paste is supported.", style); GUILayout.Space(10); @@ -51,10 +51,13 @@ private void OnGUI() Debug.Log("ABI Conversion Complete. Results copied to clipboard!"); } - + GUIStyle labelStyle = new GUIStyle(EditorStyles.label) + { + wordWrap = true + }; // Window Footer (Instructions) GUILayout.Space(10); - GUILayout.Label("This tool will automatically convert your ABI for use with the web3.unity SDK. \n", EditorStyles.largeLabel); + GUILayout.Label("This tool will fix ABI spacing and will give you the ABI wrapped around in quotation marks so that you can immediately paste it to your ABI String variable inside of your C# project \n", labelStyle); GUILayout.Label("=============", style); GUILayout.Label(" INSTRUCTIONS", style); GUILayout.Label("============= \n", style); diff --git a/Packages/io.chainsafe.web3-unity/Editor/ServerSettings.cs b/Packages/io.chainsafe.web3-unity/Editor/ServerSettings.cs index 627d6fd6e..6480b95e6 100644 --- a/Packages/io.chainsafe.web3-unity/Editor/ServerSettings.cs +++ b/Packages/io.chainsafe.web3-unity/Editor/ServerSettings.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; using ChainSafe.Gaming.UnityPackage; using Newtonsoft.Json; @@ -37,6 +38,7 @@ public class ChainSafeServerSettings : EditorWindow private string network; private string symbol; private string rpc; + private string ws; private string newRpc; private string blockExplorerUrl; private bool enableAnalytics; @@ -47,12 +49,13 @@ public class ChainSafeServerSettings : EditorWindow // Search window private StringListSearchProvider searchProvider; private ISearchWindowProvider _searchWindowProviderImplementation; - public UnityEvent onDropDownChange; private int previousNetworkDropdownIndex; private List chainList; private int selectedChainIndex; private int selectedRpcIndex; + private int selectedWebHookIndex; private FetchingStatus fetchingStatus = FetchingStatus.NotFetching; + private bool _changedRpcOrWs; private enum FetchingStatus { @@ -78,22 +81,20 @@ private void Awake() network = string.IsNullOrEmpty(projectConfig?.Network) ? NetworkDefault : projectConfig.Network; symbol = string.IsNullOrEmpty(projectConfig?.Symbol) ? SymbolDefault : projectConfig.Symbol; rpc = string.IsNullOrEmpty(projectConfig?.Rpc) ? RpcDefault : projectConfig.Rpc; - blockExplorerUrl = string.IsNullOrEmpty(projectConfig?.BlockExplorerUrl) ? BlockExplorerUrlDefault : projectConfig.BlockExplorerUrl; + blockExplorerUrl = string.IsNullOrEmpty(projectConfig?.BlockExplorerUrl) + ? BlockExplorerUrlDefault + : projectConfig.BlockExplorerUrl; enableAnalytics = projectConfig.EnableAnalytics; - // Search menu - onDropDownChange = new UnityEvent(); - onDropDownChange.AddListener(UpdateServerMenuInfo); - // Fetch supported chains + ws = projectConfig.Ws; } /// /// Updates the values in the server settings area when an item is selected /// - public void UpdateServerMenuInfo() + public void UpdateServerMenuInfo(bool chainSwitched = false) { // Get the selected chain index selectedChainIndex = Array.FindIndex(chainList.ToArray(), x => x.name == chain); - // Check if the selectedChainIndex is valid if (selectedChainIndex >= 0 && selectedChainIndex < chainList.Count) { @@ -106,6 +107,19 @@ public void UpdateServerMenuInfo() // Set the rpc rpc = chainList[selectedChainIndex].rpc[selectedRpcIndex]; blockExplorerUrl = chainList[selectedChainIndex].explorers[0].url; + + if (chainSwitched) + { + ws = chainList[selectedChainIndex].rpc.FirstOrDefault(x => x.StartsWith("wss")); + selectedWebHookIndex = chainList[selectedChainIndex].rpc.IndexOf(ws); + } + else + { + selectedWebHookIndex = chainList[selectedChainIndex].rpc.IndexOf(ws) == -1 + ? chainList[selectedChainIndex].rpc + .IndexOf(chainList[selectedChainIndex].rpc.FirstOrDefault(x => x.StartsWith("wss"))) + : chainList[selectedChainIndex].rpc.IndexOf(ws); + } } else { @@ -131,6 +145,7 @@ private async void FetchSupportedChains() chainList = JsonConvert.DeserializeObject>(json); chainList = chainList.OrderBy(x => x.name).ToList(); fetchingStatus = FetchingStatus.Fetched; + UpdateServerMenuInfo(); } // Initializes window @@ -171,11 +186,9 @@ private void OnGUI() // Null check to stop the recursive loop before the web request has completed if (chainList == null) { - if (fetchingStatus == FetchingStatus.NotFetching || fetchingStatus == FetchingStatus.Fetched) - { - fetchingStatus = FetchingStatus.Fetching; - FetchSupportedChains(); - } + if (fetchingStatus == FetchingStatus.Fetching) return; + fetchingStatus = FetchingStatus.Fetching; + FetchSupportedChains(); return; } @@ -189,7 +202,11 @@ private void OnGUI() if (GUILayout.Button(chain, EditorStyles.popup)) { searchProvider = CreateInstance(); - searchProvider.Initialize(chainOptions, x => { chain = x; }); + searchProvider.Initialize(chainOptions, x => + { + chain = x; + UpdateServerMenuInfo(true); + }); SearchWindow.Open(new SearchWindowContext(GUIUtility.GUIToScreenPoint(Event.current.mousePosition)), searchProvider); } @@ -199,33 +216,34 @@ private void OnGUI() chainID = EditorGUILayout.TextField("Chain ID: ", chainID); symbol = EditorGUILayout.TextField("Symbol: ", symbol); blockExplorerUrl = EditorGUILayout.TextField("Block Explorer: ", blockExplorerUrl); - enableAnalytics = EditorGUILayout.Toggle(new GUIContent("Collect Data for Analytics:", "Consent to collecting data for analytics purposes. This will help improve our product."), enableAnalytics); + enableAnalytics = + EditorGUILayout.Toggle( + new GUIContent("Collect Data for Analytics:", + "Consent to collecting data for analytics purposes. This will help improve our product."), + enableAnalytics); if (enableAnalytics) - { ScriptingDefineSymbols.TryAddDefineSymbol(EnableAnalyticsScriptingDefineSymbol); - } - else - { ScriptingDefineSymbols.TryRemoveDefineSymbol(EnableAnalyticsScriptingDefineSymbol); - } EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Select RPC"); // Remove "https://" so the user doesn't have to click through 2 levels for the rpc options - var rpcOptions = chainList[selectedChainIndex].rpc.Where(rpc => rpc.StartsWith("https")) - .Select(rpc => rpc.Substring(8)).ToArray(); - var selectedRpc = rpcOptions[selectedRpcIndex]; + var rpcOptions = chainList[selectedChainIndex].rpc.Where(x => x.StartsWith("https")) + .Select(x => x.Replace("/", "\u2215")).ToArray(); + var selectedRpc = chainList[selectedChainIndex].rpc[selectedRpcIndex]; // Show the rpc drop down menu if (GUILayout.Button(selectedRpc, EditorStyles.popup)) { searchProvider = CreateInstance(); searchProvider.Initialize(rpcOptions, x => { - selectedRpcIndex = Array.IndexOf(rpcOptions, x); + var str = x.Replace("\u2215", "/"); + selectedRpcIndex = chainList[selectedChainIndex].rpc.IndexOf(str); // Add "https://" back - rpc = "https://" + x; + rpc = str; + _changedRpcOrWs = true; }); SearchWindow.Open(new SearchWindowContext(GUIUtility.GUIToScreenPoint(Event.current.mousePosition)), searchProvider); @@ -233,17 +251,55 @@ private void OnGUI() EditorGUILayout.EndHorizontal(); // Allows for a custom rpc - rpc = EditorGUILayout.TextField("RPC: ", rpc); + rpc = EditorGUILayout.TextField("Custom RPC: ", rpc); GUILayout.Label("If you're using a custom RPC it will override the selection above", EditorStyles.boldLabel); + + // Remove "https://" so the user doesn't have to click through 2 levels for the rpc options + var webHookOptions = chainList[selectedChainIndex].rpc.Where(x => x.StartsWith("w")) + .Select(x => x.Replace("/", "\u2215")).ToArray(); + if (webHookOptions.Length > 0) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PrefixLabel("Select WebHook"); + selectedWebHookIndex = Mathf.Clamp(selectedWebHookIndex, 0, chainList[selectedChainIndex].rpc.Count - 1); + var webhookIndex = chainList[selectedChainIndex].rpc.IndexOf(ws); + var selectedWebHook = webhookIndex == -1 ? chainList[selectedChainIndex].rpc[selectedWebHookIndex] : ws; + if (GUILayout.Button(selectedWebHook, EditorStyles.popup)) + { + searchProvider = CreateInstance(); + searchProvider.Initialize(webHookOptions, + x => + { + var str = x.Replace("\u2215", "/"); + + selectedWebHookIndex = chainList[selectedChainIndex].rpc.IndexOf(str); + ws = str; + _changedRpcOrWs = true; + }); + SearchWindow.Open(new SearchWindowContext(GUIUtility.GUIToScreenPoint(Event.current.mousePosition)), + searchProvider); + } + + EditorGUILayout.EndHorizontal(); + ws = EditorGUILayout.TextField("Custom Webhook: ", ws); + GUILayout.Label("If you're using a custom Webhook it will override the selection above", + EditorStyles.boldLabel); + } + else + { + ws = string.Empty; + } + // Buttons // Register if (GUILayout.Button("Need To Register?")) Application.OpenURL("https://dashboard.gaming.chainsafe.io/"); // Docs if (GUILayout.Button("Check Out Our Docs!")) Application.OpenURL("https://docs.gaming.chainsafe.io/"); // Save button - if (EditorGUI.EndChangeCheck()) + if (EditorGUI.EndChangeCheck() || _changedRpcOrWs) { + _changedRpcOrWs = false; var projectConfig = ProjectConfigUtilities.CreateOrLoad(); projectConfig.ProjectId = projectID; projectConfig.ChainId = chainID; @@ -251,6 +307,7 @@ private void OnGUI() projectConfig.Network = network; projectConfig.Symbol = symbol; projectConfig.Rpc = rpc; + projectConfig.Ws = ws; projectConfig.BlockExplorerUrl = blockExplorerUrl; projectConfig.EnableAnalytics = enableAnalytics; ProjectConfigUtilities.Save(projectConfig); 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 740f135d4..140f69634 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 6fdc75770..2e4ceaa30 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 41c690ec8..7e45b7a5c 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 305c8fbe9..84a6e0462 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 ed406623c..977b3eb9d 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.SygmaClient.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.SygmaClient.dll index 724489253..717ba5411 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 deed3587e..1ac943bbf 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 2b860b05d..cb0b8dd18 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 3821ac7b9..3606ab3c9 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 3fbb3c0cc..51ef3a4cc 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.WalletConnect.dll b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.WalletConnect.dll index 3b5476209..adb76beef 100644 Binary files a/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.WalletConnect.dll and b/Packages/io.chainsafe.web3-unity/Runtime/Libraries/ChainSafe.Gaming.WalletConnect.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 e3b8eac29..ba20800e3 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/Resources/ABIContractClassTemplate.txt b/Packages/io.chainsafe.web3-unity/Runtime/Resources/ABIContractClassTemplate.txt new file mode 100644 index 000000000..061c67df8 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Runtime/Resources/ABIContractClassTemplate.txt @@ -0,0 +1,125 @@ +using System.Threading.Tasks; +using System; +using ChainSafe.Gaming.Evm.Transactions; +using Nethereum.Hex.HexTypes; +using ChainSafe.Gaming.Evm.Contracts; +using System.Numerics; +using Nethereum.RPC.Reactive.Eth.Subscriptions; +using Nethereum.JsonRpc.WebSocketStreamingClient; +using Nethereum.ABI.FunctionEncoding.Attributes; +using Nethereum.Contracts; +using UnityEngine; + + + +namespace ChainSafe.Gaming.Evm.Contracts.Custom +{ + public class {CLASS_NAME} : ICustomContract + { + + public string ABI => "{CONTRACT_ABI}"; + + public string ContractAddress { get; set; } + + public IContractBuilder ContractBuilder { get; set; } + + public Contract OriginalContract { get; set; } + + public string WebSocketUrl { get; set; } + + public bool Subscribed { get; set; } + + private StreamingWebSocketClient _webSocketClient; + + #region Methods + {METHODS} + #endregion + + + #region Event Classes + {EVENT_CLASSES} + #endregion + + #region Interface Implemented Methods + + public async ValueTask DisposeAsync() + { + if(string.IsNullOrEmpty(WebSocketUrl)) + return; + if(!Subscribed) + return; + Subscribed = false; + {EVENT_UNSUBSCRIPTION} + _webSocketClient?.Dispose(); + } + + public async ValueTask Init() + { + if(Subscribed) + return; + + if(string.IsNullOrEmpty(WebSocketUrl)) + { + Debug.LogWarning($"WebSocketUrl is not set for this class. Event Subscriptions will not work."); + return; + } + + _webSocketClient ??= new StreamingWebSocketClient(WebSocketUrl); + await _webSocketClient.StartAsync(); + Subscribed = true; + + {EVENT_SUBSCRIPTION} + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public IContract Attach(string address) + { + return OriginalContract.Attach(address); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public Task Call(string method, object[] parameters = null, TransactionRequest overwrite = null) + { + return OriginalContract.Call(method, parameters, overwrite); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public object[] Decode(string method, string output) + { + return OriginalContract.Decode(method, output); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public Task Send(string method, object[] parameters = null, TransactionRequest overwrite = null) + { + return OriginalContract.Send(method, parameters, overwrite); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public Task<(object[] response, TransactionReceipt receipt)> SendWithReceipt(string method, object[] parameters = null, TransactionRequest overwrite = null) + { + return OriginalContract.SendWithReceipt(method, parameters, overwrite); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public Task EstimateGas(string method, object[] parameters, TransactionRequest overwrite = null) + { + return OriginalContract.EstimateGas(method, parameters, overwrite); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public string Calldata(string method, object[] parameters = null) + { + return OriginalContract.Calldata(method, parameters); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public Task PrepareTransactionRequest(string method, object[] parameters, TransactionRequest overwrite = null) + { + return OriginalContract.PrepareTransactionRequest(method, parameters, overwrite); + } + #endregion + } + + {CUSTOM_CLASSES} +} diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Resources/ABIContractClassTemplate.txt.meta b/Packages/io.chainsafe.web3-unity/Runtime/Resources/ABIContractClassTemplate.txt.meta new file mode 100644 index 000000000..b31bff210 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Runtime/Resources/ABIContractClassTemplate.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 25223f3c396fecb408a64f74e41a5ad4 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Resources/CustomClassTemplate.txt b/Packages/io.chainsafe.web3-unity/Runtime/Resources/CustomClassTemplate.txt new file mode 100644 index 000000000..bcdbe3186 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Runtime/Resources/CustomClassTemplate.txt @@ -0,0 +1,4 @@ +public class {CLASSNAME} +{ + {PARAMETERS} +} \ No newline at end of file diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Resources/CustomClassTemplate.txt.meta b/Packages/io.chainsafe.web3-unity/Runtime/Resources/CustomClassTemplate.txt.meta new file mode 100644 index 000000000..0cb0f1875 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Runtime/Resources/CustomClassTemplate.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c32c7d55edee33547b131f8afc730de7 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Resources/EventTemplate.txt b/Packages/io.chainsafe.web3-unity/Runtime/Resources/EventTemplate.txt new file mode 100644 index 000000000..4ed96a668 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Runtime/Resources/EventTemplate.txt @@ -0,0 +1,10 @@ + public partial class {EVENT_NAME_CSHARP}EventDTO : {EVENT_NAME_CSHARP}EventDTOBase { } + + [Event("{EVENT_NAME}")] + public class {EVENT_NAME_CSHARP}EventDTOBase : IEventDTO + { + {EVENT_PARAMS} + } + + {EVENT_LOG_SUBSCRIPTION} + {EVENT_ACTION_SUBSCRIPTION} \ No newline at end of file diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Resources/EventTemplate.txt.meta b/Packages/io.chainsafe.web3-unity/Runtime/Resources/EventTemplate.txt.meta new file mode 100644 index 000000000..c6539fca0 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Runtime/Resources/EventTemplate.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f67dac59642d3cd4eb8ad602f5e57031 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Resources/FunctionTemplate.txt b/Packages/io.chainsafe.web3-unity/Runtime/Resources/FunctionTemplate.txt new file mode 100644 index 000000000..08551869a --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Runtime/Resources/FunctionTemplate.txt @@ -0,0 +1,8 @@ + public async Task<{RETURN_TYPE}> {METHOD_NAME}({INPUT_PARAMS}) + { + var response = await OriginalContract.{FUNCTION_CALL}("{CONTRACT_METHOD_CALL}", new object [] { + {INPUT_PARAM_NAMES} + }); + + return {RETURN_STATEMENT}; + } \ No newline at end of file diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Resources/FunctionTemplate.txt.meta b/Packages/io.chainsafe.web3-unity/Runtime/Resources/FunctionTemplate.txt.meta new file mode 100644 index 000000000..1c26f033a --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Runtime/Resources/FunctionTemplate.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0041bc87ff676374aa0bf9c6e767e446 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Resources/ParamTemplate.txt b/Packages/io.chainsafe.web3-unity/Runtime/Resources/ParamTemplate.txt new file mode 100644 index 000000000..43bf2e77d --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Runtime/Resources/ParamTemplate.txt @@ -0,0 +1,2 @@ + [Parameter("{TRUE_TYPE}", "{TRUE_NAME}", {PARAM_ORDER}, {PARAM_INDEXED})] + public virtual {CSHARP_TYPE} {CSHARP_NAME} { get; set; } \ No newline at end of file diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Resources/ParamTemplate.txt.meta b/Packages/io.chainsafe.web3-unity/Runtime/Resources/ParamTemplate.txt.meta new file mode 100644 index 000000000..debeec568 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Runtime/Resources/ParamTemplate.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 376c5fe6361ec444ea8734a7d86ea4c2 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Resources/SubscriptionTemplate.txt b/Packages/io.chainsafe.web3-unity/Runtime/Resources/SubscriptionTemplate.txt new file mode 100644 index 000000000..1ec65ff47 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Runtime/Resources/SubscriptionTemplate.txt @@ -0,0 +1,19 @@ + {ETH_LOG_CLIENT_NAME} = new EthLogsObservableSubscription(_webSocketClient); + + {ETH_LOG_CLIENT_NAME}.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event<{CLASS_DTO_NAME}>.DecodeEvent(log); + if (decoded != null) + { + {EVENT_NAME}?.Invoke(decoded.Event); + } + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await {ETH_LOG_CLIENT_NAME}.SubscribeAsync({FILTER}); \ No newline at end of file diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Resources/SubscriptionTemplate.txt.meta b/Packages/io.chainsafe.web3-unity/Runtime/Resources/SubscriptionTemplate.txt.meta new file mode 100644 index 000000000..139d21bab --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Runtime/Resources/SubscriptionTemplate.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a79307a8c6185174297dd0330ccb8db6 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Resources/TestContract.cs b/Packages/io.chainsafe.web3-unity/Runtime/Resources/TestContract.cs new file mode 100644 index 000000000..1ff41149a --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Runtime/Resources/TestContract.cs @@ -0,0 +1,1289 @@ +using System.Threading.Tasks; +using System; +using ChainSafe.Gaming.Evm.Transactions; +using Nethereum.Hex.HexTypes; +using ChainSafe.Gaming.Evm.Contracts; +using System.Numerics; +using Nethereum.RPC.Reactive.Eth.Subscriptions; +using Nethereum.JsonRpc.WebSocketStreamingClient; +using Nethereum.ABI.FunctionEncoding.Attributes; +using Nethereum.Contracts; +using UnityEngine; + + +namespace ChainSafe.Gaming.Evm.Contracts.Custom +{ + public class TestContract : ICustomContract + { + public string ABI => + "[ { \"inputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"constructor\" }, { \"inputs\": [], \"name\": \"AlreadySameStatus\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"AmountInvalid\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"CanNotModify\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"DeadlineInvalid\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"EtherTransferFailed\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"FeeReceiverInvalid\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"IncorrectAmountSupplied\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"IncorrectLength\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"ItemExpired\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"ItemIdInvalid\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"MaxFeeInvalid\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"NFTAlreadyWhitelisted\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"NftTokenInvalid\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"NotEnoughBalance\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"NotExpired\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"OperatorInvalid\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"TotalFeePercentInvalid\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"Unauthorized\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"WhitelistingDisabled\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"ZeroAddress\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"ZeroFeePercent\", \"type\": \"error\" }, { \"inputs\": [], \"name\": \"ZeroPrice\", \"type\": \"error\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": false, \"internalType\": \"address\", \"name\": \"treasury\", \"type\": \"address\" }, { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"feePercent\", \"type\": \"uint256\" } ], \"name\": \"ChainSafeFeeUpdated\", \"type\": \"event\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": false, \"internalType\": \"address\", \"name\": \"feeCollector\", \"type\": \"address\" }, { \"indexed\": false, \"internalType\": \"address\", \"name\": \"receiver\", \"type\": \"address\" }, { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"amount\", \"type\": \"uint256\" } ], \"name\": \"FeeClaimed\", \"type\": \"event\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": false, \"internalType\": \"address\", \"name\": \"feeReceiver\", \"type\": \"address\" } ], \"name\": \"FeeReceiverRemoved\", \"type\": \"event\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": false, \"internalType\": \"address\", \"name\": \"feeReceiver\", \"type\": \"address\" }, { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"feePercent\", \"type\": \"uint256\" } ], \"name\": \"FeeReceiverSet\", \"type\": \"event\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": false, \"internalType\": \"uint8\", \"name\": \"version\", \"type\": \"uint8\" } ], \"name\": \"Initialized\", \"type\": \"event\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"itemId\", \"type\": \"uint256\" }, { \"indexed\": false, \"internalType\": \"address\", \"name\": \"owner\", \"type\": \"address\" } ], \"name\": \"ItemCancelled\", \"type\": \"event\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": false, \"internalType\": \"address\", \"name\": \"nftContract\", \"type\": \"address\" }, { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"tokenId\", \"type\": \"uint256\" }, { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"itemId\", \"type\": \"uint256\" }, { \"indexed\": false, \"internalType\": \"address\", \"name\": \"seller\", \"type\": \"address\" }, { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"price\", \"type\": \"uint256\" }, { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"deadline\", \"type\": \"uint256\" } ], \"name\": \"ItemListed\", \"type\": \"event\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"itemId\", \"type\": \"uint256\" }, { \"indexed\": false, \"internalType\": \"address\", \"name\": \"buyer\", \"type\": \"address\" } ], \"name\": \"ItemSold\", \"type\": \"event\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"feePercent\", \"type\": \"uint256\" } ], \"name\": \"MaxFeeUpdated\", \"type\": \"event\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": false, \"internalType\": \"address[]\", \"name\": \"nftAddresses\", \"type\": \"address[]\" } ], \"name\": \"NFTBlacklisted\", \"type\": \"event\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": false, \"internalType\": \"address[]\", \"name\": \"nftAddresses\", \"type\": \"address[]\" } ], \"name\": \"NFTWhitelisted\", \"type\": \"event\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"role\", \"type\": \"bytes32\" }, { \"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"previousAdminRole\", \"type\": \"bytes32\" }, { \"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"newAdminRole\", \"type\": \"bytes32\" } ], \"name\": \"RoleAdminChanged\", \"type\": \"event\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"role\", \"type\": \"bytes32\" }, { \"indexed\": true, \"internalType\": \"address\", \"name\": \"account\", \"type\": \"address\" }, { \"indexed\": true, \"internalType\": \"address\", \"name\": \"sender\", \"type\": \"address\" } ], \"name\": \"RoleGranted\", \"type\": \"event\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"role\", \"type\": \"bytes32\" }, { \"indexed\": true, \"internalType\": \"address\", \"name\": \"account\", \"type\": \"address\" }, { \"indexed\": true, \"internalType\": \"address\", \"name\": \"sender\", \"type\": \"address\" } ], \"name\": \"RoleRevoked\", \"type\": \"event\" }, { \"anonymous\": false, \"inputs\": [ { \"indexed\": false, \"internalType\": \"bool\", \"name\": \"isEnabled\", \"type\": \"bool\" } ], \"name\": \"WhitelistingStatusUpdated\", \"type\": \"event\" }, { \"inputs\": [], \"name\": \"CREATOR_ROLE\", \"outputs\": [ { \"internalType\": \"bytes32\", \"name\": \"\", \"type\": \"bytes32\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [], \"name\": \"DEFAULT_ADMIN_ROLE\", \"outputs\": [ { \"internalType\": \"bytes32\", \"name\": \"\", \"type\": \"bytes32\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [], \"name\": \"UPDATER_ROLE\", \"outputs\": [ { \"internalType\": \"bytes32\", \"name\": \"\", \"type\": \"bytes32\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address\", \"name\": \"\", \"type\": \"address\" } ], \"name\": \"_feeReceiverDetails\", \"outputs\": [ { \"internalType\": \"uint256\", \"name\": \"feePercent\", \"type\": \"uint256\" }, { \"internalType\": \"uint256\", \"name\": \"feeCollected\", \"type\": \"uint256\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [], \"name\": \"activeItems\", \"outputs\": [ { \"components\": [ { \"internalType\": \"address\", \"name\": \"nftContract\", \"type\": \"address\" }, { \"internalType\": \"uint256\", \"name\": \"tokenId\", \"type\": \"uint256\" }, { \"internalType\": \"address\", \"name\": \"seller\", \"type\": \"address\" }, { \"internalType\": \"uint256\", \"name\": \"price\", \"type\": \"uint256\" }, { \"internalType\": \"uint256\", \"name\": \"deadline\", \"type\": \"uint256\" } ], \"internalType\": \"struct Marketplace.MarketItem[]\", \"name\": \"\", \"type\": \"tuple[]\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address[]\", \"name\": \"nftAddresses\", \"type\": \"address[]\" } ], \"name\": \"blacklistNFTContracts\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"uint256[]\", \"name\": \"itemIds\", \"type\": \"uint256[]\" } ], \"name\": \"cancelExpiredListings\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"uint256\", \"name\": \"itemId\", \"type\": \"uint256\" } ], \"name\": \"cancelListing\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [], \"name\": \"chainsafeTreasury\", \"outputs\": [ { \"internalType\": \"address\", \"name\": \"\", \"type\": \"address\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address\", \"name\": \"receiver\", \"type\": \"address\" } ], \"name\": \"claimFee\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"bool\", \"name\": \"isEnable\", \"type\": \"bool\" } ], \"name\": \"enableWhitelisting\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"uint256\", \"name\": \"from\", \"type\": \"uint256\" }, { \"internalType\": \"uint256\", \"name\": \"to\", \"type\": \"uint256\" } ], \"name\": \"expiredListingIds\", \"outputs\": [ { \"internalType\": \"uint256[]\", \"name\": \"\", \"type\": \"uint256[]\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address\", \"name\": \"feeReceiver\", \"type\": \"address\" } ], \"name\": \"feeCollectedByReceiver\", \"outputs\": [ { \"internalType\": \"uint256\", \"name\": \"\", \"type\": \"uint256\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"uint256\", \"name\": \"id\", \"type\": \"uint256\" } ], \"name\": \"feeReceiver\", \"outputs\": [ { \"internalType\": \"address\", \"name\": \"feeReceiver\", \"type\": \"address\" }, { \"internalType\": \"uint256\", \"name\": \"feePercent\", \"type\": \"uint256\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [], \"name\": \"feeReceiversNumber\", \"outputs\": [ { \"internalType\": \"uint256\", \"name\": \"\", \"type\": \"uint256\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"bytes32\", \"name\": \"role\", \"type\": \"bytes32\" } ], \"name\": \"getRoleAdmin\", \"outputs\": [ { \"internalType\": \"bytes32\", \"name\": \"\", \"type\": \"bytes32\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"bytes32\", \"name\": \"role\", \"type\": \"bytes32\" }, { \"internalType\": \"address\", \"name\": \"account\", \"type\": \"address\" } ], \"name\": \"grantRole\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"bytes32\", \"name\": \"role\", \"type\": \"bytes32\" }, { \"internalType\": \"address\", \"name\": \"account\", \"type\": \"address\" } ], \"name\": \"hasRole\", \"outputs\": [ { \"internalType\": \"bool\", \"name\": \"\", \"type\": \"bool\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"string\", \"name\": \"projectID\", \"type\": \"string\" }, { \"internalType\": \"string\", \"name\": \"marketplaceID\", \"type\": \"string\" }, { \"internalType\": \"address\", \"name\": \"creator\", \"type\": \"address\" }, { \"internalType\": \"address\", \"name\": \"updater\", \"type\": \"address\" }, { \"internalType\": \"address\", \"name\": \"treasury\", \"type\": \"address\" }, { \"internalType\": \"bool\", \"name\": \"isWhitelistingEnable\", \"type\": \"bool\" }, { \"internalType\": \"uint256\", \"name\": \"chainsafeFeePercent\", \"type\": \"uint256\" }, { \"internalType\": \"uint256\", \"name\": \"maxPercent\", \"type\": \"uint256\" } ], \"name\": \"initialize\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address\", \"name\": \"token\", \"type\": \"address\" } ], \"name\": \"isNftToken\", \"outputs\": [ { \"internalType\": \"bool\", \"name\": \"\", \"type\": \"bool\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"uint256\", \"name\": \"itemId\", \"type\": \"uint256\" } ], \"name\": \"itemById\", \"outputs\": [ { \"components\": [ { \"internalType\": \"address\", \"name\": \"nftContract\", \"type\": \"address\" }, { \"internalType\": \"uint256\", \"name\": \"tokenId\", \"type\": \"uint256\" }, { \"internalType\": \"address\", \"name\": \"seller\", \"type\": \"address\" }, { \"internalType\": \"uint256\", \"name\": \"price\", \"type\": \"uint256\" }, { \"internalType\": \"uint256\", \"name\": \"deadline\", \"type\": \"uint256\" } ], \"internalType\": \"struct Marketplace.MarketItem\", \"name\": \"\", \"type\": \"tuple\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address\", \"name\": \"nftContract\", \"type\": \"address\" }, { \"internalType\": \"uint256\", \"name\": \"tokenId\", \"type\": \"uint256\" }, { \"internalType\": \"uint256\", \"name\": \"price\", \"type\": \"uint256\" }, { \"internalType\": \"uint256\", \"name\": \"deadline\", \"type\": \"uint256\" } ], \"name\": \"listItem\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address[]\", \"name\": \"nftContracts\", \"type\": \"address[]\" }, { \"internalType\": \"uint256[]\", \"name\": \"tokenIds\", \"type\": \"uint256[]\" }, { \"internalType\": \"uint256[]\", \"name\": \"amounts\", \"type\": \"uint256[]\" }, { \"internalType\": \"uint256[]\", \"name\": \"prices\", \"type\": \"uint256[]\" }, { \"internalType\": \"uint256[]\", \"name\": \"deadlines\", \"type\": \"uint256[]\" } ], \"name\": \"listItems\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [], \"name\": \"marketplaceID\", \"outputs\": [ { \"internalType\": \"string\", \"name\": \"\", \"type\": \"string\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [], \"name\": \"maxFeePercent\", \"outputs\": [ { \"internalType\": \"uint256\", \"name\": \"\", \"type\": \"uint256\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"uint256\", \"name\": \"id\", \"type\": \"uint256\" } ], \"name\": \"nftToken\", \"outputs\": [ { \"internalType\": \"address\", \"name\": \"token\", \"type\": \"address\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address\", \"name\": \"operator\", \"type\": \"address\" }, { \"internalType\": \"address\", \"name\": \"from\", \"type\": \"address\" }, { \"internalType\": \"uint256[]\", \"name\": \"ids\", \"type\": \"uint256[]\" }, { \"internalType\": \"uint256[]\", \"name\": \"values\", \"type\": \"uint256[]\" }, { \"internalType\": \"bytes\", \"name\": \"data\", \"type\": \"bytes\" } ], \"name\": \"onERC1155BatchReceived\", \"outputs\": [ { \"internalType\": \"bytes4\", \"name\": \"\", \"type\": \"bytes4\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address\", \"name\": \"operator\", \"type\": \"address\" }, { \"internalType\": \"address\", \"name\": \"from\", \"type\": \"address\" }, { \"internalType\": \"uint256\", \"name\": \"id\", \"type\": \"uint256\" }, { \"internalType\": \"uint256\", \"name\": \"value\", \"type\": \"uint256\" }, { \"internalType\": \"bytes\", \"name\": \"data\", \"type\": \"bytes\" } ], \"name\": \"onERC1155Received\", \"outputs\": [ { \"internalType\": \"bytes4\", \"name\": \"\", \"type\": \"bytes4\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address\", \"name\": \"operator\", \"type\": \"address\" }, { \"internalType\": \"address\", \"name\": \"from\", \"type\": \"address\" }, { \"internalType\": \"uint256\", \"name\": \"id\", \"type\": \"uint256\" }, { \"internalType\": \"bytes\", \"name\": \"data\", \"type\": \"bytes\" } ], \"name\": \"onERC721Received\", \"outputs\": [ { \"internalType\": \"bytes4\", \"name\": \"\", \"type\": \"bytes4\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [], \"name\": \"projectID\", \"outputs\": [ { \"internalType\": \"string\", \"name\": \"\", \"type\": \"string\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"uint256\", \"name\": \"itemId\", \"type\": \"uint256\" } ], \"name\": \"purchaseItem\", \"outputs\": [], \"stateMutability\": \"payable\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address\", \"name\": \"feeReceiver\", \"type\": \"address\" } ], \"name\": \"removeFeeReceiver\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"bytes32\", \"name\": \"role\", \"type\": \"bytes32\" }, { \"internalType\": \"address\", \"name\": \"account\", \"type\": \"address\" } ], \"name\": \"renounceRole\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"bytes32\", \"name\": \"role\", \"type\": \"bytes32\" }, { \"internalType\": \"address\", \"name\": \"account\", \"type\": \"address\" } ], \"name\": \"revokeRole\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address\", \"name\": \"feeReceiver\", \"type\": \"address\" }, { \"internalType\": \"uint256\", \"name\": \"feePercent\", \"type\": \"uint256\" } ], \"name\": \"setFeeReceiver\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"uint256\", \"name\": \"feePercent\", \"type\": \"uint256\" } ], \"name\": \"setMaxFeePercent\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"bytes4\", \"name\": \"interfaceId\", \"type\": \"bytes4\" } ], \"name\": \"supportsInterface\", \"outputs\": [ { \"internalType\": \"bool\", \"name\": \"\", \"type\": \"bool\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [], \"name\": \"totalFeePercent\", \"outputs\": [ { \"internalType\": \"uint256\", \"name\": \"feePercent\", \"type\": \"uint256\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [], \"name\": \"totalListings\", \"outputs\": [ { \"internalType\": \"uint256\", \"name\": \"\", \"type\": \"uint256\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address\", \"name\": \"treasury\", \"type\": \"address\" }, { \"internalType\": \"uint256\", \"name\": \"feePercent\", \"type\": \"uint256\" } ], \"name\": \"updateChainSafeTreasury\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address\", \"name\": \"user\", \"type\": \"address\" } ], \"name\": \"usersListingIds\", \"outputs\": [ { \"internalType\": \"uint256[]\", \"name\": \"\", \"type\": \"uint256[]\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address\", \"name\": \"user\", \"type\": \"address\" } ], \"name\": \"usersListings\", \"outputs\": [ { \"components\": [ { \"internalType\": \"address\", \"name\": \"nftContract\", \"type\": \"address\" }, { \"internalType\": \"uint256\", \"name\": \"tokenId\", \"type\": \"uint256\" }, { \"internalType\": \"address\", \"name\": \"seller\", \"type\": \"address\" }, { \"internalType\": \"uint256\", \"name\": \"price\", \"type\": \"uint256\" }, { \"internalType\": \"uint256\", \"name\": \"deadline\", \"type\": \"uint256\" } ], \"internalType\": \"struct Marketplace.MarketItem[]\", \"name\": \"\", \"type\": \"tuple[]\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"inputs\": [ { \"internalType\": \"address[]\", \"name\": \"nftAddresses\", \"type\": \"address[]\" } ], \"name\": \"whitelistNFTContracts\", \"outputs\": [], \"stateMutability\": \"nonpayable\", \"type\": \"function\" }, { \"inputs\": [], \"name\": \"whitelistingEnable\", \"outputs\": [ { \"internalType\": \"bool\", \"name\": \"\", \"type\": \"bool\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }, { \"stateMutability\": \"payable\", \"type\": \"receive\" } ]"; + + public string ContractAddress { get; set; } + + public IContractBuilder ContractBuilder { get; set; } + + public Contract OriginalContract { get; set; } + + public string WebSocketUrl { get; set; } + + public bool Subscribed { get; set; } + + private StreamingWebSocketClient _webSocketClient; + + #region Methods + + public async Task CREATOR_ROLE() + { + var response = await OriginalContract.Call("CREATOR_ROLE", new object[] + { + }); + + return response; + } + + + public async Task DEFAULT_ADMIN_ROLE() + { + var response = await OriginalContract.Call("DEFAULT_ADMIN_ROLE", new object[] + { + }); + + return response; + } + + + public async Task UPDATER_ROLE() + { + var response = await OriginalContract.Call("UPDATER_ROLE", new object[] + { + }); + + return response; + } + + + public async Task<(BigInteger feePercent, BigInteger feeCollected)> FeeReceiverDetails(string address) + { + var response = await OriginalContract.Call("_feeReceiverDetails", new object[] + { + }); + + return ((BigInteger)response[0], (BigInteger)response[1]); + } + + + public async Task ActiveItems() + { + var response = await OriginalContract.Call("activeItems", new object[] + { + }); + + return response; + } + + + public async Task BlacklistNFTContracts(string[] nftAddresses) + { + var response = await OriginalContract.Send("blacklistNFTContracts", new object[] + { + nftAddresses + }); + } + + public async Task BlacklistNFTContractsWithReceipt(string[] nftAddresses) + { + var response = await OriginalContract.SendWithReceipt("blacklistNFTContracts", new object[] + { + nftAddresses + }); + + return response.receipt; + } + + public async Task CancelExpiredListings(BigInteger[] itemIds) + { + var response = await OriginalContract.Send("cancelExpiredListings", new object[] + { + itemIds + }); + } + + public async Task CancelExpiredListingsWithReceipt(BigInteger[] itemIds) + { + var response = await OriginalContract.SendWithReceipt("cancelExpiredListings", new object[] + { + itemIds + }); + + return response.receipt; + } + + public async Task CancelListing(BigInteger itemId) + { + var response = await OriginalContract.Send("cancelListing", new object[] + { + itemId + }); + } + + public async Task CancelListingWithReceipt(BigInteger itemId) + { + var response = await OriginalContract.SendWithReceipt("cancelListing", new object[] + { + itemId + }); + + return response.receipt; + } + + public async Task ChainsafeTreasury() + { + var response = await OriginalContract.Call("chainsafeTreasury", new object[] + { + }); + + return response; + } + + + public async Task ClaimFee(string receiver) + { + var response = await OriginalContract.Send("claimFee", new object[] + { + receiver + }); + } + + public async Task ClaimFeeWithReceipt(string receiver) + { + var response = await OriginalContract.SendWithReceipt("claimFee", new object[] + { + receiver + }); + + return response.receipt; + } + + public async Task EnableWhitelisting(bool isEnable) + { + var response = await OriginalContract.Send("enableWhitelisting", new object[] + { + isEnable + }); + } + + public async Task EnableWhitelistingWithReceipt(bool isEnable) + { + var response = await OriginalContract.SendWithReceipt("enableWhitelisting", new object[] + { + isEnable + }); + + return response.receipt; + } + + public async Task ExpiredListingIds(BigInteger from, BigInteger to) + { + var response = await OriginalContract.Call("expiredListingIds", new object[] + { + from, to + }); + + return response; + } + + + public async Task FeeCollectedByReceiver(string feeReceiver) + { + var response = await OriginalContract.Call("feeCollectedByReceiver", new object[] + { + feeReceiver + }); + + return response; + } + + + public async Task<(string feeReceiver, BigInteger feePercent)> FeeReceiver(BigInteger id) + { + var response = await OriginalContract.Call("feeReceiver", new object[] + { + id + }); + + return ((string)response[0], (BigInteger)response[1]); + } + + + public async Task FeeReceiversNumber() + { + var response = await OriginalContract.Call("feeReceiversNumber", new object[] + { + }); + + return response; + } + + + public async Task GetRoleAdmin(byte[] role) + { + var response = await OriginalContract.Call("getRoleAdmin", new object[] + { + role + }); + + return response; + } + + + public async Task GrantRole(byte[] role, string account) + { + var response = await OriginalContract.Send("grantRole", new object[] + { + role, account + }); + } + + public async Task GrantRoleWithReceipt(byte[] role, string account) + { + var response = await OriginalContract.SendWithReceipt("grantRole", new object[] + { + role, account + }); + + return response.receipt; + } + + public async Task HasRole(byte[] role, string account) + { + var response = await OriginalContract.Call("hasRole", new object[] + { + role, account + }); + + return response; + } + + + public async Task Initialize(string projectID, string marketplaceID, string creator, string updater, + string treasury, bool isWhitelistingEnable, BigInteger chainsafeFeePercent, BigInteger maxPercent) + { + var response = await OriginalContract.Send("initialize", new object[] + { + projectID, marketplaceID, creator, updater, treasury, isWhitelistingEnable, chainsafeFeePercent, + maxPercent + }); + } + + public async Task InitializeWithReceipt(string projectID, string marketplaceID, + string creator, string updater, string treasury, bool isWhitelistingEnable, BigInteger chainsafeFeePercent, + BigInteger maxPercent) + { + var response = await OriginalContract.SendWithReceipt("initialize", new object[] + { + projectID, marketplaceID, creator, updater, treasury, isWhitelistingEnable, chainsafeFeePercent, + maxPercent + }); + + return response.receipt; + } + + public async Task IsNftToken(string token) + { + var response = await OriginalContract.Call("isNftToken", new object[] + { + token + }); + + return response; + } + + + public async Task ItemById(BigInteger itemId) + { + var response = await OriginalContract.Call("itemById", new object[] + { + itemId + }); + + return response; + } + + + public async Task ListItem(string nftContract, BigInteger tokenId, BigInteger price, BigInteger deadline) + { + var response = await OriginalContract.Send("listItem", new object[] + { + nftContract, tokenId, price, deadline + }); + } + + public async Task ListItemWithReceipt(string nftContract, BigInteger tokenId, + BigInteger price, BigInteger deadline) + { + var response = await OriginalContract.SendWithReceipt("listItem", new object[] + { + nftContract, tokenId, price, deadline + }); + + return response.receipt; + } + + public async Task ListItems(string[] nftContracts, BigInteger[] tokenIds, BigInteger[] amounts, + BigInteger[] prices, BigInteger[] deadlines) + { + var response = await OriginalContract.Send("listItems", new object[] + { + nftContracts, tokenIds, amounts, prices, deadlines + }); + } + + public async Task ListItemsWithReceipt(string[] nftContracts, BigInteger[] tokenIds, + BigInteger[] amounts, BigInteger[] prices, BigInteger[] deadlines) + { + var response = await OriginalContract.SendWithReceipt("listItems", new object[] + { + nftContracts, tokenIds, amounts, prices, deadlines + }); + + return response.receipt; + } + + public async Task MarketplaceID() + { + var response = await OriginalContract.Call("marketplaceID", new object[] + { + }); + + return response; + } + + + public async Task MaxFeePercent() + { + var response = await OriginalContract.Call("maxFeePercent", new object[] + { + }); + + return response; + } + + + public async Task NftToken(BigInteger id) + { + var response = await OriginalContract.Call("nftToken", new object[] + { + id + }); + + return response; + } + + + public async Task OnERC1155BatchReceived(string @operator, string from, BigInteger[] ids, + BigInteger[] values, byte[] data) + { + var response = await OriginalContract.Call("onERC1155BatchReceived", new object[] + { + @operator, from, ids, values, data + }); + + return response; + } + + + public async Task OnERC1155Received(string @operator, string from, BigInteger id, BigInteger value, + byte[] data) + { + var response = await OriginalContract.Call("onERC1155Received", new object[] + { + @operator, from, id, value, data + }); + + return response; + } + + + public async Task OnERC721Received(string @operator, string from, BigInteger id, byte[] data) + { + var response = await OriginalContract.Call("onERC721Received", new object[] + { + @operator, from, id, data + }); + + return response; + } + + + public async Task ProjectID() + { + var response = await OriginalContract.Call("projectID", new object[] + { + }); + + return response; + } + + + public async Task PurchaseItem(BigInteger itemId) + { + var response = await OriginalContract.Send("purchaseItem", new object[] + { + itemId + }); + } + + public async Task PurchaseItemWithReceipt(BigInteger itemId) + { + var response = await OriginalContract.SendWithReceipt("purchaseItem", new object[] + { + itemId + }); + + return response.receipt; + } + + public async Task RemoveFeeReceiver(string feeReceiver) + { + var response = await OriginalContract.Send("removeFeeReceiver", new object[] + { + feeReceiver + }); + } + + public async Task RemoveFeeReceiverWithReceipt(string feeReceiver) + { + var response = await OriginalContract.SendWithReceipt("removeFeeReceiver", new object[] + { + feeReceiver + }); + + return response.receipt; + } + + public async Task RenounceRole(byte[] role, string account) + { + var response = await OriginalContract.Send("renounceRole", new object[] + { + role, account + }); + } + + public async Task RenounceRoleWithReceipt(byte[] role, string account) + { + var response = await OriginalContract.SendWithReceipt("renounceRole", new object[] + { + role, account + }); + + return response.receipt; + } + + public async Task RevokeRole(byte[] role, string account) + { + var response = await OriginalContract.Send("revokeRole", new object[] + { + role, account + }); + } + + public async Task RevokeRoleWithReceipt(byte[] role, string account) + { + var response = await OriginalContract.SendWithReceipt("revokeRole", new object[] + { + role, account + }); + + return response.receipt; + } + + public async Task SetFeeReceiver(string feeReceiver, BigInteger feePercent) + { + var response = await OriginalContract.Send("setFeeReceiver", new object[] + { + feeReceiver, feePercent + }); + } + + public async Task SetFeeReceiverWithReceipt(string feeReceiver, BigInteger feePercent) + { + var response = await OriginalContract.SendWithReceipt("setFeeReceiver", new object[] + { + feeReceiver, feePercent + }); + + return response.receipt; + } + + public async Task SetMaxFeePercent(BigInteger feePercent) + { + var response = await OriginalContract.Send("setMaxFeePercent", new object[] + { + feePercent + }); + } + + public async Task SetMaxFeePercentWithReceipt(BigInteger feePercent) + { + var response = await OriginalContract.SendWithReceipt("setMaxFeePercent", new object[] + { + feePercent + }); + + return response.receipt; + } + + public async Task SupportsInterface(byte[] interfaceId) + { + var response = await OriginalContract.Call("supportsInterface", new object[] + { + interfaceId + }); + + return response; + } + + + public async Task TotalFeePercent() + { + var response = await OriginalContract.Call("totalFeePercent", new object[] + { + }); + + return response; + } + + + public async Task TotalListings() + { + var response = await OriginalContract.Call("totalListings", new object[] + { + }); + + return response; + } + + + public async Task UpdateChainSafeTreasury(string treasury, BigInteger feePercent) + { + var response = await OriginalContract.Send("updateChainSafeTreasury", new object[] + { + treasury, feePercent + }); + } + + public async Task UpdateChainSafeTreasuryWithReceipt(string treasury, BigInteger feePercent) + { + var response = await OriginalContract.SendWithReceipt("updateChainSafeTreasury", new object[] + { + treasury, feePercent + }); + + return response.receipt; + } + + public async Task UsersListingIds(string user) + { + var response = await OriginalContract.Call("usersListingIds", new object[] + { + user + }); + + return response; + } + + + public async Task UsersListings(string user) + { + var response = await OriginalContract.Call("usersListings", new object[] + { + user + }); + + return response; + } + + + public async Task WhitelistNFTContracts(string[] nftAddresses) + { + var response = await OriginalContract.Send("whitelistNFTContracts", new object[] + { + nftAddresses + }); + } + + public async Task WhitelistNFTContractsWithReceipt(string[] nftAddresses) + { + var response = await OriginalContract.SendWithReceipt("whitelistNFTContracts", new object[] + { + nftAddresses + }); + + return response.receipt; + } + + public async Task WhitelistingEnable() + { + var response = await OriginalContract.Call("whitelistingEnable", new object[] + { + }); + + return response; + } + + #endregion + + + #region Event Classes + + public partial class ChainSafeFeeUpdatedEventDTO : ChainSafeFeeUpdatedEventDTOBase + { + } + + [Event("ChainSafeFeeUpdated")] + public class ChainSafeFeeUpdatedEventDTOBase : IEventDTO + { + [Parameter("address", "treasury", 0, false)] + public virtual string Treasury { get; set; } + + [Parameter("uint256", "feePercent", 1, false)] + public virtual BigInteger FeePercent { get; set; } + } + + private EthLogsObservableSubscription eventChainSafeFeeUpdated; + public event Action OnChainSafeFeeUpdated; + + public partial class FeeClaimedEventDTO : FeeClaimedEventDTOBase + { + } + + [Event("FeeClaimed")] + public class FeeClaimedEventDTOBase : IEventDTO + { + [Parameter("address", "feeCollector", 0, false)] + public virtual string FeeCollector { get; set; } + + [Parameter("address", "receiver", 1, false)] + public virtual string Receiver { get; set; } + + [Parameter("uint256", "amount", 2, false)] + public virtual BigInteger Amount { get; set; } + } + + private EthLogsObservableSubscription eventFeeClaimed; + public event Action OnFeeClaimed; + + public partial class FeeReceiverRemovedEventDTO : FeeReceiverRemovedEventDTOBase + { + } + + [Event("FeeReceiverRemoved")] + public class FeeReceiverRemovedEventDTOBase : IEventDTO + { + [Parameter("address", "feeReceiver", 0, false)] + public virtual string FeeReceiver { get; set; } + } + + private EthLogsObservableSubscription eventFeeReceiverRemoved; + public event Action OnFeeReceiverRemoved; + + public partial class FeeReceiverSetEventDTO : FeeReceiverSetEventDTOBase + { + } + + [Event("FeeReceiverSet")] + public class FeeReceiverSetEventDTOBase : IEventDTO + { + [Parameter("address", "feeReceiver", 0, false)] + public virtual string FeeReceiver { get; set; } + + [Parameter("uint256", "feePercent", 1, false)] + public virtual BigInteger FeePercent { get; set; } + } + + private EthLogsObservableSubscription eventFeeReceiverSet; + public event Action OnFeeReceiverSet; + + public partial class InitializedEventDTO : InitializedEventDTOBase + { + } + + [Event("Initialized")] + public class InitializedEventDTOBase : IEventDTO + { + [Parameter("uint8", "version", 0, false)] + public virtual byte Version { get; set; } + } + + private EthLogsObservableSubscription eventInitialized; + public event Action OnInitialized; + + public partial class ItemCancelledEventDTO : ItemCancelledEventDTOBase + { + } + + [Event("ItemCancelled")] + public class ItemCancelledEventDTOBase : IEventDTO + { + [Parameter("uint256", "itemId", 0, false)] + public virtual BigInteger ItemId { get; set; } + + [Parameter("address", "owner", 1, false)] + public virtual string Owner { get; set; } + } + + private EthLogsObservableSubscription eventItemCancelled; + public event Action OnItemCancelled; + + public partial class ItemListedEventDTO : ItemListedEventDTOBase + { + } + + [Event("ItemListed")] + public class ItemListedEventDTOBase : IEventDTO + { + [Parameter("address", "nftContract", 0, false)] + public virtual string NftContract { get; set; } + + [Parameter("uint256", "tokenId", 1, false)] + public virtual BigInteger TokenId { get; set; } + + [Parameter("uint256", "itemId", 2, false)] + public virtual BigInteger ItemId { get; set; } + + [Parameter("address", "seller", 3, false)] + public virtual string Seller { get; set; } + + [Parameter("uint256", "price", 4, false)] + public virtual BigInteger Price { get; set; } + + [Parameter("uint256", "deadline", 5, false)] + public virtual BigInteger Deadline { get; set; } + } + + private EthLogsObservableSubscription eventItemListed; + public event Action OnItemListed; + + public partial class ItemSoldEventDTO : ItemSoldEventDTOBase + { + } + + [Event("ItemSold")] + public class ItemSoldEventDTOBase : IEventDTO + { + [Parameter("uint256", "itemId", 0, false)] + public virtual BigInteger ItemId { get; set; } + + [Parameter("address", "buyer", 1, false)] + public virtual string Buyer { get; set; } + } + + private EthLogsObservableSubscription eventItemSold; + public event Action OnItemSold; + + public partial class MaxFeeUpdatedEventDTO : MaxFeeUpdatedEventDTOBase + { + } + + [Event("MaxFeeUpdated")] + public class MaxFeeUpdatedEventDTOBase : IEventDTO + { + [Parameter("uint256", "feePercent", 0, false)] + public virtual BigInteger FeePercent { get; set; } + } + + private EthLogsObservableSubscription eventMaxFeeUpdated; + public event Action OnMaxFeeUpdated; + + public partial class NFTBlacklistedEventDTO : NFTBlacklistedEventDTOBase + { + } + + [Event("NFTBlacklisted")] + public class NFTBlacklistedEventDTOBase : IEventDTO + { + [Parameter("address[]", "nftAddresses", 0, false)] + public virtual string[] NftAddresses { get; set; } + } + + private EthLogsObservableSubscription eventNFTBlacklisted; + public event Action OnNFTBlacklisted; + + public partial class NFTWhitelistedEventDTO : NFTWhitelistedEventDTOBase + { + } + + [Event("NFTWhitelisted")] + public class NFTWhitelistedEventDTOBase : IEventDTO + { + [Parameter("address[]", "nftAddresses", 0, false)] + public virtual string[] NftAddresses { get; set; } + } + + private EthLogsObservableSubscription eventNFTWhitelisted; + public event Action OnNFTWhitelisted; + + public partial class RoleAdminChangedEventDTO : RoleAdminChangedEventDTOBase + { + } + + [Event("RoleAdminChanged")] + public class RoleAdminChangedEventDTOBase : IEventDTO + { + [Parameter("bytes32", "role", 0, true)] + public virtual byte[] Role { get; set; } + + [Parameter("bytes32", "previousAdminRole", 1, true)] + public virtual byte[] PreviousAdminRole { get; set; } + + [Parameter("bytes32", "newAdminRole", 2, true)] + public virtual byte[] NewAdminRole { get; set; } + } + + private EthLogsObservableSubscription eventRoleAdminChanged; + public event Action OnRoleAdminChanged; + + public partial class RoleGrantedEventDTO : RoleGrantedEventDTOBase + { + } + + [Event("RoleGranted")] + public class RoleGrantedEventDTOBase : IEventDTO + { + [Parameter("bytes32", "role", 0, true)] + public virtual byte[] Role { get; set; } + + [Parameter("address", "account", 1, true)] + public virtual string Account { get; set; } + + [Parameter("address", "sender", 2, true)] + public virtual string Sender { get; set; } + } + + private EthLogsObservableSubscription eventRoleGranted; + public event Action OnRoleGranted; + + public partial class RoleRevokedEventDTO : RoleRevokedEventDTOBase + { + } + + [Event("RoleRevoked")] + public class RoleRevokedEventDTOBase : IEventDTO + { + [Parameter("bytes32", "role", 0, true)] + public virtual byte[] Role { get; set; } + + [Parameter("address", "account", 1, true)] + public virtual string Account { get; set; } + + [Parameter("address", "sender", 2, true)] + public virtual string Sender { get; set; } + } + + private EthLogsObservableSubscription eventRoleRevoked; + public event Action OnRoleRevoked; + + public partial class WhitelistingStatusUpdatedEventDTO : WhitelistingStatusUpdatedEventDTOBase + { + } + + [Event("WhitelistingStatusUpdated")] + public class WhitelistingStatusUpdatedEventDTOBase : IEventDTO + { + [Parameter("bool", "isEnabled", 0, false)] + public virtual bool IsEnabled { get; set; } + } + + private EthLogsObservableSubscription eventWhitelistingStatusUpdated; + public event Action OnWhitelistingStatusUpdated; + + #endregion + + #region Interface Implemented Methods + + public async ValueTask DisposeAsync() + { + if (string.IsNullOrEmpty(WebSocketUrl)) + return; + if (!Subscribed) + return; + Subscribed = false; + + await eventChainSafeFeeUpdated.UnsubscribeAsync(); + OnChainSafeFeeUpdated = null; + await eventFeeClaimed.UnsubscribeAsync(); + OnFeeClaimed = null; + await eventFeeReceiverRemoved.UnsubscribeAsync(); + OnFeeReceiverRemoved = null; + await eventFeeReceiverSet.UnsubscribeAsync(); + OnFeeReceiverSet = null; + await eventInitialized.UnsubscribeAsync(); + OnInitialized = null; + await eventItemCancelled.UnsubscribeAsync(); + OnItemCancelled = null; + await eventItemListed.UnsubscribeAsync(); + OnItemListed = null; + await eventItemSold.UnsubscribeAsync(); + OnItemSold = null; + await eventMaxFeeUpdated.UnsubscribeAsync(); + OnMaxFeeUpdated = null; + await eventNFTBlacklisted.UnsubscribeAsync(); + OnNFTBlacklisted = null; + await eventNFTWhitelisted.UnsubscribeAsync(); + OnNFTWhitelisted = null; + await eventRoleAdminChanged.UnsubscribeAsync(); + OnRoleAdminChanged = null; + await eventRoleGranted.UnsubscribeAsync(); + OnRoleGranted = null; + await eventRoleRevoked.UnsubscribeAsync(); + OnRoleRevoked = null; + await eventWhitelistingStatusUpdated.UnsubscribeAsync(); + OnWhitelistingStatusUpdated = null; + + _webSocketClient?.Dispose(); + } + + public async ValueTask Init() + { + if (Subscribed) + return; + + if (string.IsNullOrEmpty(WebSocketUrl)) + { + Debug.LogWarning($"WebSocketUrl is not set for this class. Event Subscriptions will not work."); + return; + } + + _webSocketClient ??= new StreamingWebSocketClient(WebSocketUrl); + await _webSocketClient.StartAsync(); + Subscribed = true; + + var filterChainSafeFeeUpdatedEvent = Event.GetEventABI().CreateFilterInput(); + eventChainSafeFeeUpdated = new EthLogsObservableSubscription(_webSocketClient); + + eventChainSafeFeeUpdated.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnChainSafeFeeUpdated?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventChainSafeFeeUpdated.SubscribeAsync(filterChainSafeFeeUpdatedEvent); + var filterFeeClaimedEvent = Event.GetEventABI().CreateFilterInput(); + eventFeeClaimed = new EthLogsObservableSubscription(_webSocketClient); + + eventFeeClaimed.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnFeeClaimed?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventFeeClaimed.SubscribeAsync(filterFeeClaimedEvent); + var filterFeeReceiverRemovedEvent = Event.GetEventABI().CreateFilterInput(); + eventFeeReceiverRemoved = new EthLogsObservableSubscription(_webSocketClient); + + eventFeeReceiverRemoved.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnFeeReceiverRemoved?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventFeeReceiverRemoved.SubscribeAsync(filterFeeReceiverRemovedEvent); + var filterFeeReceiverSetEvent = Event.GetEventABI().CreateFilterInput(); + eventFeeReceiverSet = new EthLogsObservableSubscription(_webSocketClient); + + eventFeeReceiverSet.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnFeeReceiverSet?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventFeeReceiverSet.SubscribeAsync(filterFeeReceiverSetEvent); + var filterInitializedEvent = Event.GetEventABI().CreateFilterInput(); + eventInitialized = new EthLogsObservableSubscription(_webSocketClient); + + eventInitialized.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnInitialized?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventInitialized.SubscribeAsync(filterInitializedEvent); + var filterItemCancelledEvent = Event.GetEventABI().CreateFilterInput(); + eventItemCancelled = new EthLogsObservableSubscription(_webSocketClient); + + eventItemCancelled.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnItemCancelled?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventItemCancelled.SubscribeAsync(filterItemCancelledEvent); + var filterItemListedEvent = Event.GetEventABI().CreateFilterInput(); + eventItemListed = new EthLogsObservableSubscription(_webSocketClient); + + eventItemListed.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnItemListed?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventItemListed.SubscribeAsync(filterItemListedEvent); + var filterItemSoldEvent = Event.GetEventABI().CreateFilterInput(); + eventItemSold = new EthLogsObservableSubscription(_webSocketClient); + + eventItemSold.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnItemSold?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventItemSold.SubscribeAsync(filterItemSoldEvent); + var filterMaxFeeUpdatedEvent = Event.GetEventABI().CreateFilterInput(); + eventMaxFeeUpdated = new EthLogsObservableSubscription(_webSocketClient); + + eventMaxFeeUpdated.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnMaxFeeUpdated?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventMaxFeeUpdated.SubscribeAsync(filterMaxFeeUpdatedEvent); + var filterNFTBlacklistedEvent = Event.GetEventABI().CreateFilterInput(); + eventNFTBlacklisted = new EthLogsObservableSubscription(_webSocketClient); + + eventNFTBlacklisted.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnNFTBlacklisted?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventNFTBlacklisted.SubscribeAsync(filterNFTBlacklistedEvent); + var filterNFTWhitelistedEvent = Event.GetEventABI().CreateFilterInput(); + eventNFTWhitelisted = new EthLogsObservableSubscription(_webSocketClient); + + eventNFTWhitelisted.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnNFTWhitelisted?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventNFTWhitelisted.SubscribeAsync(filterNFTWhitelistedEvent); + var filterRoleAdminChangedEvent = Event.GetEventABI().CreateFilterInput(); + eventRoleAdminChanged = new EthLogsObservableSubscription(_webSocketClient); + + eventRoleAdminChanged.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnRoleAdminChanged?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventRoleAdminChanged.SubscribeAsync(filterRoleAdminChangedEvent); + var filterRoleGrantedEvent = Event.GetEventABI().CreateFilterInput(); + eventRoleGranted = new EthLogsObservableSubscription(_webSocketClient); + + eventRoleGranted.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnRoleGranted?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventRoleGranted.SubscribeAsync(filterRoleGrantedEvent); + var filterRoleRevokedEvent = Event.GetEventABI().CreateFilterInput(); + eventRoleRevoked = new EthLogsObservableSubscription(_webSocketClient); + + eventRoleRevoked.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnRoleRevoked?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventRoleRevoked.SubscribeAsync(filterRoleRevokedEvent); + var filterWhitelistingStatusUpdatedEvent = + Event.GetEventABI().CreateFilterInput(); + eventWhitelistingStatusUpdated = new EthLogsObservableSubscription(_webSocketClient); + + eventWhitelistingStatusUpdated.GetSubscriptionDataResponsesAsObservable().Subscribe(log => + { + try + { + var decoded = Event.DecodeEvent(log); + if (decoded != null) OnWhitelistingStatusUpdated?.Invoke(decoded.Event); + } + catch (Exception ex) + { + Debug.LogError("Log Address: " + log.Address + " is not a standard transfer log:" + ex.Message); + } + }); + + await eventWhitelistingStatusUpdated.SubscribeAsync(filterWhitelistingStatusUpdatedEvent); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public IContract Attach(string address) + { + return OriginalContract.Attach(address); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public Task Call(string method, object[] parameters = null, TransactionRequest overwrite = null) + { + return OriginalContract.Call(method, parameters, overwrite); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public object[] Decode(string method, string output) + { + return OriginalContract.Decode(method, output); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public Task Send(string method, object[] parameters = null, TransactionRequest overwrite = null) + { + return OriginalContract.Send(method, parameters, overwrite); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public Task<(object[] response, TransactionReceipt receipt)> SendWithReceipt(string method, + object[] parameters = null, TransactionRequest overwrite = null) + { + return OriginalContract.SendWithReceipt(method, parameters, overwrite); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public Task EstimateGas(string method, object[] parameters, TransactionRequest overwrite = null) + { + return OriginalContract.EstimateGas(method, parameters, overwrite); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public string Calldata(string method, object[] parameters = null) + { + return OriginalContract.Calldata(method, parameters); + } + + [Obsolete("It's not advisable to use this method. Use the pre-generated methods instead.")] + public Task PrepareTransactionRequest(string method, object[] parameters, + TransactionRequest overwrite = null) + { + return OriginalContract.PrepareTransactionRequest(method, parameters, overwrite); + } + + #endregion + } + + public class MarketItem + { + [Parameter("address", "nftContract", 0, false)] + public virtual string NftContract { get; set; } + + [Parameter("uint256", "tokenId", 1, false)] + public virtual BigInteger TokenId { get; set; } + + [Parameter("address", "seller", 2, false)] + public virtual string Seller { get; set; } + + [Parameter("uint256", "price", 3, false)] + public virtual BigInteger Price { get; set; } + + [Parameter("uint256", "deadline", 4, false)] + public virtual BigInteger Deadline { get; set; } + } +} \ No newline at end of file diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Resources/TestContract.cs.meta b/Packages/io.chainsafe.web3-unity/Runtime/Resources/TestContract.cs.meta new file mode 100644 index 000000000..0e3ad2233 --- /dev/null +++ b/Packages/io.chainsafe.web3-unity/Runtime/Resources/TestContract.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d3bb186c69834af408e613637c9a10bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ProjectConfigScriptableObject.cs b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ProjectConfigScriptableObject.cs index d071ad4e9..a45360161 100644 --- a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ProjectConfigScriptableObject.cs +++ b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ProjectConfigScriptableObject.cs @@ -13,6 +13,7 @@ public class ProjectConfigScriptableObject : ScriptableObject, ICompleteProjectC [SerializeField] private string network; [SerializeField] private string symbol; [SerializeField] private string rpc; + [SerializeField] private string ws; [SerializeField] private string blockExplorerUrl; [SerializeField] private bool enableAnalytics; @@ -60,8 +61,8 @@ public string Ipc public string Ws { - get => rpc; - set => rpc = value; + get => ws; + set => ws = value; } public string BlockExplorerUrl diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ProjectConfigUtilities.cs b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ProjectConfigUtilities.cs index 7dcd820b4..82b2b4b59 100644 --- a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ProjectConfigUtilities.cs +++ b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/ProjectConfigUtilities.cs @@ -15,8 +15,8 @@ public static ProjectConfigScriptableObject Load() return projectConfig ? projectConfig : null; } - public static ProjectConfigScriptableObject Load(string projectId, string chainId, string chain, string network, - string symbol, string rpc, string blockExplorerUrl, bool enableAnalytics) + public static ProjectConfigScriptableObject Create(string projectId, string chainId, string chain, string network, + string symbol, string rpc, string blockExplorerUrl, bool enableAnalytics, string ws = "") { var projectConfig = ScriptableObject.CreateInstance(); @@ -26,6 +26,7 @@ public static ProjectConfigScriptableObject Load(string projectId, string chainI projectConfig.Network = network; projectConfig.Symbol = symbol; projectConfig.Rpc = rpc; + projectConfig.Ws = ws; projectConfig.BlockExplorerUrl = blockExplorerUrl; projectConfig.EnableAnalytics = enableAnalytics; diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/Web3Accessor.cs b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/Web3Accessor.cs index 0476184e0..d13835a66 100644 --- a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/Web3Accessor.cs +++ b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/Web3Accessor.cs @@ -1,3 +1,4 @@ +using System; using System.Threading.Tasks; using UnityEngine; using UnityEngine.SceneManagement; diff --git a/Packages/io.chainsafe.web3-unity/Tests/Runtime/SampleTestsBase.cs b/Packages/io.chainsafe.web3-unity/Tests/Runtime/SampleTestsBase.cs index 0bf39e652..bd89a9d74 100644 --- a/Packages/io.chainsafe.web3-unity/Tests/Runtime/SampleTestsBase.cs +++ b/Packages/io.chainsafe.web3-unity/Tests/Runtime/SampleTestsBase.cs @@ -48,8 +48,8 @@ internal static ValueTask BuildTestWeb3(Web3Builder.ConfigureServicesDeleg var projectConfigScriptableObject = ProjectConfigUtilities.Load(); if (projectConfigScriptableObject == null) { - projectConfigScriptableObject = ProjectConfigUtilities.Load("3dc3e125-71c4-4511-a367-e981a6a94371", "11155111", - "Ethereum", "Sepolia", "Seth", "https://sepolia.infura.io/v3/287318045c6e455ab34b81d6bcd7a65f", "https://sepolia.etherscan.io/", false); + projectConfigScriptableObject = ProjectConfigUtilities.Create("3dc3e125-71c4-4511-a367-e981a6a94371", "11155111", + "Ethereum", "Sepolia", "Seth", "https://sepolia.infura.io/v3/287318045c6e455ab34b81d6bcd7a65f", "https://sepolia.etherscan.io/", false, "wss://sepolia.drpc.org"); } // Create web3builder & assign services diff --git a/libs/Nethereum-UnityAOT/Nethereum.JsonRpc.WebSocketClient.dll b/libs/Nethereum-UnityAOT/Nethereum.JsonRpc.WebSocketClient.dll new file mode 100644 index 000000000..e3cc428f5 Binary files /dev/null and b/libs/Nethereum-UnityAOT/Nethereum.JsonRpc.WebSocketClient.dll differ diff --git a/libs/Nethereum-UnityAOT/Nethereum.RPC.Reactive.dll b/libs/Nethereum-UnityAOT/Nethereum.RPC.Reactive.dll new file mode 100644 index 000000000..a6a75c634 Binary files /dev/null and b/libs/Nethereum-UnityAOT/Nethereum.RPC.Reactive.dll differ diff --git a/scripts/data/published_dependencies.txt b/scripts/data/published_dependencies.txt index 6ae1f950e..fb08bba5a 100644 --- a/scripts/data/published_dependencies.txt +++ b/scripts/data/published_dependencies.txt @@ -5,6 +5,8 @@ Packages/io.chainsafe.web3-unity/Runtime/Libraries/: Nethereum.RLP.dll ChainSafe.Gaming.Debugging.dll Nethereum.RPC.dll + Nethereum.RPC.Reactive.dll + Nethereum.JsonRpc.WebSocketClient.dll ChainSafe.Gaming.Gelato.dll ChainSafe.Gaming.SygmaClient.dll Nethereum.Signer.EIP712.dll diff --git a/src/ChainSafe.Gaming/ChainSafe.Gaming.csproj b/src/ChainSafe.Gaming/ChainSafe.Gaming.csproj index cb395f804..06f304ea0 100644 --- a/src/ChainSafe.Gaming/ChainSafe.Gaming.csproj +++ b/src/ChainSafe.Gaming/ChainSafe.Gaming.csproj @@ -28,8 +28,10 @@ + + diff --git a/src/ChainSafe.Gaming/RPC/Contracts/Builders/ContractBuilder.cs b/src/ChainSafe.Gaming/RPC/Contracts/Builders/ContractAbiManager.cs similarity index 93% rename from src/ChainSafe.Gaming/RPC/Contracts/Builders/ContractBuilder.cs rename to src/ChainSafe.Gaming/RPC/Contracts/Builders/ContractAbiManager.cs index 762fd031a..d7e775b9b 100644 --- a/src/ChainSafe.Gaming/RPC/Contracts/Builders/ContractBuilder.cs +++ b/src/ChainSafe.Gaming/RPC/Contracts/Builders/ContractAbiManager.cs @@ -11,25 +11,25 @@ namespace ChainSafe.Gaming.Evm.Contracts.Builders /// /// Represents a builder pattern class used to build a contract. /// - public class ContractBuilder + public class ContractAbiManager { /// - /// Initializes a new instance of the class using ABI string and contract address. + /// Initializes a new instance of the class using ABI string and contract address. /// /// ABI string of the contract. /// Ethereum address of the contract. - public ContractBuilder(string abi, string contractAddress) + public ContractAbiManager(string abi, string contractAddress) { ContractABI = ABIDeserialiserFactory.DeserialiseContractABI(abi); Address = contractAddress; } /// - /// Initializes a new instance of the class using a contract message type and contract address. + /// Initializes a new instance of the class using a contract message type and contract address. /// /// Type containing attributes representing the contract ABI. /// Ethereum address of the contract. - public ContractBuilder(Type contractMessageType, string contractAddress) + public ContractAbiManager(Type contractMessageType, string contractAddress) { var abiExtractor = new AttributesToABIExtractor(); ContractABI = abiExtractor.ExtractContractABI(contractMessageType); @@ -37,11 +37,11 @@ public ContractBuilder(Type contractMessageType, string contractAddress) } /// - /// Initializes a new instance of the class using multiple contract message types and contract address. + /// Initializes a new instance of the class using multiple contract message types and contract address. /// /// Array of Types containing attributes representing the contract ABI. /// Ethereum address of the contract. - public ContractBuilder(Type[] contractMessagesTypes, string contractAddress) + public ContractAbiManager(Type[] contractMessagesTypes, string contractAddress) { var abiExtractor = new AttributesToABIExtractor(); ContractABI = abiExtractor.ExtractContractABI(contractMessagesTypes); @@ -51,12 +51,12 @@ public ContractBuilder(Type[] contractMessagesTypes, string contractAddress) /// /// Gets or sets the ABI of the contract. /// - public ContractABI ContractABI { get; set; } + private ContractABI ContractABI { get; } /// /// Gets or sets the Ethereum address of the contract. /// - public string Address { get; set; } + private string Address { get; } /// /// Retrieves the default filter input for the contract. diff --git a/src/ChainSafe.Gaming/RPC/Contracts/Contract.cs b/src/ChainSafe.Gaming/RPC/Contracts/Contract.cs index b9215f538..d90e444ed 100644 --- a/src/ChainSafe.Gaming/RPC/Contracts/Contract.cs +++ b/src/ChainSafe.Gaming/RPC/Contracts/Contract.cs @@ -1,11 +1,13 @@ using System; using System.Linq; using System.Threading.Tasks; +using ChainSafe.Gaming.Evm.Contracts.Builders; using ChainSafe.Gaming.Evm.Providers; using ChainSafe.Gaming.Evm.Signers; using ChainSafe.Gaming.Evm.Transactions; using ChainSafe.Gaming.Web3.Analytics; using ChainSafe.Gaming.Web3.Core.Evm; +using Nethereum.ABI.Model; using Nethereum.Hex.HexTypes; namespace ChainSafe.Gaming.Evm.Contracts @@ -19,7 +21,7 @@ public class Contract : IContract private readonly string address; private readonly IRpcProvider provider; private readonly ISigner signer; - private readonly Builders.ContractBuilder contractBuilder; + private readonly ContractAbiManager contractAbiManager; private readonly ITransactionExecutor transactionExecutor; private readonly IAnalyticsClient analyticsClient; @@ -44,7 +46,7 @@ internal Contract(string abi, string address, IRpcProvider provider, ISigner sig this.signer = signer; this.transactionExecutor = transactionExecutor; this.analyticsClient = analyticsClient; - contractBuilder = new Builders.ContractBuilder(abi, address); + contractAbiManager = new ContractAbiManager(abi, address); } public string Address => address; @@ -99,6 +101,32 @@ public async Task Call(string method, object[] parameters = null, Tran return Decode(method, result); } + public async Task Call(string method, object[] parameters = null, TransactionRequest overwrite = null) + { + if (string.IsNullOrEmpty(address)) + { + throw new Exception("contract address is not set"); + } + + if (provider == null) + { + throw new Exception("provider or signer is not set"); + } + + parameters ??= Array.Empty(); + + var txReq = await PrepareTransactionRequest(method, parameters, overwrite); + + var result = await provider.Call(txReq); + analyticsClient.CaptureEvent(new AnalyticsEvent() + { + EventName = method, + PackageName = "io.chainsafe.web3.unity", + }); + + return contractAbiManager.GetFunctionBuilder(method).DecodeTypeOutput(result); + } + /// /// Decodes a result. /// @@ -107,7 +135,7 @@ public async Task Call(string method, object[] parameters = null, Tran /// The decoded outputs of a provided method. public object[] Decode(string method, string output) { - var function = contractBuilder.GetFunctionBuilder(method); + var function = contractAbiManager.GetFunctionBuilder(method); var decodedOutput = function.DecodeOutput(output); var array = new object[decodedOutput.Count]; for (var i = 0; i < decodedOutput.Count; i++) @@ -130,6 +158,20 @@ public async Task Send(string method, object[] parameters = null, Tran return (await SendWithReceipt(method, parameters, overwrite)).response; } + /// + /// Sends the transaction. + /// + /// The method. + /// The parameters. + /// An existing TransactionRequest to use instead of making a new one. + /// Type of object you want to use. + /// The outputs of the method. + public async Task Send(string method, object[] parameters = null, TransactionRequest overwrite = null) + { + var result = (await SendWithReceipt(method, parameters, overwrite)).response; + return result; + } + /// /// Sends the transaction. /// @@ -154,7 +196,7 @@ public async Task Send(string method, object[] parameters = null, Tran parameters ??= Array.Empty(); - var function = contractBuilder.GetFunctionBuilder(method); + var function = contractAbiManager.GetFunctionBuilder(method); var txReq = await PrepareTransactionRequest(method, parameters, overwrite); @@ -173,6 +215,47 @@ public async Task Send(string method, object[] parameters = null, Tran return (outputValues, receipt); } + /// + /// Sends the transaction. + /// + /// The method. + /// The parameters. + /// An existing TransactionRequest to use instead of making a new one. + /// Type of object you want to use. + /// The outputs of the method and the transaction receipt. + public async Task<(T response, TransactionReceipt receipt)> SendWithReceipt( + string method, + object[] parameters = null, + TransactionRequest overwrite = null) + { + if (string.IsNullOrEmpty(address)) + { + throw new Exception("contract address is not set"); + } + + if (signer == null) + { + throw new Exception("signer is not set"); + } + + parameters ??= Array.Empty(); + + var txReq = await PrepareTransactionRequest(method, parameters, overwrite); + + var tx = await transactionExecutor.SendTransaction(txReq); + var receipt = await provider.WaitForTransactionReceipt(tx.Hash); + + var outputValues = contractAbiManager.GetFunctionBuilder(method).DecodeTypeOutput(tx.Data); + + analyticsClient.CaptureEvent(new AnalyticsEvent() + { + EventName = method, + PackageName = "io.chainsafe.web3.unity", + }); + + return (outputValues, receipt); + } + /// /// Estimate gas. /// @@ -233,7 +316,7 @@ public string Calldata(string method, object[] parameters = null) }; var dataObject = GameLogger.Log("", "", dataWebGL); #endif - var function = contractBuilder.GetFunctionBuilder(method); + var function = contractAbiManager.GetFunctionBuilder(method); analyticsClient.CaptureEvent(new AnalyticsEvent() { @@ -248,7 +331,7 @@ public async Task PrepareTransactionRequest(string method, o { parameters ??= Array.Empty(); - var function = contractBuilder.GetFunctionBuilder(method); + var function = contractAbiManager.GetFunctionBuilder(method); var txReq = overwrite ?? new TransactionRequest(); txReq.From ??= signer?.PublicAddress; diff --git a/src/ChainSafe.Gaming/RPC/Contracts/ContractBuilder.cs b/src/ChainSafe.Gaming/RPC/Contracts/ContractBuilder.cs index 387f7ac3c..2f935bf7e 100644 --- a/src/ChainSafe.Gaming/RPC/Contracts/ContractBuilder.cs +++ b/src/ChainSafe.Gaming/RPC/Contracts/ContractBuilder.cs @@ -1,43 +1,48 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using ChainSafe.Gaming.Evm.Providers; using ChainSafe.Gaming.Evm.Signers; using ChainSafe.Gaming.Web3; using ChainSafe.Gaming.Web3.Analytics; +using ChainSafe.Gaming.Web3.Core; using ChainSafe.Gaming.Web3.Core.Evm; +using ChainSafe.Gaming.Web3.Environment; namespace ChainSafe.Gaming.Evm.Contracts { - public class ContractBuilder : IContractBuilder + public class ContractBuilder : IContractBuilder, ILifecycleParticipant { private readonly Dictionary registeredContracts; private readonly IRpcProvider rpcProvider; private readonly ISigner signer; private readonly ITransactionExecutor transactionExecutor; private readonly IAnalyticsClient analyticsClient; // Added analytics client + private readonly IChainConfig chainConfig; + private readonly ILogWriter logWriter; - public ContractBuilder(IRpcProvider rpcProvider, IAnalyticsClient analyticsClient) - : this(new(), rpcProvider, null, null, analyticsClient) + public ContractBuilder(IRpcProvider rpcProvider, IAnalyticsClient analyticsClient, ILogWriter logWriter, IChainConfig chainConfig) + : this(new(), rpcProvider, null, null, analyticsClient, logWriter, chainConfig) { } - public ContractBuilder(IRpcProvider rpcProvider, ISigner signer, IAnalyticsClient analyticsClient) - : this(new(), rpcProvider, signer, null, analyticsClient) + public ContractBuilder(IRpcProvider rpcProvider, ISigner signer, IAnalyticsClient analyticsClient, ILogWriter logWriter, IChainConfig chainConfig) + : this(new(), rpcProvider, signer, null, analyticsClient, logWriter, chainConfig) { } - public ContractBuilder(ContractBuilderConfig config, IRpcProvider rpcProvider, ISigner signer, IAnalyticsClient analyticsClient) - : this(config, rpcProvider, signer, null, analyticsClient) + public ContractBuilder(ContractBuilderConfig config, IRpcProvider rpcProvider, ISigner signer, IAnalyticsClient analyticsClient, ILogWriter logWriter, IChainConfig chainConfig) + : this(config, rpcProvider, signer, null, analyticsClient, logWriter, chainConfig) { } - public ContractBuilder(IRpcProvider rpcProvider, ISigner signer, ITransactionExecutor transactionExecutor, IAnalyticsClient analyticsClient) - : this(new(), rpcProvider, signer, transactionExecutor, analyticsClient) + public ContractBuilder(IRpcProvider rpcProvider, ISigner signer, ITransactionExecutor transactionExecutor, IAnalyticsClient analyticsClient, ILogWriter logWriter, IChainConfig chainConfig) + : this(new(), rpcProvider, signer, transactionExecutor, analyticsClient, logWriter, chainConfig) { } - public ContractBuilder(ContractBuilderConfig config, IRpcProvider rpcProvider, ISigner signer, ITransactionExecutor transactionExecutor, IAnalyticsClient analyticsClient) + public ContractBuilder(ContractBuilderConfig config, IRpcProvider rpcProvider, ISigner signer, ITransactionExecutor transactionExecutor, IAnalyticsClient analyticsClient, ILogWriter logWriter, IChainConfig chainConfig) { try { @@ -52,8 +57,16 @@ public ContractBuilder(ContractBuilderConfig config, IRpcProvider rpcProvider, I this.signer = signer; this.transactionExecutor = transactionExecutor; this.analyticsClient = analyticsClient; // Initialize analytics client + this.chainConfig = chainConfig; + this.logWriter = logWriter; + BasicContracts = new Dictionary(); + CustomContracts = new Dictionary(); } + private Dictionary BasicContracts { get; } + + private Dictionary CustomContracts { get; } + public Contract Build(string name) { if (!registeredContracts.TryGetValue(name, out ContractData data)) @@ -64,7 +77,53 @@ public Contract Build(string name) return new Contract(data.Abi, data.Address, rpcProvider, signer, transactionExecutor, analyticsClient); // Pass analytics client to Contract } - public Contract Build(string abi, string address) => - new Contract(abi, address, rpcProvider, signer, transactionExecutor, analyticsClient); // Pass analytics client to Contract + public Contract Build(string abi, string address) + { + if (BasicContracts.TryGetValue(address, out var value)) + { + return value; + } + + var contract = new Contract(abi, address, rpcProvider, signer, transactionExecutor, analyticsClient); // Pass analytics client to Contract + BasicContracts.Add(address, contract); + return contract; + } + + public async Task Build(string address) + where T : ICustomContract, new() + { + if (CustomContracts.TryGetValue(address, out var value)) + { + await value.Init(); + return (T)value; + } + + var contract = new T + { + ContractAddress = address, + }; + + contract.OriginalContract = Build(contract.ABI, contract.ContractAddress); + contract.WebSocketUrl = chainConfig.Ws; + + CustomContracts.Add(contract.ContractAddress, contract); + + await contract.Init(); + + return contract; + } + + public ValueTask WillStartAsync() + { + return default; + } + + public async ValueTask WillStopAsync() + { + foreach (var contractsValue in CustomContracts.Values) + { + await contractsValue.DisposeAsync(); + } + } } } diff --git a/src/ChainSafe.Gaming/RPC/Contracts/IContractBuilder.cs b/src/ChainSafe.Gaming/RPC/Contracts/IContractBuilder.cs index 8e14ea6b9..9345f73b5 100644 --- a/src/ChainSafe.Gaming/RPC/Contracts/IContractBuilder.cs +++ b/src/ChainSafe.Gaming/RPC/Contracts/IContractBuilder.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; namespace ChainSafe.Gaming.Evm.Contracts { @@ -9,5 +10,8 @@ public interface IContractBuilder Contract Build(string name); Contract Build(string abi, string address); + + Task Build(string address) + where T : ICustomContract, new(); } } diff --git a/src/ChainSafe.Gaming/RPC/Contracts/ICustomContract.cs b/src/ChainSafe.Gaming/RPC/Contracts/ICustomContract.cs new file mode 100644 index 000000000..a0c497ffa --- /dev/null +++ b/src/ChainSafe.Gaming/RPC/Contracts/ICustomContract.cs @@ -0,0 +1,20 @@ +using System; +using System.Threading.Tasks; + +namespace ChainSafe.Gaming.Evm.Contracts +{ + public interface ICustomContract : IContract, IAsyncDisposable + { + public string ABI { get; } + + public string ContractAddress { get; set; } + + public Contract OriginalContract { get; set; } + + public string WebSocketUrl { get; set; } + + public bool Subscribed { get; set; } + + public ValueTask Init(); + } +} \ 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 57958a8c2..3386c18bc 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs @@ -4,6 +4,7 @@ using ChainSafe.Gaming.Evm.Contracts; using ChainSafe.Gaming.Evm.Contracts.BuiltIn; using ChainSafe.Gaming.LocalStorage; +using ChainSafe.Gaming.Web3.Core; using ChainSafe.Gaming.Web3.Core.Evm.EventPoller; using ChainSafe.Gaming.Web3.Core.Logout; using ChainSafe.Gaming.Web3.Environment; @@ -25,9 +26,9 @@ private Web3Builder() // Bind default services serviceCollection .UseEventPoller() + .AddSingleton() .AddSingleton() .AddSingleton() - .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() diff --git a/src/ChainSafe.Gaming/Web3/Core/Build/Web3ServiceCollectionExtensions.cs b/src/ChainSafe.Gaming/Web3/Core/Build/Web3ServiceCollectionExtensions.cs index 17aae2ab2..9d3ca2dd1 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Build/Web3ServiceCollectionExtensions.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Build/Web3ServiceCollectionExtensions.cs @@ -45,7 +45,8 @@ public static void AssertConfigurationNotBound(this IWeb3ServiceCollection se /// The second contract type. /// The implementation type. /// The Web3 service collection. - public static void AddSingleton(this IWeb3ServiceCollection serviceCollection) + /// Modified Web3 Service Collection. + public static IWeb3ServiceCollection AddSingleton(this IWeb3ServiceCollection serviceCollection) where TInterface1 : class where TInterface2 : class where TImplementation : class, TInterface1, TInterface2 @@ -60,6 +61,8 @@ public static void AddSingleton(this serviceCollection.AddSingleton(); serviceCollection.AddSingleton(sp => sp.GetRequiredService()); serviceCollection.AddSingleton(sp => sp.GetRequiredService()); + + return serviceCollection; } /// @@ -70,7 +73,8 @@ public static void AddSingleton(this /// The first contract type. /// The second contract type. /// The implementation type. - public static void AddSingleton(this IWeb3ServiceCollection serviceCollection, Func implementationFactory) + /// Web3 Service Collection. + public static IWeb3ServiceCollection AddSingleton(this IWeb3ServiceCollection serviceCollection, Func implementationFactory) where TInterface1 : class where TInterface2 : class where TImplementation : class, TInterface1, TInterface2 @@ -78,6 +82,8 @@ public static void AddSingleton(this serviceCollection.AddSingleton(implementationFactory); serviceCollection.AddSingleton(sp => sp.GetRequiredService()); serviceCollection.AddSingleton(sp => sp.GetRequiredService()); + + return serviceCollection; } /// @@ -88,7 +94,8 @@ public static void AddSingleton(this /// The second contract type. /// The third contract type. /// The implementation type. - public static void AddSingleton(this IWeb3ServiceCollection serviceCollection) + /// Web3 Service Collection. + public static IWeb3ServiceCollection AddSingleton(this IWeb3ServiceCollection serviceCollection) where TInterface1 : class where TInterface2 : class where TInterface3 : class @@ -98,6 +105,8 @@ public static void AddSingleton(sp => sp.GetRequiredService()); serviceCollection.AddSingleton(sp => sp.GetRequiredService()); serviceCollection.AddSingleton(sp => sp.GetRequiredService()); + + return serviceCollection; } /// @@ -109,7 +118,8 @@ public static void AddSingletonThe second contract type. /// The third contract type. /// The implementation type. - public static void AddSingleton(this IWeb3ServiceCollection serviceCollection, Func implementationFactory) + /// Web3 Service Collection. + public static IWeb3ServiceCollection AddSingleton(this IWeb3ServiceCollection serviceCollection, Func implementationFactory) where TInterface1 : class where TInterface2 : class where TInterface3 : class @@ -119,6 +129,8 @@ public static void AddSingleton(sp => sp.GetRequiredService()); serviceCollection.AddSingleton(sp => sp.GetRequiredService()); serviceCollection.AddSingleton(sp => sp.GetRequiredService()); + + return serviceCollection; } } } \ No newline at end of file diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK Web3Auth/2.6.0/Web3Auth Samples/Scenes/SampleLogin - Web3Auth.unity b/src/UnitySampleProject/Assets/Samples/web3.unity SDK Web3Auth/2.6.0/Web3Auth Samples/Scenes/SampleLogin - Web3Auth.unity index 642ed1d09..1d4f0ced3 100644 --- a/src/UnitySampleProject/Assets/Samples/web3.unity SDK Web3Auth/2.6.0/Web3Auth Samples/Scenes/SampleLogin - Web3Auth.unity +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK Web3Auth/2.6.0/Web3Auth Samples/Scenes/SampleLogin - Web3Auth.unity @@ -1437,65 +1437,6 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: rampConfig: {fileID: 11400000, guid: d1f58846e4fc71d4e90f287a86f328f9, type: 2} ---- !u!1 &1712945644 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1712945646} - - component: {fileID: 1712945645} - m_Layer: 0 - m_Name: _countly - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &1712945645 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1712945644} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 3830ecbe0f874710af3c6377b4540a81, type: 3} - m_Name: - m_EditorClassIdentifier: - Auth: - ServerUrl: - AppKey: - DeviceId: - Config: - Salt: - EnablePost: 0 - EnableTestMode: 0 - EnableConsoleLogging: 0 - NotificationMode: 0 - SessionDuration: 0 - EventQueueThreshold: 0 - StoredRequestLimit: 0 - TotalBreadcrumbsAllowed: 0 - EnableAutomaticCrashReporting: 0 ---- !u!4 &1712945646 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1712945644} - serializedVersion: 2 - 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: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1799608969 GameObject: m_ObjectHideFlags: 0 @@ -3153,4 +3094,3 @@ SceneRoots: - {fileID: 1025578983} - {fileID: 1679801099} - {fileID: 1799608973} - - {fileID: 1712945646} diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scenes/SampleLogin - WalletConnect.unity b/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scenes/SampleLogin - WalletConnect.unity index 328c09cab..57cbe800f 100644 --- a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scenes/SampleLogin - WalletConnect.unity +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scenes/SampleLogin - WalletConnect.unity @@ -104,7 +104,7 @@ NavMeshSettings: serializedVersion: 2 m_ObjectHideFlags: 0 m_BuildSettings: - serializedVersion: 2 + serializedVersion: 3 agentTypeID: 0 agentRadius: 0.5 agentHeight: 2 @@ -117,7 +117,7 @@ NavMeshSettings: cellSize: 0.16666667 manualTileSize: 0 tileSize: 256 - accuratePlacement: 0 + buildHeightMesh: 0 maxJobWorkers: 0 preserveTilesOutsideBounds: 0 debug: @@ -154,7 +154,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 920270120} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0.25, y: 1} @@ -231,7 +230,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1701305867} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -363,7 +361,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 920270120} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.25, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -500,7 +497,6 @@ RectTransform: - {fileID: 2126730552} - {fileID: 1491563362} m_Father: {fileID: 1701305867} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -577,7 +573,6 @@ RectTransform: m_Children: - {fileID: 1900245909} m_Father: {fileID: 724612375} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0.25, y: 0.5} @@ -647,13 +642,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 492023254} + serializedVersion: 2 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: 0} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &492023256 MonoBehaviour: @@ -723,7 +718,6 @@ RectTransform: - {fileID: 787012149} - {fileID: 724612375} m_Father: {fileID: 2036998554} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -803,7 +797,6 @@ RectTransform: - {fileID: 351786045} - {fileID: 1791429089} m_Father: {fileID: 654334440} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -909,7 +902,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1491563362} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -963,6 +955,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 654334440} m_Modifications: - target: {fileID: 4764608378852082086, guid: 50ad8ea555027414b8ddfc03fc7d41ab, type: 3} @@ -1062,6 +1055,12 @@ PrefabInstance: value: 18.85 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: + - targetCorrespondingSourceObject: {fileID: 8775736491206355084, guid: 50ad8ea555027414b8ddfc03fc7d41ab, type: 3} + insertIndex: -1 + addedObject: {fileID: 787012152} m_SourcePrefab: {fileID: 100100000, guid: 50ad8ea555027414b8ddfc03fc7d41ab, type: 3} --- !u!224 &787012149 stripped RectTransform: @@ -1135,7 +1134,6 @@ RectTransform: - {fileID: 23680381} - {fileID: 253290329} m_Father: {fileID: 1880270956} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.725} m_AnchorMax: {x: 1, y: 1} @@ -1168,13 +1166,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1334079840} + serializedVersion: 2 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: 0} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &1334079842 MonoBehaviour: @@ -1251,7 +1249,6 @@ RectTransform: - {fileID: 786896301} - {fileID: 8930114541282302188} m_Father: {fileID: 279245843} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1290,7 +1287,6 @@ RectTransform: m_Children: - {fileID: 2036998554} m_Father: {fileID: 1880270956} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 0.725} @@ -1369,7 +1365,6 @@ RectTransform: - {fileID: 108583392} - {fileID: 279245843} m_Father: {fileID: 1880270956} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1420,7 +1415,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 724612375} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.25, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1600,7 +1594,9 @@ Canvas: m_OverrideSorting: 0 m_OverridePixelPerfect: 0 m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 m_AdditionalShaderChannelsFlag: 25 + m_UpdateRectTransformForStandalone: 0 m_SortingLayerID: 0 m_SortingOrder: 0 m_TargetDisplay: 0 @@ -1620,7 +1616,6 @@ RectTransform: - {fileID: 1621534068} - {fileID: 1701305867} m_Father: {fileID: 0} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1658,7 +1653,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 351786045} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1734,7 +1728,6 @@ RectTransform: m_Children: - {fileID: 654334440} m_Father: {fileID: 1621534068} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1792,7 +1785,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 279245843} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 1, y: 1} @@ -1881,9 +1873,17 @@ Camera: m_projectionMatrixMode: 1 m_GateFitMode: 2 m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 m_SensorSize: {x: 36, y: 24} m_LensShift: {x: 0, y: 0} - m_FocalLength: 50 m_NormalizedViewPortRect: serializedVersion: 2 x: 0 @@ -1917,13 +1917,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2132619529} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 1, z: -10} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &4374818084218070658 MonoBehaviour: @@ -2111,7 +2111,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8930114541282302188} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -2132,10 +2131,17 @@ RectTransform: m_Children: - {fileID: 8875635999967305692} m_Father: {fileID: 1491563362} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 0} m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 0, y: 50} m_Pivot: {x: 0.5, y: 0} +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 1880270956} + - {fileID: 492023255} + - {fileID: 1334079841} + - {fileID: 2132619532} diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scenes/SampleMain.unity b/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scenes/SampleMain.unity index 49781fcb6..a81b8930e 100644 --- a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scenes/SampleMain.unity +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scenes/SampleMain.unity @@ -1226,6 +1226,7 @@ MonoBehaviour: messageSignVerify: A man chooses, a slave obeys. messageSha: "It\u2019s dangerous to go alone, take this!" toAddress: 0xdD4c825203f97984e7867F11eeCc813A036089D1 + value: 12300000000000000 registeredContractName: CsTestErc20 ecdsaKey: 0x78dae1a22c7507a4ed30c06172e7614eb168d3546c13856340771e63ad3c0081 ecdsaMessage: This is a test message @@ -3151,7 +3152,7 @@ MonoBehaviour: m_HandleRect: {fileID: 37375165} m_Direction: 0 m_Value: 0 - m_Size: 0.17716347 + m_Size: 0.23710066 m_NumberOfSteps: 0 m_OnValueChanged: m_PersistentCalls: @@ -3965,7 +3966,8 @@ MonoBehaviour: marketplaceContractToListTo: Set marketplace contract to list to collectionContractToList: Set collection contract to list from marketplaceContractToBuyFrom: Set marketplace contract to buy from - tokenIdToBuy: Set token ID to buy + itemIdToBuy: Set item ID to buy (the index id of the nft in the marketplace i.e + 0 or 1) weiPriceToBuy: Set price in wei to buy with i.e 100000000000000 --- !u!1 &519420028 GameObject: @@ -17837,10 +17839,22 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: Widely adopted standard for creating and implementing fungible tokens on - the Ethereum blockchain. It defines a set of rules and functions that enable - the creation of tokens that can be easily exchanged, transferred, and interacted - with within the Ethereum ecosystem. + m_text: 'RAMP.NETWORK is a widely used fiat on/off-ramp provider that facilitates + the seamless exchange of fiat currencies to cryptocurrencies and vice versa. + It integrates effortlessly with various platforms and wallets, providing users + with an easy and secure way to enter and exit the crypto market. With robust + compliance and user-friendly interfaces, RAMP.NETWORK supports multiple payment + methods, making it a preferred choice for developers and users looking to enhance + the accessibility and usability of cryptocurrencies within the broader financial + ecosystem. + + + + + + + +' m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scripts/Scenes/SampleMain/Erc20/Erc20Calls.cs b/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scripts/Scenes/SampleMain/Erc20/Erc20Calls.cs index 75340fb9a..0a7a5f7bb 100644 --- a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scripts/Scenes/SampleMain/Erc20/Erc20Calls.cs +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scripts/Scenes/SampleMain/Erc20/Erc20Calls.cs @@ -37,6 +37,8 @@ public class Erc20Calls : MonoBehaviour #endregion + + /// /// Balance Of ERC20 Address /// diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scripts/Scenes/SampleMain/Erc721/Erc721Calls.cs b/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scripts/Scenes/SampleMain/Erc721/Erc721Calls.cs index 8998dad99..e7f62f2fc 100644 --- a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scripts/Scenes/SampleMain/Erc721/Erc721Calls.cs +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.6.0/Web3.Unity Samples/Scripts/Scenes/SampleMain/Erc721/Erc721Calls.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Text; using ChainSafe.Gaming.Evm.Contracts.BuiltIn; +using ChainSafe.Gaming.Evm.Contracts.Extensions; using ChainSafe.Gaming.UnityPackage; using Scripts.EVM.Token; using UnityEngine;