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

react native not support fetch data from provider(v5.0.8) #993

Closed
282931 opened this issue Aug 10, 2020 · 43 comments
Closed

react native not support fetch data from provider(v5.0.8) #993

282931 opened this issue Aug 10, 2020 · 43 comments
Labels
discussion Questions, feedback and general information. fixed/complete This Bug is fixed or Enhancement is complete and published.

Comments

@282931
Copy link

282931 commented Aug 10, 2020

It shows the error:
Error: missing response (requestBody=null, requestMethod="GET", serverError={}, url="https://api-kovan.etherscan.io/api?module=account&action=balance&address=0xD0FB2864a573F4a828cdc3971450Ae164182965d&tag=latest&apikey=46PPUBQYXPJBCX4I3E4JEVU9WYJN9F5XEM", code=SERVER_ERROR, version=web/5.0.3)

I tried to use 4.0.47 the response looks fine

@282931
Copy link
Author

282931 commented Aug 11, 2020

Looks like in this file packages/web/src.ts/geturl.ts, http and https module only works in node

@ricmoo
Copy link
Member

ricmoo commented Aug 11, 2020

@282931 that means your bundler is picking up the nodejs version, not the browser version.

Do you have a rollup config or webpack? Make sure you add "browser" to your mainFields in the config. Otherwise, if you require the ethers/dist/ethers.umd.js directly this bundling is already complete. :)

I am planning to put together a specific react/expo version at some point too, but that will be a while yet I think...

@ricmoo ricmoo added the discussion Questions, feedback and general information. label Aug 11, 2020
@282931
Copy link
Author

282931 commented Aug 11, 2020

not work
I import this module like this :

import {ethers, Wallet} from 'ethers/dist/ethers.umd.js';
const provider = new ethers.providers.EtherscanProvider(
      'kovan',
      Config.etherscan,
    );
....
provider.getGasPrice()
...

still get the same problom

@garyng2000
Copy link

@ricmoo,

I have no issue using ethers.js in expo(other than the slow decrypt geth wallet issue). In fact, ethers.js fulfill full some other dependencies I need in my app.

@282931
Copy link
Author

282931 commented Aug 11, 2020

@garyng2000 what ethers version you using? I try expo the same error

@garyng2000
Copy link

5.0.5, though I am not using etherscan and only standard JSONRPC provider(my own). via this

import { ethers } from 'ethers';

@282931
Copy link
Author

282931 commented Aug 11, 2020

check the snack I just created on expo : https://snack.expo.io/@3dtheo/ethers-provider-test

@282931
Copy link
Author

282931 commented Aug 11, 2020

@garyng2000 you switch to expo-web it works fine, IOS and Android shows the problem

@garyng2000
Copy link

@282931
works alright on my iPhone, though I was not using await but standard .then .catch but shouldn't make a difference

@vikil143
Copy link

