Skip to content

Commit

Permalink
DAppstrosities: Fix a few observed dApp connection issues (#3593)
Browse files Browse the repository at this point in the history
- Uniswap should now update default wallet without reloads (closes
#3578).
- Stargate should correctly handle transfers when the chain needs to be
changed behind the scenes.
- Generally sites that may interact with event handlers before Taho's
default status is read should no longer have issues.

## Testing

- [x] Go to Uniswap with Taho as default and try to connect with
MetaMask. In the popup, switch away from Taho as default. MetaMask
should connect normally.
- [x] Go to Uniswap with Taho as default and try to connect with
MetaMask. In the popup, reject. Switch Taho as default off in the
popover. Try to connect with MetaMask again. MetaMask should connect
normally.
- [x] Go to Uniswap with Taho as not-default. Switch Taho as default on
in the popover. Try to connect with MetaMask. Taho should connect
normally.
- [x] Go to Stargate with Taho as default. Connect. Set up a swap from a
*different* network than the one you connected on (I typically connect
on Ethereum mainnet, then set a swap from Arbitrum ETH to mainnet ETH).
Try to submit the transaction. You should get a transaction
confirmation.

Latest build:
[extension-builds-3593](https://github.com/tahowallet/extension/suites/14936639887/artifacts/851517366)
(as of Wed, 09 Aug 2023 02:29:24 GMT).
  • Loading branch information
hyphenized authored Aug 9, 2023
2 parents 80c90e0 + 8997db9 commit 7989723
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 16 deletions.
2 changes: 2 additions & 0 deletions env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type BaseWalletProvider = {
identityFlag?: string
checkIdentity?: (provider: WalletProvider) => boolean
}
emit: (eventName: string | symbol, ...args: unknown[]) => boolean
on: (
eventName: string | symbol,
listener: (...args: unknown[]) => void
Expand Down Expand Up @@ -60,6 +61,7 @@ interface Window {
shouldReload?: boolean
) => void
routeToNewNonTahoDefault: (request: unknown) => Promise<unknown>
reemitTahoEvent: (event: string | symbol, ...args: unknown[]) => boolean
getProviderInfo: (
provider: WalletProvider
) => WalletProvider["providerInfo"]
Expand Down
74 changes: 58 additions & 16 deletions src/window-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const tahoRoutedProperties = new Set(
// function below.
const metaMaskMock: WalletProvider = {
isMetaMask: true,
emit: (_: string | symbol, ...__: unknown[]) => false,
on: () => {},
removeListener: () => {},
_state: {
Expand All @@ -49,12 +50,29 @@ const metaMaskMock: WalletProvider = {
}

// A tracking list of MetaMask wrappers that allow us to avoid double-wrapping.
const metaMaskWrappers = new Set()
// The map key is the provider that *was wrapped*, i.e. the original, and the
// map value is the wrapping provider, i.e. the proxy that makes sure default
// settings are respected.
const metaMaskWrapperByWrappedProvider = new Map<
WalletProvider,
WalletProvider
>()
let metaMaskMockWrapper: WalletProvider | undefined

function wrapMetaMaskProvider(provider: WalletProvider): WalletProvider {
if (metaMaskWrappers.has(provider)) {
return provider
function wrapMetaMaskProvider(provider: WalletProvider): {
provider: WalletProvider
wasMetaMaskLike: boolean
} {
if (metaMaskWrapperByWrappedProvider.has(provider)) {
return {
// `get` is guarded by the `has` check above.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
provider: metaMaskWrapperByWrappedProvider.get(provider)!,
wasMetaMaskLike: true,
}
}
if (new Set(metaMaskWrapperByWrappedProvider.values()).has(provider)) {
return { provider, wasMetaMaskLike: true }
}

if (
Expand Down Expand Up @@ -89,16 +107,19 @@ function wrapMetaMaskProvider(provider: WalletProvider): WalletProvider {
},
})

metaMaskWrappers.add(wrapper)
metaMaskWrapperByWrappedProvider.set(provider, wrapper)

if (provider === metaMaskMock) {
metaMaskMockWrapper = wrapper
}

return wrapper
return {
provider: wrapper,
wasMetaMaskLike: true,
}
}

return provider
return { provider, wasMetaMaskLike: false }
}

/**
Expand Down Expand Up @@ -132,20 +153,21 @@ function metaMaskWrappedProviders(
return { defaultManagedProviders, metaMaskDetected }
}

const defaultManaged = wrapMetaMaskProvider(provider)
const { provider: defaultManaged, wasMetaMaskLike } =
wrapMetaMaskProvider(provider)

return {
defaultManagedProviders: [...defaultManagedProviders, defaultManaged],
// MetaMask is the only one whose return value will differ from the
// underlying object.
metaMaskDetected: metaMaskDetected || defaultManaged !== provider,
metaMaskDetected: metaMaskDetected || wasMetaMaskLike,
}
},
{ defaultManagedProviders: [], metaMaskDetected: false }
)

if (!metaMaskDetected && tahoIsDefault) {
return [wrapMetaMaskProvider(metaMaskMock), ...defaultManagedProviders]
const { provider: metaMaskMockProvider } =
wrapMetaMaskProvider(metaMaskMock)
return [metaMaskMockProvider, ...defaultManagedProviders]
}

return defaultManagedProviders
Expand Down Expand Up @@ -173,10 +195,15 @@ if (!window.walletRouter) {
]),
].filter((item) => item !== undefined)

const wrappedLastInjectedProvider: WalletProvider | undefined =
window.ethereum === undefined
? undefined
: wrapMetaMaskProvider(window.ethereum).provider

Object.defineProperty(window, "walletRouter", {
value: {
currentProvider: window.tally,
lastInjectedProvider: window.ethereum,
lastInjectedProvider: wrappedLastInjectedProvider,
tallyProvider: window.tally,
providers: dedupedProviders,
shouldSetTallyForCurrentProvider(
Expand Down Expand Up @@ -238,13 +265,28 @@ if (!window.walletRouter) {
}
)
},
reemitTahoEvent(event: string | symbol, ...args: unknown[]): boolean {
if (
this.currentProvider !== this.tallyProvider ||
this.lastInjectedProvider === undefined ||
this.currentProvider === this.lastInjectedProvider
) {
return false
}

return this.lastInjectedProvider.emit(event, ...args)
},
setSelectedProvider() {},
addProvider(newProvider: WalletProvider) {
if (!this.providers.includes(newProvider)) {
this.providers.push(wrapMetaMaskProvider(newProvider))
const wrappedProvider = wrapMetaMaskProvider(newProvider).provider
if (
!this.providers.includes(newProvider) &&
!this.providers.includes(wrappedProvider)
) {
this.providers.push(wrappedProvider)
}

this.lastInjectedProvider = newProvider
this.lastInjectedProvider = wrappedProvider
},
},
writable: false,
Expand Down
11 changes: 11 additions & 0 deletions window-provider/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,17 @@ export default class TahoWindowProvider extends EventEmitter {
})
}

override emit(event: string | symbol, ...args: unknown[]): boolean {
const hadAdditionalListeners = window.walletRouter?.reemitTahoEvent(
event,
...args
)

const hadDirectListeners = super.emit(event, ...args)

return hadAdditionalListeners || hadDirectListeners
}

handleChainIdChange(chainId: string): void {
this.chainId = chainId
this.emit("chainChanged", chainId)
Expand Down

0 comments on commit 7989723

Please sign in to comment.