Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Mobile DApp Best Practices (ETHDenver 2018)

Mobile DApp Best Practices (ETHDenver 2018)

Peter Jihoon Kim

February 17, 2018
Tweet

More Decks by Peter Jihoon Kim

Other Decks in Programming

Transcript

  1. Cipher Browser - ETHDenver Cipher Browser A full-featured mobile Ethereum

    wallet & Web 3 DApp browser www.cipherbrowser.com
  2. Cipher Browser - ETHDenver How web3 object is injected (iOS)

    • iOS WebKit provides a built-in way to inject custom JS (WKUserScript) • web3 object is injected right after DOM initialization and before page load • This is very reliable Start navigation/ HTTP request Initialize DOM Receive HTTP response Load document Inject web3 Document ready (window.onload)
  3. Cipher Browser - ETHDenver How web3 object is injected (Android)

    • Android WebView does not provide a way to inject JS before page load • Workaround: To inject web3 before page load, the HTTP request is intercepted and its response body is mutated ◦ <script> containing web3 is injected right after <head> Start navigation/ HTTP request Initialize DOM Receive HTTP response Load document Intercept req, look for <head>, inject <script> containing web3 Document ready (window.onload)
  4. Cipher Browser - ETHDenver Problems with web3 injection on Android

    • Only GET requests for the main page load can be intercepted ◦ Form submissions (POST) can’t be intercepted • <head> tag must be present (without any attributes) • Cookies don’t get loaded • A more reliable and hack-free web3 injection is possible after page load ◦ However, most existing DApps expect web3 object to be available immediately
  5. Cipher Browser - ETHDenver Prefer SPA with AJAX • Prefer

    a single page app that uses AJAX to load or submit data ◦ A SPA is loaded via a single GET request ◦ Only the main page (containing SPA) needs web3 injection • If the DApp has be a backend-rendered multi-page app, ensure responses to form submissions are 302 redirects ◦ This forces browser to issue a GET request to load page content • Use localStorage/sessionStorage to store user data ◦ Cookies don’t get loaded on intercepted pages on Android • Ensure HTML contains <head> (must be exact match) Android: Cookies aren’t loaded on web3-injected pages Android: Responses to form submissions or non-GET requests don’t get web3 injection
  6. Cipher Browser - ETHDenver Do not assume that web3 object

    is available immediately • Instead, poll and wait for it to become available. • In near future, DApp browsers (both mobile and desktop) may only inject web3 when requested by user for privacy
  7. Cipher Browser - ETHDenver Do not assume that web3 object

    is available immediately function checkForWeb3 () { if (window.web3 && web3.currentProvider) { startDApp() return } window.setTimeout(checkForWeb3, 100) } document.addEventListener('load', checkForWeb3, false)
  8. Cipher Browser - ETHDenver • Improper use of filter/log/watch API

    can render app unresponsive and may also inadvertently cause a DoS attack on a node • Instead of relying on events and logs, poll and read blockchain for changes ◦ Do not poll too aggressively (once every 4 or 5 seconds is OK) ◦ Near future: web3.js 1.0 and WebSocket provider will make event tracking easier Avoid Filter/Watch API
  9. Cipher Browser - ETHDenver Polling: Avoid setInterval, use setTimeout •

    setInterval: App is blocked (e.g. in the BG) (Enqueued) (Flushed) • setTimeout: App is blocked (e.g. in the BG)
  10. Cipher Browser - ETHDenver Polling: Avoid setInterval, use setTimeout let

    timer function fn () { if (success) { window.clearInterval(timer) } } timer = window.setInterval(fn, 4000) function fn () { if (success) { return } window.setTimeout(fn, 4000) } fn()
  11. Cipher Browser - ETHDenver Listen for account and network changes

    function checkNetworkAndAccount () { if (web3.eth.accounts[0] !== currentAccount || web3.version.network !== currentNetwork) { handleChange() } window.setTimeout(checkNetworkAndAccount, 1000) } checkNetworkAndAccount()
  12. Cipher Browser - ETHDenver Mobile-friendly user interface • Have a

    fixed, non-zoomable viewport <meta name=”viewport” content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no"> • Create responsive CSS with media queries • Avoid hover (mouseover) actions • Avoid horizontal scrolling
  13. Cipher Browser - ETHDenver Other Recommendations • Don’t open popups

    or new tabs (e.g. <a target=”_blank”>) • Avoid window.alert/confirm/prompt (blocks JS) ◦ Instead, show modal dialogs within the web app • Frequently save app state and restore state when app is reloaded ◦ Use localStorage to persist state ◦ Mobile OSes kill background apps aggressively • Use polyfills for ES6/ES7+ functions! (core-js)
  14. Cipher Browser - ETHDenver Debugging with Chrome Dev Tools 1.

    Enable USB Debugging in Settings 2. Connect with USB 3. Open DApp in Cipher
  15. Cipher Browser - ETHDenver Debugging with Chrome Dev Tools 4.

    Navigate to chrome://inspect/#devices on Chrome browser
  16. Cipher Browser - ETHDenver Have fun building mobile DApps! Cipher

    Browser is available on both iOS App Store and Android Google Play store.