# Wallet Introduction

The Premier Multi-Chain Crypto Wallet

## Introduction

The Magic Eden Wallet allows you to manage your assets across popular blockchains, including Solana, Bitcoin, Ethereum, Base and Polygon. Enjoy secure cross-chain swaps directly in the wallet that enable you to connect anywhere and collect everywhere

#### Download Here:

* [Browser Extension](https://chromewebstore.google.com/detail/magic-eden-wallet/mkpegjkblkkefacfnmkajcjmabijhclg)
* [IOS app](https://apps.apple.com/us/app/magic-eden-wallet/id6478631482)
* [Android app](https://play.google.com/store/apps/details?id=com.magiceden.wallet\&hl=en_US?utm_source=website\&utm_medium=internal\&utm_campaign=mobile-wallet-ga\&utm_content=button)&#x20;

#### Resources

* [Website](https://wallet.magiceden.io/)
* [X](https://x.com/MagicEdenWallet)
* [Discord](https://discord.com/invite/magiceden)
* [Linktree](https://linktr.ee/magiceden)

The majority of these docs are intended to help developers build applications that interact with the Magic Eden Wallet. For user oriented concerns and FAQs, please reach out or reference our support articles [here](https://help.magiceden.io/en/collections/6642921-magic-eden-wallet).


# Diving into Bitcoin

The Magic Eden wallet has native support for all things Bitcoin, Ordinals and Runes. Since there are currently not as many go-to wallet frameworks, this section will give you a step by step walkthrough on how to integrate the ME wallet into your dApp. We'll also explore creating and signing PSBTs (partially signed Bitcoin transactions).

## Direct Integration

The most straightforward way to interact with the ME wallet on the Bitcoin network is via the provider that is globally available at `window.magicEden.bitcoin.` This unique namespace ensures that the ME BTC provider is always available in the window. The ME BTC provider also attempts to inject at `window.BitcoinProvider`, but this can occasionally clash if users have multiple Bitcoin browser wallets installed.

## The Bitcoin Wallet Standard

The ME Bitcoin wallet makes use of the [Bitcoin Wallet Standard](https://github.com/ExodusMovement/bitcoin-wallet-standard), an extension of the chain agnostic [Wallet Standard](https://github.com/wallet-standard/wallet-standard). This standard makes use of a set of interfaces and conventions designed to improve the user experience and developer experience of wallets and applications. You can use these libraries to connect to the ME wallet without locating the provider directly if you so choose.

## Sats-Connect

The provider also extends methods from [sats-connect](https://docs.xverse.app/sats-connect/), an easy-to-understand javascript library that allows apps to interact with Bitcoin wallets. Sats Connect enables developers to easily retrieve user wallet addresses + interact with PSBTs

## Demo

You can find a code demo [here](https://github.com/Tcadle434/me-wallet-bitcoin-react) that illustrates how to integrate with the ME Wallet, create viable PSBTs, and utilize core sats-connect functions.

{% hint style="info" %}
**Note:**

This demo assumes use of the Bitcoin Wallet Standard. By connecting directly to the provider, you can ignore a lot of the boilerplate from the wallet standard libraries
{% endhint %}


# 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](https://github.com/ExodusMovement/bitcoin-wallet-standard) to successfully identify the correct provider in this case.&#x20;

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:

```typescript
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/";
};
```

{% hint style="info" %}
**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
{% endhint %}

## Utilizing the Wallet Standard

Alternatively, you can utilize the [Bitcoin Wallet Standard ](https://github.com/ExodusMovement/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**](https://github.com/Tcadle434/me-wallet-bitcoin-react) **for a full code breakdown of this implementation style.**

{% hint style="warning" %}
**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.
{% endhint %}

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.

```jsx
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

```typescript
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.

```jsx
<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>
```


# Connecting to the Wallet

## Connect Wallet

This function is designed to initiate the connection process to a user's Bitcoin wallet. It leverages the [Sats Connect getAddress API](https://docs.xverse.app/sats-connect-v1/methods/getaddress) to request a user's payment address (native segwit) and ordinals/runes address (taproot).&#x20;

It makes use of the `getBtcProvider` method we defined in [Detecting the Provider](/bitcoin/detecting-the-provider).

```typescript
import { getAddress, AddressPurpose, BitcoinNetworkType } from "sats-connect";

async function connectOrDeselect() {
	await getAddress({
		getProvider: getBtcProvider,
		payload: {
			purposes: [AddressPurpose.Ordinals, AddressPurpose.Payment],
			message: "Address for receiving Ordinals and payments",
			network: {
				type: BitcoinNetworkType.Mainnet,
			},
		},
		onFinish: (response) => {
			console.log("onFinish response, ", response.addresses);
	
			// do some action like updating your app context
			connectionStatus?.setAccounts(response.addresses as unknown as Account[]);
		},
		onCancel: () => {
			alert("Request canceled");
		},
	});
}
```

The `getAddresss` method returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) that resolves if the user approves the connection request.

<figure><img src="https://3057797283-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUE3YlWFGNzodYaTOyoul%2Fuploads%2FQgn9743IZomVz2hA3yeU%2FScreenshot%202024-07-08%20at%203.08.26%E2%80%AFAM.png?alt=media&amp;token=2c74a13a-b37e-4d5f-aafd-e54886f8f1c1" alt=""><figcaption></figcaption></figure>

Once resolved, the method returns an array of the user’s wallet address objects, defined as:

```typescript
type address = {
    address: string;
    publicKey: string;
    purpose: "payment" | "ordinals";
}
```

Where:

| address field | Description                                                                                                                                                                       |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `address`     | The user’s connected  address                                                                                                                                                     |
| `publicKey`   | A hex string representing the bytes of the public key of the account.                                                                                                             |
| `purpose`     | <p>The purpose of the address:</p><ul><li><code>payment</code> is used to manage the user’s bitcoin</li><li><code>ordinals</code> is used to manage the user’s ordinals</li></ul> |


# Signing a Message

When a web application has established a connection to the ME wallet, it can prompt users to sign a message. This is commonplace amongst many dApps, as it gives application owners the ability to verify ownership of the wallet. Signing a message does not require any transaction fees.

[Sats Connect](https://docs.xverse.app/sats-connect-v1/methods/signmessage) provides an easy way to request message signing. Let's take a look at the code below.

```javascript
import { BitcoinNetworkType, signMessage } from 'sats-connect';

// in a real app, you'll use the ME 'payment' address returned after a connection
const nativeSegwitAddress = 'bc1qcdmvsc8qqk8sr2st3mttu6fsmfrjzh5xrf4dch'

async function signWalletMessage() {
  try {
    await signMessage({
      payload: {
        network: {
          type: BitcoinNetworkType.Mainnet,
        },
        address: nativeSegwitAddress,
        message: 'Hello World. Welcome to the Magic Eden wallet!',
      },
      onFinish: (response) => {
        alert(`Successfully signed message: ${response}`);
      },
      onCancel: () => {
        alert('Request canceled');
      },
    });
  } catch (err) {
    console.error(err);
  }
}
```

A successful prompt to sign a message will look something like this:

<br>

<figure><img src="https://files.readme.io/f75adb0-Screenshot_2024-02-08_at_12.08.41_AM.png" alt="" width="375"><figcaption></figcaption></figure>

{% hint style="info" %}
**Message Format**

The ME wallet currently follows the spec design in [BIP 322](https://bips.xyz/322) for message signature types for all addresses. We are looking into adding more explicit support for legacy/ECDSA signing, as we are aware this may be needed for certain circumstances.
{% endhint %}


# Signing a Transaction

The Magic Eden Wallet support the Sats Connect method of [signing a transaction](https://docs.xverse.app/sats-connect-v1/methods/signtransaction). This requires a base64 encoded PSBT to execute.

Let's take a look at a basic example, where we want to send an arbitrary amount of BTC to another wallet. The top-level function call should look something like this:

```javascript
async function signWalletTransaction() {
  const utxos = await fetchUTXO(nativeSegwitAddress);
  if (!utxos) {
    alert('No UTXOs found! Please deposit some funds to your wallet.');
    return;
  }
  const selectedUTXO = await selectUTXO(10000, utxos);
  const scriptPubKey = await fetchScriptPubKey(selectedUTXO.txid, selectedUTXO.vout);
  const psbt = await createPSBT({
    utxo: selectedUTXO,
    recipientAddress: RECIPIENT_ADDRESS,
    changeAddress: nativeSegwitAddress,
    amountToSend: 1000,
    scriptPubKey,
  });

  try {
    await signTransaction({
      payload: {
        network: {
          type: BitcoinNetworkType.Mainnet,
        },
        psbtBase64: psbt,
        broadcast: true,
        message: "tip the author! Don't worry this will not be broadcasted.",
        inputsToSign: [
          {
            address: nativeSegwitAddress!,
            signingIndexes: [0],
      },
      ],
    },
    onFinish: (response) => {
      const psbResponse = Psbt.fromBase64(response.psbtBase64);
      psbResponse.finalizeAllInputs();
      const signedTx = psbResponse.extractTransaction();
      const txHex = signedTx.toHex();
    },
      onCancel: () => {
        alert('Request canceled');
      },
  });
} catch (err) {
  console.error(err);
}
}
```

There's a lot going on here, so here's a breakdown of each part.

## Understanding UTXOs:

In the world of Bitcoin, the concept of a "balance" operates differently compared to traditional bank accounts or even some other blockchain networks. Rather than representing your funds as a single total amount, your Bitcoin balance is actually the sum of all values from [Unspent Transaction Outputs (UTXOs)](https://learnmeabitcoin.com/technical/transaction/utxo/). UTXOs are essentially fragments of Bitcoin left over from previous transactions that you have received but not yet spent.

When someone sends you Bitcoin, the amount is recorded in the blockchain as a UTXO, earmarked for your address. Your wallet then aggregates all UTXOs associated with your address to display your total balance. It's similar to having a wallet full of various bills and coins; each piece has value, and your total wealth is the sum of these individual pieces.

To initiate a Bitcoin transaction, your wallet selects enough UTXOs to cover the amount you wish to send, plus the transaction fee. These selected UTXOs are then consumed and effectively transformed: the amount sent to the recipient becomes a new UTXO linked to their address, and any change not sent to the recipient (the remainder after subtracting the amount sent and the transaction fee) returns to you as a new UTXO, ready to be spent in future transactions.

In this particular example, we are just going with the first UTXO that fits the bill. Actual production implementations should expand on this. An easy way to fetch all UTXO's of an address is utilizing [mempool's API](https://mempool.space/docs/api/rest#get-address-utxo)

```javascript
/**
 * Fetches UTXOs from the mempool.space API for a specified address.
 *
 * @param {string} address The Bitcoin address to fetch UTXOs for.
 * @returns {Promise<UTXO[]>} A promise that resolves with an array of UTXOs for the given address.
 * @throws {Error} If the request to the mempool.space API fails. Most likely due to not found (no balance) or invalid address.
 */
export const fetchUTXO = async (address: string): Promise<UTXO[]> => {
    const response = await fetch(`https://mempool.space/api/address/${address}/utxo`);
    if (!response.ok) {
        throw new Error('Error fetching UTXO from mempool.space API.');
    }
    return response.json();
};

```

## Script

In this example, we are looking at a transaction payment. That makes use of our segwit address instead of our taproot address. In the ME wallet, your main BTC address for sending bitcoin is a native segwit address.[ SegWit (or Segregated Witness)](https://learnmeabitcoin.com/technical/upgrades/segregated-witness/) was introduced to make Bitcoin transactions more efficient and secure

In the context of creating PSBTs, ScriptPubKey and WitnessUTXO are essential for SegWit transactions because they ensure that bitcoins are securely and efficiently sent across the Bitcoin network. ScriptPubKey ensures that only the intended recipient can spend the bitcoins, while WitnessUTXO makes transactions more space-efficient, allowing for faster processing and lower fees.

{% hint style="info" %}
**Note:**

This is a rather naiive description of Script. For more detail on Script and unlocking/locking UTXOs, check out [this resource](https://learnmeabitcoin.com/technical/script/).

Additionally, the introduction of [Segragated Witness (BIP 141)](https://bips.xyz/141), brought around a different way of working with these locks, which is why the [Witness](https://learnmeabitcoin.com/technical/transaction/witness/) field is needed for segwit addresses.
{% endhint %}

You can find the given scriptPubKey for a UTXO transaction id from the mempool APIs as well:

```javascript
/**
 * Fetches the scriptPubKey for a given UTXO transactionId from the mempool.space API.
 * This is necessary for creating a PSBT for a segwit transaction.
 *
 * @param {string} txId The transaction ID of the UTXO.
 * @param {number} vout The vout index of the UTXO.
 * @returns {Promise<string>} A promise that resolves with the hex representation of the scriptPubKey.
 * @throws {Error} If the request to the mempool.space API fails, or if the scriptPubKey is not found for the given vout.
 */
export const fetchScriptPubKey = async (txId: string, vout: number): Promise<string> => {
    const response = await fetch(`https://mempool.space/api/tx/${txId}`);
    if (!response.ok) {
        throw new Error('Error fetching transaction details from mempool.space API.');
    }
    const transaction = await response.json();
    if (transaction.vout && transaction.vout.length > vout && transaction.vout[vout].scriptpubkey) {
        return transaction.vout[vout].scriptpubkey;
    } else {
        throw new Error('scriptPubKey not found for the given vout.');
    }
};

```

## Creating PSBTs

Now for the fun part! We've put together all the pieces, now let's create a PSBT that we can actually execute. PSBTs are a flexible, standardized format for Bitcoin transactions that can be partially signed and completed by multiple parties.

This example walks through creating a PSBT for Segwit transactions, but taproot transactions are similar and you can follow the documentation from [sats-connect](https://docs.xverse.app/sats-connect/guides/creating-psbts) if need be. This example process involves sending Bitcoin from one address to another and returning any leftover balance from the UTXO back to the sender.

```javascript
import { UTXO } from './fetchUTXO';
import { Psbt, networks } from 'bitcoinjs-lib';

interface SegwitProps {
    utxo: UTXO;
    recipientAddress: string;
    changeAddress: string;
    amountToSend: number;
    scriptPubKey?: string;
    senderPubKey?: string;
}

/**
 * A basic implementation of creating a PSBT for a segwit transaction. This consists of
 * sending btc from one address to another, returning the leftover balance from the UTXO to the sender.
 * For a real-world application, you would want to implement more checks and error handling.
 *
 * @param {SegwitProps} props The properties needed to create a PSBT.
 * @returns {Promise<string>} A promise that resolves with the base64 representation of the PSBT.
 */
export const createPSBT = async ({
    utxo,
    recipientAddress,
    changeAddress,
    amountToSend,
    scriptPubKey,
}: SegwitProps) => {
    const psbt = new Psbt({ network: networks.bitcoin });

    // change to return to sender minus the amount to send and the transaction fee (500 sats for this example)
    const changeValue = utxo.value! - amountToSend - 500;

    psbt.addInput({
        hash: utxo?.txid!,
        index: utxo?.vout!,
        witnessUtxo: {
            script: Buffer.from(scriptPubKey!, 'hex'),
            value: utxo.value!,
        },
    });

    psbt.addOutput({
        address: recipientAddress,
        value: amountToSend,
    });

    // change from the UTXO needs to be returned to the sender
    psbt.addOutput({
        address: changeAddress,
        value: changeValue,
    });

    return psbt.toBase64();
};

```

This formed PSBT can be decoded and sent back to the original code snippet to be executed in our SignTransaction function we created at the top of this section.


# Sending BTC

Since creating PSBTs from scratch can be rather intensive, the ME wallet exposes a simple method on the provider called `sendBtcTransaction` to facilitate the basic request of sending bitcoin to another address.

In pattern with the previous methods, the ME provider extends [Sats Connect](https://docs.xverse.app/sats-connect-v1/methods/sendbtctransaction) to ensure a clear format to send BTC.

```typescript
import { sendBtcTransaction, BitcoinNetworkType } from "sats-connect";

// in a real app, you'll use the ME 'payment' address returned after a connection
const nativeSegwitAddress = 'bc1qcdmvsc8qqk8sr2st3mttu6fsmfrjzh5xrf4dch'
const recipientAddress = 'dummyAddress'

await sendBtcTransaction({
  payload: {
    network: {
      type: BitcoinNetworkType.Mainnet,
    },
    recipients: [
      {
        address: recipientAddress!,
        amountSats: BigInt(1500),
      },
    ],
    senderAddress: nativeSegwitAddress!,
  },
  onFinish: (response) => {
    alert(response);
  },
  onCancel: () => alert("Canceled"),
});
```

This will prompt the user to send the specified amount of sats to the `recipientAddress`&#x20;

<figure><img src="https://3057797283-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUE3YlWFGNzodYaTOyoul%2Fuploads%2FAup8hhOy8Uf8retx6k4o%2FScreenshot%202024-07-08%20at%2012.23.42%E2%80%AFPM.png?alt=media&amp;token=72a22db7-3cb0-4dbc-a097-5d0eb0a39cf5" alt=""><figcaption></figcaption></figure>


# Provider API Methods

Using the [Sats Connect methods](https://docs.xverse.app/sats-connect-v1) is the easiest way to format the request strings that get passed down to our actual provider method parameters. Below is all of the methods we support directly on the provider.

## Provider Methods

### `Connect`

Prompts a connection to a user's Magic Eden Wallet account.

#### Params

Without using Sats Connect, you could encode your request payload like below. However, [getAddress](https://docs.xverse.app/sats-connect-v1/methods/getaddress) takes care of this for you

```typescript
import * as jsontokens from 'jsontokens'

enum AddressPurposes {
  PAYMENT = 'payment',
  ORDINALS = 'ordinals',
}

const payload = {
  purposes: [AddressPurposes.PAYMENT, AddressPurposes.ORDINALS],
}
const request = jsontokens.createUnsecuredToken(payload)
```

| Property  | Type     | Description              |
| --------- | -------- | ------------------------ |
| `request` | `string` | The json encoded payload |

#### Response

| Property                     | Type    | Description                                     |
| ---------------------------- | ------- | ----------------------------------------------- |
| `Promise<getAddressRespose>` | `array` | Array of the connected user’s `Address` objects |

#### `Address` Response Properties

| Property    | Type                             | Description                                                                                                            |
| ----------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `address`   | `string`                         | The user's BTC address                                                                                                 |
| `publicKey` | `string`                         | A hex string representing the full publicKey of your BTC account. Your address is shortened from this                  |
| `purpose`   | `enum - 'payment' \| 'ordinals'` | The purpose of the address is used to indicate whether this address is preferrably used for payments or ordinals/runes |

### `signMessage`

Prompts to sign a message with the user's connected Magic Eden Wallet account

#### Params

Without using Sats Connect, you could encode your request payload like below. However, [signMessage](https://docs.xverse.app/sats-connect-v1/methods/signmessage) takes care of this for you

```typescript
import * as jsontokens from 'jsontokens'

export interface SignMessagePayload {
  address: string
  message: string
  protocol?: string
}

const payload = {
  'bc1qcdmvsc8qqk8sr2st3mttu6fsmfrjzh5xrf4dch',
  'Welcome to my dApp!',
}
const request = jsontokens.createUnsecuredToken(payload)
```

| Property  | Type     | Description              |
| --------- | -------- | ------------------------ |
| `request` | `string` | The json encoded payload |

Where protocol accepts either `'BIP322'` or `'ECDSA'` and defaults to the former if no value is provided. By default all signatures will follow the up to date [bip322](https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki) standard, but certain apps require legacy signing. Passing in `'ECDSA'` will ensure legacy signing only for segwit/payment addresses.

#### Response

| Property          | Type     | Description                     |
| ----------------- | -------- | ------------------------------- |
| `Promise<string>` | `string` | String containing the signature |

### `signTransaction`

Prompts to sign a PSBT with the user's connected Magic Eden Wallet account.

#### Params

Without using Sats Connect, you could encode your request payload like below. However, [signTransaction](https://docs.xverse.app/sats-connect-v1/methods/signtransaction) takes care of this for you

```typescript
import * as jsontokens from 'jsontokens'

const payload: any = {
  network: {
    type: 'Mainnet',
  },
  message: 'wow',
  psbtBase64: `cHNidP8BAIkCAAAAAcdT+1joxn7quCzc5RHnqjiUO3odlGn2dznH7/QY4uwlAgAAAAD/////AugDAAAAAAAAIgAgQw4WXibgytGq1y25JPXvYiECxZCpUo6L31w+KfQtgk2HmQAAAAAAACIAIEMOFl4m4MrRqtctuST172IhAsWQqVKOi99cPin0LYJNAAAAAAABASv4pwAAAAAAACIAIEMOFl4m4MrRqtctuST172IhAsWQqVKOi99cPin0LYJNAQMEggAAAAEFR1IhA9/z2Wg/zWhuy2Wtm8KZC+NuwqQzhN3PG+L5GrmOOecFIQP3thdmUgZQrE2gZFZt1red4El15NcoNxCj6syNnj19i1KuAAAA`,
  broadcast: false,
  inputsToSign: [
    {
      address,
      signingIndexes: [1],
    },
  ],
}

if (sigHash) {
  payload.inputsToSign[0].sigHash = sigHash
}

const request = jsontokens.createUnsecuredToken(payload)
```

| Property  | Type     | Description              |
| --------- | -------- | ------------------------ |
| `request` | `string` | The json encoded payload |

#### Response

| Property                           | Type     | Description                              |
| ---------------------------------- | -------- | ---------------------------------------- |
| `Promise<SignTransactionResponse>` | `object` | The returned psbt in base64 and the txId |

#### `SignTransactionResponse` Response Properties

| Property     | Type     | Description                           |
| ------------ | -------- | ------------------------------------- |
| `psbtBase64` | `string` | The base64 encoded psbt string        |
| `txId`       | `string` | an optional transaction Id on success |

### `sendBtcTransaction`

Prompts to send BTC from the user's connected Magic Eden Wallet account.

#### Params

Without using Sats Connect, you could encode your request payload like below. However, [sendBtcTransaction](https://docs.xverse.app/sats-connect-v1/methods/sendbtctransaction) takes care of this for you

```typescript
import * as jsontokens from 'jsontokens'

const payload: any = {
  recipients: [
    {
      // recipient BTC address
      'bc1qcdmvsc8qqk8sr2st3mttu6fsmfrjzh5xrf4dch',
      amountSats: `3000`,
    },
  ],
  senderAddress: address,
}

const request = jsontokens.createUnsecuredToken(payload)
```

| Property  | Type     | Description              |
| --------- | -------- | ------------------------ |
| `request` | `string` | The json encoded payload |

#### Response

| Property          | Type     | Description                          |
| ----------------- | -------- | ------------------------------------ |
| `Promise<string>` | `string` | String containing the transaction Id |

### `signMultipleTransactions (custom)`

Prompts to sign multiple PSBTs under one approval with the user's connected Magic Eden Wallet account. *This is currently a private wallet method that is whitelisted to the magic eden marketplace domain*

#### Params

This is a custom feature of the Magic Eden Wallet and thus cannot be invoked with sats-connect, as you have the choice to do with the other provider methods. Rather, you can call this method with a similar request string as `signTransaction`

```typescript
import * as jsontokens from 'jsontokens'

const payload: any = {
  network: {
    type: 'Mainnet',
  },
  message: 'Sign Multiple Transactions dummy message',
  psbts: [
    {
      psbtBase64:
        'cHNidP8BAIkCAAAAAcdT+1joxn7quCzc5RHnqjiUO3odlGn2dznH7/QY4uwlAgAAAAD/////AugDAAAAAAAAIgAgQw4WXibgytGq1y25JPXvYiECxZCpUo6L31w+KfQtgk2HmQAAAAAAACIAIEMOFl4m4MrRqtctuST172IhAsWQqVKOi99cPin0LYJNAAAAAAABASv4pwAAAAAAACIAIEMOFl4m4MrRqtctuST172IhAsWQqVKOi99cPin0LYJNAQMEggAAAAEFR1IhA9/z2Wg/zWhuy2Wtm8KZC+NuwqQzhN3PG+L5GrmOOecFIQP3thdmUgZQrE2gZFZt1red4El15NcoNxCj6syNnj19i1KuAAAA',
      inputsToSign: [
        {
          address,
          signingIndexes: [1],
          sigHash: 0x82,
        },
      ],
    },
    {
      psbtBase64:
        'cHNidP8BAFMCAAAAAYZhHMQ1Mjf1j3mtKvSHg128Nird1Lz62NyvyCF+xvG/AQAAAAD/////ATCmBwAAAAAAF6kUoaCqiRUca/0Ct3DHsaLnYllpTLiHAAAAAAj8Am1lA3NpZ0ALaP+AC+tlBfBS6QdQEv1c8blRxYKVxCdL/MEmw1DMoQEWySlU3ejsBZ+Nh+IjpAWUWYyOSdmpJgdUmPfvolpdC/wCbWUGc2lnZXhwCEJ5Hs28doAAAAEBKyICAAAAAAAAIlEg39xRNMrlIZlVJKDvuPjChZEYR0U314t+SXHBxHd08SMBAwSDAAAAARcgSuLJW58BUTAvZxKpS0E4abC/u9pAXsb/SeTXM/CrP/MADvwCbWUJcHJpY2VTYXRzBjUwMDAwMAA=',
      inputsToSign: [
        {
          address: addressOrdinals,
          signingIndexes: [0],
          sigHash: 0x83,
        },
      ],
    },
  ],
}

const request = jsontokens.createUnsecuredToken(payload)
```

You can then pass this stringified request into the provider method like so: `window.magicEden.bitcoin.signMultipleTransactions(request)`<br>

| Property  | Type     | Description              |
| --------- | -------- | ------------------------ |
| `request` | `string` | The json encoded payload |

#### Response

| Property                             | Type     | Description                                       |
| ------------------------------------ | -------- | ------------------------------------------------- |
| `Promise<SignTransactionResponse[]>` | `object` | Array of the returned psbt in base64 and the txId |

#### `SignTransactionResponse` Response Properties

| Property     | Type     | Description                           |
| ------------ | -------- | ------------------------------------- |
| `psbtBase64` | `string` | The base64 encoded psbt string        |
| `txId`       | `string` | an optional transaction Id on success |


# Provider Events

## Provider Events

### **`accountsChanged`** <a href="#accountschanged" id="accountschanged"></a>

#### **Description**

An event that is emitted when a user changes the account they are looking at on the ME Wallet

**Properties**

| Property   | Type               | Description                                                     |
| ---------- | ------------------ | --------------------------------------------------------------- |
| `accounts` | `BitcoinAccount[]` | The array of `BitcoinAccount` objects from the user's ME wallet |

`BitcoinAccount` **Response Properties**

| Property  | Type                             | Description                                                                                                            |
| --------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `address` | `string`                         | The user's BTC address                                                                                                 |
| `purpose` | `enum - 'payment' \| 'ordinals'` | The purpose of the address is used to indicate whether this address is preferrably used for payments or ordinals/runes |


# FAQs

<details>

<summary>Lot of talk of Sats Connect, why don't your method calls match their <a href="https://docs.xverse.app/sats-connect">newest documentation</a>?</summary>

Sats Connect recently upgraded to a newer version, where RPC calls follow a more general `Wallet.request` format. The ME wallet currently does not support this new format for invoking requests.

We also do not support any of the Xverse custom methods or Stacks methods

</details>

<details>

<summary>Why is Xverse prompting when I try to connect to Magic Eden wallet?</summary>

For apps that try to connect to the ME wallet via the `BitcoinProvider`, there can be namespace clashing if a user has BOTH the ME wallet and Xverse wallet installed. See [Detecting the Provider](/bitcoin/detecting-the-provider) for more info.

</details>

<details>

<summary>Why is Xverse prompting when I try to invoke Sats Connect functions for the Magic Eden wallet?</summary>

Sats Connect will default to their `BitcoinProvider` object in the window if no provider is explictly passed to ANY of the Sats Connect calls. In the case where a user has multiple BTC wallets installed on their browser, this can create some confusion.

You can ensure that the ME wallet is always called properly by specifying the provider in each and every Sats Connect call. the `getProvider` param is accepted in all their method calls.

Here's an example, notice the use of `getProvider` within the `sendBtcTransaction` call:

```typescript
import { sendBtcTransaction, BitcoinNetworkType } from "sats-connect";
	
const getBtcProvider = (): any | undefined => {
	if ("magicEden" in window) {
		const anyWindow: any = window;
		if (anyWindow.magicEden.bitcoin) return anyWindow.magicEden.bitcoin;
	}
};
	
// in a real app, you'll use the ME 'payment' address returned after a connection
const nativeSegwitAddress = 'bc1qcdmvsc8qqk8sr2st3mttu6fsmfrjzh5xrf4dch'
const recipientAddress = 'dummyAddress'

await sendBtcTransaction({
  getProvider: getBtcProvider,
  payload: {
    network: {
      type: BitcoinNetworkType.Mainnet,
    },
    recipients: [
      {
        address: recipientAddress!,
        amountSats: BigInt(1500),
      },
    ],
    senderAddress: nativeSegwitAddress!,
  },
  onFinish: (response) => {
    alert(response);
  },
  onCancel: () => alert("Canceled"),
});
```

</details>


# Diving Into Solana

## Solana Wallet Adapter

The [Solana Wallet Adapter](https://github.com/anza-xyz/wallet-adapter) is the most common way for solana dApps to incorporate wallet connection and management. Follow the instructions on their [github](https://github.com/anza-xyz/wallet-adapter) to get started. With the Solana Wallet Adapter, the ME wallet works automatically, out of the box.

If you are interested in building a new dApp on Solana, consider checking [create-solana-dapp](https://github.com/solana-developers/create-solana-dapp) which makes use of the Solana Wallet Adapter from the jump.

## Direct Integration

You also have the option of connecting directly to the Magic Eden wallet via the provider injected into your web application. The provider is available at `window.magicEden.solana`

We'll explore this later in the docs.


# Solana Wallet Adapter

## Overview

The [SWA (Solana Wallet Adapter)](https://github.com/anza-xyz/wallet-adapter) is built on top of the [Wallet Standard](https://github.com/anza-xyz/wallet-standard), both of which are maintained by [Anza](https://x.com/anza_xyz), a Solana focused dev shop stemming from Solana Labs.\
\
This is the most widely used solution in the Solana ecosystem to connect dApps -> Wallets, so we encourage teams to consider using SWA. You get plenty of UI customization options, while ensuring your app can connect to all major Solana wallets.

{% hint style="info" %}
**Note:**&#x20;

If you implement Solana Wallet Adapter on your app, Magic Eden Wallet should work out of the box.
{% endhint %}

Let's dive into a quick React demo.

## Install

Install the adapter specific dependencies

```
npm install --save \
    @solana/wallet-adapter-base \
    @solana/wallet-adapter-react \
    @solana/wallet-adapter-react-ui \
```

## Guide

### Create a SolanaProvider Component

Create a `SolanaProvider` component that will wrap your application. The goal of this component is to setup a connection to the Solana blockchain on a given network and communicate with via the specified RPC url.\
\
The component wraps its children with providers that pass down the blockchain connection and wallet context, allowing child components to interact with the Solana blockchain.

```jsx
'use client';

import dynamic from 'next/dynamic';
import { WalletError } from '@solana/wallet-adapter-base';
import {
  ConnectionProvider,
  WalletProvider,
} from '@solana/wallet-adapter-react';
import { WalletModalProvider } from '@solana/wallet-adapter-react-ui';
import { ReactNode, useCallback, useMemo } from 'react';
import { useCluster } from '../cluster/cluster-data-access';

require('@solana/wallet-adapter-react-ui/styles.css');

export const WalletButton = dynamic(
  async () =>
    (await import('@solana/wallet-adapter-react-ui')).WalletMultiButton,
  { ssr: false }
);

export function SolanaProvider({ children }: { children: ReactNode }) {
  const { cluster } = useCluster();
  const endpoint = useMemo(() => cluster.endpoint, [cluster]);
  const onError = useCallback((error: WalletError) => {
    console.error(error);
  }, []);

  return (
    <ConnectionProvider endpoint={endpoint}>
      <WalletProvider wallets={[]} onError={onError} autoConnect={true}>
        <WalletModalProvider>{children}</WalletModalProvider>
      </WalletProvider>
    </ConnectionProvider>
  );
}
```

We've also gone ahead and created a WalletButton we can import into our Navbar / UI layout from the wallet adapter packages.

{% hint style="info" %}
You'll notice a custom `useCluster` method used in the above snippet. This is just a helper function to specify the desired cluster (devnet, mainnet, etc) + the associated RPC details. Hardcoding this information is also fine. Learn more here: <https://solana.com/docs/core/clusters>
{% endhint %}

### Wrap your App with the SolanaProvider

Next we are going to wrap our React application with the `SolanaProvider` component we created above. It may look something like this

```jsx
import './global.css';
import { UiLayout } from '@/components/ui/ui-layout';
import { SolanaProvider } from '@/components/solana/solana-provider';
import { ReactQueryProvider } from './react-query-provider';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <ReactQueryProvider>
            <SolanaProvider>
              <UiLayout>{children}</UiLayout>
            </SolanaProvider>
        </ReactQueryProvider>
      </body>
    </html>
  );
}
```

### Add the Wallet Button to your UI Layout / Navbar

Finally, add the `WalletButton` created in the first step to your UI. It is most common to add to your Navbar, or a UiLayout you can wrap your app in, but theoretically you can place this button wherever you please.

```jsx
'use client';

import { WalletButton } from '../solana/solana-provider';
import * as React from 'react';

export function SimplifiedLayout() {
  return (
    <div>
      <div className="flex-none">
        <WalletButton />
      </div>
    </div>
  );
}
```

## Additional Resources

Feel free to reference the popular [create-solana-dapp](https://github.com/solana-developers/create-solana-dapp) for full context on how to implement the Solana Wallet Adapter in a functional custom Solana application.<br>


# Connect Directly to the ME Solana Provider

## Detecting the Provider

If you've built a custom wallet connection solution and want to add support for the Magic Eden Wallet, you can directly access the Solana Provider at `magicEden.solana` in the Window.

A code snippet to find the provider might look like the following:

```javascript
const getProvider = () => {
  // check if the magicEden object is available
  if ('magicEden' in window) {
    const magicProvider = window.magicEden?.solana;
    if (magicProvider?.isMagicEden) {
      return magicProvider;
    }
  }
  window.location.href = 'https://wallet.magiceden.io/'
};
```

The above will return the provider if the user has the extension installed, otherwise it'll redirect the user to the magic eden wallet website to download it.

## Connecting

Once the magicEden provider object has been found, a user is able to connect their wallet to the site. The connection request will prompt the user to approve the connection, so that their wallet can be used to make requests, such as sending transactions.

The easiest way to connect to the ME wallet is by calling `window.magicEden.solana.connect()`

```javascript
const provider = getProvider();

const handleConnect = async () => {
  try {
    await provider.connect();
  } catch (error) {
    console.error(error);
  }
};
```

The provider saves information like a user's pubkey once a connection has been established.

### More Info

A code demo for basic ME wallet connection can be found [here](https://github.com/Tcadle434/me-wallet-solana-react). A demo video can be found in the readme.


# Signing a Message

Once a web application has connected to the ME Solana wallet, it can prompt users to sign a message, send transactions, and more. Signing is commonplace amongst many dApps, as it gives application owners the ability to verify ownership of the wallet. Signing a message does not require any transaction fees.

To invoke, you can call the `signMessage` method on the provider directly.

```javascript
import { MagicEdenProvider } from "../types/types";

/**
 * Prompts the user to sign a message using the MagicEden Provider object
 * @param {MagicEdenProvider} provider The MagicEdenProvider object
 * @param {string} message The message to sign
 * @returns {Promise<string>} A promise that resolves to the signed message
 * @throws {Error} If an unexpected error occurs while signing the message
 */
export const signMessage = async (
  provider: MagicEdenProvider,
  message: string
): Promise<string> => {
  try {
    const encodedText = new TextEncoder().encode(message);
    const signedMessage = await provider.signMessage(encodedText);
    return signedMessage;
  } catch (error) {
    console.warn(error);
    throw new Error("An unexpected error occured while signing the message.");
  }
};
```

Signing a message is relatively simple and doesn't require any real interaction with web3 libraries. Check out the [signMessage](https://github.com/Tcadle434/me-wallet-solana-react/blob/main/src/utils/signMessage.ts) functionality in the demo app for a more well rounded implementation.


# Sending a Transaction

Sending a transaction on the Solana network requires the creation of a Transaction object, followed by the transaction being signed and submitted by the user's Magic Eden wallet.

{% hint style="info" %}
:green\_book:**Solana Web3js**

For more information on interacting with Solana on the client side, check out the docs for [Solana Web3js](https://solana-labs.github.io/solana-web3.js/)

For more general Solana development information, check out the courses and resources offered on [Soldev](https://www.soldev.app/)
{% endhint %}

## Creating a Transaction

Before you can sign or send a transaction, you must create one! Below is a basic example of creating a tx that has a user send funds right back to themselves

```javascript
import {
  Transaction,
  SystemProgram,
  Connection,
  PublicKey,
} from "@solana/web3.js";

/**
 * Creates an example transaction to transfer 100 lamports to the same account.
 * @param {String} publicKey a wallet public key
 * @param {Connection} connection an RPC connection
 * @returns {Transaction} a transaction
 */
export const createTransaction = async (
  publicKey: PublicKey,
  connection: Connection
): Promise<Transaction> => {
  const latestBlockhash = (await connection.getLatestBlockhash()).blockhash;
  const transaction = new Transaction().add(
    SystemProgram.transfer({
      fromPubkey: publicKey,
      toPubkey: publicKey,
      lamports: 1000,
    })
  );
  transaction.feePayer = publicKey;
  transaction.recentBlockhash = latestBlockhash;

  return transaction;
};

```

## Signing and Sending a Transaction

Once the transaction is created, you can then prompt the user to sign and send it using the `signAndSendTransaction` method exposed by the provider

```javascript
import { Transaction } from "@solana/web3.js";

import { MagicEdenProvider } from "../types/types";

/**
 * Signs and sends the given created transaction using the MagicEdenProvider object.
 * @param {MagicEdenProvider} provider The MagicEdenProvider object
 * @param {Transaction} transaction The transaction to sign and send
 * @returns {Promise<string>} A promise that resolves to the signature of the transaction
 */
export const signAndSendTransaction = async (
  provider: MagicEdenProvider,
  transaction: Transaction
): Promise<string> => {
  try {
    const { signature } = await provider.signAndSendTransaction(transaction);
    return signature;
  } catch (error) {
    console.warn(error);
    throw new Error(
      "An unexpected error occured while signing the transaction."
    );
  }
};

```

All of this functionality and more can be found at our [Solana Demo](https://github.com/Tcadle434/me-wallet-solana-react/blob/main/src/App.tsx), so feel free to check it out if you want to learn more about handling wallet functionality when connecting directly to the Magic Eden wallet.

{% hint style="info" %}
**Note** :pencil:\
The signAndSendTransaction method supports both Legacy and [Versioned Transactions](https://solana.com/docs/advanced/versions). The newer Versioned Txs allow for [Address Lookup Tables](https://solana.com/docs/advanced/lookup-tables)
{% endhint %}


# Provider API Methods

The ME Wallet follows the specs defined in the [Solana Wallet Standard ](https://github.com/anza-xyz/wallet-standard/tree/master)

## Provider Methods

### `Connect`

Prompts a connection to a user's Magic Eden Wallet account.

#### Params

| Property        | Type      | Description   |
| --------------- | --------- | ------------- |
| `onlyIfTrusted` | `boolean` | Optional flag |

#### Response

| Property                          | Type        | Description                                                                                                           |
| --------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------- |
| `Promise<{publicKey: PublicKey}>` | `PublicKey` | The returned [PublicKey](https://solana-labs.github.io/solana-web3.js/classes/PublicKey.html) of the connected wallet |

### `signMessage`

Prompts to sign a message with the user's connected Magic Eden Wallet account

#### Params

| Property  | Type                   | Description                                |
| --------- | ---------------------- | ------------------------------------------ |
| `message` | `Uint8Array \| string` | The message to sign for                    |
| `display` | `"utf8" \| "hex"`      | Encoding format for displaying the message |

#### Response

| Property                                              | Type                | Description                                                                                                                                 |
| ----------------------------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `Promise<{ signature: Bytes; publicKey: PublicKey }>` | `Bytes & PublicKey` | The signed message in Bytes and the associated [PublicKey](https://solana-labs.github.io/solana-web3.js/classes/PublicKey.html) that signed |

### `signAndSendTransaction`

Prompts to both sign and send a transaction with the user's connected Magic Eden Wallet account

#### Params

| Property             | Type                                    | Description                                                                                                                                                                                                                       |
| -------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `transactionOrBytes` | `LegacyOrVersionedTransaction \| Bytes` | A [Transaction](https://solana-labs.github.io/solana-web3.js/classes/Transaction.html) or [VersionedTransaction](https://solana-labs.github.io/solana-web3.js/classes/VersionedTransaction.html) object, or the associated bytes. |
| `options`            | `SendOptions`                           | Options for sending transactions                                                                                                                                                                                                  |

where `SendOptions` is defined as such:

```typescript
export declare type SendOptions = {
    /** disable transaction verification step */
    skipPreflight?: boolean;
    /** preflight commitment level */
    preflightCommitment?: Commitment;
    /** Maximum number of times for the RPC node to retry sending the transaction to the leader. */
    maxRetries?: number;
    /** The minimum slot that the request can be evaluated at */
    minContextSlot?: number;
};

export declare type Commitment = 'processed' | 'confirmed' | 'finalized' | 'recent' | 'single' | 'singleGossip' | 'root' | 'max';
```

#### Response

| Property                                | Type              | Description               |
| --------------------------------------- | ----------------- | ------------------------- |
| Promise<{ signature: string \| Bytes }> | `string \| Bytes` | The transaction signature |

### `signTransaction`

Prompts to sign a transaction (but not send) with the user's connected Magic Eden Wallet account

#### Params

| Property             | Type                                    | Description                                                                                                                                                                                                                                 |
| -------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `transactionOrBytes` | `LegacyOrVersionedTransaction \| Bytes` | An unsigned [Transaction](https://solana-labs.github.io/solana-web3.js/classes/Transaction.html) or [VersionedTransaction](https://solana-labs.github.io/solana-web3.js/classes/VersionedTransaction.html) object, or the associated bytes. |

#### Response

| Property                                         | Type                                    | Description                                                                                                                                                                                                                              |
| ------------------------------------------------ | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Promise<LegacyOrVersionedTransaction \| Bytes>` | `LegacyOrVersionedTransaction \| Bytes` | A signed [Transaction](https://solana-labs.github.io/solana-web3.js/classes/Transaction.html) or [VersionedTransaction](https://solana-labs.github.io/solana-web3.js/classes/VersionedTransaction.html) object, or the associated bytes. |

### `signAllTransactions`

Prompts to sign all passed transactions (but not send) with the user's connected Magic Eden Wallet account

Prompts to sign a transaction (but not send) with the user's connected Magic Eden Wallet account

#### Params

| Property             | Type                                        | Description                                                                                                                                                                                                                                             |
| -------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `transactionOrBytes` | `(LegacyOrVersionedTransaction \| Bytes)[]` | An unsigned [Transaction](https://solana-labs.github.io/solana-web3.js/classes/Transaction.html) or [VersionedTransaction](https://solana-labs.github.io/solana-web3.js/classes/VersionedTransaction.html) object array, or the associated bytes array. |

#### Response

| Property                                             | Type                                        | Description                                                                                                                                                                                                                                          |
| ---------------------------------------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Promise(<LegacyOrVersionedTransaction \| Bytes>)[]` | `(LegacyOrVersionedTransaction \| Bytes)[]` | A signed [Transaction](https://solana-labs.github.io/solana-web3.js/classes/Transaction.html) or [VersionedTransaction](https://solana-labs.github.io/solana-web3.js/classes/VersionedTransaction.html) object array, or the associated bytes array. |


# Provider Events

## Provider Events

### **`accountChanged`** <a href="#accountschanged" id="accountschanged"></a>

#### **Description**

An event that is emitted when a user changes the account they are looking at on the ME Wallet

**Properties**

| Property   | Type       | Description                                              |
| ---------- | ---------- | -------------------------------------------------------- |
| `accounts` | `string[]` | The array of string publicKeys from the user's ME wallet |


# FAQs

*coming soon...*


# Diving into the EVM

Web applications can interact with the Magic Eden Wallet via the injected provider at `window.magiceden.ethereum`. This provider conforms to the [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) standard and is also injected at `window.ethereum` to support legacy integrations.&#x20;

The Magic Eden wallet also supports [EIP-6963](https://eip6963.org/) to conform to the latest wallet standards and be as globally available as possible on all EVM dApps + wallet connection solutions.

## Direct Integration

You can connect directly to the Magic Eden wallet and facilitate all interactions from there via the `window.magiceden.ethereum` provider. We'll get to the steps required for this later on in this section.

## Wallet Adapter Frameworks

The ME wallet is also available out of the box on the EVM's most widely used wallet connection libraries, including:

* [Wallet Connect](https://walletconnect.com/)
* [Rainbow Kit](https://www.rainbowkit.com/)
* [Wagmi](https://wagmi.sh/)

EIP-6963 integration also ensures that users with the ME wallet already installed on their browser can use it in places where there might not be explicit support. Examples include:

* [Dynamic](https://www.dynamic.xyz/)
* [Privy](https://www.privy.io/)
* and many more


# Connect Directly to the ME EVM Provider

## Detecting the Provider

If you've built a custom wallet connection solution and want to add support for the Magic Eden Wallet, you can directly access the EVM Provider at `magicEden.ethereum` in the Window.

A code snippet to find the provider might look like the following:

```javascript
const getProvider = () => {
  // check if the magicEden object is available
  if ('magicEden' in window) {
    const magicProvider = window.magicEden?.ethereum;
    if (magicProvider?.isMagicEden) {
      return magicProvider;
    }
  }
  window.location.href = 'https://wallet.magiceden.io/'
};
```

The above will return the provider if the user has the extension installed, otherwise it'll redirect the user to the magic eden wallet website to download it.

{% hint style="info" %}
**Note:**

An actual production implementation to detect the provider might want to make use of timeout + some sort of loop to give the provider object time to inject in the window.
{% endhint %}

## Connecting

Once the magicEden provider object has been found, a user is able to connect their wallet to the site. The connection request will prompt the user to approve the connection, so that their wallet can be used to make requests, such as sending transactions and signing messages.

The default way to prompt a connection with a user's ME wallet is with the `window.ethereum.request` function and passing in the `eth_requestAccounts` method.

```typescript
const connect = async () => {
  if (!provider) return;
  try {
    const accounts = await provider.request({ method: "eth_requestAccounts" });
    console.log(accounts[0]);
    // 0x6aDdF38602487b7a159D926bc08151eBaEEF2B70
    
    // do some logic here to update your app context with the connected account	
  } catch (err) {
      console.error(err);
  }
};
```

The `eth_requestAccounts` method will return a Promise that resolves into an array where the connected address is at the 0th index.


# Signing a Message

Once a web application has connected to the ME Ethereum wallet, it can prompt users to sign messages. Signing is commonplace amongst many dApps, as it gives application owners the ability to verify ownership of the wallet, without requiring any transaction fees.

## Direct Signing

Triggering this directly would look make use of the provider `request` function and look like this:

```typescript
const message =
	"Hello, World! 🌍 Welcome to the Magic Eden wallet on Ethereum";

// can also use Buffer.from for a simpler implementation, but polyfills :/
const msg =
	"0x" +
	Array.from(message)
		.map((c) => c.charCodeAt(0).toString(16).padStart(2, "0"))
		.join("");
const sign = await provider.request({
	method: "personal_sign",
	params: [msg, address, "Example password"],
});
```

## Using Ethers.js

Alternatively, you can make use of the popular web3 javascript library [ethers.js](https://docs.ethers.org/v5/) to abstract away some of the above complexity. Instead of directly invoking `personal_sign` on the provider `request`, you can wrap the ME browser provider in a `Web3Provider` object from ethers. Doing so allows you to invoke the `signMessage` function directly.

```typescript
 const signer = await provider?.getSigner();
 await signer!.signMessage(
   "Hello, World! 🌍 Welcome to the Magic Eden wallet on Ethereum"
 );
```


# Sending a Transaction

To send a transaction, you must construct a valid transaction object and then prompt the user to sign the transaction with their private key.

## Direct Sending

Triggering this directly would look make use of the provider `request` function and look like this:

```javascript
const result = await provider.request({
        method: 'eth_sendTransaction',
        params: [
          {
            from: address,
            to: '0x6aDdF38602487b7a159D926bc08151eBaEEF2B70',
            value: '0x0',
            gasLimit: '0x5028',
            gasPrice: '0x2540be400',
            type: '0x0',
          },
        ],
});
```

However, there are several other parts of a transaction object that might need to be specfied, and therefore it is suggested to make use of a web3 library that abstracts away a lot of this complexity, like [ethers.js](https://docs.ethers.org/v5/)

## Using Ethers.js

Below is a code example that builds out a valid transaction object and prompts the transaction to send with permission from the signer, utilizing ethers.js

```typescript
import { TransactionResponse, Web3Provider } from "@ethersproject/providers";
import { utils } from "ethers";

/**
 * Send 1 wei from the connected wallet to itself
 * @param {Web3Provider} provider a web3 provider
 * @returns {Promise<TransactionResponse>} a raw transaction object
 */
export async function sendTransaction(
  provider: Web3Provider
): Promise<TransactionResponse> {
  try {
    const signer = provider.getSigner();
    const address = await signer.getAddress();
    const gasPrice = await provider.getGasPrice();
    const transactionParameters = {
      nonce: await provider.getTransactionCount(address),
      gasPrice,
      gasLimit: utils.hexlify(100000),
      to: address,
      from: address,
      value: utils.parseUnits("1", "wei"),
    };
    return signer.sendTransaction(transactionParameters);
  } catch (error) {
    console.warn(error);
    throw new Error("Error sending transaction");
  }
}

```

You'll notice a lot more structure with the parameters needed to invoke `signer.sendTransaction` . Due to the abstraction and wide use of libraries like ethers, we recommend this method when constructing your evm transactions. &#x20;


# Library Integrations

Here we will cover a number of EVM wallet connection frameworks that are compatible with the ME wallet. There are numerous benefits for using any of these solutions as they provide an even greater level of abstraction away from the provider and come with native support for many popular injected wallets.

Specifically, we will look at:

* [Wallet Connect](https://walletconnect.com/)
* [Rainbow Kit](https://www.rainbowkit.com/)
* [Wagmi](https://wagmi.sh/)

We'll ignore other solutions that don't (yet) have native integration for the ME wallet, even if you are able to use it via [EIP-6963](https://eip6963.org/)


# Wallet Connect

the ME wallet works out of the box with the wallet connect [Appkit](https://docs.walletconnect.com/appkit/overview) / [Web3modal](https://github.com/WalletConnect/web3modal/tree/V2). Their documentation is extensive, so we will keep this short.

Here we'll walk through an example in React, but check out [their docs](https://docs.walletconnect.com/appkit/overview) for other compatible frameworks.

## Install Dependencies

```
npm install @web3modal/wagmi wagmi viem @tanstack/react-query
```

## Register your App

Head to <https://cloud.walletconnect.com/sign-in> to register your app. You'll need the project Id to complete your setup

## Implementation

The implementation steps make use of [Wagmi](https://wagmi.sh/), and the `defaultWagmiConfig` we can import from web3Modal. We can customize this to strictly make use of the ME wallet or any specific wallet, but the default config is good for our use case.

Here is a code example pulled from the Wallet Connect docs

```jsx
import { createWeb3Modal } from '@web3modal/wagmi/react'
import { defaultWagmiConfig } from '@web3modal/wagmi/react/config'

import { WagmiProvider } from 'wagmi'
import { arbitrum, mainnet } from 'wagmi/chains'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

// 0. Setup queryClient
const queryClient = new QueryClient()

// 1. Get projectId from https://cloud.walletconnect.com
const projectId = 'YOUR_PROJECT_ID'

// 2. Create wagmiConfig
const metadata = {
  name: 'Web3Modal',
  description: 'Web3Modal Example',
  url: 'https://web3modal.com', // origin must match your domain & subdomain
  icons: ['https://avatars.githubusercontent.com/u/37784886']
}

const chains = [mainnet] as const
const config = defaultWagmiConfig({
  chains,
  projectId,
  metadata,
})

// 3. Create modal
createWeb3Modal({
  wagmiConfig: config,
  projectId,
  enableAnalytics: true, // Optional - defaults to your Cloud configuration
  enableOnramp: true // Optional - false as default
})

export function Web3ModalProvider({ children }) {
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
    </WagmiProvider>
  )
}
```

## Opening the Modal

We can also make use of the out of the box `<w3m-button/>` directly from the web3Modal

```jsx
export default function ConnectButton() {
  return <w3m-button />
}
```

## Wrap the App in the Web3ModalProvider

Finally, wrap your app in the Web3ModalProvider you exported in the implementation phase

```jsx
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { Web3ModalProvider } from "./App";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <Web3ModalProvider>
      <App />
    </Web3ModalProvider>
  </React.StrictMode>
);
```

If all is configured correctly, you should have out of the box wallet connection functionality for the EVM that will look like this:

<figure><img src="https://3057797283-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUE3YlWFGNzodYaTOyoul%2Fuploads%2FgR9qBg26AoJqvoLo3A5O%2FScreenshot%202024-07-08%20at%206.00.14%E2%80%AFPM.png?alt=media&amp;token=dc83418d-86ed-4732-b86c-724088e7ecec" alt=""><figcaption></figcaption></figure>

You'll notice that installed wallets automatically show up at the top of the modal. [EIP-6963](https://eip6963.org/) for the win.


# Rainbow Kit

This tutorial will illustrate a step-by-step walkthrough in NextJS of how to setup a project using [RainbowKit](https://www.rainbowkit.com/docs/introduction) and how to set up a custom wallet list that recommends the ME Wallet.

{% hint style="info" %}
**Note:**

The ME wallet works out of the box in the RainbowKit default config if a user has the wallet installed on their browser, because all installed wallets that conform to EIP-6963 will be detected. This guide is to illustrate how you can control the specific wallets shown in a custom list.
{% endhint %}

## Installation

```
npm install @rainbow-me/rainbowkit wagmi viem@2.x @tanstack/react-query
```

## Implementation

Here we will import the necessary libraries, create a custom `connectors` list, and a config that communicates with those connectors and Ethereum mainnet.

Once you've done that, you can wrap your application with `RainbowKitProvider`, [`WagmiProvider`](https://wagmi.sh/react/api/WagmiProvider#wagmiprovider), and [`QueryClientProvider`](https://tanstack.com/query/v4/docs/framework/react/reference/QueryClientProvider).

```tsx
import "../styles/globals.css";
import "@rainbow-me/rainbowkit/styles.css";
import type { AppProps } from "next/app";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { WagmiProvider } from "wagmi";
import { RainbowKitProvider, connectorsForWallets } from "@rainbow-me/rainbowkit";
import { magicEdenWallet } from "@rainbow-me/rainbowkit/wallets";
import { http, createConfig } from "wagmi";
import { mainnet } from "wagmi/chains";

const connectors = connectorsForWallets(
	[
		{
			groupName: "Recommended",
			wallets: [magicEdenWallet],
		},
	],
	{
		appName: "My RainbowKit App",
		projectId: "YOUR_PROJECT_ID",
	}
);

const config = createConfig({
	connectors,
	chains: [mainnet],
	ssr: true,
	transports: {
		[mainnet.id]: http(),
	},
});

const client = new QueryClient();

function MyApp({ Component, pageProps }: AppProps) {
	return (
		<WagmiProvider config={config}>
			<QueryClientProvider client={client}>
				<RainbowKitProvider>
					<Component {...pageProps} />
				</RainbowKitProvider>
			</QueryClientProvider>
		</WagmiProvider>
	);
}

export default MyApp;
```

## Add the Connect Button

In your `index.tsx` file, go ahead and add the `ConnectButton` supplied by RainbowKit

```tsx
import { ConnectButton } from "@rainbow-me/rainbowkit";
import type { NextPage } from "next";
import Head from "next/head";
import styles from "../styles/Home.module.css";

const Home: NextPage = () => {
	return (
		<div className={styles.container}>
			<Head>
				<title>RainbowKit App</title>
				<meta content="Generated by @rainbow-me/create-rainbowkit" name="description" />
				<link href="/favicon.ico" rel="icon" />
			</Head>

			<main className={styles.main}>
				<ConnectButton />
			</main>
		</div>
	);
};

export default Home;

```

And that's all. When you trigger the button, you should get a nice modal that recognizes installed wallets and sets up the ME wallet in a standalone "reccommended" catagory. It may look something like this:

<figure><img src="https://3057797283-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUE3YlWFGNzodYaTOyoul%2Fuploads%2FHRiT6OqeYeW2jkvfnauN%2FScreenshot%202024-07-08%20at%206.19.57%E2%80%AFPM.png?alt=media&amp;token=103053e5-c1cf-46a0-8044-fdce923773da" alt=""><figcaption></figcaption></figure>


# Wagmi

## Getting Started

If you are interested in using WAGMI in your brand new react application, follow the instructions [here](https://wagmi.sh/react/getting-started) to initialize your app with the CLI. Otherwise, follow the instructions below.

First you will need to install [WAGMI](https://wagmi.sh/react/installation)

```shell
pnpm add wagmi viem@2.x @tanstack/react-query
```

## WAGMI Config Setup

Next you will need to create a wagmi config file:\
In this example you can find it under `wagmi-config.ts`

Here you need to create the default WAGMI config, and under connector, add a\
Magic Eden Wallet Injector.

This is necessary to have WAGMI pick up the Magic Eden Wallet option,\
and add it to the Wallet Options a user can choose from.

```jsx
import { http, createConfig } from "wagmi";
import { mainnet, sepolia } from "wagmi/chains";
import { coinbaseWallet, injected } from "wagmi/connectors";

// Extend the global Window interface directly in this file
declare global {
  interface Window {
    magicEden?: {
      ethereum?: {
        request: (args: { method: string; params?: any[] }) => Promise<any>;
        on: (event: string, handler: (...args: any[]) => void) => void;
        removeAllListeners: () => void;
        // Add other methods and properties as needed
      };
    };
  }
}

// Define the Magic Eden Wallet Connector
const ME_CONNECT = injected({
  target() {
    const provider =
      typeof window !== "undefined" ? window.magicEden?.ethereum : undefined;
    return {
      id: "Magic Eden",
      name: "Magic Eden",
      provider: provider as any, // We still use `any` here to bypass strict type checking for the provider from WAGMI
    };
  },
});

// Create the configuration
export const config = createConfig({
  chains: [mainnet, sepolia],
  connectors: [ME_CONNECT, coinbaseWallet({ appName: "Create Wagmi" })],
  ssr: true,
  transports: {
    [mainnet.id]: http(),
    [sepolia.id]: http(),
  },
});

// Declare the module to register the config type with wagmi
declare module "wagmi" {
  interface Register {
    config: typeof config;
  }
}

```

## Setup WAGMI Provider and QueryClient

Once you have the config setup, you need to wrap your page or app with\
`WagmiProvider` using the config object we previously created, and `QueryClient`.

> If using NextJS 14 with App Router, make sure you add `use client;` at the top of the file.

```jsx
"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

export default function EvmDemoPage() {
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <div className="flex min-h-screen flex-col items-center justify-between p-24">
          {wallet component will go here}
        </div>
      </QueryClientProvider>
    </WagmiProvider>
  );
}
```

## Display Wallet Options Component

Once we have the page setup, we need to create components that handle:

1. Detects Wallet Options from WAGMI.
2. Shows Wallet Options.
3. Handles selecting and authenticating a wallet.
4. Handles disconnecting a wallet.

### Update Imports

Start by updating your imports:

```jsx
"use client";
import {
  Connector,
  WagmiProvider,
  useAccount,
  useConnect,
  useDisconnect,
  useEnsAvatar,
  useEnsName,
} from "wagmi";
import { config } from "../../../wagmi-config";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { useState, useEffect } from "react";
```

### Display Wallet Options

Next create a component that detects and displays all wallets available.

This code creates a `WalletOptions` component that uses the `useConnect` hook from the `wagmi` library to get a list of available wallet connectors. It then maps over these connectors to create a `WalletOption` component for each one.

The `WalletOption` component takes a `connector` and an `onClick` function as props. It uses the `useState` and `useEffect` hooks from React to check if the provider for the given connector is ready. If the provider is ready, it enables a button that displays the name of the connector and calls the `onClick` function when clicked.

This allows users to see all available wallet options and connect to their chosen wallet.

```jsx
export function WalletOptions() {
  const { connectors, connect } = useConnect();

  return connectors.map((connector) => (
    <WalletOption
      key={connector.uid}
      connector={connector}
      onClick={() => connect({ connector })}
    />
  ));
}

function WalletOption({
  connector,
  onClick,
}: {
  connector: Connector;
  onClick: () => void;
}) {
  const [ready, setReady] = useState(false);

  useEffect(() => {
    (async () => {
      const provider = await connector.getProvider();
      setReady(!!provider);
    })();
  }, [connector]);

  return (
    <button
      disabled={!ready}
      onClick={onClick}
      className="px-4 py-2 rounded border"
    >
      {connector.name}
    </button>
  );
}
```

### Connect an active wallet

Now create a component that handles a wallet being connected and displays the account

This `Account` component handles the display of the connected wallet's account information. It uses the `useAccount` hook from the `wagmi` library to get the address of the connected wallet. It also uses the `useDisconnect` hook to provide a function that can be called to disconnect the wallet.

The `useEnsName` and `useEnsAvatar` hooks are used to get the ENS name and avatar for the connected wallet, if they exist. The ENS name and avatar are then displayed along with the wallet's address.

A button is then provided to allow the user to disconnect their wallet. When this button is clicked, the `disconnect` function provided by the `useDisconnect` hook is called.

This component is designed to be used once a wallet has been connected. If no wallet is connected, it will not display anything.

```jsx
const queryClient = new QueryClient();

export function Account() {
  const { address } = useAccount();
  const { disconnect } = useDisconnect();
  const { data: ensName } = useEnsName({ address });
  const { data: ensAvatar } = useEnsAvatar({ name: ensName! });

  return (
    <div>
      {ensAvatar && <img alt="ENS Avatar" src={ensAvatar} />}
      {address && (
        <div className="px-4 py-2 rounded border">
          {ensName ? `${ensName} (${address})` : address}
        </div>
      )}
      <button onClick={() => disconnect()} className="px-4 py-2 rounded border">
        Disconnect
      </button>
    </div>
  );
}
```

### Create a Connect Wallet Component

Now, create a component that detects when a wallet is present, and if none are connected\
displays all available wallet options.

This `ConnectWallet` component checks if a wallet is already connected using the `isConnected` property from the `useAccount` hook. If a wallet is connected, it returns the `Account` component which displays the connected wallet's account information and provides a disconnect button. If no wallet is connected, it returns the `WalletOptions` component which displays all available wallet options for the user to connect to.

```jsx
function ConnectWallet() {
  const { isConnected } = useAccount();
  if (isConnected) return <Account />;
  return (
    <div className="flex space-x-4">
      <WalletOptions />
    </div>
  );
}
```

### Add Wallet Button to Page or Component

Finally, add your `ConnectWallet` component to your page, and you should now be able to see all wallet options. Select Magic Eden Wallet and use it to transact.

```jsx
export default function EvmDemoPage() {
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <div className="flex min-h-screen flex-col items-center justify-between p-24">
          <ConnectWallet />
        </div>
      </QueryClientProvider>
    </WagmiProvider>
  );
}
```

## Full Page

```jsx
"use client";
import {
  Connector,
  WagmiProvider,
  useAccount,
  useConnect,
  useDisconnect,
  useEnsAvatar,
  useEnsName,
} from "wagmi";
import { config } from "../../../wagmi-config";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { useState, useEffect } from "react";

const queryClient = new QueryClient();

export function WalletOptions() {
  const { connectors, connect } = useConnect();

  return connectors.map((connector) => (
    <WalletOption
      key={connector.uid}
      connector={connector}
      onClick={() => connect({ connector })}
    />
  ));
}

function WalletOption({
  connector,
  onClick,
}: {
  connector: Connector;
  onClick: () => void;
}) {
  const [ready, setReady] = useState(false);

  useEffect(() => {
    (async () => {
      const provider = await connector.getProvider();
      setReady(!!provider);
    })();
  }, [connector]);

  return (
    <button
      disabled={!ready}
      onClick={onClick}
      className="px-4 py-2 rounded border"
    >
      {connector.name}
    </button>
  );
}

export function Account() {
  const { address } = useAccount();
  const { disconnect } = useDisconnect();
  const { data: ensName } = useEnsName({ address });
  const { data: ensAvatar } = useEnsAvatar({ name: ensName! });

  return (
    <div>
      {ensAvatar && <img alt="ENS Avatar" src={ensAvatar} />}
      {address && (
        <div className="px-4 py-2 rounded border">
          {ensName ? `${ensName} (${address})` : address}
        </div>
      )}
      <button onClick={() => disconnect()} className="px-4 py-2 rounded border">
        Disconnect
      </button>
    </div>
  );
}

function ConnectWallet() {
  const { isConnected } = useAccount();
  if (isConnected) return <Account />;
  return (
    <div className="flex space-x-4">
      <WalletOptions />
    </div>
  );
}

export default function EvmDemoPage() {
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <div className="flex min-h-screen flex-col items-center justify-between p-24">
          <ConnectWallet />
        </div>
      </QueryClientProvider>
    </WagmiProvider>
  );
}
```

Congratulations! You should now be able to select and use Magic Eden Wallet in your React app!


# Provider API Methods

## Provider Methods

### `request`

The EVM provider exposes a general `request` function that has support for most wallet related [RPC calls](https://ethereum.org/en/developers/docs/apis/json-rpc/#json-rpc-methods) that you could need. The particular RPC call is passed under the `method` param

#### Params

| Property | Type               | Description                                              |
| -------- | ------------------ | -------------------------------------------------------- |
| `args`   | `RequestArguments` | The request arguments to specify the underlying RPC call |

Where `RequestArguments` is defined as

```typescript
export interface RequestArguments {
  method: string
  params?: unknown[] | Record<string, unknown>
}
```

#### Response

| Property           | Type      | Description |
| ------------------ | --------- | ----------- |
| `Promise<unknown>` | `unknown` | unknown     |

### `isConnected`

`boolean` to see if the ME wallet account is currently connected

#### Params

None

#### Response

| Property  | Type      | Description                                          |
| --------- | --------- | ---------------------------------------------------- |
| `boolean` | `boolean` | flag indicating whether the user is connected or not |


# Provider Events

## Provider Events

### **`accountsChanged`** <a href="#accountschanged" id="accountschanged"></a>

#### **Description**

An event that is emitted when a user changes the account they are looking at on the ME Wallet

**Properties**

| Property   | Type       | Description                                             |
| ---------- | ---------- | ------------------------------------------------------- |
| `accounts` | `string[]` | The array of string addresses from the user's ME wallet |

### **`chainChanged`** <a href="#accountschanged" id="accountschanged"></a>

#### **Description**

An event that is emitted when a user changes the chain they are connected to

**Properties**

| Property  | Type      | Description                             |
| --------- | --------- | --------------------------------------- |
| `chainId` | `ChainId` | The EVM ChainId of the connected chain. |

`chainId` in this instance is just of type `string`.


# FAQs

<details>

<summary>What EVM chains does the ME Wallet support?</summary>

Currently we support Ethereum mainnet, Base and Polygon. Although we are not currently able to naturally support all L2s, we are constantly exploring solutions to expand our visibility across the EVM

</details>


# Demo Apps

## Bitcoin

The [BTC demo app](https://github.com/Tcadle434/me-wallet-bitcoin-react) utilizes the Bitcoin Wallet Standard mentioned in [Detecting the Provider.](/bitcoin/detecting-the-provider)

Keep in mind that[ ](/bitcoin/detecting-the-provider)directly accessing the unique provider in the `window.magicEden.bitcoin` namespace will simplify a lot of the code around the provider. A separate demo is coming soon for that, but referencing the BTC provider code snippets should be easy enough to follow.

<figure><img src="https://3057797283-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUE3YlWFGNzodYaTOyoul%2Fuploads%2FRGAeiUxbEGpc25VZhcHt%2FScreenshot%202024-07-08%20at%206.37.34%E2%80%AFPM.png?alt=media&amp;token=1aeafd4e-57d2-4de4-8032-3e35e887306b" alt=""><figcaption></figcaption></figure>

## Solana

The [Solana demo app](https://github.com/Tcadle434/me-wallet-solana-react) shows off how you can interact with the Magic Eden Solana provider directly.

<figure><img src="https://3057797283-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUE3YlWFGNzodYaTOyoul%2Fuploads%2FTDi3CzMz7aFuyS1ELRJ4%2FScreenshot%202024-07-08%20at%206.39.47%E2%80%AFPM.png?alt=media&amp;token=b15dc7a1-b8cc-47a5-a0de-3218a68c51d6" alt=""><figcaption></figcaption></figure>

## EVM

The [EVM demo app](https://github.com/Tcadle434/me-wallet-ethereum-react) shows off how you can interact with the Magic Eden EVM provider directly using [ethers.js](https://docs.ethers.org/v5/). For code examples on how to use a popular wallet connection libray, please view [Library Integrations](/evm/library-integrations).

<figure><img src="https://3057797283-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUE3YlWFGNzodYaTOyoul%2Fuploads%2FwgvCAzVouRPdNk4Kq7Fy%2FScreenshot%202024-07-08%20at%206.42.36%E2%80%AFPM.png?alt=media&amp;token=c53e2fa9-d231-4a21-b479-1027445d9c49" alt=""><figcaption></figcaption></figure>


# Logos and Brand Assets

## Logos

{% file src="/files/NtJjzQViA1EpyhvT5l59" %}

## Brand Guide

{% file src="/files/d0KexjixBRvB76Bl7sCh" %}

## General

When integrating or displaying assets around the Magic Eden Wallet, please make sure to use our updated logo, which is different from the marketplace logo!

<figure><img src="https://3057797283-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUE3YlWFGNzodYaTOyoul%2Fuploads%2FBZY4ngPcLomMeN76YYAa%2FME_Wallet_ProfilePhoto_400x400.png?alt=media&amp;token=01f8f9b3-4fbe-426a-873c-77724cb03492" alt=""><figcaption></figcaption></figure>


