Skip to content

Commit

Permalink
Merge all of internal /js (#85)
Browse files Browse the repository at this point in the history
* Merge internal into public

* Port over changes from WalletLinkRelay needed for new UI

* Merge all of /js

* Handle in page provider (#54)

* WIP - Show correct dialog UI based on feature flag

* Use in page provider if available

* Override setAppInfo.  Implement setting chain id and custom rpc url.

* Fix formatting

* Add ability to set provider info to wallet link provider

* Add setAppInfo method to provider

* Fix lint error

* Fix typo

* Remove non-working feature flag code

* Revert "Remove non-working feature flag code"

This reverts commit 7c2328412b209fc1055c11704683ceb836932c6e.

* Remove todo comments

Co-authored-by: Alex Shoykhet <alex.shoykhet@coinbase.com>

* Merge chainId fix, initialize relay if eip1102 already authorized

* Remove console\.error

Co-authored-by: Alex Shoykhet <alex.shoykhet@coinbase.com>
Co-authored-by: Vishnu Madhusoodanan <vishnu.madhusoodanan@coinbase.com>
  • Loading branch information
3 people committed Apr 22, 2021
1 parent c02816c commit 6f73706
Show file tree
Hide file tree
Showing 14 changed files with 448 additions and 143 deletions.
66 changes: 59 additions & 7 deletions js/src/WalletLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { WalletLinkRelay } from "./relay/WalletLinkRelay"
import { getFavicon } from "./util"
import { WalletLinkUI, WalletLinkUIOptions } from "./provider/WalletLinkUI"
import { WalletLinkSdkUI } from "./provider/WalletLinkSdkUI"
import url from "url"
import { ScopedLocalStorage } from "./lib/ScopedLocalStorage"
import { WalletLinkRelayEventManager } from "./relay/WalletLinkRelayEventManager"

const WALLETLINK_URL =
process.env.WALLETLINK_URL! || "https://www.walletlink.org"
Expand All @@ -29,6 +32,8 @@ export interface WalletLinkOptions {
walletLinkUIConstructor?: (
options: Readonly<WalletLinkUIOptions>
) => WalletLinkUI
/** @optional whether wallet link provider should override the isMetaMask property. */
overrideIsMetaMask?: boolean
}

export class WalletLink {
Expand All @@ -39,13 +44,17 @@ export class WalletLink {

private _appName = ""
private _appLogoUrl: string | null = null
private _relay: WalletLinkRelay
private _relay: WalletLinkRelay | null = null
private _relayEventManager: WalletLinkRelayEventManager | null = null
private _storage: ScopedLocalStorage
private _overrideIsMetaMask: boolean

/**
* Constructor
* @param options WalletLink options object
*/
constructor(options: Readonly<WalletLinkOptions>) {
let walletLinkUrl = options.walletLinkUrl || WALLETLINK_URL
let walletLinkUIConstructor: (
options: Readonly<WalletLinkUIOptions>
) => WalletLinkUI
Expand All @@ -55,11 +64,29 @@ export class WalletLink {
walletLinkUIConstructor = options.walletLinkUIConstructor
}

if (typeof options.overrideIsMetaMask === "undefined") {
this._overrideIsMetaMask = false
} else {
this._overrideIsMetaMask = options.overrideIsMetaMask
}

const u = url.parse(walletLinkUrl)
const walletLinkOrigin = `${u.protocol}//${u.host}`
this._storage = new ScopedLocalStorage(`-walletlink:${walletLinkOrigin}`)

if (typeof window.walletLinkExtension !== "undefined") {
return
}

this._relayEventManager = new WalletLinkRelayEventManager()

this._relay = new WalletLinkRelay({
walletLinkUrl: options.walletLinkUrl || WALLETLINK_URL,
walletLinkUrl: walletLinkUrl,
version: WALLETLINK_VERSION,
darkMode: !!options.darkMode,
walletLinkUIConstructor: walletLinkUIConstructor
walletLinkUIConstructor: walletLinkUIConstructor,
storage: this._storage,
relayEventManager: this._relayEventManager
})
this.setAppInfo(options.appName, options.appLogoUrl)
this._relay.attachUI()
Expand All @@ -75,10 +102,25 @@ export class WalletLink {
jsonRpcUrl: string,
chainId: number = 1
): WalletLinkProvider {
if (typeof window.walletLinkExtension !== "undefined") {
//@ts-ignore
window.walletLinkExtension.setProviderInfo(jsonRpcUrl, chainId)

return window.walletLinkExtension
}

const relay = this._relay
if (!relay || !this._relayEventManager || !this._storage) {
throw new Error("Relay not initialized, should never happen")
}

return new WalletLinkProvider({
relay: this._relay,
relayProvider: () => Promise.resolve(relay),
relayEventManager: this._relayEventManager,
storage: this._storage,
jsonRpcUrl,
chainId
chainId,
overrideIsMetaMask: this._overrideIsMetaMask
})
}

Expand All @@ -93,14 +135,24 @@ export class WalletLink {
): void {
this._appName = appName || "DApp"
this._appLogoUrl = appLogoUrl || getFavicon()
this._relay.setAppInfo(this._appName, this._appLogoUrl)

if (typeof window.walletLinkExtension !== "undefined") {
//@ts-ignore
window.walletLinkExtension.setAppInfo(this._appName, this._appLogoUrl)
} else {
this._relay?.setAppInfo(this._appName, this._appLogoUrl)
}
}

/**
* Disconnect. After disconnecting, this will reload the web page to ensure
* all potential stale state is cleared.
*/
public disconnect(): void {
this._relay.resetAndReload()
if (typeof window.walletLinkExtension !== "undefined") {
window.walletLinkExtension.close()
} else {
this._relay?.resetAndReload()
}
}
}
80 changes: 63 additions & 17 deletions js/src/components/LinkFlow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
// Licensed under the Apache License, version 2.0

import { h, render } from "preact"
import { Observable, Subscription } from "rxjs"
import { BehaviorSubject, Observable, Subscription } from "rxjs"
import { LinkDialog } from "./LinkDialog"
import { first } from "rxjs/operators"
import { TryExtensionLinkDialog } from "./TryExtensionLinkDialog"

export interface LinkFlowOptions {
darkMode: boolean
Expand All @@ -16,6 +18,10 @@ export interface LinkFlowOptions {
connected$: Observable<boolean>
}

interface Optional<T> {
value?: T
}

export class LinkFlow {
private readonly darkMode: boolean
private readonly version: string
Expand All @@ -25,6 +31,9 @@ export class LinkFlow {
private readonly isParentConnection: boolean

private readonly connected$: Observable<boolean>
private readonly extensionUI$: BehaviorSubject<
Optional<boolean>
> = new BehaviorSubject({})
private readonly subscriptions = new Subscription()

private isConnected = false
Expand All @@ -41,6 +50,21 @@ export class LinkFlow {
this.walletLinkUrl = options.walletLinkUrl
this.isParentConnection = options.isParentConnection
this.connected$ = options.connected$

// Check if extension UI is enabled
fetch("https://api.wallet.coinbase.com/rpc/v2/getFeatureFlags")
.then(res => res.json())
.then(json => {
const enabled: boolean | undefined = json.result.desktop.extension_ui
if (typeof enabled === "undefined") {
this.extensionUI$.next({ value: false })
} else {
this.extensionUI$.next({ value: enabled })
}
})
.catch(err => {
this.extensionUI$.next({ value: false })
})
}

public attach(el: Element): void {
Expand Down Expand Up @@ -85,21 +109,43 @@ export class LinkFlow {
return
}

// TODO - Vishnu: Use feature flag to show correct dialog UI

render(
<LinkDialog
darkMode={this.darkMode}
version={this.version}
sessionId={this.sessionId}
sessionSecret={this.sessionSecret}
walletLinkUrl={this.walletLinkUrl}
isOpen={this.isOpen}
isConnected={this.isConnected}
isParentConnection={this.isParentConnection}
onCancel={this.onCancel}
/>,
this.root
)
const subscription = this.extensionUI$
.pipe(first(enabled => enabled.value !== undefined)) // wait for a valid value before rendering
.subscribe(enabled => {
if (!this.root) {
return
}

render(
enabled.value! ? (
<TryExtensionLinkDialog
darkMode={this.darkMode}
version={this.version}
sessionId={this.sessionId}
sessionSecret={this.sessionSecret}
walletLinkUrl={this.walletLinkUrl}
isOpen={this.isOpen}
isConnected={this.isConnected}
isParentConnection={this.isParentConnection}
onCancel={this.onCancel}
/>
) : (
<LinkDialog
darkMode={this.darkMode}
version={this.version}
sessionId={this.sessionId}
sessionSecret={this.sessionSecret}
walletLinkUrl={this.walletLinkUrl}
isOpen={this.isOpen}
isConnected={this.isConnected}
isParentConnection={this.isParentConnection}
onCancel={this.onCancel}
/>
),
this.root
)
})

this.subscriptions.add(subscription)
}
}
5 changes: 4 additions & 1 deletion js/src/components/TryExtensionLinkDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ export const TryExtensionLinkDialog: FunctionComponent<{
>
<TryExtensionBox
onInstallClick={() => {
// TODO - Vishnu: Redirect users to extension download page
window.open(
"https://api.wallet.coinbase.com/rpc/v2/desktop/chrome",
"_blank"
)
}}
/>
<ScanQRBox
Expand Down
1 change: 1 addition & 0 deletions js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ declare global {
WalletLink: typeof WalletLink
WalletLinkProvider: typeof WalletLinkProvider
ethereum?: WalletLinkProvider
walletLinkExtension?: WalletLinkProvider
}
}

Expand Down
Loading

0 comments on commit 6f73706

Please sign in to comment.