I m facing the same issue in the v5 the error was
Error: could not detect network (event="noNetwork", code=NETWORK_ERROR, version=providers/5.0.5

@lew
Copy link

lew commented Aug 13, 2020 via email

@ricmoo
Copy link
Member

ricmoo commented Aug 20, 2020

Hi, sorry, I was away for a bit. I'm back.

Are you still experiencing this problem?

The noNetwork error indicates that your node did not respond meaningfully to either eth_chainId or eth_networkId. What backend are you using? Are you certain it is up an running when you code runs? Is the device connected to the network? Does the device have a functioning fetch implementation?

@282931
Copy link
Author

282931 commented Aug 25, 2020

@ricmoo I found the problem, react-native not support Body.arrayBuffer() this method

const body = await response.arrayBuffer();

@ricmoo
Copy link
Member

ricmoo commented Aug 25, 2020

Hmmmmm... Do you have any documentation for what it does support? Is there an alternative? Or someway to shim it?

@282931
Copy link
Author

282931 commented Aug 25, 2020

I find a way to use from readAsDataURL:
from facebook/react-native#21209 (comment)
difference is that I delete the ";base64," from "data:application/octet-stream;base64," to make it work

const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
const atob = (input = '') => {
	let str = input.replace(/=+$/, '');
	let output = '';
	if (str.length % 4 == 1) {
		throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");
	}
	for (let bc = 0, bs = 0, buffer, i = 0;
		buffer = str.charAt(i++);
		~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
			bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
	) {
		buffer = chars.indexOf(buffer);
	}
	return output;
}
FileReader.prototype.readAsArrayBuffer = function (blob) {
	if (this.readyState === this.LOADING) throw new Error("InvalidStateError");
	this._setReadyState(this.LOADING);
	this._result = null;
	this._error = null;
	const fr = new FileReader();
	fr.onloadend = () => {
		const content = atob(fr.result.substr("data:application/octet-stream".length));
		const buffer = new ArrayBuffer(content.length);
		const view = new Uint8Array(buffer);
		view.set(Array.from(content).map(c => c.charCodeAt(0)));
		this._result = buffer;
		this._setReadyState(this.DONE);
	};
	fr.readAsDataURL(blob);
}

@garyng2000
Copy link

now I am confused. I have no problem calling my own JSONRPC endpoint which should all be using the same routine to handle the return which is some form of RLE in the form of byte array(thus the body.arrayBuffer) ? It build and run fine on my iPhone.

@282931
Copy link
Author

282931 commented Aug 25, 2020

@garyng2000 because v5.0.5 is using response.text(); You get this problem if you update to V5.0.8

const body = await response.text();

@garyng2000
Copy link

ah, I see. thanks. I only knew RN is bad in this area for binary upload when I was working on ipfs, didn't know even fetch(and I assume xmlhttprequest as well) has this issue. and yes, that is the only work around I know unless one goes to the react-native link route.

@ricmoo
does it mean for <= 5.0.5 it is possible that the returned content may not be properly decoded if .text() didn't some transformation of non utf8 valid return ?

@ricmoo
Copy link
Member

ricmoo commented Aug 25, 2020

I think those versions used .text(). Does the above polyfil not work? If it does, I'd like to add it to my shim directory, which is mainly for react/expo and similar non-compliant platforms.

I'm hoping to get an actual dist/ethers-react.js built at some point in the near future, because there seems to be a bunch of little issues that are difficult to handle in a generic way, but if react/expo had their own bundle, I won't have to worry about sprinkling little fixes all over, and could keep the fixes isolated. :)

@garyng2000
Copy link

@ricmoo
I am wondering what would be the effect of revert it back to .text() and just use raw charCodeAt() to brute force covert it to Uint8array ? Or this would not work if the content has invalid utf8 content.

@ricmoo
Copy link
Member

ricmoo commented Aug 25, 2020

The change was made to handle working with binary data though, so the effort put into the web package could be used by other projects. It’s partly for other projects and partly a step towards v6, which will have a better API.

I think in the case of bad UTF-8 data, the .text() result it handled through JavaScript, so it likely already undergone the "replace" strategy for invalid strings and could not be recovered.

I have an idea though, I need to experiment with a simple react app though to see if it will work. :)

I’ll try a few things out today...

mnzaki added a commit to jolocom/jolo-did-method that referenced this issue Aug 25, 2020
@mnzaki
Copy link

mnzaki commented Aug 25, 2020

Note that there is also https://github.com/joltup/rn-fetch-blob for handling the binary data issue.
But overwriting the global.fetch with rn-fetch-blob's (0.10.15) polyfill does not work with ethers

mnzaki added a commit to jolocom/jolocom-lib that referenced this issue Aug 25, 2020
@garyng2000
Copy link

@mnzaki
but in the context of expo, unless rn-fetch-blob is included in their 'OOB', it would not work. I have to write my own ipfs interface because I don't want to expo eject(and would need OS X for building iOS), too much trouble. This is also what I mentioned in a prior comment that ethers.js has pulled in some RN(as in expo) friendly dependencies that I like.

