From 470929d67b36e4ebe5be286dbca9dbd92cbdd9c4 Mon Sep 17 00:00:00 2001 From: oleksandrchainsafe <127766834+oleksandrchainsafe@users.noreply.github.com> Date: Mon, 29 Apr 2024 17:06:17 +0100 Subject: [PATCH] Package built-in dependencies fix (#925) * Package built-in dependencies fix * Added polling and timeout to GetTransaction method Introduced DelayUtil --------- Co-authored-by: oleksandr <59798783+creeppak@users.noreply.github.com> Co-authored-by: Robel Getnet Geremew --- scripts/data/published_dependencies.txt | 4 +- .../WalletConnectTransactionExecutor.cs | 2 - src/ChainSafe.Gaming/Web3/Core/DelayUtil.cs | 26 +++++++++++++ .../Web3/Core/Evm/RpcProviderExtensions.cs | 38 +++++++++++++------ 4 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 src/ChainSafe.Gaming/Web3/Core/DelayUtil.cs diff --git a/scripts/data/published_dependencies.txt b/scripts/data/published_dependencies.txt index 1973fd315..a12f33d70 100644 --- a/scripts/data/published_dependencies.txt +++ b/scripts/data/published_dependencies.txt @@ -1,2 +1,2 @@ -Packages/io.chainsafe.web3-unity/Runtime/Libraries/:ADRaffy.ENSNormalize;Nethereum.Model;BouncyCastle.Crypto;Nethereum.RLP;ChainSafe.Gaming.Debugging;Nethereum.RPC;ChainSafe.Gaming.Gelato;ChainSafe.Gaming.SygmaClient;Nethereum.Signer.EIP712;ChainSafe.Gaming.InProcessSigner;Nethereum.Signer;ChainSafe.Gaming.InProcessTransactionExecutor;Nethereum.Util;ChainSafe.Gaming.Unity.ThirdParty;Nethereum.Web3;ChainSafe.Gaming.Unity;System.Buffers;ChainSafe.Gaming.WalletConnect;System.Memory;ChainSafe.Gaming;System.Numerics.Vectors;Microsoft.Bcl.AsyncInterfaces;System.Reactive;Microsoft.Extensions.DependencyInjection.Abstractions;System.Runtime.CompilerServices.Unsafe;Microsoft.Extensions.DependencyInjection;System.Runtime.InteropServices.WindowsRuntime;Microsoft.Extensions.Logging.Abstractions;System.Security.Cryptography.Cng;Microsoft.IdentityModel.Abstractions;System.Text.Encodings.Web;Microsoft.IdentityModel.Logging;System.Text.Json;Microsoft.IdentityModel.Tokens;System.Threading.Channels;NBitcoin;System.Threading.Tasks.Extensions;Nethereum.ABI;WalletConnectSharp.Auth;Nethereum.Accounts;WalletConnectSharp.Common;WalletConnectSharp.Events;Nethereum.BlockchainProcessing;WalletConnectSharp.Core;Nethereum.Contracts;WalletConnectSharp.Crypto;Nethereum.Hex;Nethereum.JsonRpc.Client;WalletConnectSharp.Network.Websocket;Nethereum.JsonRpc.IpcClient;WalletConnectSharp.Network;Nethereum.JsonRpc.RpcClient;WalletConnectSharp.Sign;Nethereum.KeyStore;WalletConnectSharp.Storage;Nethereum.Merkle.Patricia;WalletConnectSharp.Web3Wallet;Nethereum.Merkle;Websocket.Client;Nethereum.Metamask;Nethereum.Siwe.Core;Nethereum.Siwe;Nethereum.UI;Nethereum.Unity.Metamask;Nethereum.Unity;ChainSafe.Gaming.MetaMask;ChainSafe.Gaming.MetaMask.Unity;ChainSafe.Gaming.InProcessTransactionExecutor.Unity -Packages/io.chainsafe.web3-unity.lootboxes/Chainlink/Runtime/Libraries/:Chainsafe.Gaming.Chainlink;ChainSafe.Gaming.Lootboxes.Chainlink;ChainSafe.Gaming.Marketplace \ No newline at end of file +Packages/io.chainsafe.web3-unity/Runtime/Libraries/:ADRaffy.ENSNormalize;Nethereum.Model;BouncyCastle.Crypto;Nethereum.RLP;ChainSafe.Gaming.Debugging;Nethereum.RPC;ChainSafe.Gaming.Gelato;ChainSafe.Gaming.SygmaClient;Nethereum.Signer.EIP712;ChainSafe.Gaming.InProcessSigner;Nethereum.Signer;ChainSafe.Gaming.InProcessTransactionExecutor;Nethereum.Util;ChainSafe.Gaming.Unity.ThirdParty;Nethereum.Web3;ChainSafe.Gaming.Unity;System.Buffers;ChainSafe.Gaming.WalletConnect;System.Memory;ChainSafe.Gaming;System.Numerics.Vectors;Microsoft.Bcl.AsyncInterfaces;System.Reactive;Microsoft.Extensions.DependencyInjection.Abstractions;System.Runtime.CompilerServices.Unsafe;Microsoft.Extensions.DependencyInjection;System.Runtime.InteropServices.WindowsRuntime;Microsoft.Extensions.Logging.Abstractions;System.Security.Cryptography.Cng;Microsoft.IdentityModel.Abstractions;System.Text.Encodings.Web;Microsoft.IdentityModel.Logging;System.Text.Json;Microsoft.IdentityModel.Tokens;System.Threading.Channels;NBitcoin;System.Threading.Tasks.Extensions;Nethereum.ABI;WalletConnectSharp.Auth;Nethereum.Accounts;WalletConnectSharp.Common;WalletConnectSharp.Events;Nethereum.BlockchainProcessing;WalletConnectSharp.Core;Nethereum.Contracts;WalletConnectSharp.Crypto;Nethereum.Hex;Nethereum.JsonRpc.Client;WalletConnectSharp.Network.Websocket;Nethereum.JsonRpc.IpcClient;WalletConnectSharp.Network;Nethereum.JsonRpc.RpcClient;WalletConnectSharp.Sign;Nethereum.KeyStore;WalletConnectSharp.Storage;Nethereum.Merkle.Patricia;WalletConnectSharp.Web3Wallet;Nethereum.Merkle;Websocket.Client;Nethereum.Metamask;Nethereum.Siwe.Core;Nethereum.Siwe;Nethereum.UI;Nethereum.Unity.Metamask;Nethereum.Unity;ChainSafe.Gaming.MetaMask;ChainSafe.Gaming.MetaMask.Unity;ChainSafe.Gaming.InProcessTransactionExecutor.Unity;ChainSafe.Gaming.Marketplace +Packages/io.chainsafe.web3-unity.lootboxes/Chainlink/Runtime/Libraries/:Chainsafe.Gaming.Chainlink;ChainSafe.Gaming.Lootboxes.Chainlink \ No newline at end of file diff --git a/src/ChainSafe.Gaming.WalletConnect/WalletConnectTransactionExecutor.cs b/src/ChainSafe.Gaming.WalletConnect/WalletConnectTransactionExecutor.cs index ae2f9f7f5..ca0adfa45 100644 --- a/src/ChainSafe.Gaming.WalletConnect/WalletConnectTransactionExecutor.cs +++ b/src/ChainSafe.Gaming.WalletConnect/WalletConnectTransactionExecutor.cs @@ -54,8 +54,6 @@ public async Task SendTransaction(TransactionRequest transa WCLogger.Log($"Transaction executed successfully. Hash: {hash}."); - await Task.Delay(TimeSpan.FromSeconds(1)); // hack: rpcProvider.GetTransaction can't find transaction by hash - return await rpcProvider.GetTransaction(hash); bool ValidateResponseHash(string hash) diff --git a/src/ChainSafe.Gaming/Web3/Core/DelayUtil.cs b/src/ChainSafe.Gaming/Web3/Core/DelayUtil.cs new file mode 100644 index 000000000..8b8da91ad --- /dev/null +++ b/src/ChainSafe.Gaming/Web3/Core/DelayUtil.cs @@ -0,0 +1,26 @@ +using System; +using System.Threading.Tasks; + +namespace ChainSafe.Gaming.Web3.Core +{ + /// + /// Utility class for delay operations. + /// + public static class DelayUtil + { + /// + /// Replicates Task.Delay behaviour. Works on a single-threaded platforms like Unity WebGL. + /// + /// The time to wait. + /// A representing the asynchronous operation. + public static async Task SafeDelay(TimeSpan delay) // TODO: use default method if platform supports multithreading + { + var start = DateTime.UtcNow; + + while (DateTime.UtcNow - start < delay) + { + await Task.Yield(); + } + } + } +} \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/Evm/RpcProviderExtensions.cs b/src/ChainSafe.Gaming/Web3/Core/Evm/RpcProviderExtensions.cs index 971c4963c..8af9faa80 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Evm/RpcProviderExtensions.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Evm/RpcProviderExtensions.cs @@ -1,10 +1,9 @@ using System; -using System.Collections.Generic; using System.Numerics; -using System.Runtime.CompilerServices; using System.Threading.Tasks; using ChainSafe.Gaming.Evm.Transactions; using ChainSafe.Gaming.Web3; +using ChainSafe.Gaming.Web3.Core; using Nethereum.Hex.HexConvertors.Extensions; using Nethereum.Hex.HexTypes; using Nethereum.RPC.Eth.DTOs; @@ -289,38 +288,53 @@ public static async Task EstimateGas(this IRpcProvider provider, /// /// The RPC provider. /// The hash of the transaction to retrieve. + /// (Optional) The time after which the method will fail if we can't find the transaction by hash. 15 seconds by default. /// /// A representing the asynchronous operation. /// The task result contains the transaction details as a . /// - public static async Task GetTransaction(this IRpcProvider provider, string transactionHash) + public static async Task GetTransaction(this IRpcProvider provider, string transactionHash, TimeSpan? timeOut = null) { + timeOut ??= TimeSpan.FromSeconds(15); + + // Poll transaction till it's available on the given node + TransactionResponse transaction = null; var parameters = new object[] { transactionHash }; + var pollStartTime = DateTime.UtcNow; + while (DateTime.UtcNow - pollStartTime < timeOut) + { + transaction = await provider.Perform("eth_getTransactionByHash", parameters); - var result = await provider.Perform("eth_getTransactionByHash", parameters); + if (transaction != null) + { + break; + } - if (result == null) + await DelayUtil.SafeDelay(TimeSpan.FromSeconds(1)); + } + + if (transaction == null) { - throw new Web3Exception("transaction not found"); + throw new Web3Exception("Transaction not found."); } - if (result.BlockNumber == null) + if (transaction.BlockNumber == null) { - result.Confirmations = 0; + transaction.Confirmations = 0; } - else if (result.Confirmations == null) + else if (transaction.Confirmations == null) { var blockNumber = await provider.GetBlockNumber(); - var confirmations = (blockNumber.ToUlong() - result.BlockNumber.ToUlong()) + 1; + var confirmations = (blockNumber.ToUlong() - transaction.BlockNumber.ToUlong()) + 1; if (confirmations <= 0) { confirmations = 1; } - result.Confirmations = confirmations; + transaction.Confirmations = confirmations; } - return result; + return transaction; } ///