0

I encountered a problem with our Flutter based dApp while migrating to WalletConnect v2 from v1. Our dApp interacts with an erc721 contract that we deployed on the polygon blockchain. Executing ‘eth_sendTransaction’ or ‘eth_signTransaction’ requests via a WalletConnect v2 session fail while this was not an issue in case of v1. I would highly appreciate any suggestions resolving the issue.

Below are code snippets for the v1- and v2 case. In case of v2 I manage to successfully create a session with MetaMask using SignClient, but signClient.request() does not materialise into a successful transfer. The wallet also does not ask for approval.

Behaviour executing the v2 code may differ depending on the wallet (Trust or Metamask), platform (IOS or Android) and the network (test - or main net). In case of IOS using the Metamask wallet on polygon while debugging, we may hit an rpc exception like

_JsonRpcError (JsonRpcError(code: 5000, message: undefined is not an object (evaluating 'e[n]'))) > code: 5000 message: "undefined is not an object (evaluating 'e[n]')"

In other cases we get to see similar (although not exactly the same) errors.

Some details of the development environment:

  • Flutter 3.10.5
  • walletconnect_flutter_v2: '2.0.14
  • http: '1.1.0'

WalletConnect V1 (working code)

connector = WalletConnect(
    bridge: "https://bridge.walletconnect.org",
    clientMeta: const PeerMeta(
        name: "My App",
        description: “My app",
        url: "https://walletconnect.org",
        icons: [
          "https://files.gitbook.com/v0/b/gitbook-legacy-files/o/spaces%2F-LJJeCjcLrr53DcT1Ml7%2Favatar.png?alt=media"
        ]));

String walletUri = “”;
session = await connector.createSession(onDisplayUri: (uri) {
      walletUri = uri;
      launchUrlString(uri, mode: LaunchMode.externalApplication)});

provider = EthereumWalletConnectProvider(connector);

final client = Web3Client(“https://polygon-rpc.com”, Client());

String fromWallet = session.accounts[0];
String toWallet =
BigInt tokenId = 
String contractAddress = 
String abiCode = 
EthereumAddress ethContractAddr = EthereumAddress.fromHex(contractAddress);
EthereumAddress ethFromWallet = EthereumAddress.fromHex(fromWallet);

final contract = DeployedContract(ContractAbi.fromJson(abiCode, "contract"), EthContractAddr);
List<dynamic> params = [fromWallet, toWallet, tokenId];
ContractFunction? func = findFunctionInABI(“safeTransferFrom”, params.length);
int nonce = await client.getTransactionCount(ethFromWallet);

var tx = Transaction.callContract(
      contract: contract,
      function: func!,
      parameters: params,
      gasPrice: null,
      nonce: nonce,
    );

var result = provider.sendTransaction(from: fromWallet, to: contractAddress, data: tx.data);
launchUrlString(walletUri, mode: LaunchMode.externalApplication);

WalletConnect V2

signClient = SignClient.createInstance(
    relayUrl:  'wss://relay.walletconnect.com', 
    projectId: ‘123’,
    metadata: PairingMetadata(
        name: 'dApp (Requester)',
        description: 'A dapp that can request that transactions be signed',
        url: 'https://walletconnect.com',
        icons: ['https://avatars.githubusercontent.com/u/37784886'],
    ),
);

ConnectResponse resp = await signClient.connect(requiredNamespaces: {
        'eip155': RequiredNamespace(
                chains: ['eip155:137'], 
                    methods: ['eth_sendTransaction', 'eth_signTransaction'], 
                    events: []
    ),
 });

String walletUri = resp.uri.toString();
launchUrlString(walletUri, mode: LaunchMode.externalApplication);

SessionData session = await resp.session.future;
String pairingTopic = resp.pairingTopic;

final client = Web3Client(“https://polygon-rpc.com”, Client()

var nameSpace = metamaskSession.namespaces["eip155"];
String fromWallet = nameSpace!.accounts[0].split(":")[2];
String toWallet = 
BigInt tokenId = 
String contractAddress = 
String abiCode =
EthereumAddress ethContractAddr = EthereumAddress.fromHex(contractAddress);
EthereumAddress ethFromWallet = EthereumAddress.fromHex(fromWallet);

final contract = DeployedContract(ContractAbi.fromJson(abiCode, "contract"), EthContractAddr);
List<dynamic> params = [fromWallet, toWallet, tokenId];
ContractFunction? func = findFunctionInABI(“safeTransferFrom”, params.length);
int nonce = await client.getTransactionCount(ethFromWallet);

var tx = Transaction.callContract(
      contract: contract,
      function: func!,
      parameters: params,
      gasPrice: null,
      nonce: nonce,
    );

 String paramJson = '0x' + hex.encode(tx.data!);
 //launchUrlString(walletUri, mode: LaunchMode.externalApplication);
   
 final dynamic signResponse = await signClient.request(
        topic: session.topic,
        chainId: 'eip155:137', 
        request: SessionRequestParams(
        method: "eth_sendTransaction", 
        params: {
                "from": fromWallet,
                "to": contractAddress,
                "data":paramJson
            }
    )
);
    
launchUrlString(walletUri, mode: LaunchMode.externalApplication);

I adapted our dApp according according to the instructions given for migrating and tried on both IOS/Android simulators/emulators ad real hardware. I also tried on the mumbai test network and the Polygon main network, using different wallets Trust and Metamask. I played with the parameters that we pass to the request to see if that would make a difference. I might have missed or misunderstood something in the implementation and hope anyone could pinpoint what the issue is.

0 Answers0