All files metamask.ts

33.33% Statements 14/42
40% Branches 8/20
44.44% Functions 4/9
34.14% Lines 14/41

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 13338x                                         1x 1x 1x       1x                         1x                                                                                           1x 1x       1x 1x                                                                     2x 2x 2x 2x    
import type {EIP6963AnnounceProviderEvent, MetaMaskInpageProvider} from '@metamask/providers'
 
export type Snap = {
    permissionName: string
    id: string
    version: string
    initialPermissions: Record<string, unknown>
}
 
export type InvokeSnapParams = {
    method: string
    params?: Record<string, unknown>
}
 
/**
 * Check if the current provider supports snaps by calling `wallet_getSnaps`.
 *
 * @param provider - The provider to use to check for snaps support. Defaults to
 * `window.ethereum`.
 * @returns True if the provider supports snaps, false otherwise.
 */
export async function hasSnapsSupport(provider: MetaMaskInpageProvider = window.ethereum) {
    try {
        await provider.request({
            method: 'wallet_getSnaps',
        })
 
        return true
    } catch {
        return false
    }
}
 
/**
 * Get a MetaMask provider using EIP6963. This will return the first provider
 * reporting as MetaMask. If no provider is found after 500ms, this will
 * return null instead.
 *
 * @returns A MetaMask provider if found, otherwise null.
 */
export async function getMetaMaskEIP6963Provider() {
    return new Promise<MetaMaskInpageProvider | null>((rawResolve) => {
        // Timeout looking for providers after 500ms
        const timeout = setTimeout(() => {
            resolve(null)
        }, 500)
 
        /**
         * Resolve the promise with a MetaMask provider and clean up.
         *
         * @param provider - A MetaMask provider if found, otherwise null.
         */
        function resolve(provider: MetaMaskInpageProvider | null) {
            window.removeEventListener('eip6963:announceProvider', onAnnounceProvider)
            clearTimeout(timeout)
            rawResolve(provider)
        }
 
        /**
         * Listener for the EIP6963 announceProvider event.
         *
         * Resolves the promise if a MetaMask provider is found.
         *
         * @param event - The EIP6963 announceProvider event.
         * @param event.detail - The details of the EIP6963 announceProvider event.
         */
        function onAnnounceProvider({detail}: EIP6963AnnounceProviderEvent) {
            const {info, provider} = detail
 
            Iif (info.rdns.includes('io.metamask')) {
                resolve(provider)
            }
        }
 
        window.addEventListener('eip6963:announceProvider', onAnnounceProvider)
 
        window.dispatchEvent(new Event('eip6963:requestProvider'))
    })
}
 
/**
 * Get a provider that supports snaps. This will loop through all the detected
 * providers and return the first one that supports snaps.
 *
 * @returns The provider, or `null` if no provider supports snaps.
 */
export async function getSnapsProvider() {
    Iif (typeof window === 'undefined') {
        return null
    }
 
    if (await hasSnapsSupport()) {
        return window.ethereum
    }
 
    Iif (window.ethereum?.detected) {
        for (const provider of window.ethereum.detected) {
            Iif (await hasSnapsSupport(provider)) {
                return provider
            }
        }
    }
 
    Iif (window.ethereum?.providers) {
        for (const provider of window.ethereum.providers) {
            Iif (await hasSnapsSupport(provider)) {
                return provider
            }
        }
    }
 
    const eip6963Provider = await getMetaMaskEIP6963Provider()
 
    Iif (eip6963Provider && (await hasSnapsSupport(eip6963Provider))) {
        return eip6963Provider
    }
 
    return null
}
 
/**
 * Check if the current provider is a Flask provider by checking the client version.
 *
 * @param provider - The provider to use to check for Flask. Defaults to
 * `window.ethereum`.
 * @returns True if the provider is a Flask provider, false otherwise.
 */
export async function checkIsFlask(provider: MetaMaskInpageProvider | null) {
    Iif (!provider) return false
    const clientVersion = await provider.request({method: 'web3_clientVersion'})
    return (clientVersion as string[])?.includes('flask')
}