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: Connection Failure' on Android/iOS connection to custom LWS server- Cannot connect/create wallets #26

Open
1 task
CryptoGrampy opened this issue May 19, 2022 · 15 comments
Assignees

Comments

@CryptoGrampy
Copy link

Description

Connecting the latest Android/iOS MyMonero wallet to my custom LWS server results in an Error: Connection Failure alert when creating a new wallet. The Desktop app does seem to have a 500 error upon saving the custom server url, but seems to function totally fine (can create wallets / send tx's) despite this error. Additionally, the Android wallet is definitely calling the server (seeing some communication happening in the LWS logs, but no errors).

  • Can you reproduce the issue?

Steps to reproduce

  1. Specify my custom LWS URL in settings: https://mylws.myserver.myhost.com - there is a 'Connection Failure' error on saving the server address on Android, however there is an 'Unknown 500 error' when saving the LWS address from the desktop wallet.
  2. Create a new wallet
  3. Press 'Confirm' button on the Verify your mnemonic screen
  4. Yellow connection failure alert pops up on the top, and wallet does not get created. On desktop wallet, the wallet gets created totally fine and can send tx's.

Expected behavior:

I expect a wallet to get created.

Actual behavior:

Remains on the Verify your mnemonic screen with the error at the top

Versions

  • Mark Text version: 1.2.1 (I'm using the latest version from Github release, but the 'About MyMonero' says 1.2.1)
  • Operating system: Android/iOS

One thing that seemed to be a little different from the Desktop app was the request headers:

Android:

2022-05-19 05:29:52.424 T HTTP HEAD:
2022-05-19 05:29:52.424 T Host: customlws.cool.grampyserver.com
2022-05-19 05:29:52.424 T User-Agent: Mozilla/5.0 (Linux; Android 12; Pixel 3 XL Build/SP2A.220505.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.127 Mobile Safari/537.36
2022-05-19 05:29:52.424 T Accept: */*
2022-05-19 05:29:52.424 T Accept-Encoding: gzip, deflate
2022-05-19 05:29:52.424 T Accept-Language: en-US,en;q=0.9
2022-05-19 05:29:52.424 T Access-Control-Request-Headers: content-type
2022-05-19 05:29:52.424 T Access-Control-Request-Method: POST
2022-05-19 05:29:52.424 T Origin: https://com.mymonero.android
2022-05-19 05:29:52.424 T Referer: https://com.mymonero.android/
2022-05-19 05:29:52.424 T Sec-Fetch-Dest: empty
2022-05-19 05:29:52.424 T Sec-Fetch-Mode: cors
2022-05-19 05:29:52.424 T Sec-Fetch-Site: cross-site

Desktop:

2022-05-19 05:32:55.274 T HTTP HEAD:
2022-05-19 05:32:55.274 T Host: customlws.cool.grampyserver.com
2022-05-19 05:32:55.274 T User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) MyMonero/1.2.7 Chrome/83.0.4103.122 Electron/9.4.4 Safari/537.36
2022-05-19 05:32:55.274 T Content-Length: 74
2022-05-19 05:32:55.274 T Accept: application/json
2022-05-19 05:32:55.274 T Accept-Encoding: gzip, deflate, br
2022-05-19 05:32:55.274 T Accept-Language: en-US
2022-05-19 05:32:55.274 T Content-Type: application/json
2022-05-19 05:32:55.274 T Sec-Fetch-Dest: empty
2022-05-19 05:32:55.274 T Sec-Fetch-Mode: cors
2022-05-19 05:32:55.274 T Sec-Fetch-Site: cross-site
@devinpearson
Copy link
Contributor

Will take a look into this.

Will also check that the version numbers are updated correctly in app

@CryptoGrampy
Copy link
Author

Just want to share that I tested the latest 1.2.4 release on Android and it still does not connect to my custom lws server. I'm using VDO's monero-lws image vdo1138/monero-lws:0.17-15bce7f with Docker and Traefik. Having no issues connecting from the Desktop app, but the mobile app does not seem to recognize the server correctly when entering it into the custom server input (still shows an error).

@karlbuys
Copy link
Collaborator

Hi @CryptoGrampy

Thank you for all the rigorous testing and for the feedback.

Would you be opposed to sharing a URL for your LWS instance that I can use for debugging, please? I would greatly appreciate it, and would be able to get straight onto debugging much faster than if I was to have to sync the blockchain to a local image.

@karlbuys karlbuys self-assigned this Jun 14, 2022
@CryptoGrampy
Copy link
Author

CryptoGrampy commented Jun 14, 2022

Hi @karlbuys - I temporarily set up a custom LWS server you can test with- please reach out to me on Matrix for details: @CryptoGrampy:monero.social

@CryptoGrampy
Copy link
Author

CryptoGrampy commented Jul 1, 2022

@karlbuys @devinpearson I was able to successfully connect my Android app to my custom LWS server by replacing @mymonero/mymonero-net-service-utils/index.js code with:

const http = require('@capacitor-community/http')

function New_ParametersForWalletRequest (address, view_key__private) {
  return {
    address: address,
    view_key: view_key__private
  }
}
exports.New_ParametersForWalletRequest = New_ParametersForWalletRequest

function AddUserAgentParamters (parameters, appUserAgent_product, appUserAgent_version) {
  // setting these on params instead of as header field User-Agent so as to retain all info found in User-Agent, such as platform… and these are set so server has option to control delivery
  parameters['app_name'] = appUserAgent_product
  parameters['app_version'] = appUserAgent_version
}
exports.AddUserAgentParamters = AddUserAgentParamters

function HTTPRequest (
  request_conformant_module, // such as 'request' or 'xhr' .. TODO: consider switching to 'fetch'
  apiAddress_authority, // authority means [subdomain.]host.…[:…] with no trailing slash
  endpointPath,
  final_parameters,
  fn
) {
  // fn: (err?, data?) -> new Request
  if (typeof final_parameters === 'undefined' || final_parameters == null) {
    throw 'final_parameters must not be nil'
    // return null
  }
  const completeURL = apiAddress_authority + endpointPath
  console.log('📡  ' + completeURL)
  //
  const request_options = _new_requestOptions_base(
    'POST',
    completeURL,
    final_parameters
  )

  console.log('final params', JSON.stringify(final_parameters))

  const err_orProgressEvent = 'blah'
  const requestHandle = http.Http.request({
    method: 'POST',
    url: completeURL,
    headers: {
      'Content-Type': 'application/json',
      Accept: 'application/json'
    },  
    data: JSON.stringify(final_parameters)
  }).then(res => {
    _new_HTTPRequestHandlerFunctionCallingFn(fn)(
      // <- called manually instead of directly passed to request_conformant_module call to enable passing completeURL
      completeURL,
      err_orProgressEvent,
      res,
      res.data
    )
  })

  // const old_requestHandle = request_conformant_module(
  //   request_options,
  //   function (err_orProgressEvent, res, body) {
  //     _new_HTTPRequestHandlerFunctionCallingFn(fn)(
  //       // <- called manually instead of directly passed to request_conformant_module call to enable passing completeURL
  //       completeURL,
  //       err_orProgressEvent,
  //       res,
  //       body
  //     )
  //   }
  // )
  
  return requestHandle
}
exports.HTTPRequest = HTTPRequest

function _new_APIAddress_baseURLString (
  apiAddress_authority // authority means [subdomain.]host.…[:…]
) {
  return apiAddress_authority
}

function _new_requestOptions_base (methodName, completeURL, json_parameters) {
  return {
    method: methodName,
    url: completeURL,
    headers: {
      'Content-Type': 'application/json',
      Accept: 'application/json'
    },
    json: json_parameters,
    useXDR: true, // CORS
    withCredentials: true // CORS
  }
}

function _new_HTTPRequestHandlerFunctionCallingFn (fn) {
  return function (completeURL, err_orProgressEvent, res, body) {
    // err appears to actually be a ProgressEvent
    var err = null
    const statusCode = typeof res !== 'undefined' ? res.status : -1
    if (statusCode == 0 || statusCode == -1) {
      // we'll treat 0 as a lack of internet connection.. unless there's a better way to make use of err_orProgressEvent which is apparently going to be typeof ProgressEvent here
      err = new Error('Connection Failure')
    } else if (statusCode !== 200) {
      const body_Error =
				body && typeof body === 'object' ? body.Error : undefined
      const statusMessage =
				res && res.status ? res.status : undefined
      if (typeof body_Error !== 'undefined' && body_Error) {
        err = new Error(body_Error)
      } else if (typeof statusMessage !== 'undefined' && statusMessage) {
        err = new Error(statusMessage)
      } else {
        err = new Error('Unknown ' + statusCode + ' error')
      }
    }
    if (err) {
      console.error('❌  ' + err)
      // console.error("Body:", body)
      fn(err, null)
      return
    }
    var json
    if (typeof body === 'string') {
      console.log('body', body)
      try {
        json = JSON.parse(body)
      } catch (e) {
        console.error(
          '❌  HostedMoneroAPIClient Error: Unable to parse json with exception:',
          e,
          '\nbody:',
          body
        )
        fn(e, null)
      }
    } else {
      json = body
    }
    console.log('✅  ' + completeURL + ' ' + statusCode)
    fn(null, json)
  }
}

Basically replaced the existing http req library with the native http request library provided by the capacitor dependency at the top. This library needs to be installed in the net-service-utils folder (package.json). I believe Capacitor is building a standardized, non-community version of this lib in the near future as well. It's probably better than the library that's in there that hasn't been updated in 2 years 😛 .

I roughly added this in. You'll have to take a look at the gross callback stuff that happens after the .then( and see if I implemented that correctly. Wasn't sure what to do with that errOrOnProgress variable.

Was able to receive transactions as well. Haven't tested sending yet.

@devinpearson
Copy link
Contributor

Awesome. Will give it a spin and add it to the apps

@CryptoGrampy
Copy link
Author

Link to the official plugin that is in-progress: ionic-team/capacitor#5145

@CryptoGrampy
Copy link
Author

CryptoGrampy commented Jul 1, 2022

@devinpearson In addition to the instructions above, I needed to run npm install @capacitor-community/http && npx cap sync in the root mymonero-mobile directory for this to work- it looks like this updates a few of the build files with plugin lists etc.

@karlbuys
Copy link
Collaborator

karlbuys commented Jul 4, 2022

@CryptoGrampy thank you for your assistance on this. Very much appreciated. Will look at getting this update into the next release

@sethforprivacy
Copy link

After the update (v1.2.6) that theoretically fixes this I get "http plugin not supported on Android" repeatedly and can't use custom LWS.

@devinpearson
Copy link
Contributor

Will get a fix out for this in the next 24 hours

@sethforprivacy
Copy link

sethforprivacy commented Jul 13, 2022

Will get a fix out for this in the next 24 hours

Tested v1.2.7 with custom LWS and it seems to be working perfectly now! No errors and no issues at all that I can see so far, sync is working properly along with receives.

Edit: Sends are broken ATM.

@sethforprivacy
Copy link

Spoke too soon, new error on sending of "hasPickedContact is not defined" even after I have entered an address and amount -- can't send funds ATM.

@devinpearson
Copy link
Contributor

@sethforprivacy was just about to mention we picked that up. the android version will go out today still to sort that out

@sethforprivacy
Copy link

sethforprivacy commented Jul 14, 2022

@devinpearson yet another bug when sending -- it does send properly but immediately after sending a transaction there is another error popup w/ "Cannot read properties of null (reading 'includes')".

Edit: Also "req.abort is not a function" when re-opening the app after it was closed for a while... Would it make more sense for me to open a new issue to keep reporting these?

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

No branches or pull requests

4 participants