@ricmoo
Copy link
Member

ricmoo commented Aug 25, 2020

(Random aside; is there a reason RN and Expo did not implement these? Would it be worth my while to add to these projects and do they generally accept pull requests?)

@garyng2000
Copy link

Expo depends on RN for the base implementations like fetch() or Blob() or FormData(), sometimes they then amend their package say there was no randombyte() equivalent in RN and Expo add extra(their own 'native' extension which is similar to rn-fetch-blob but packaged as part of Expo so we don't need to do that). I would not raise my hope of having them do the PR. For me I would rather do what @282931 is doing which is replace the body.arrayBuffer() with body.blob() then turn that into arrayBuffer. Though that would mean some form of detection of whether this is RN.

That is what I do for my ipfs implementation. so I can still use the same 'helper' calls be it RN or browser(but I don't care about node.js backend nor service worker for me, so I just test existence of window object, probably harder for this as it is supposed to cover broader usages)

@ricmoo
Copy link
Member

ricmoo commented Aug 25, 2020

Sorry... I have lots of questions. :)

If it works (or fails) on one react-native, will it work (or fail) on all?

Like if I set up the CI to create a demo app on a macOS instance will it adequately test whether it would work on iOS or on Android? Or is it possible the .arrayBuffer works on macOS and not on Android?

@garyng2000
Copy link

my experience(limited though) in Expo is still need to test separately on iPhone and Android phone(I don't know about emulator and found it to be more troublesome to setup), there can be subtle difference which don't show up until it is run on the device. That is why I opt for re-implementation using the common denominator :-(

@282931
Copy link
Author

282931 commented Aug 26, 2020

arrayBuffer not work on all platform. react-native has not implemented this method yet:
https://github.com/facebook/react-native/blob/master/Libraries/Blob/FileReader.js#L84-L86
if you do this:

const result=await fetch('https://testtesttest.com')
const body=result.arrayBuffer();

it just throw the Error: FileReader.readAsArrayBuffer is not implemented

@ricmoo
Copy link
Member

ricmoo commented Aug 26, 2020

@282931 I've fixed this by adding this shim: facebook/react-native#21209

I'm working on a test suite right now that will validate all features work in React Native (with the shim). I just need to make an App that embeds my test suite. I'm close...

@ricmoo
Copy link
Member

ricmoo commented Aug 26, 2020

(oh an macOS seems to adequately fail where needed, so I can test ;))

@ricmoo ricmoo added the on-deck This Enhancement or Bug is currently being worked on. label Aug 26, 2020
@ricmoo
Copy link
Member

ricmoo commented Sep 5, 2020

Can you try updating to 5.0.10 and using the shim provided?

They should make RN happier. The tests also currently build and run entire test suite inside an iOS simulator during the CI, so these issues should be caught before being published in the future. :)

@ricmoo ricmoo added fixed/complete This Bug is fixed or Enhancement is complete and published. and removed on-deck This Enhancement or Bug is currently being worked on. labels Sep 5, 2020
@manoj398
Copy link

manoj398 commented Sep 5, 2020

How to use shims in v5? shims are not bundled with ethers package right?

I am using this way, import '@ethersproject/shims/dist'.
Does installing this package is necessary?

Btw, fetch is working after updating to 5.0.10 and after using this shim

@garyng2000
Copy link

@manoj398,
I am also puzzled by this shim thing when use ethers.js in the context of Expo. Don't even know where it should be loaded(and from where).
I didn't need to do anything in 5.0.5, so what is what is suggested the right way to 'load the shim' ?

@ricmoo
Copy link
Member

ricmoo commented Sep 5, 2020

I don’t know much about expo. I just spent enough time learning React Native And it’s source code enough to get tests running and all the internal libraries working properly in React Native.

Is Expo the same as RN, based on JavaScriptCore with many (but not all) common web API’s?

The main change was that ethers now uses the binary fetch API features, which RN does not support. So the main goal of the shim is to add request.arrayBuffer(). If expo properly fills in the API though, the shims likely are not necessary. :)

@garyng2000
Copy link

Expo is a wrapper of RN, it is the 'where to load the shim' that I is a bit different. and also, where is the shim if I just do 'npm install ethers.js'

@ricmoo
Copy link
Member

ricmoo commented Sep 6, 2020

@garyng2000

For partial environments (like React Native, and I'm guessing Expo), you also need to do:

/home/ricmoo/project> npm install @ethersproject/shims

And in your code to import ethers, would should import the shims before it:

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

This will shim missing features (only if not present or a broken implementation is detected), such as atob and FileReaders.prototype.readArrayBuffer.

@282931
Copy link
Author

282931 commented Sep 8, 2020

It works,i add the library (@ethersproject/shims) as the first import in index.js file

@manoj398
Copy link

manoj398 commented Sep 8, 2020

error: Error: While trying to resolve module @ethersproject/shims from file D:\User\New folder\GitHub\react-native-starter\src\modules\AppView.tsx, the package D:\User\New folder\GitHub\react-native-starter\node_modules\@ethersproject\shims\package.json was successfully found. However, this package itself specifies a main module field that could not be resolved (D:\User\New folder\GitHub\react-native-starter\node_modules\@ethersproject\shims\lib\index.js. Indeed, none of these files exist:

  • D:\User\New folder\GitHub\react-native-starter\node_modules@ethersproject\shims\lib\index.js(.native|.android.js|.native.js|.js|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx)
  • D:\User\New folder\GitHub\react-native-starter\node_modules@ethersproject\shims\lib\index.js\index(.native|.android.js|.native.js|.js|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx)
    at ResolutionRequest.resolveDependency (D:\User\New folder\GitHub\react-native-starter\node_modules\metro\src\node-haste\DependencyGraph\ResolutionRequest.js:65:15)
    at DependencyGraph.resolveDependency (D:\User\New folder\GitHub\react-native-starter\node_modules\metro\src\node-haste\DependencyGraph.js:287:16)
    at Object.resolve (D:\User\New folder\GitHub\react-native-starter\node_modules\metro\src\lib\transformHelpers.js:267:42)

I get this problem if i just use 'import "@ethersproject/shims"'
works fine with 'import "@ethersproject/shims/dist"'

My env is not expo, but react native 0.63.2

@manoj398
Copy link

manoj398 commented Sep 8, 2020

Also I have this warning while using ethers
image
How to resolve this?

@282931
Copy link
Author

282931 commented Sep 8, 2020

@manoj398 guess you are using the old version @ethersproject/shims which the package.json file not include browser field.
In react-native it resolve the field by this order ''react-native"=>"browser"=>"main"
just update the package will solve the problem.
2nd problem is a android http request timeout warning.You can just ignore it

Exulansis pushed a commit to jolocom/jolo-did-method that referenced this issue Sep 9, 2020
@ricmoo
Copy link
Member

ricmoo commented Sep 11, 2020

@manoj398 Yes, can you try the suggestion by @282931 ? Updating to the most recent version of the shim should fix your import issue.

That error can be safely ignored. There are many work-arounds lying around though. :)

@ricmoo
Copy link
Member

ricmoo commented Sep 12, 2020

Seems like the OP issue is fixed, so I'm. going to close this now. If you still have problems though, please feel free to re-open.

Thanks! :)

@Asthay97
Copy link

Asthay97 commented Nov 7, 2021

5.0.5, though I am not using etherscan and only standard JSONRPC provider(my own). via this

import { ethers } from 'ethers';

Worked for EtherscanProvider as well. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion Questions, feedback and general information. fixed/complete This Bug is fixed or Enhancement is complete and published.
Projects
None yet
Development

No branches or pull requests

8 participants