Skip to content

SELF-2650: Add WebView Ethereum bridge PoC with common bridge, Android/iOS implementations, and UI#1989

Merged
transphorm merged 5 commits intodevfrom
codex/prepare-webview-integration-for-self-2650
Apr 18, 2026
Merged

SELF-2650: Add WebView Ethereum bridge PoC with common bridge, Android/iOS implementations, and UI#1989
transphorm merged 5 commits intodevfrom
codex/prepare-webview-integration-for-self-2650

Conversation

@transphorm
Copy link
Copy Markdown
Member

@transphorm transphorm commented Apr 17, 2026

Motivation

  • Provide a proof-of-concept native<->web WebView bridge that exposes a window.ethereum.request-style API to demo provider methods from the sample app.
  • Centralize bridge protocol types and dispatching logic so platform implementations can decode requests, call registered handlers, and return structured responses.
  • Add a small demo UI and HTML page to exercise method calls and error paths from JavaScript through the native registry.

Description

  • Introduces common bridge types and logic in webview/EthereumBridge.kt, including ProviderRequest, ProviderResponse, ProviderError, MethodRegistry, BridgeMethodException, ETHEREUM_BRIDGE_STUB, and BRIDGE_DEMO_HTML.
  • Adds a WebViewBridgeScreen composable that registers demo methods demo_echo and demo_reject and calls PlatformWebViewBridge(registry); declares the expect for the platform implementation.
  • Implements Android WebView bridge in PlatformWebViewBridge.android.kt which wires a WebView, injects the JS stub, registers a JavascriptInterface, decodes ProviderRequest, dispatches to MethodRegistry, and evaluates the response JS callback.
  • Implements iOS WebView bridge in PlatformWebViewBridge.ios.kt using WKWebView and WKScriptMessageHandler, injecting the JS stub and sending responses via evaluateJavaScript.
  • Updates navigation and UI: adds a webview-bridge route in App.kt, and a button on HomeScreen that navigates to the WebView Bridge PoC.

Testing

  • No automated tests were added or run for this change.

Codex Task

Summary by CodeRabbit

  • New Features
    • Added a WebView Bridge screen for native↔web communication with Android and iOS support.
    • Home screen includes an "Open WebView Bridge PoC" button to launch the bridge.
    • Included a demo page showcasing echo, rejection, unknown-method, and concurrent request behaviors with visible results.

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
self-webview-app Ignored Ignored Preview Apr 17, 2026 11:22pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 17, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fb3434ea-b2da-4f6a-aba1-466b284a7990

📥 Commits

Reviewing files that changed from the base of the PR and between e8f7c8f and 6270f76.

📒 Files selected for processing (1)
  • packages/kmp-minipay-sample/composeApp/src/commonMain/kotlin/xyz/self/minipay/webview/EthereumBridge.kt

📝 Walkthrough

Walkthrough

Adds a multiplatform WebView Ethereum bridge: shared request/response models and method registry, a Compose screen and navigation to exercise it, plus platform-specific WebView integrations for Android and iOS that route JS requests to native handlers and return responses.

Changes

Cohort / File(s) Summary
Ethereum Bridge Core
packages/kmp-minipay-sample/composeApp/src/commonMain/kotlin/xyz/self/minipay/webview/EthereumBridge.kt
Adds serializable models (ProviderRequest, ProviderResponse, ProviderError) and ProviderErrorCodes; implements MethodRegistry, BridgeMethodException, JS bootstrap (ETHEREUM_BRIDGE_STUB) and demo HTML (BRIDGE_DEMO_HTML).
Platform WebView Implementations
packages/kmp-minipay-sample/composeApp/src/androidMain/kotlin/xyz/self/minipay/webview/PlatformWebViewBridge.android.kt, packages/kmp-minipay-sample/composeApp/src/iosMain/kotlin/xyz/self/minipay/webview/PlatformWebViewBridge.ios.kt
Adds actual fun PlatformWebViewBridge(registry: MethodRegistry) for Android and iOS. Both set up web views, inject the JS stub, attach native bridge handlers, maintain pendingRequests, deserialize requests, dispatch to MethodRegistry, map exceptions to ProviderResponse, and execute JS to resolve promises.
WebView Bridge Screen
packages/kmp-minipay-sample/composeApp/src/commonMain/kotlin/xyz/self/minipay/screens/WebViewBridgeScreen.kt
New WebViewBridgeScreen composable that remembers a MethodRegistry with demo_echo and demo_reject handlers and calls the multiplatform PlatformWebViewBridge. Adds expect fun PlatformWebViewBridge(registry: MethodRegistry).
Navigation & UI
packages/kmp-minipay-sample/composeApp/src/commonMain/kotlin/xyz/self/minipay/App.kt, packages/kmp-minipay-sample/composeApp/src/commonMain/kotlin/xyz/self/minipay/screens/HomeScreen.kt
Registers new webview-bridge route in navigation; updates HomeScreen signature to accept onOpenWebViewBridge and adds a button to navigate to the bridge demo.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description covers motivation, implementation details across all files, and navigation updates. However, it does not follow the repository's required template structure with 'Summary' and 'Test plan' sections, and the Native Consolidation Checklist is missing. Restructure the description to match the template: add a 'Summary' section, 'Test plan' section, and include the Native Consolidation Checklist with appropriate items checked or removed.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: adding a WebView Ethereum bridge PoC with implementations for both Android and iOS platforms plus UI integration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/prepare-webview-integration-for-self-2650

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 35fdc02225

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 17, 2026

Greptile Summary

This PR adds a proof-of-concept native↔WebView Ethereum bridge to the kmp-minipay-sample app. It introduces shared bridge types and dispatch logic in EthereumBridge.kt, platform actual implementations for Android (JavascriptInterface) and iOS (WKScriptMessageHandler), a WebViewBridgeScreen composable that wires two demo methods, and a navigation entry point on HomeScreen.

The common layer (EthereumBridge.kt, WebViewBridgeScreen.kt, routing, UI) is clean and well-structured. The two platform implementations have issues that affect correctness:

  • Android (P0): ETHEREUM_BRIDGE_STUB is evaluated via evaluateJavascript before loadDataWithBaseURL is called. When the HTML page loads, it creates a new document context, discarding the previously injected window.ethereum object. Every demo button will throw at runtime. The fix is to inject the stub in WebViewClient.onPageFinished.
  • iOS (P1): sendResponseToJs uses a manual string-escaping chain that omits Unicode line terminators (\u2028, \u2029), which are valid in JSON but are statement terminators in JavaScript string literals. Responses containing these characters will produce a syntax error in evaluateJavaScript, leaving the pending promise unresolved. The Android side already uses JSONObject.quote() correctly.
  • iOS (P1): addScriptMessageHandler retains the handler strongly, creating a WKWebView → userContentController → IosEthereumBridge → WKWebView retain cycle and leaking the bridge for the lifetime of the view.
  • Both (P2): The pendingRequests map is effectively inert — MethodRegistry.dispatch is synchronous, so the stored callback is always invoked in the same call-stack frame it was stored.

Confidence Score: 2/5

Not safe to merge — the Android demo is non-functional due to stub injection ordering, and the iOS implementation has an incomplete escaping chain and a memory leak.

The common layer is solid, but both platform implementations have concrete correctness problems: the Android bridge produces a broken demo (P0 — window.ethereum is undefined at runtime), and the iOS implementation has an escaping bug that causes silent failures on valid JSON responses plus a retain cycle memory leak.

PlatformWebViewBridge.android.kt (P0 stub injection order) and PlatformWebViewBridge.ios.kt (P1 escaping + retain cycle) need fixes before this PoC can be considered functional.

Important Files Changed

Filename Overview
packages/kmp-minipay-sample/composeApp/src/androidMain/kotlin/xyz/self/minipay/webview/PlatformWebViewBridge.android.kt Android WebView bridge — critical bug: stub injected before page load so window.ethereum is absent in the demo HTML; also contains a non-functional pendingRequests map and misleading package declaration.
packages/kmp-minipay-sample/composeApp/src/iosMain/kotlin/xyz/self/minipay/webview/PlatformWebViewBridge.ios.kt iOS WKWebView bridge — stub injection via WKUserScript is correct, but sendResponseToJs uses incomplete manual escaping (missing \u2028/\u2029) and the message handler creates a WKWebView retain cycle.
packages/kmp-minipay-sample/composeApp/src/commonMain/kotlin/xyz/self/minipay/webview/EthereumBridge.kt Common bridge types, JS stub, and demo HTML — well-structured; MethodRegistry.dispatch correctly handles both BridgeMethodException and generic exceptions via Result.fold.
packages/kmp-minipay-sample/composeApp/src/commonMain/kotlin/xyz/self/minipay/screens/WebViewBridgeScreen.kt Composable screen that registers demo_echo / demo_reject handlers and declares expect fun PlatformWebViewBridge — clean and straightforward.
packages/kmp-minipay-sample/composeApp/src/commonMain/kotlin/xyz/self/minipay/App.kt Adds webview-bridge route and wires onOpenWebViewBridge callback — minimal, correct change.
packages/kmp-minipay-sample/composeApp/src/commonMain/kotlin/xyz/self/minipay/screens/HomeScreen.kt Adds a "Open WebView Bridge PoC" button wired to onOpenWebViewBridge — straightforward UI addition with no issues.

Sequence Diagram

sequenceDiagram
    participant JS as WebView JS<br/>(BRIDGE_DEMO_HTML)
    participant Stub as window.ethereum<br/>(ETHEREUM_BRIDGE_STUB)
    participant Native as Native Bridge<br/>(Android/iOS)
    participant Registry as MethodRegistry

    JS->>Stub: ethereum.request({ method, params })
    Stub->>Stub: assign id, store {resolve,reject} in pending map
    Stub->>Native: postMessage / webkit.messageHandlers (JSON)
    Native->>Native: decodeFromString ProviderRequest
    Native->>Registry: dispatch(request)
    Registry->>Registry: lookup handler
    alt handler found
        Registry-->>Native: ProviderResponse(result)
    else handler not found
        Registry-->>Native: ProviderResponse(error: UNKNOWN_METHOD)
    end
    Native->>Native: encodeToString(response)
    Native->>JS: evaluateJavascript window.__selfEthereumResolve
    JS->>Stub: __selfEthereumResolve(responseJson)
    Stub->>Stub: JSON.parse, lookup pending entry
    alt success
        Stub->>JS: resolve(result)
    else error
        Stub->>JS: reject(providerError)
    end
Loading

Reviews (1): Last reviewed commit: "Merge branch 'dev' into codex/prepare-we..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b32f47c0-eb3a-4854-939d-dcfd187d18b1

📥 Commits

Reviewing files that changed from the base of the PR and between b51ea30 and 35fdc02.

📒 Files selected for processing (6)
  • packages/kmp-minipay-sample/composeApp/src/androidMain/kotlin/xyz/self/minipay/webview/PlatformWebViewBridge.android.kt
  • packages/kmp-minipay-sample/composeApp/src/commonMain/kotlin/xyz/self/minipay/App.kt
  • packages/kmp-minipay-sample/composeApp/src/commonMain/kotlin/xyz/self/minipay/screens/HomeScreen.kt
  • packages/kmp-minipay-sample/composeApp/src/commonMain/kotlin/xyz/self/minipay/screens/WebViewBridgeScreen.kt
  • packages/kmp-minipay-sample/composeApp/src/commonMain/kotlin/xyz/self/minipay/webview/EthereumBridge.kt
  • packages/kmp-minipay-sample/composeApp/src/iosMain/kotlin/xyz/self/minipay/webview/PlatformWebViewBridge.ios.kt

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 232769be-0768-447c-a1a9-2e541c04e55e

📥 Commits

Reviewing files that changed from the base of the PR and between 35fdc02 and e8f7c8f.

📒 Files selected for processing (3)
  • packages/kmp-minipay-sample/composeApp/src/androidMain/kotlin/xyz/self/minipay/webview/PlatformWebViewBridge.android.kt
  • packages/kmp-minipay-sample/composeApp/src/commonMain/kotlin/xyz/self/minipay/webview/EthereumBridge.kt
  • packages/kmp-minipay-sample/composeApp/src/iosMain/kotlin/xyz/self/minipay/webview/PlatformWebViewBridge.ios.kt
✅ Files skipped from review due to trivial changes (1)
  • packages/kmp-minipay-sample/composeApp/src/androidMain/kotlin/xyz/self/minipay/webview/PlatformWebViewBridge.android.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/kmp-minipay-sample/composeApp/src/iosMain/kotlin/xyz/self/minipay/webview/PlatformWebViewBridge.ios.kt

@transphorm transphorm changed the title Add WebView Ethereum bridge PoC with common bridge, Android/iOS implementations, and UI SELF-2650: Add WebView Ethereum bridge PoC with common bridge, Android/iOS implementations, and UI Apr 17, 2026
@transphorm transphorm merged commit dee6eba into dev Apr 18, 2026
28 checks passed
@transphorm transphorm deleted the codex/prepare-webview-integration-for-self-2650 branch April 18, 2026 05:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant