npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@wanderapp/embed-sdk

v0.0.7

Published

Wander Embedded SDK.

Readme

Wander Embedded SDK

npm version License: MIT

A lightweight, customizable SDK for integrating Wander wallet functionality into your web applications.

Features

  • 🔌 Easy Integration: Simple API to embed Wander wallet functionality in any web app
  • 🎨 Customizable UI: Extensive theming options for both light and dark modes
  • 📱 Responsive Design: Adapts to different screen sizes with multiple layout options
  • 🔒 Secure: Communication with Wander wallet happens in a secure iframe
  • 🔔 Event Callbacks: Listen to authentication, balance changes, and transaction requests

Installation

npm install @wanderapp/embed-sdk

or

yarn add @wanderapp/embed-sdk

Basic Usage

React

import { useEffect, useState } from "react";
import { WanderEmbedded } from "@wanderapp/embed-sdk";

function WalletConnect() {
  const [instance, setInstance] = useState(null);

  useEffect(() => {
    // Initialize the wallet
    const wanderInstance = new WanderEmbedded({
      iframe: {
        routeLayout: {
          auth: "modal"
        }
      },
      button: {
        position: "bottom-right",
        theme: "light",
        label: true,
        wanderLogo: "default"
      }
    });

    setInstance(wanderInstance);

    // Clean up on unmount
    return () => {
      if (wanderInstance) {
        wanderInstance.destroy();
      }
    };
  }, []);

  return ...;
}

export default WalletConnect;

Configuration Options

const wander = new WanderEmbedded({
  // Button configuration
  button: {
    position: "bottom-right", // "bottom-right", "bottom-left", "top-right", "top-left", "static"
    theme: "system",
    wanderLogo: "default", // 'none', 'default', or 'text-color'
    label: true
  },

  // Iframe configuration
  iframe: {
    routeLayout: {
      auth: "popup" // "popup" | "modal" | "half" | "sidebar";
    }
  }
});

Advanced Configuration

Button Configuration

Custom Button Styling

const wander = new WanderEmbedded({
  button: {
    position: "top-right",
    cssVars: {
      // Light theme variables
      light: {
        background: "#ffffff",
        color: "#000000",
        borderRadius: 16,
        boxShadow: "0 4px 12px rgba(0, 0, 0, 0.1)"
      },
      // Dark theme variables
      dark: {
        background: "#1a1a1a",
        color: "#ffffff",
        borderRadius: 16,
        boxShadow: "0 4px 12px rgba(0, 0, 0, 0.3)"
      }
    }
  }
});

Custom CSS Styles

You can add custom CSS styles to the button using customStyles option. When using this option, you must use CSS selectors to target specific elements.

Available selectors:

  • :host - Targets the button container
  • .button - Targets the button element
  • .wanderLogo - Targets the Wander logo SVG
  • .label - Targets the button text label
  • .balance - Targets the balance display
  • .indicator - Targets the connection status indicator
  • .notifications - Targets the notifications badge

Example usage:

const wander = new WanderEmbedded({
  button: {
    customStyles: `
      /* Position the button container */
      :host {
        position: fixed;
        top: 20px;
        right: 20px;
      }

      /* Target the button element */
      .button {
        width: 200px;
        display: flex;
        align-items: center;
        justify-content: center;
      }

      /* Target the Wander logo */
      .wanderLogo {
        width: 24px;
        height: 24px;
      }

      /* Target the button label */
      .label {
        font-size: 14px;
        font-weight: 500;
      }

      /* Target the balance display */
      .balance {
        font-size: 12px;
        opacity: 0.8;
      }

      /* Target the connection indicator */
      .indicator {
        width: 6px;
        height: 6px;
      }

      /* Target the notifications badge */
      .notifications {
        font-size: 10px;
        padding: 2px 6px;
      }
    `
  }
});

The button element has a data-variant HTML attribute you can use for styling:

  • [data-variant="loading|onboarding|authenticated|not-authenticated"]

As well as some CSS classes that are added based on its state:

  • .isConnected - Added when the wallet is connected
  • .isOpen - Added when the wallet interface is open

Additionally, the button's .label and .balance elements also have some modifiers:

  • .label.isLoading
  • .balance.isLoading
  • .balance.isHidden

You can use these classes in your customStyles to style different states:

customStyles: `
  .button.isAuthenticated {
    border-color: green;
  }

  .button.isConnected {
    background: rgba(0, 255, 0, 0.1);
  }

  .button.isOpen {
    transform: scale(0.95);
  }
`;

Custom Button Positioning

There are two approaches to positioning the Wander button:

1. Using Predefined Positions
const wander = new WanderEmbedded({
  button: {
    position: "bottom-right" // Options: "bottom-right", "bottom-left", "top-right", "top-left"
  }
});
2. Using Custom Positioning with "static"

You have three methods for custom positioning:

2.1. Using a Parent Element

First, create a container element:

<div id="wanderButtonContainer"></div>

Then reference it in your configuration:

