Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error null reference in get request from dapp exchange intro file Sto… #197

Closed
wants to merge 1 commit into from

Conversation

MassoudKargar
Copy link

…re method Set property map

@skibitsky
Copy link
Member

Hey @MassoudKargar,

Thank you for the PR! Could you please explain what exact issue it solves? The map is statically initialized, so I'm curious about the conditions that result in the null reference.

@MassoudKargar
Copy link
Author

I was programming an inter-voltage connection that I wrote myself with a dapp exchange like pancakeswap, and when I received the eth_sendTransaction event, I was getting an error and I couldn't continue, and the system didn't react at all, that's why I started debugging your system and realized the problem. I think it is because of the new system of Asp .net 8 about enable that this feature has created the issue.
However, I know that this small change can help solve the problem.

@skibitsky
Copy link
Member

I am trying to understand why the map is null for you. It is automatically initialized with an empty dictionary when an instance of the Store object is created, even before Init() is called. The map is set to null only in the Dispose() method. This makes me think that you are trying to access the store after it has been disposed.

While your suggestion fixes the error message, you may encounter more issues later because you are operating on a disposed Store.

Could you share your code or explain how you initialize the SDK and handle session requests?

@MassoudKargar
Copy link
Author

I am programming in blazor webassembly application


And I get this error

