ethers-io / ethers.js

Complete Ethereum library and wallet implementation in JavaScript.
https://ethers.org/
MIT License
7.8k stars 1.8k forks source link

could not detect network (event="noNetwork", code=NETWORK_ERROR, version=providers/5.7.2) #4758

Open amarstb opened 4 weeks ago

amarstb commented 4 weeks ago

Ethers Version

5.7.2

Search Terms

No response

Describe the Problem

Not able to detect the network, i have ensured my device has active internet connection.

Screenshot 2024-06-10 at 5 42 40 PM

Code Snippet

import '@ethersproject/shims';
import {ethers} from 'ethers';

const provider = new ethers.providers.JsonRpcProvider(
  'https://coston-api.flare.network/ext/C/rpc',
);

console.log(provider, 'provider');

Contract ABI

No response

Errors

Error: could not detect network (event="noNetwork", code=NETWORK_ERROR, version=providers/5.7.2)

Environment

React Native/Expo/JavaScriptCore

Environment (Other)

react-native: 0.66.1

ricmoo commented 3 weeks ago

Can you add provider.on("debug", console.log) to your provider to capture the data being exchanged between the client and the server?

Also, have you tried using v6?

amarstb commented 3 weeks ago

Hi @ricmoo, thank you for taking the time to look into this issue, here is the data exchanged:

Request:

Screenshot 2024-06-18 at 9 38 30 AM

Response:

Screenshot 2024-06-18 at 9 39 10 AM

I did try v6, but i am facing a different issue regarding @adraffy/ens-normalize resolution, and i have created a separate issue for it here

ricmoo commented 1 week ago

Based on the error, the shims are definitely not being applied. That error is exactly what the shim fixes. :)

In ESM, imports behave asynchronously, which breaks anonymous imports as a shims.

The easiest thing to do is wrap your code in (async function() { /* code here */ })() or if your transpiler doesn’t like that setTimeout(() => { /* code here */ }, 0). These will punt your code u til the next event loop, at which time the import phase will have completed.

You should also check to make sure the shims aren’t getting shaken out or such, by some other part of your build process.

Alternatively, if you use v6, this is no longer necessary as the fetch no longer relies on ArrayBuffer and if you do want to customize the fetching, it can be substituted synchronously.

amarstb commented 1 week ago

Hi @ricmoo, thank you for the reply,

I moved the shims import to the entry file of the project i.e index.js, and wrote a few functions to check if the shims are being imported correctly and ran them in a useEffect as follows:

useEffect(() => {

const testResults = []; 

// Test String.prototype.normalize
try {
  const result = "é".normalize('NFD') === 'e\u0301';
  testResults.push('String.prototype.normalize:' + ${result ? 'Passed' : 'Failed'}`);
} catch (error) {
  testResults.push('String.prototype.normalize: Failed');
}

// Test atob and btoa
try {
  const encoded = btoa('Hello, world!');
  const decoded = atob(encoded);
  const result = (encoded === 'SGVsbG8sIHdvcmxkIQ==') && (decoded === 'Hello, world!');
  testResults.push(`atob/btoa: ${result ? 'Passed' : 'Failed'}`);
} catch (error) {
  testResults.push('atob/btoa: Failed');
}

// Test ArrayBuffer.isView
try {
  const buffer = new ArrayBuffer(8);
  const view = new Uint8Array(buffer);
  const result = ArrayBuffer.isView(view) === true;
  testResults.push(`ArrayBuffer.isView: ${result ? 'Passed' : 'Failed'}`);
} catch (error) {
  testResults.push('ArrayBuffer.isView: Failed');
}

// Test nextTick
try {
  let executed = false;
  global.nextTick(() => {
    executed = true;
    testResults.push(`nextTick: ${executed ? 'Passed' : 'Failed'}`);
    setResults([...testResults]);
  });
  setTimeout(() => {
    if (!executed) {
      testResults.push('nextTick: Failed');
      setResults([...testResults]);
    }
  }, 100);
} catch (error) {
  testResults.push('nextTick: Failed');
}

// Test crypto.getRandomValues
try {
  const buffer = new Uint8Array(10);
  global.crypto.getRandomValues(buffer);
  const result = buffer.every(value => value >= 0 && value < 256);
  testResults.push(`crypto.getRandomValues: ${result ? 'Passed' : 'Failed'}`);
} catch (error) {
  testResults.push('crypto.getRandomValues: Failed');
}

// Test FileReader.readAsArrayBuffer
try {
  const blob = new Blob(['Hello, world!'], { type: 'text/plain' });
  const fr = new FileReader();
  fr.onloadend = () => {
    const result = fr.result instanceof ArrayBuffer;
    testResults.push(`FileReader.readAsArrayBuffer: ${result ? 'Passed' : 'Failed'}`);
    setResults([...testResults]);
  };
  fr.readAsArrayBuffer(blob);
} catch (error) {
  testResults.push('FileReader.readAsArrayBuffer: Failed');
}

console.log('testResults',testResults)

setTimeout(() => {
  const provider =  new ethers.providers.JsonRpcProvider(
    'https://coston-api.flare.network/ext/C/rpc',
  );
  provider.on('debug', (data) => console.log(data,'providerDebug'))
},0)   }, []);

If i run these tests without importing the shims i get the following result:

[
    "String.prototype.normalize: Passed",
    "atob/btoa: Passed",
    "ArrayBuffer.isView: Passed",
    "nextTick: Failed",
    "crypto.getRandomValues: Passed",
    "FileReader.readAsArrayBuffer: Failed"
]

Now when i import the shims and run the same tests i get the following result:

[
    "String.prototype.normalize: Passed",
    "atob/btoa: Passed",
    "ArrayBuffer.isView: Passed",
    "crypto.getRandomValues: Passed",
    "nextTick: Passed",
    "FileReader.readAsArrayBuffer: Passed"
]

This confirms that the shims for nextTick and FileReader are being imported correctly and working fine. Also I could see the following log which is coming from the node_modules/@ethersproject/shims/src/index.js.

Screenshot 2024-06-27 at 1 32 09 PM

But even after all the tests passing, i get the same error for the provider which is created at the bottom of the useEffect.

Also i did try v6 but i am facing a different issue related to @adraffy/ens-normalize there. I have mentioned the issue here