const wander = new WanderEmbedded({
  button: {
    position: "static",
    parent: document.getElementById("wanderButtonContainer")
  }
});
2.2. Using Custom Styles
const wander = new WanderEmbedded({
  button: {
    position: "static",
    // Using customStyles for precise control over button appearance and position
    customStyles: `
      /* Position the button container */
      :host {
        position: fixed;
        top: 20px;
        right: 20px;
      }

      /* Style the button itself */
      .button {
        background: rgba(255, 255, 255, 0.9);
        backdrop-filter: blur(8px);
      }
    `
  }
});
2.3. Using External CSS

Define the button with a custom ID:

const wander = new WanderEmbedded({
  button: {
    position: "static",
    id: "my-wander-button" // Default is "wanderEmbeddedButtonHost"
  }
});

Then style it with external CSS:

/* Position the button container */
#my-wander-button {
  position: fixed;
  top: 20px;
  right: 20px;
}

Iframe Configuration

Custom Modal Layouts

const wander = new WanderEmbedded({
  iframe: {
    routeLayout: {
      // Different layouts for different routes
      default: {
        type: "popup",
        position: "bottom-right"
      },
      auth: {
        type: "modal"
      },
      "auth-request": {
        type: "sidebar",
        position: "right",
        expanded: true
      }
    },
    cssVars: {
      background: "#f5f5f5",
      borderRadius: 12,
      boxShadow: "0 8px 32px rgba(0, 0, 0, 0.12)"
    }
  }
});

Custom CSS Styles

You can add custom CSS styles to the iframe using customStyles option. When using this option, you must use CSS selectors to target specific elements.

Available selectors:

  • .backdrop - Targets the backdrop overlay behind the iframe
    • .backdrop.show - Applied when the backdrop is visible
  • .iframe-wrapper - Targets the container that wraps the iframe
    • .iframe-wrapper.show - Applied when the iframe is visible
  • .iframe - Targets the actual iframe element
  • .half-image - Targets the image element used in half layout mode
    • .half-image.show - Applied when the half-image is visible

The HTML structure is follows:

<div class="wrapper">
  <iframe class="iframe"></iframe>
</div>
<div class="backdrop"></div>
<div class="half-image"></div>

Example usage:

const wander = new WanderEmbedded({
  iframe: {
    customStyles: `
      /* Style the backdrop */
      .backdrop {
        background: rgba(0, 0, 0, 0.5);
        backdrop-filter: blur(8px);
        transition: opacity 200ms ease;
      }

      .backdrop.show {
        opacity: 1;
      }

      /* Style the iframe wrapper */
      .iframe-wrapper {
        border: none;
        border-radius: 16px;
        box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
        transition: transform 200ms ease, opacity 200ms ease;
      }

      .iframe-wrapper.show {
        opacity: 1;
        transform: none;
      }

      /* Style the iframe itself */
      .iframe {
        border-radius: inherit;
        background: white;
      }

      /* Style the half-image */
      .half-image {
        object-fit: cover;
        transition: opacity 300ms ease;
      }

      .half-image.show {
        opacity: 1;
      }

      /* Mobile-specific styles */
      @media (max-width: 540px) {
        .backdrop {
          backdrop-filter: none;
        }

        .iframe-wrapper {
          border-radius: 0;
        }
      }
    `
  }
});

The iframe wrapper element (.iframe-wrapper) has several data attributes that you can use for conditional styling:

  • [data-layout="popup|modal|sidebar|half"] - Current layout type
  • [data-position="left|right|top-left|top-right|bottom-left|bottom-right"] - Position of the iframe
  • [data-expanded="true|false"] - Whether the iframe is in expanded mode
  • [data-expand-on-mobile="true|false"] - Whether the iframe expands on mobile devices

You can also use these when targeting the iframe element (.iframe):

.iframe-wrapper[data-layout="popup"] > .iframe {
  ...;
}

Or the backdrop element (.backdrop):

.iframe-wrapper[data-layout="popup"] + .backdrop {
  ...;
}

You can use these attributes in your customStyles to style different states:

customStyles: `
  /* Style popup layout */
  .iframe-wrapper[data-layout="popup"] {
    transform: scale(0.95);
  }

  .iframe-wrapper[data-layout="popup"].show {
    transform: scale(1);
  }

  /* Style expanded sidebar */
  .iframe-wrapper[data-layout="sidebar"][data-expanded="true"] {
    border: none;
    border-radius: 0;
  }

  /* Style right-positioned half layout */
  .iframe-wrapper[data-layout="half"][data-position="right"] {
    border-left: 2px solid rgba(0, 0, 0, 0.1);
  }

  /* Style mobile expanded state */
  .iframe-wrapper[data-expand-on-mobile="true"] {
    width: 100vw;
    height: 100vh;
    border: none;
    border-radius: 0;
  }

  /* Combine attributes for specific cases */
  .iframe-wrapper[data-layout="sidebar"][data-position="right"][data-expanded="true"] {
    box-shadow: -8px 0 32px rgba(0, 0, 0, 0.1);
  }
`;

API Reference

Methods

  • open() - Opens the wallet interface
  • close() - Closes the wallet interface
  • destroy() - Removes all elements and event listeners

Using with Arweave

The SDK automatically sets up window.arweaveWallet for compatibility with Arweave applications:

