Skip to content

Commit

Permalink
feat(sdk): Add support for Magic Eden Wallet (#123)
Browse files Browse the repository at this point in the history
* Extract sats-connect wallet methods from xverse wallet

* Update lockfile

* Add support for MagicEden wallet

* Minor fixes to address PR comments

* Remove unnecessary line

* Add Magic Eden selected wallet check

* Minor fixes for PR comments

* Add support for MagicEden wallet

* Add Magic Eden selected wallet check

* Minor fixes for PR comments

* Change all MagicEden to Magic Eden

* Change all MagicEden to Magic Eden

* refactor(magiceden): remove export

* fix(lint): ci

---------

Co-authored-by: Nanosync <[email protected]>
  • Loading branch information
danadi7 and Nanosync authored Feb 22, 2024
1 parent 0e04617 commit dfba3cc
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 7 deletions.
43 changes: 36 additions & 7 deletions apps/browser-tests/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import { useCallback, useMemo, useState } from "react";
import { Address, PSBTBuilder, PSBTBuilderOptions } from "@ordzaar/ordit-sdk";
import * as magiceden from "@ordzaar/ordit-sdk/magiceden";
import * as unisat from "@ordzaar/ordit-sdk/unisat";
import * as xverse from "@ordzaar/ordit-sdk/xverse";

import { RadioInput } from "./components/RadioInput";
import { Select } from "./components/Select";

type WalletProvider = "unisat" | "xverse";
type WalletProvider = "unisat" | "xverse" | "magiceden";

const TESTNET = "testnet" as const;
// const MAINNET = "mainnet" as const;

// Change here to use the network you want to use
// MagicEden only supports mainnet
const network = TESTNET;

async function createAndPreparePsbt(psbtParams: PSBTBuilderOptions) {
const psbt = new PSBTBuilder(psbtParams);
Expand Down Expand Up @@ -54,7 +62,7 @@ function Transactions({
value: amount,
},
],
network: "testnet" as const,
network,
}),
[
amount,
Expand Down Expand Up @@ -87,7 +95,17 @@ function Transactions({
signPsbtResponse = await unisat.signPsbt(psbt.toPSBT());
} else if (provider === "xverse") {
signPsbtResponse = await xverse.signPsbt(psbt.toPSBT(), {
network: "testnet",
network,
inputsToSign: [
{
address: inputAddressInfo.address,
signingIndexes: [0],
},
],
});
} else if (provider === "magiceden") {
signPsbtResponse = await magiceden.signPsbt(psbt.toPSBT(), {
network,
inputsToSign: [
{
address: inputAddressInfo.address,
Expand Down Expand Up @@ -118,7 +136,13 @@ function Transactions({
signMessageResponse = await xverse.signMessage(
message,
inputAddressInfo.address,
"testnet",
network,
);
} else if (provider === "magiceden") {
signMessageResponse = await magiceden.signMessage(
message,
inputAddressInfo.address,
network,
);
} else {
throw new Error("Unknown provider");
Expand Down Expand Up @@ -218,13 +242,17 @@ function App() {

const handleConnect = useCallback(async () => {
if (provider === "unisat") {
const addresses = await unisat.getAddresses("testnet");
const addresses = await unisat.getAddresses(network);
console.log("Unisat Connected: ", addresses);
setConnectedAddresses(addresses);
} else if (provider === "xverse") {
const addresses = await xverse.getAddresses("testnet");
const addresses = await xverse.getAddresses(network);
setConnectedAddresses(addresses);
console.log("Xverse Connected: ", addresses);
} else if (provider === "magiceden") {
const addresses = await magiceden.getAddresses(network);
setConnectedAddresses(addresses);
console.log("MagicEden Connected: ", addresses);
} else {
console.log("Unknown provider", provider);
}
Expand All @@ -248,11 +276,12 @@ function App() {
options={[
{ name: "Unisat", value: "unisat" },
{ name: "Xverse", value: "xverse" },
{ name: "Magic Eden", value: "magiceden" },
]}
value={provider}
disabled={!!connectedAddresses}
/>
<p>Network: Testnet</p>
<p>Network: {network} </p>
<button
type="button"
style={{ marginTop: "12px" }}
Expand Down
1 change: 1 addition & 0 deletions packages/sdk/magiceden.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./dist/magiceden";
5 changes: 5 additions & 0 deletions packages/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./magiceden": {
"import": "./dist/magiceden.js",
"require": "./dist/magiceden.cjs"
},
"./unisat": {
"import": "./dist/unisat.js",
"require": "./dist/unisat.cjs"
Expand All @@ -23,6 +27,7 @@
"files": [
"dist/*",
"index.d.ts",
"magiceden.d.ts",
"unisat.d.ts",
"xverse.d.ts"
],
Expand Down
103 changes: 103 additions & 0 deletions packages/sdk/src/browser-wallets/magiceden/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { Psbt } from "bitcoinjs-lib";
import { BitcoinProvider } from "sats-connect";

import { BrowserWalletNetwork } from "../../config/types";
import { BrowserWalletNotInstalledError, OrditSDKError } from "../../errors";
import {
satsConnectWalletGetAddresses,
satsConnectWalletSignMessage,
satsConnectWalletSignPsbt,
} from "../internal/sats-connect";
import type { SatsConnectSignPSBTOptions } from "../internal/sats-connect/types";
import { BrowserWalletSignResponse, WalletAddress } from "../types";

export interface MagicEdenBitcoinProvider extends BitcoinProvider {
isMagicEden: boolean | undefined;
}

export interface MagicEdenWindow extends Window {
BitcoinProvider?: MagicEdenBitcoinProvider;
}

/**
* Checks if the MagicEden Wallet extension is installed.
*
* @returns `true` if installed, `false` otherwise.
* @throws {OrditSDKError} Function is called outside a browser without `window` object
*/
function isInstalled(): boolean {
if (typeof window === "undefined") {
throw new OrditSDKError("Cannot call this function outside a browser");
}

return (
typeof (window as MagicEdenWindow).BitcoinProvider?.isMagicEden !==
"undefined"
);
}

async function getMagicEdenWalletProvider(): Promise<BitcoinProvider> {
if (!isInstalled()) {
throw new BrowserWalletNotInstalledError(
"Magic Eden not installed or set as prioritised wallet.",
);
}

return window.BitcoinProvider!;
}

async function getAddresses(
network: BrowserWalletNetwork = "mainnet",
): Promise<WalletAddress[]> {
if (!isInstalled()) {
throw new BrowserWalletNotInstalledError(
"Magic Eden not installed or set as prioritised wallet.",
);
}

return satsConnectWalletGetAddresses(getMagicEdenWalletProvider, network);
}

async function signPsbt(
psbt: Psbt,
{
finalize = true,
extractTx = true,
network,
inputsToSign,
}: SatsConnectSignPSBTOptions = { network: "mainnet", inputsToSign: [] },
): Promise<BrowserWalletSignResponse> {
if (!isInstalled()) {
throw new BrowserWalletNotInstalledError(
"Magic Eden not installed or set as prioritised wallet.",
);
}

return satsConnectWalletSignPsbt(getMagicEdenWalletProvider, psbt, {
finalize,
extractTx,
network,
inputsToSign,
});
}

async function signMessage(
message: string,
address: string,
network: BrowserWalletNetwork = "mainnet",
): Promise<BrowserWalletSignResponse> {
if (!isInstalled()) {
throw new BrowserWalletNotInstalledError(
"Magic Eden not installed or set as prioritised wallet.",
);
}

return satsConnectWalletSignMessage(
getMagicEdenWalletProvider,
message,
address,
network,
);
}

export { getAddresses, isInstalled, signMessage, signPsbt };
1 change: 1 addition & 0 deletions packages/sdk/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default defineConfig({
lib: {
entry: {
index: resolve(__dirname, "src/index.ts"),
magiceden: resolve(__dirname, "src/browser-wallets/magiceden/index.ts"),
unisat: resolve(__dirname, "src/browser-wallets/unisat/index.ts"),
xverse: resolve(__dirname, "src/browser-wallets/xverse/index.ts"),
},
Expand Down

0 comments on commit dfba3cc

Please sign in to comment.