---
title: Connect to XT Wallet
slug: signum/connect-to-xt-wallet
docTags: 
createdAt: 2022-09-07T16:09:48.000Z
---

## Communication Concept

Once the XT wallet is installed, it ramps up an internal message based communication server. Each new tab loads a small script provided by the extension, that acts as a client listening to the messages coming from the wallet.&#x20;

:::hint{type="success"}
The wallet stores the keys in an extra protected "backend" area of the extension and never provides any secret. The keys are encrypted by the users secret he provided when installed the extension. Between a DApp and the wallet only public information like accounts public key and current selected node host is transmitted.
:::

The wallet dispatches the following events:

- Connection/Disconnection
- Account Selection
- Node Selection
- Account and/or Permission Removal
- Confirmation Responses, i.e. on signing

The SignumJS Wallets package simplifies the communication as much as possible. The interaction life-cycle of the wallet is like this:

1. Connect to wallet
2. Add Event Listeners to the connection object
3. Interact according to the events
4. Disconnect
5. Detach the event listeners

## Usage Example

The following code is just an excerpt from a [working example](https://github.com/signum-network/signumjs/tree/main/examples/web/connect-xt-wallet). More elaborated demos for [React (NextJS)](https://github.com/ohager/signum-xt-wallet-react-demo) and [Vanilla HTML, JS](https://github.com/ohager/signum-xt-wallet-vanilla-demo) are available also and serve as a starting point.

:::CodeblockTabs
```javascript
const {LedgerClientFactory} = require('@signumjs/core')
const {GenericExtensionWallet} = require('@signumjs/wallets')

let walletListener = null;
// In vanilla JS, we can abuse the global object
// The wallet connection should be a singleton
window.wallet = new GenericExtensionWallet()
window.signumLedger = null

// we need to reconstruct the ledger client to use the correct node, i.e. the one selected by
// the wallet
function createLedgerClient(nodeHost){
    window.signumLedger = LedgerClientFactory.createClient({
        nodeHost
    })
}

// for better encapsulation, it's not the worst idea to dispatch global events
function propagateWalletEvent(action, data = {}){
    window.dispatchEvent(new CustomEvent('wallet-event', {detail: {
            action,
            payload: {...data}
        }}))
}

// We need to listen to network changes...
function onNetworkChange(args) {
    propagateWalletEvent('networkChanged')
    // check if we are still within the same network
    if (args.networkName === 'Signum-TESTNET') {
        if (!window.wallet.connection) {
            connectWallet()
        } else{
            createLedgerClient(args.nodeHost)
        }
    } else {
        showError("Wallet changed to another network - Disconnect wallet")
        disconnectWallet()
    }
}

function onAccountChange() {
    propagateWalletEvent('accountChanged')
}

function onPermissionOrAccountRemoval() {
    // it's possible that the user revokes the DApps permission
    // we need to disconnect the wallet then
    propagateWalletEvent('permissionRemoved' )
    showError("Wallet removed this DApps permission")
    disconnectWallet();
}

async function connectWallet() {
    if (window.wallet.connection) return;

    try {
        // connecting the wallet is easy
        const connection = await window.wallet.connect({
            appNam: 'SignumJS XT Wallet Demo',
            networkName: 'Signum-TESTNET'
        })

        if (walletListener) {
            walletListener.unlisten();
        }

        // but we need also attach event listeners
        // this is where a bit more complexity comes into the game
        // but the XT wallet knows only four events...no rocket science here
        walletListener = connection.listen({
            onNetworkChanged: onNetworkChange,
            onAccountChanged: onAccountChange,
            onPermissionRemoved: onPermissionOrAccountRemoval,
            onAccountRemoved: onPermissionOrAccountRemoval,
        });

        createLedgerClient(connection.currentNodeHost)
        // tell everybody that we connected
        propagateWalletEvent('connected')
    } catch (e) {
        showError(e.message)
    }
}

async function disconnectWallet() {
    // when disconnecting, we should make tabula rasa and reinstantiate the wallet instance.
    window.wallet = new GenericExtensionWallet();
    window.signumLedger = null;
    // DO NOT FORGET TO UNLISTEN THE LISTENERS!
    walletListener.unlisten();
    propagateWalletEvent('disconnected');
}


```

\<script/>

```javascript

let walletListener = null;
// In vanilla JS, we can abuse the global object
// The wallet connection should be a singleton
window.wallet = new sig$wallets.GenericExtensionWallet()
window.signumLedger = null

// we need to reconstruct the ledger client to use the correct node, i.e. the one selected by
// the wallet
function createLedgerClient(nodeHost){
    window.signumLedger = sig$.LedgerClientFactory.createClient({
        nodeHost
    })
}

// for better encapsulation, it's not the worst idea to dispatch global events
function propagateWalletEvent(action, data = {}){
    window.dispatchEvent(new CustomEvent('wallet-event', {detail: {
            action,
            payload: {...data}
        }}))
}

// We need to listen to network changes...
function onNetworkChange(args) {
    propagateWalletEvent('networkChanged')
    // check if we are still within the same network
    if (args.networkName === 'Signum-TESTNET') {
        if (!window.wallet.connection) {
            connectWallet()
        } else{
            createLedgerClient(args.nodeHost)
        }
    } else {
        showError("Wallet changed to another network - Disconnect wallet")
        disconnectWallet()
    }
}

function onAccountChange() {
    propagateWalletEvent('accountChanged')
}

function onPermissionOrAccountRemoval() {
    // it's possible that the user revokes the DApps permission
    // we need to disconnect the wallet then
    propagateWalletEvent('permissionRemoved' )
    showError("Wallet removed this DApps permission")
    disconnectWallet();
}

async function connectWallet() {
    if (window.wallet.connection) return;

    try {
        // connecting the wallet is easy
        const connection = await window.wallet.connect({
            appNam: 'SignumJS XT Wallet Demo',
            networkName: 'Signum-TESTNET'
        })

        if (walletListener) {
            walletListener.unlisten();
        }

        // but we need also attach event listeners
        // this is where a bit more complexity comes into the game
        // but the XT wallet knows only four events...no rocket science here
        walletListener = connection.listen({
            onNetworkChanged: onNetworkChange,
            onAccountChanged: onAccountChange,
            onPermissionRemoved: onPermissionOrAccountRemoval,
            onAccountRemoved: onPermissionOrAccountRemoval,
        });

        createLedgerClient(connection.currentNodeHost)
        // tell everybody that we connected
        propagateWalletEvent('connected')
    } catch (e) {
        showError(e.message)
    }
}

async function disconnectWallet() {
    // when disconnecting, we should make tabula rasa and reinstantiate the wallet instance.
    window.wallet = new sig$wallets.GenericExtensionWallet();
    window.signumLedger = null;
    // DO NOT FORGET TO UNLISTEN THE LISTENERS!
    walletListener.unlisten();
    propagateWalletEvent('disconnected');
}


```
:::
