Skip to content

Commit

Permalink
Merge pull request #22 from decentraland/feat/approbable-wallets
Browse files Browse the repository at this point in the history
feat: support approbable wallets
  • Loading branch information
abarmat authored Nov 1, 2018
2 parents 4194b53 + ac290c0 commit 2bb6dfe
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 6 deletions.
17 changes: 14 additions & 3 deletions src/modules/wallet/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ import {
all
} from 'redux-saga/effects'
import { eth, Contract } from 'decentraland-eth'
import { BaseWallet } from './types'
import { EthereumWindow, BaseWallet } from './types'
import {
connectWalletSuccess,
connectWalletFailure,
CONNECT_WALLET_REQUEST
} from './actions'
import { connectEthereumWallet } from './utils'
import { isApprovableWallet, connectEthereumWallet } from './utils'
import { getData } from './selectors'

export type WalletSagaOptions = {
provider: string
provider: object | string
contracts: Contract[]
eth: typeof eth
}
Expand All @@ -29,6 +29,17 @@ export function createWalletSaga({
}: WalletSagaOptions): () => IterableIterator<ForkEffect> {
function* handleConnectWalletRequest() {
try {
if (isApprovableWallet()) {
const { ethereum } = window as EthereumWindow
yield call(() => ethereum!.enable())

// Unfortunately we need to override the provider supplied to this method
// if we're dealing with approbable wallets (the first being Metamask, probably more to come).
// When a wallet is needs to call `enable` to work (to whitelist the URL), the correct provider is `ethereum`
// but if we're using a different kind of wallet (like a Ledger) the user supplied provider should be ok.
provider = ethereum!
}

const walletData: BaseWallet = yield select(getData)

yield call(() =>
Expand Down
9 changes: 9 additions & 0 deletions src/modules/wallet/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,12 @@ export interface BaseWallet {
locale?: string
derivationPath?: string
}

export interface EthereumWindow {
ethereum?: {
_metamask: { isApproved: () => Promise<boolean> }
isApproved: () => Promise<boolean>

enable: () => Promise<string[]>
}
}
21 changes: 20 additions & 1 deletion src/modules/wallet/utils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { eth, wallets, Contract } from 'decentraland-eth'
import { isMobile } from '../../lib/utils'
import { EthereumWindow } from './types'

interface ConnectOptions {
address: string
provider: string
provider: object | string
contracts: Contract[]
derivationPath?: string
eth: typeof eth
Expand Down Expand Up @@ -49,3 +50,21 @@ function getWallets(
export function isLedgerWallet() {
return eth.wallet instanceof wallets.LedgerWallet
}

export function isApprovableWallet() {
const { ethereum } = window as EthereumWindow
return ethereum !== undefined && typeof ethereum.enable === 'function'
}

export async function isWalletApproved() {
const { ethereum } = window as EthereumWindow

if (ethereum === undefined) {
return false
}

// `isApproved` is not standard. It's supported by MetaMask and it's expected to be implemented by other wallet vendors
// but we need to check just in case.
const aprobable = ethereum._metamask || ethereum
return aprobable.isApproved ? await aprobable.isApproved() : true
}
18 changes: 16 additions & 2 deletions src/providers/WalletProvider/WalletProvider.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
import * as React from 'react'
import {
isApprovableWallet,
isWalletApproved
} from '../../modules/wallet/utils'
import { DefaultProps, Props } from './WalletProvider.types'

export default class WalletProvider extends React.PureComponent<Props> {
static defaultProps: DefaultProps = {
children: null
}

componentWillMount() {
async componentWillMount() {
const { onConnect } = this.props
onConnect()

if (await this.shouldConnect()) {
onConnect()
}
}

async shouldConnect() {
return (
!isApprovableWallet() ||
(isApprovableWallet() && (await isWalletApproved()))
)
}

render() {
Expand Down

0 comments on commit 2bb6dfe

Please sign in to comment.