// After initializing WanderEmbedded, you can use window.arweaveWallet
const wander = new WanderEmbedded();

// Example Arweave interaction
async function connectWallet() {
  try {
    await window.arweaveWallet.connect(["ACCESS_ADDRESS", "SIGN_TRANSACTION"]);
    const address = await window.arweaveWallet.getActiveAddress();
    console.log("Connected to wallet address:", address);
  } catch (error) {
    console.error("Error connecting to wallet:", error);
  }
}

Browser Support

The SDK supports all modern browsers (Chrome, Firefox, Safari, Edge).

Development Setup

  1. yarn install

    Install the project dependencies.

  2. yarn build:wallet-api

    The TS/JS SDK imports some shared dependencies (setupWalletSDK()) from an already built version of the main repo.

    Until we have a monorepo, this command builds the bundle with this shared dependency under wander-embedded-sdk/sdk-dist.

  3. yarn dev:iframe

    The Wander Embedded App should now be running at http://localhost:5173.

After this, you can use the Wander Embedded App in 2 different ways:

  • As a standalone app, you can just access http://localhost:5173 and start using it. Note, however, that this is not how developers will be using it, so you might find some differences when testing some features (e.g. when running inside an iframe, we must use unpartitioned state for some features, like authentication, to work properly).

  • Embedded inside an iframe (recommended). In this case, you need a "test app" that install the Wander Embedded SDK to load the app inside an iframe. The section below explains different ways to do that.

Using the Wander Embedded SDK

The minimum setup you must do to get Wander Embedded to work on a project looks like this:

  import { WanderEmbedded } from "@wanderapp/embed-sdk";

  // ...

  useEffect(() => {
    async function initAndTestWander() {
      const wander = new WanderEmbedded({
        clientId: "ALPHA",
      });

      // After `new WanderEmbedded`, `window.arweaveWallet` is now the Wander Embedded API, rather
      than the Wander BE one.

      // Calling API methods will open/highlight the Wander Embedded iframe (popup/modal) if
      // authentication and/or authorization is needed:

      await window.arweaveWallet.connect(["SIGNATURE"]);

      const tx = ...;

      await window.arweaveWallet.sign(tx);

      // You can also manually open the popup/modal:
      wander.open();
    }

    initAndTestWander();
  }, []);

You can play around with Wander Embedded at https://playground.othent.io/, which uses:

Most likely you need that playground to load your local version of the app, SDK, and/or server. See below the different options available.

Local Playground + Local App + Latest SDK + Local/Latest Server

App:

After running yarn dev:iframe, the Wander Embedded App should be running at http://localhost:5173.

By default, the app will point its tRPC client to http://localhost:3001 when running in development mode, or to https://embed-api.wander.app/ when running in production mode. See:

  • createTRPCClient call in src/utils/embedded/embedded.utils.ts for the setup logic.
  • .env / .env.example for the development values.
  • Vercel's Environment variables, for the production values.

Playground & SDK:

Next, clone https://github.com/Othent/KMS-test-repo/ and run pnpm install && pnpm start. The playground should be running at http://localhost:3000, using the published version of @wanderapp/embed-sdk.

By default, the published version of @wanderapp/embed-sdk will point to the latest version of the Wander Embedded app, which in turn will point its tRPC client to the latest version of the server (https://embed-api.wander.app/).

You now need to make the SDK load http://localhost:5173, which you can do using the baseURL option. If you also need to connect to a server hosted elsewhere, you can use the baseServerURL options:

const wander = new WanderEmbedded({
  clientId: "ALPHA",
  baseURL: "http://localhost:5173",
  baseServerURL: "http://localhost:3001"
});

[!TIP] You can get an actual clientId from the Wander Dashboard by creating a Team and an Application.

Server:

Go to the embed-api repo and run:

  • pnpm install

  • pnpm dev - The server & tRPC API will run at http://localhost:3001 (if the Playground was already running on port 3000).

  • pnpm sdk:dev - Only if you want to use a local instance of embed-api:

    • If local, then the package.json a the root of this project should say: "embed-api": "link:../embed-api/",

    • If you want to use the currently published version of embed-api, then it should say: "embed-api": "https://github.com/wanderwallet/embed-api#<SOME_HASH>",

Local Playground + Local App + Local SDK + Local/Latest Server

To use a local @wanderapp/embed-sdk, go to the playground repo and run pnpm link-embed, which changes the @wanderapp/embed-sdk dependency to:

  "@wanderapp/embed-sdk": "link:./../wander/Wander/wander-embedded-sdk/"`

You can revert this change running pnpm link-embed, which changes the @wanderapp/embed-sdk dependency back to:

  "@wanderapp/embed-sdk": "^0.0.1"`

Then, go into wander-embedded-sdk in this repo and run pnpm install and pnpm dev.

When running in development mode, the SDK will use http://localhost:5173 as the default value for baseURL, instead of https://embed.wander.app/. See wander-embedded-sdk/src/wander-embedded.ts.

[!WARNING] Temporarily, the https://embed.wander.app/ URLs are actually https://embed-dev.wander.app/. This should be replaced before launch.