Detecting the Provider

The ME wallet injects a magicEden object into the window of most any web page that a user may visit. To interact with the Bitcoin provider directly, you can access at the unique namespace window.magicEden.bitcoin.

Simultaneously, the Bitcoin provider is injected into window.BitcoinProvider. There are a few different reasons for this, but occasionally the BitcoinProvider can be overwritten by other wallets who occupy the same namespace. Therefore, we make use of the Bitcoin extension of the Wallet Standard to successfully identify the correct provider in this case.

We recommend interacting via our unique window.magicEden.bitcoin namespace whenever possible to avoid the above conflicts.

Directly Locating the Provider

To properly detect if the ME wallet is installed, you can look for an additional isMagicEden flag. All together it will look something like this:

const getBtcProvider = () => {
	if ("magicEden" in window) {
		const anyWindow: any = window;
		if (anyWindow.magicEden.bitcoin && anyWindow.magicEden.bitcoin.isMagicEden)
			return anyWindow.magicEden.bitcoin;
	}
	window.location.href = "https://wallet.magiceden.io/";
};

Note:

This includes a redirect to our website to download the wallet if a user does not have it installed. This is not mandatory for detecting the provider, but a suggested action to take in that case

Utilizing the Wallet Standard

Alternatively, you can utilize the Bitcoin Wallet Standard to identify a list of all wallets that comply with the standard, and select Magic Eden from there. This requires a bit more leg work up front, but allows app developers to easily discover all compatible BTC wallets.

Reference our Wallet Standard BTC Demo for a full code breakdown of this implementation style.

Caution:

The BTC development community is still rather young, and there isn't an "agreed upon" standard like you might find in Solana. Due to this, not all wallets comply to the above standard, and therefore you will not be able to locate all wallets with one blanket solution for now.

To start:

Install Dependencies

npm i @exodus/bitcoin-wallet-standard-features@0.0.1 @exodus/bitcoin-wallet-standard-react@0.0.0 @wallet-standard/react@0.1.4 sats-connect@1.3.0

Wrap your application in the Wallet Standard Provider

The WalletStandardProvider is a React context provider from @wallet-standard/react, designed to interface with cryptocurrency wallets, specifically focusing on Bitcoin transactions in this context. It abstracts wallet interactions, providing a standardized way to connect to, manage, and perform transactions with BTC wallets.

import { WalletStandardProvider } from '@wallet-standard/react';
import { ConnectionStatusProvider } from './ConnectionStatus';
import type { FC, ReactNode } from 'react';
import React from 'react';

export const AppContext: FC<{ children: NonNullable<ReactNode> }> = ({ children }) => {
    return (
        <WalletStandardProvider>
            <ConnectionStatusProvider>{children}</ConnectionStatusProvider>
        </WalletStandardProvider>
    );
};

}

Detect the Provider via Wallet Standard

import { useWallet, useWallets } from '@wallet-standard/react';
import type { Wallet, WalletWithFeatures } from '@wallet-standard/base';

const SatsConnectNamespace = 'sats-connect:';
const { setWallet, wallet } = useWallet();
const { wallets } = useWallets();

function isSatsConnectCompatibleWallet(wallet: Wallet) {
    return SatsConnectNamespace in wallet.features;
}

function getBtcProvider(){
    return (wallet as unknown as WalletWithFeatures<any>).features[SatsConnectNamespace]?.provider
}

Set the Desired Provider

After setting up the above helper functions, you can display a list of all compliant Wallet Standard wallets and have a user select which they would like to connect to.

<ul className="mb-8 flex flex-col">
    {wallets.filter(isSatsConnectCompatibleWallet).map((wallet, index) => (
        <li key={wallet.name}>
            <button
                className={classNames(
                    'w-full rounded-md bg-[#e93a88] px-2 py-1 text-xs uppercase tracking-wide text-white',
                    {
                        'mb-2': index !== wallets.length - 1,
                    }
                )}
                type="button"
                onClick={() => setWallet(wallet)}
            >
                {wallet.name}
            </button>
        </li>
    ))}
</ul>

Last updated