Debugging hotkey: Shift+Alt+D (when application has focus)
[MONO] /__w/1/s/src/mono/mono/metadata/icall.c:6177
[MONO] /__w/1/s/src/mono/mono/metadata/icall.c:6186
(null)
Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance of an object.
at WalletConnectSharp.Core.Controllers.Store2[[System.Int64, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[WalletConnectSharp.Sign.Models.PendingRequestStruct, WalletConnectSharp.Sign, Version=2.3.7.0, Culture=neutral, PublicKeyToken=null]].Set(Int64 key, PendingRequestStruct value) at WalletConnectSharp.Sign.Engine.WalletConnectSharp.Sign.Interfaces.IEnginePrivate.SetPendingSessionRequest(PendingRequestStruct pendingRequest) at WalletConnectSharp.Sign.Models.SessionRequestEventHandler2.d__6[[BlazorApp1.Pages.Home.EthGetTransactionReceiptWrapper, BlazorApp1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[BlazorApp1.Pages.Home.EthSignTransactionResponse, BlazorApp1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
at WalletConnectSharp.Sign.Models.TypedEventHandler2.<RequestCallback>d__34[[WalletConnectSharp.Sign.Models.Engine.Methods.SessionRequest1[[BlazorApp1.Pages.Home.EthGetTransactionReceiptWrapper, BlazorApp1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], WalletConnectSharp.Sign, Version=2.3.7.0, Culture=neutral, PublicKeyToken=null],[BlazorApp1.Pages.Home.EthSignTransactionResponse, BlazorApp1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
at WalletConnectSharp.Core.Controllers.TypedMessageHandler.<>c__DisplayClass18_02.<<HandleMessageType>g__RequestCallback|0>d[[WalletConnectSharp.Sign.Models.Engine.Methods.SessionRequest1[[BlazorApp1.Pages.Home.EthGetTransactionReceiptWrapper, BlazorApp1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], WalletConnectSharp.Sign, Version=2.3.7.0, Culture=neutral, PublicKeyToken=null],[BlazorApp1.Pages.Home.EthSignTransactionResponse, BlazorApp1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
--- End of stack trace from previous location ---
at System.Threading.Tasks.Task.<>c.b__128_1(Object state)
at System.Threading.QueueUserWorkItemCallbackDefaultContext.Execute()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading.ThreadPool.BackgroundJob


And this is my code


@page "/"
@using Newtonsoft.Json
@using WalletConnectSharp.Common.Utils
@using WalletConnectSharp.Network.Models
@using WalletConnectSharp.Sign
@using WalletConnectSharp.Sign.Models
@using WalletConnectSharp.Sign.Models.Engine.Events
@using WalletConnectSharp.Storage

Home

Hello, world!

@if (dataset) { }

Welcome to your new app.
@code
{
public string? Uri { get; set; }
public static string? Uris { get; set; }
static readonly string words = "....";
Wallet? wallet;
static Account? account;
WalletConnectSignClient? client;
ProposalStruct? proposalStruct;
Engine? engin;
bool dataset;
public Dictionary<int, string>? ChainList { get; set; }
}
@functions
{
protected override async Task OnInitializedAsync()
{
ChainList = new Dictionary<int, string>()
{
{ 56, "https://binance.llamarpc.com" },
{ 97, "https://endpoints.omniatech.io/v1/bsc/testnet/public" },
{ 11155111, "https://endpoints.omniatech.io/v1/eth/sepolia/public" },
};
dataset = false;
await InitData();
}

private async Task InitData()
{
    wallet = new Wallet(words, null);
    account = wallet.GetAccount(0);

    var dappOptions = new SignClientOptions()
        {
            ProjectId = "....",
            Metadata = new Metadata()
            {
                Description = "An example dapp to showcase WalletConnectSharpv2",
                Icons = new[] { "https://walletconnect.com/meta/favicon.ico" },
                Name = "WalletConnectSharpv2 Dapp Example",
                Url = "https://walletconnect.com",
            },
            Storage = new InMemoryStorage(),
            Name = "my-app",
        };

    client = await WalletConnectSignClient.Init(dappOptions);
    dataset = true;
}

public async Task OnConnectUrl()
{
    if (client != null)
    {
        try
        {
            client.PendingRequests.Dispose();
            client.SessionProposed += SessionProposed;
            proposalStruct = await client.Pair(Uri);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }
}

private async void SessionProposed(object? sender, SessionProposalEvent e)
{
    string[]? manespacesMethods = e.Proposal.OptionalNamespaces.Values.Select(s => s.Methods).FirstOrDefault();
    engin = sender as Engine;
    if (engin != null && client != null && account != null)
    {
        engin.SessionRequestEvents<EthGetTransactionReceiptWrapper, EthSignTransactionResponse>().OnRequest += OnRequestEthGetTransactionReceiptWrapper;
        var approveData = await client.Approve(e.Proposal, new[] { account.Address });
        await approveData.Acknowledged();
    }
}

private async Task OnRequestEthGetTransactionReceiptWrapper(RequestEventArgs<EthGetTransactionReceiptWrapper, EthSignTransactionResponse> requestData)
{
    try
    {
        var chainId = int.Parse(client.AddressProvider.DefaultChainId.Split(':')[1]);
        var ethGetTransaction = requestData.Request.Params.FirstOrDefault();
        var account = new Account(Home.account.PrivateKey);
        Web3 web3 = new(new Account(account.PrivateKey), url: ChainList[chainId]) { TransactionManager = { UseLegacyAsDefault = true, } };
        var tx = new TransactionInput()
            {
                Data = ethGetTransaction.Data,
                From = ethGetTransaction.From,
                To = ethGetTransaction.To,
                Gas = new HexBigInteger(ethGetTransaction.Gas),
                Value = new HexBigInteger(ethGetTransaction.Value),
                ChainId = new HexBigInteger($"0x{chainId}")
            };
        var receipt = await web3.Eth.TransactionManager.TransactionReceiptService.DeployContractAndWaitForReceiptAsync(tx);
        await engin.Respond<EthGetTransactionReceiptWrapper, EthSignTransactionResponse>(requestData.Topic, new JsonRpcResponse<EthSignTransactionResponse>(requestData.Request.Id, new Error(), new EthSignTransactionResponse(receipt)));
        requestData.Response = receipt;
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
    }
}

[RpcResponseOptions(Clock.ONE_MINUTE, 99999)]
[JsonConverter(typeof(ConvertToStr<TransactionReceipt>))]
public class EthSignTransactionResponse
{
    private readonly TransactionReceipt _response;

    public EthSignTransactionResponse(TransactionReceipt response)
    {
        _response = response;
    }

    public static implicit operator EthSignTransactionResponse(TransactionReceipt response)
    {
        if (response == null)
            return null;

        return new EthSignTransactionResponse(response);
    }

    public override string ToString()
    {
        return _response.BlockHash;
    }
}


public class ConvertToStr<T> : JsonConverter where T : class
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(string) || objectType == typeof(T);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // Deserialize the value as usual
        return serializer.Deserialize<string>(reader) as T;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value.ToString());
    }
}
[RpcMethod("eth_sendTransaction"), RpcRequestOptions(Clock.ONE_MINUTE, 99999)]
public class EthGetTransactionReceiptWrapper : List<EthGetTransaction?>
{
}

public class EthGetTransaction
{
    [JsonProperty("from")]
    public string? From { get; set; }

    [JsonProperty("to")]
    public string? To { get; set; }

    [JsonProperty("data")]
    public string? Data { get; set; }

    [JsonProperty("gas")]
    public string? Gas { get; set; }

    [JsonProperty("value")]
    public string? Value { get; set; }
}

}

@skibitsky
Copy link
Member

@MassoudKargar I believe the issue might be in your OnConnectUrl method, specifically with disposing client.PendingRequests. You should dispose the client when it is no longer needed and don't dispose individual parts of the client.

@MassoudKargar
Copy link
Author

I did not understand exactly, can you give me a sample code or give an example please?

@skibitsky
Copy link
Member

skibitsky commented Jun 7, 2024

@MassoudKargar from your code:

public async Task OnConnectUrl()
{
    if (client != null)
    {
        try
        {
            client.PendingRequests.Dispose(); // ← REMOVE
            client.SessionProposed += SessionProposed;
            proposalStruct = await client.Pair(Uri);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }
}

@MassoudKargar
Copy link
Author

Thanks, the problem is solved, but I don't remember why I used such a code.
But I have another problem and thank you for your help.
I have a problem with the response for the OnRequestEthGetTransactionReceiptWrapper method for the eth_sendTransaction event. Is it possible for you to give me an example?
I get this error on pancakeswap.finance service

Swap failed: Unknown error: "Request expired. Please try again.". Try increasing your slippage tolerance.
Dismiss

@skibitsky
Copy link
Member

@MassoudKargar could you please open an issue? In the issue please specify if you're building a wallet or an app.

@skibitsky skibitsky closed this Jun 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants