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

feat: Injected Universal Provider #3177

Merged
merged 20 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/appkit/exports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CoreHelperUtil } from '@reown/appkit-core'
import { AppKit } from '../src/client.js'
import type { AppKitOptions } from '../src/utils/TypesUtil.js'
import { PACKAGE_VERSION } from './constants.js'
export { UniversalAdapterClient as UniversalAdapter } from '../src/universal-adapter/client.js'
tomiir marked this conversation as resolved.
Show resolved Hide resolved

// -- Views ------------------------------------------------------------
export * from '@reown/appkit-scaffold-ui'
Expand Down
22 changes: 19 additions & 3 deletions packages/appkit/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,14 @@ export { AccountController }

// -- Types --------------------------------------------------------------------
export interface OpenOptions {
view: 'Account' | 'Connect' | 'Networks' | 'ApproveTransaction' | 'OnRampProviders'
view:
| 'Account'
| 'Connect'
| 'Networks'
| 'ApproveTransaction'
| 'OnRampProviders'
| 'ConnectingWalletConnectBasic'
uri?: string
}

// -- Helpers -------------------------------------------------------------------
Expand Down Expand Up @@ -93,6 +100,10 @@ export class AppKit {
// -- Public -------------------------------------------------------------------
public async open(options?: OpenOptions) {
await this.initOrContinue()
if (options?.uri && this.universalAdapter) {
console.log('options.uri', options.uri)
tomiir marked this conversation as resolved.
Show resolved Hide resolved
ConnectionController.setUri(options.uri)
}
ModalController.open(options)
}

Expand Down Expand Up @@ -546,8 +557,13 @@ export class AppKit {
networks: this.caipNetworks,
defaultNetwork: this.defaultCaipNetwork
}

this.universalAdapter = new UniversalAdapterClient(extendedOptions)
console.log('extendedOptions', extendedOptions)
const providedUniversalAdapter = options.adapters?.find(
a => a instanceof UniversalAdapterClient
) as UniversalAdapterClient
console.log('providedUniversalAdapter', providedUniversalAdapter)
this.universalAdapter = providedUniversalAdapter || new UniversalAdapterClient(extendedOptions)
ConnectionController.state.manualControl = this.universalAdapter.manualControl
ChainController.initializeUniversalAdapter(this.universalAdapter, options.adapters || [])
this.universalAdapter.construct?.(this, extendedOptions)
}
Expand Down
1 change: 1 addition & 0 deletions packages/appkit/src/library/react/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type { ChainNamespace } from '@reown/appkit-common'

type OpenOptions = {
view: 'Account' | 'Connect' | 'Networks' | 'ApproveTransaction' | 'OnRampProviders'
uri?: string
}

