Closed Reckless-Satoshi closed 2 years ago
Currently under development: https://github.com/Reckless-Satoshi/robosats/pull/170
Encountering issues that require help from more experienced developers:
Special thanks and compensation (Sats) available to anyone that can help the embedded Android app work well with native tor.
For JS injection and message handling we could learn of what Hampus did for WebLN in Webview apps. https://github.com/hsjoberg/react-native-webln maybe even build a wrapper package "react-native-torified-webview" that can be helpful for other projects and be better maintained.
Other things that must be done for a functional and useful Android App:
Bumping total rewards on this task x2 (from 1M to 2M Sats)
Hello @Reckless-Satoshi ,I think I can start with fixing react-router
Hello @Reckless-Satoshi ,I think I can start with fixing react-router
Assigned you. This task is pretty hard for a newbie like me. Ongoing work with everything needed to build/develop the Android App is in this branch https://github.com/Reckless-Satoshi/robosats/tree/android-webview-app-ts check /mobile/setup.md for my findings on how to setup a react-native development environment and build the webview app.
Will leave here some hints that @hsjoberg left on the Blixt wallet group to achieve a torified webview:
I don't know how react-native-webview does it, but in general, react-native uses OkHttp to handle web traffic. It's used by for example the Javascript fetch function.
So OkHttp has to be re-configured to run via the SOCKS proxy. Here is some code that I started working on before I ran into other things
class CustomNetworkModule implements OkHttpClientFactory { public OkHttpClient createNewNetworkModuleClient() { return new OkHttpClient.Builder() .cookieJar(new ReactCookieJarContainer()) .setProxy$okhttp(new Proxy(null, null)) .build(); } }
This would be done in MainActivity.java for the application in question, not in a react-native-torified-webview lib
I never got it to work properly but you should be able to set a new client with:
com.facebook.react.modules.network.OkHttpClientProvider.setOkHttpClientFactory();
...or something like that.I'm not sure the JS injection path you are taking about on GitHub is feasible because of security policies and whatnot that browsers often have. But yes I've had that thought too.
I think the proper fix has to be to take control over the traffic and make sure it's proxied via SOCKS.
OkHttp is used in react-native. But. Actually it's probably not true for the react-native-webview, because it makes use of the Android WebView component
@Reckless-Satoshi I think the main point on loading the local bundle is based on this line https://github.com/Reckless-Satoshi/robosats/pull/170/files#diff-c92a46984ef937c6501f1fa10feebdf928270c5f2fbd7fe7b24aee34812a9c2cR24, but the URL doesn't seem to exist anymore 😅 Any other suggestion? do you think should I just start from scratch?
@Reckless-Satoshi I think the main point on loading the local bundle is based on this line https://github.com/Reckless-Satoshi/robosats/pull/170/files#diff-c92a46984ef937c6501f1fa10feebdf928270c5f2fbd7fe7b24aee34812a9c2cR24
I think this URL only was interesting because it was a general solution that would work in both Android and iOS. I managed to access the content on that URL exported as PDF here
I have been working on this and I would like to share what I have learned so far and expose the actual situation I'm facing. I explored 2 different ways for doing this, each of them with their own issues, so I'll try to expose them here the best I can:
I have been trying to make this work, but looks like webview doesn't really likes to deal with directly Tor, there is still the possibility to overwrite the Http2 calls but as far I have seen, there is no clear solution for that.
The JS load is something unrelated to the Tor API requests, so far it's working fine and I found way less problems than expected.
That lead us to 2 posibilities:
This was the original approach. It actually works pretty well because I designed the Tor calls on a way it's independent from the JS source location.
window.location
Webpack can be configured to deploy the front-end to the /mobile
folder so the JS code will stay inside of the App, that will help to create specific conditions on the code to deal better with the special cases on Android.
Let's have a talk! I would love to hear different oppinions
Thanks a lot for this update and the work you are putting into getting the Android app done!
Build the JS inside the App
CONS
Android will have his own controlled versions and releases, which lead us to be careful on the back-end and be retro-compatible and news featres won't appear automatically.
The specific configuration and implementations for Android are there as part of the main JS build
Working locally has his own issues on WebView
I believe bundling the react.JS app inside the Android app is the way to go.
The fact that backend and Android app will have to be versioned and updated at the same time is already contemplated https://github.com/Reckless-Satoshi/robosats/issues/241 . We will hardcode the version of the react.JS app, and fetch from /api/info the version of the backend. If there is a mistmatch on major+minor (x.x.0), a Dialog will show with an explanation on how to keep RoboSats android client updated. We can release small patches (-.-.x) that won't trigger the Update dialog (can be done whenever the Backend API is still fully compatible).
What are the issues this approach has with the WebView? I was able to bundle the main.js with the app.apk, it worked except for the react-router (the bottom bar was there, but the UserGenPage did not render. What I did was to place main.js into /mobile/html/Web.bundle/frontend/main.js
and in App.tsx set source={{ html: htmlPath }}
on <WebView/>
For the record and answering @Reckless-Satoshi I'll leave here the issues I'm working on:
https://github.com/react-native-webview/react-native-webview/issues/2643#issuecomment-1250315133 It seems to be an issue on react-native-webview
. When loading the build using Web.bundle
, cookies are not available.
Using https://github.com/Reckless-Satoshi/robosats/pull/247/files#diff-167fc1803bf1acdbd0d427666ac0f21ada0aecdae06acca7029fc8495c49fa7eR3 we can send and obtain the cookies information from Android's local storage.
https://github.com/Reckless-Satoshi/robosats/pull/247/files#diff-d051bd00dd2196f76966e30471e3d9d9644b5026ef8d30e7f0b1bbe6113eebe9R206
while the avatar image loads properly everywhere, when loading it with MUI Avatar
doesn't work, so it doesn't triggers and set avatarLoaded
to true
. It also fails even loading the JS from https://robosats.onion.moe .
Stop using MUI Avatar and use https://github.com/Reckless-Satoshi/robosats/blob/1771b4d18a4826f5aa36ece7953aeaa7d80138e2/frontend/src/components/Robots/RobotAvatar/index.tsx, which seems to work. We can do a fetch
to the avatar URL and set avatarLoaded
to true
once the request succeeds.
https://github.com/Reckless-Satoshi/robosats/pull/247/files#diff-a3ab21f543adced6d1570ef4288a66c0f02a7f1d606265b398a5c8bc5ec97f76R83 Some external sources requires dynamic calculations so I have to find a way to obtain this throught Tor
Didn't tried yet but probably with Tor we can just obtain the Blob.
Related with previous issue, as an example the i18n
json files, which also requires a specific configuration to deal with the i18n
library. Looks like the fetch
action does not allow access to urls with files://
protocol
Fetch API cannot load file:///android_asset/my_wasm_file.wasm. URL scheme "file" is not supported.
https://github.com/react-native-webview/react-native-webview/issues/1560
So far the only case is i18n
so I'm considering configuring webpack to bundle the json files only for the android build.
react-native-tor
does not implement PUTThis is complicated, I can only figure out 2 solutions:
I also found this https://github.com/Sifir-io/react-native-tor/issues/30#issuecomment-891060913, which is true for my local, I just thought it was related to my connection.
Excellent work! This "torification" is certainly proving to be way more challenging than expected (... and the expectation was for it to be very hard).
This is complicated, I can only figure out 2 solutions:
* Check and create a PR for react-native-tor to include PUT actions * Change our only PUT request to POST (I don't like this one)
Ha! We can simply open an issue in react-native-tor repo and do nothing to fix it for the moment: Android app users won't be able to disable Stealth Invoices, not a big deal. However, we wanted to use more PUT on API v1, it's good to know this is a limitation.
I also found this Sifir-io/react-native-tor#30 (comment), which is true for my local, I just thought it was related to my connection.
Nasty, it reads as if BlueWallet devs gave up on react-native-tor ?
The MUI Avatar
component onLoad is basically a plain html tag <img onLoad={}/>
it should be very generic so it is weird it is not working. In any case, it seems like no image is going to load and all of them will have to be fetch via TOR request as a blob as you suggested....
As for the cookies issues I see you have some clue leading to possible solutions, awesome! :rocket:
Closing this issue. Current steps towards Android torified app in https://github.com/Reckless-Satoshi/robosats/issues/258 and #257
It might be a low hanging fruit to create a tiny react-native webview app wrapping the current webapp. It might also be possible to use react-native-tor https://github.com/Sifir-io/react-native-tor, so the user does not need TOR Browser nor Orbot, but only the .apk.
This could be a good start towards something more versatile and smartphone friendly.