> For the complete documentation index, see [llms.txt](https://docs.toolkit.equs.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.toolkit.equs.ai/docs/embedded-ui/embedding-web-wallet.md).

# Embedding Web Wallet

Show the Holder's credentials and Offer notifications from the Web Wallet inside your site

Embedded UI can bring the Web Wallet into your site: a button that opens the User's credentials, and a notifications bell for new Offers. Drop in the ready-made web components, or build your own controls on the functions behind them.

{% hint style="info" %}
The **Web Wallet** is disabled by default and is only available on request.
{% endhint %}

**Before you start**, initialize Embed UI with `enableWebComponents: true` - see [Overview](/docs/embedded-ui/overview.md). That defines the web components and sets up the Web Wallet sign-in this page relies on.

### Sign the Holder in 🔑

The Web Wallet only shows credentials and notifications to a Holder signed in to it. Follow the sign-in state with `subscribeToAuthEvents`, and sign the Holder in with `signIntoWallet,` for example from a *Connect wallet* button you show while they're signed out.

{% code collapsedlinecount="1000" %}

```javascript
import { signIntoWallet, subscribeToAuthEvents } from '@equs-ai/dtk-embedded-ui'

const unsubscribe = subscribeToAuthEvents(({ isLoggedIn }) => {
  // show the wallet controls when true, a "Connect wallet" button when false
})

signIntoWallet({
  onSignedIn: () => { /* the User is signed in */ },
  onFailed: (reason) => { /* sign-in failed */ },
})
```

{% endcode %}

`signIntoWallet` opens a sign-in pop-up, so call it from the Holder's click. Both callbacks are optional.

### Web components

`wallet-view-vc-list-button` and `wallet-notifications` are native HTML custom elements, so they work in plain HTML and in frameworks such as React and Angular. Configure them with attributes, and style them with the global classes listed for each.

#### wallet-view-vc-list-button

A button that opens the Holder's credentials in the Web Wallet.

| Attribute         | Values                   | Default    | Description                                                           |
| ----------------- | ------------------------ | ---------- | --------------------------------------------------------------------- |
| `web-wallet-mode` | `embedded`, `standalone` | `embedded` | `embedded` opens the wallet over your page, `standalone` in a new tab |
| `show-offers`     | `true`, `false`          | `false`    | Shows the Offers tab, where pending Offer cards appear                |

Global classes: `.wallet-view-vc-list-button`, `.wallet-view-vc-list-button-loading-spin`.

{% code collapsedlinecount="1000" %}

```html
<wallet-view-vc-list-button web-wallet-mode="embedded"
                            show-offers="true">
</wallet-view-vc-list-button>
```

{% endcode %}

{% code collapsedlinecount="1000" %}

```css
.wallet-view-vc-list-button {
  padding: 12px;
  color: #117911;
  border-radius: 12px;
  border: 1px solid #117911;
}
```

{% endcode %}

#### wallet-notifications

A bell that opens a dropdown of the User's notifications, such as new Offers.

| Attribute            | Values                             | Default      | Description                                             |
| -------------------- | ---------------------------------- | ------------ | ------------------------------------------------------- |
| `web-wallet-mode`    | `embedded`, `standalone`           | `embedded`   | How the wallet opens when the User picks a notification |
| `dropdown-placement` | A placement such as `bottom-start` | `bottom-end` | Where the dropdown opens relative to the bell           |
| `dropdown-offset`    | A number of pixels                 | `2`          | Gap between the bell and the dropdown                   |

Global classes: `.wallet-notifications-button`, `.wallet-notifications-dropdown`.

{% code collapsedlinecount="1000" %}

```html
<wallet-notifications web-wallet-mode="embedded"></wallet-notifications>
```

{% endcode %}

### Build your own controls 🧩

If the components don't fit your UI (say you want a button from your own design system), use the functions behind them.

#### Open the wallet

`viewVCs` opens the User's credentials, signing them in first if needed.

{% code collapsedlinecount="1000" %}

```javascript
import { viewVCs } from '@equs-ai/dtk-embedded-ui'

viewVCs({ webWalletMode: 'embedded', showOffers: false, onLoading })
```

{% endcode %}

Called with no argument, `viewVCs()` opens the wallet over your page with the Offers tab hidden. `webWalletMode` and `showOffers` work like the button's attributes above, and `onLoading` is `(loading: boolean) => void`: the wallet takes a moment to open, so use it to show a spinner. `cleanUpViewVCs()` cancels a pending call.

#### Build your own notifications dropdown

Load the wallet's notifications list into an `iframe` of your own, and follow what happens in it:

1. `constructNotificationsUrl()` returns the URL to load in your `iframe`.
2. `subscribeToNotificationEvents(callback)` reports its events, and returns a function that stops the subscription.
3. `updateNotifications({ iframe })` asks the list to refresh, for example each time your dropdown opens.

| Event                       | Data          | When                                                                          |
| --------------------------- | ------------- | ----------------------------------------------------------------------------- |
| `hasNotifications`          | `boolean`     | Whether there is anything to show. Use it for an unread dot on your bell      |
| `notificationDetailsOpened` | The Offer URI | The User picked a notification. Open the Offer with `issueVCInInternalWallet` |
| `notificationClosed`        | N/A           | The list asked to be closed                                                   |
| `notificationError`         | N/A           | Something went wrong inside the list                                          |

{% code collapsedlinecount="1000" %}

```javascript
import {
  constructNotificationsUrl,
  subscribeToNotificationEvents,
  updateNotifications,
  issueVCInInternalWallet,
} from '@equs-ai/dtk-embedded-ui'

iframe.src = constructNotificationsUrl()

const unsubscribe = subscribeToNotificationEvents((event, data) => {
  switch (event) {
    case 'hasNotifications':
      setHasNotifications(data)
      break
    case 'notificationDetailsOpened':
      closeDropdown()
      issueVCInInternalWallet({ offerUri: data, webWalletMode: 'embedded' })
      break
    case 'notificationClosed':
      closeDropdown()
      break
  }
})

// when your dropdown opens
updateNotifications({ iframe })
```

{% endcode %}

#### Open an Offer in the wallet 🛠️

`issueVCInInternalWallet` opens an Offer straight in the User's Web Wallet, with no wallet picker. It takes `offerUri` (required), `webWalletMode` (default `embedded`) and `onLoading`.

{% hint style="warning" %}
**Call `issueVCInInternalWallet` synchronously.** Don't `await` anything before it, or some browsers block the window it opens.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.toolkit.equs.ai/docs/embedded-ui/embedding-web-wallet.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