type ThemeModeOptions = AppKitOptions['themeMode']
Expand Down
28 changes: 25 additions & 3 deletions packages/appkit/src/universal-adapter/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,22 @@ export class UniversalAdapterClient {

public reportErrors = true

// In manual control, devs provide connection uri & provider instance to the adapter
public manualControl: boolean

public constructor(options: AppKitOptionsWithCaipNetworks) {
const { siweConfig, metadata } = options
const { siweConfig, metadata, manualControl } = options

this.caipNetworks = options.networks

this.chainNamespace = CommonConstantsUtil.CHAIN.EVM

this.metadata = metadata

this.walletConnectProvider = options?.provider

this.manualControl = manualControl || false

this.networkControllerClient = {
// @ts-expect-error switchCaipNetwork is async for some adapter but not for this adapter
switchCaipNetwork: caipNetwork => {
Expand Down Expand Up @@ -125,6 +132,17 @@ export class UniversalAdapterClient {

this.connectionControllerClient = {
connectWalletConnect: async onUri => {
console.log(
'on Connect WalletConnect',
this.manualControl,
ConnectionController.state.wcUri
)
if (this.manualControl && ConnectionController.state.wcUri) {
console.log('on Connect WalletConnect, onUri', ConnectionController.state.wcUri)
onUri(ConnectionController.state.wcUri)

return
}
const WalletConnectProvider = await this.getWalletConnectProvider()

if (!WalletConnectProvider) {
Expand Down Expand Up @@ -213,9 +231,9 @@ export class UniversalAdapterClient {
}
} else {
const optionalNamespaces = WcHelpersUtil.createNamespaces(this.caipNetworks)
console.log('optionalNamespaces', optionalNamespaces, this.caipNetworks)
await WalletConnectProvider.connect({ optionalNamespaces })
}
this.setWalletConnectProvider()
}
},

Expand Down Expand Up @@ -311,10 +329,13 @@ export class UniversalAdapterClient {
public construct(appkit: AppKit, options: AppKitOptionsWithCaipNetworks) {
this.appKit = appkit
this.options = options

this.caipNetworks = options.networks
this.createProvider()
this.syncRequestedNetworks(this.caipNetworks)
this.syncConnectors()
this.walletConnectProvider?.on('connect', () => {
this.setWalletConnectProvider()
})
}

public switchNetwork(caipNetwork: CaipNetwork) {
Expand Down Expand Up @@ -348,6 +369,7 @@ export class UniversalAdapterClient {
// -- Private -----------------------------------------------------------------
private createProvider() {
if (
!this.walletConnectProvider &&
!this.walletConnectProviderInitPromise &&
typeof window !== 'undefined' &&
this.options?.projectId
Expand Down
3 changes: 3 additions & 0 deletions packages/appkit/src/utils/TypesUtil.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { AppKitNetwork, CaipNetwork, ThemeVariables } from '@reown/appkit-common'
import type { ChainAdapter, Metadata, OptionsControllerState, ThemeMode } from '@reown/appkit-core'
import type { AppKitSIWEClient } from '@reown/appkit-siwe'
import type IUniversalProvider from '@walletconnect/universal-provider'

export type AppKitOptions = {
/**
Expand Down Expand Up @@ -77,4 +78,6 @@ export type AppKitOptions = {
export type AppKitOptionsWithCaipNetworks = Omit<AppKitOptions, 'defaultNetwork' | 'networks'> & {
defaultNetwork?: CaipNetwork
networks: [CaipNetwork, ...CaipNetwork[]]
provider?: IUniversalProvider
manualControl?: boolean
}
7 changes: 4 additions & 3 deletions packages/core/src/controllers/ChainController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,13 @@

initialize(adapters: ChainsInitializerAdapter[]) {
const adapterToActivate = adapters?.[0]

if (adapters?.length === 0) {
const additionalAdapters = adapters?.filter(a => a.adapterType !== 'universal') ?? []
console.log('additionalProviders', additionalAdapters)

Check failure on line 112 in packages/core/src/controllers/ChainController.ts

View workflow job for this annotation

GitHub Actions / code_style (lint)

Unexpected console statement
if (additionalAdapters.length === 0) {
state.noAdapters = true
}

if (!state.noAdapters) {
if (adapterToActivate) {
state.activeChain = adapterToActivate?.chainNamespace
PublicStateController.set({ activeChain: adapterToActivate?.chainNamespace })

Expand Down
8 changes: 6 additions & 2 deletions packages/core/src/controllers/ConnectionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export interface ConnectionControllerState {
recentWallet?: WcWallet
buffering: boolean
status?: 'connecting' | 'connected' | 'disconnected'
manualControl?: boolean
}

type StateKey = keyof ConnectionControllerState
Expand Down Expand Up @@ -131,8 +132,7 @@ export const ConnectionController = {
} else {
await ChainController.state?.universalAdapter?.connectionControllerClient?.connectWalletConnect?.(
uri => {
state.wcUri = uri
state.wcPairingExpiry = CoreHelperUtil.getPairingExpiry()
this.setUri(uri)
}
)
}
Expand Down Expand Up @@ -227,6 +227,10 @@ export const ConnectionController = {
TransactionsController.resetTransactions()
StorageUtil.deleteWalletConnectDeepLink()
},
setUri(uri: string) {
enesozturk marked this conversation as resolved.
Show resolved Hide resolved
state.wcUri = uri
state.wcPairingExpiry = CoreHelperUtil.getPairingExpiry()
},

setWcLinking(wcLinking: ConnectionControllerState['wcLinking']) {
state.wcLinking = wcLinking
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/controllers/RouterController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export interface RouterControllerState {
| 'ConnectingExternal'
| 'ConnectingFarcaster'
| 'ConnectingWalletConnect'
| 'ConnectingWalletConnectBasic'
| 'ConnectingSiwe'
| 'ConnectingSocial'
| 'ConnectSocials'
Expand Down
1 change: 1 addition & 0 deletions packages/scaffold-ui/exports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export * from '../src/views/w3m-connect-view/index.js'
export * from '../src/views/w3m-connecting-external-view/index.js'
export * from '../src/views/w3m-connecting-multi-chain-view/index.js'
export * from '../src/views/w3m-connecting-wc-view/index.js'
export * from '../src/views/w3m-connecting-wc-basic-view/index.js'
export * from '../src/views/w3m-choose-account-name-view/index.js'
export * from '../src/views/w3m-downloads-view/index.js'
export * from '../src/views/w3m-get-wallet-view/index.js'
Expand Down
2 changes: 2 additions & 0 deletions packages/scaffold-ui/src/modal/w3m-router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ export class W3mRouter extends LitElement {
return html`<w3m-connect-view walletGuide="explore"></w3m-connect-view>`
case 'ConnectingWalletConnect':
return html`<w3m-connecting-wc-view></w3m-connecting-wc-view>`
case 'ConnectingWalletConnectBasic':
return html`<w3m-connecting-wc-basic-view></w3m-connecting-wc-basic-view>`
case 'ConnectingExternal':
return html`<w3m-connecting-external-view></w3m-connecting-external-view>`
case 'ConnectingSiwe':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ import { html } from 'lit'
import { ifDefined } from 'lit/directives/if-defined.js'
import { W3mConnectingWidget } from '../../utils/w3m-connecting-widget/index.js'
import styles from './styles.js'
import { state } from 'lit/decorators.js'

@customElement('w3m-connecting-wc-qrcode')
export class W3mConnectingWcQrcode extends W3mConnectingWidget {
public static override styles = styles

// -- State & Properties -------------------------------- //
@state() private manualControl = ConnectionController.state.manualControl

public constructor() {
super()
window.addEventListener('resize', this.forceUpdate)
Expand Down Expand Up @@ -47,8 +51,12 @@ export class W3mConnectingWcQrcode extends W3mConnectingWidget {
</wui-text>
${this.copyTemplate()}
</wui-flex>

<w3m-mobile-download-links .wallet=${this.wallet}></w3m-mobile-download-links>
${this.manualControl
? html`<wui-flex flexDirection="column" .padding=${['0', 'xl', 'xl', 'xl']} gap="xl">
<w3m-all-wallets-widget></w3m-all-wallets-widget>
</wui-flex>`
: null}
`
}

Expand Down
1 change: 1 addition & 0 deletions packages/scaffold-ui/src/partials/w3m-header/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ function headings() {
BuyInProgress: 'Buy',
ConnectingExternal: name ?? 'Connect Wallet',
ConnectingWalletConnect: name ?? 'WalletConnect',
ConnectingWalletConnectBasic: 'WalletConnect',
ConnectingSiwe: 'Sign In',
Convert: 'Convert',
ConvertSelectToken: 'Select token',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { ApiController, CoreHelperUtil, OptionsController, StorageUtil } from '@reown/appkit-core'
import { customElement } from '@reown/appkit-ui'
import { LitElement, html } from 'lit'
import { state } from 'lit/decorators.js'

@customElement('w3m-connecting-wc-basic-view')
export class W3mConnectingWcBasicView extends LitElement {
@state() private isMobile = CoreHelperUtil.isMobile()

public constructor() {
super()
}
// -- Render -------------------------------------------- //
public override render() {
console.log('W3mConnectingWcBasicView.constructor()', this.isMobile)

if (this.isMobile) {
const { featured, recommended } = ApiController.state
const { customWallets } = OptionsController.state
const recent = StorageUtil.getRecentWallets()

const showConnectors =
featured.length || recommended.length || customWallets?.length || recent.length
console.log('W3mConnectingWcBasicView.constructor()', recommended)
tomiir marked this conversation as resolved.
Show resolved Hide resolved

return html`<wui-flex
flexDirection="column"
gap="xs"
.margin=${['3xs', 's', 's', 's'] as const}
>
${showConnectors ? html`<w3m-connector-list></w3m-connector-list>` : null}
<w3m-all-wallets-widget></w3m-all-wallets-widget>
</wui-flex>`
}

return html`<w3m-connecting-wc-view></w3m-connecting-wc-view>`
}
}
declare global {
interface HTMLElementTagNameMap {
'w3m-connecting-wc-basic-view': W3mConnectingWcBasicView
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ export class W3mConnectingWcView extends LitElement {

// -- Render -------------------------------------------- //
public override render() {
if (!this.wallet) {
return html`<w3m-connecting-wc-qrcode></w3m-connecting-wc-qrcode>`
}

tomiir marked this conversation as resolved.
Show resolved Hide resolved
return html`
${this.headerTemplate()}
<div>${this.platformTemplate()}</div>
Expand Down
Loading