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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@gabrielkuettel/use-wallet

v1.0.7

Published

React hooks for using Algorand compatible wallets in dApps.

Readme

@TxnLab/use-wallet

React hooks for using Algorand compatible wallets with web applications.

Supported Providers

Demo

Preview a basic implementation in Storybook or check out this example.

Quick Start

⚠️ If you're using create-react-app and webpack 5 (most newer React projects), you will need to install polyfills. Follow these directions.

Yarn

yarn add @txnlab/use-wallet

Install peer dependencies (if needed)

yarn add algosdk @blockshake/defly-connect @perawallet/connect @randlabs/myalgo-connect @walletconnect/client algorand-walletconnect-qrcode-modal @json-rpc-tools/utils

NPM

npm install @txnlab/use-wallet

Install peer dependencies (if needed)

npm install algosdk @blockshake/defly-connect @perawallet/connect @randlabs/myalgo-connect @walletconnect/client algorand-walletconnect-qrcode-modal @json-rpc-tools/utils

Set up the Wallet Provider

In app.js, initialize the Wallet Provider so that the useWallet hook can be used in the child components, and use the reconnectProviders function to restore sessions for users returning to the app.

import React from "react";
import {
  reconnectProviders,
  initializeProviders,
  WalletProvider,
} from "@txnlab/use-wallet";

const walletProviders = initializeProviders();

export default function App() {
  // Reconnect the session when the user returns to the dApp
  React.useEffect(() => {
    reconnectProviders(walletProviders);
  }, []);

  return (
    <WalletProvider value={walletProviders}>
      ...
    </WalletProvider>);
}

The reconnectProviders function is used to restore session states of wallets that rely on the WalletConnect protocol.

By default, all of the supported providers except for KMD are returned by useConnectWallet. An array can be passed to initializeProviders to determine which providers your dApp supports, as shown below.

import { initializeProviders, PROVIDER_ID } from "@txnlab/use-wallet";

const walletProviders = initializeProviders([
  PROVIDER_ID.KMD_WALLET,
  PROVIDER_ID.WALLET_CONNECT,
]);

For more configuration options, see Provider Configuration.

Connect

Map through the providers object to list the providers and enable users to connect.

import React from "react";
import { useWallet } from "@txnlab/use-wallet";

export default function Connect() {
  const { providers, activeAccount } = useWallet();

  // Map through the providers.
  // Render account information and "connect", "set active", and "disconnect" buttons.
  // Finally, map through the `accounts` property to render a dropdown for each connected account.
  return (
    <div>
      {providers?.map((provider) => (
        <div key={"provider-" + provider.metadata.id}>
          <h4>
            <img width={30} height={30} alt="" src={provider.metadata.icon} />
            {provider.metadata.name} {provider.isActive && "[active]"}
          </h4>
          <div>
            <button onClick={provider.connect} disabled={provider.isConnected}>
              Connect
            </button>
            <button
              onClick={provider.disconnect}
              disabled={!provider.isConnected}
            >
              Disconnect
            </button>
            <button
              onClick={provider.setActiveProvider}
              disabled={!provider.isConnected || provider.isActive}
            >
              Set Active
            </button>
            <div>
              {provider.isActive && provider.accounts.length && (
                <select
                  value={activeAccount?.address}
                  onChange={(e) => provider.setActiveAccount(e.target.value)}
                >
                  {provider.accounts.map((account) => (
                    <option key={account.address} value={account.address}>{account.address}</option>
                  ))}
                </select>
              )}
            </div>
          </div>
        </div>
      ))}
    </div>
  );
}

Each provider has two connection states: isConnected and isActive.

isConnected means that the user has authorized the provider to talk to the dApp. The connection flow does not need to be restarted when switching to this wallet from a different one.

isActive indicates that the provider is currently active and will be used to sign and send transactions when using the useWallet hook.

The activeAccount is the primary account that is currently active and will be used to sign and send transactions.

Sign and send transactions

Construct a transaction using algosdk, and sign and send the transaction using the signTransactions and sendTransactions functions provided by the useWallet hook.

import React from "react";
import {
  useWallet,
  DEFAULT_NODE_BASEURL,
  DEFAULT_NODE_TOKEN,
  DEFAULT_NODE_PORT,
} from "@txnlab/use-wallet";
import algosdk from "algosdk";

const algodClient = new algosdk.Algodv2(
  DEFAULT_NODE_TOKEN,
  DEFAULT_NODE_BASEURL,
  DEFAULT_NODE_PORT
);

export default function Transact() {
  const { activeAddress, signTransactions, sendTransactions } = useWallet();

  const sendTransaction = async (
    from?: string,
    to?: string,
    amount?: number
  ) => {
    if (!from || !to || !amount) {
      throw new Error("Missing transaction params.");
    }

    const suggestedParams = await algodClient.getTransactionParams().do();

    const transaction = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
      from,
      to,
      amount,
      suggestedParams,
    });

    const encodedTransaction = algosdk.encodeUnsignedTransaction(transaction);

    const signedTransactions = await signTransactions([encodedTransaction]);

    const waitRoundsToConfirm = 4;

    const { id } = await sendTransactions(
      signedTransactions,
      waitRoundsToConfirm
    );

    console.log("Successfully sent transaction. Transaction ID: ", id);
  };

  if (!activeAddress) {
    return <p>Connect an account first.</p>;
  }

  return (
    <div>
      <button
        onClick={() => sendTransaction(activeAddress, activeAddress, 1000)}
        className="button"
      >
        Sign and send transactions
      </button>
    </div>
  );
}

Display account details

The activeAccount object can be used to display details for the currently active account. For convenience, the activeAddress property shows the currently active address.

import React from "react";
import { useWallet } from "@txnlab/use-wallet";

export default function Account() {
  const { activeAccount } = useWallet();

  if (!activeAccount) {
    return <p>No account active.</p>;
  }

  return (
    <div>
      <h4>Active Account</h4>
      <p>
        Name: <span>{activeAccount.name}</span>
      </p>
      <p>
        Address: <span>{activeAccount.address}</span>
      </p>
      <p>
        Provider: <span>{activeAccount.providerId}</span>
      </p>
    </div>
  );
}

Provider Configuration

The initializeProviders functon accepts a configuration object that can be used to configure the nodes that the providers use to send transactions, as shown below.

const walletProviders = initializeProviders([], {
  network: "devmodenet",
  nodeServer: "http://algod",
  nodeToken: "xxxxxxxxx",
  nodePort: "8080",
});

Passing an empty array as the first argument enables all of the default providers. The network property should be specified as betanet, testnet, mainnet or the name of your local development network.

For more custom configuration options, the providers can be configured individually by creating an object and passing it to the WalletProvider where the key contains the provider ID, and the value calls the init function of the provider client. See below for an example:

...

import {
  PROVIDER_ID,
  pera,
  myalgo,
} from "@txnlab/use-wallet";

const walletProviders = {
  [PROVIDER_ID.PERA]: pera.init({
    clientOptions: {
      shouldShowSignTxnToast: true,
    },
  }),
  [PROVIDER_ID.MYALGO]: myalgo.init({
    network: "devmodenet",
    algodOptions: ["xxxxxxxxx", "http://algod", "8080"],
    clientOptions: { disableLedgerNano: true },
  }),
};

... 

<WalletProvider value={walletProviders}>
  ...
</WalletProvider>

Static Imports

By default, use-wallet dynamically imports all of the dependencies for the providiers, as well as algosdk, to reduce bundle size.

Some React frameworks, like Remix, do not support dynamic imports. To get around this, those dependencies can be imported in your application and passed to the useWallet provider. See below for an example.

...

import algosdk from "algosdk";
import MyAlgoConnect from "@randlabs/myalgo-connect";
import { PeraWalletConnect } from "@perawallet/connect";
import { DeflyWalletConnect } from "@blockshake/defly-connect";
import WalletConnect from "@walletconnect/client";
import QRCodeModal from "algorand-walletconnect-qrcode-modal";

const walletProviders = {
  [PROVIDER_ID.PERA]: pera.init({
    algosdkStatic: algosdk,
    clientStatic: PeraWalletConnect,
  }),
  [PROVIDER_ID.MYALGO]: myalgo.init({
    algosdkStatic: algosdk,
    clientStatic: MyAlgoConnect,
  }),
  [PROVIDER_ID.DEFLY]: defly.init({
    algosdkStatic: algosdk,
    clientStatic: DeflyWalletConnect,
  }),
  [PROVIDER_ID.EXODUS]: exodus.init({
    algosdkStatic: algosdk,
  }),
  [PROVIDER_ID.ALGOSIGNER]: algosigner.init({
    algosdkStatic: algosdk,
  }),
  [PROVIDER_ID.WALLETCONNECT]: walletconnect.init({
    algosdkStatic: algosdk,
    clientStatic: WalletConnect,
    modalStatic: QRCodeModal,
  }),
};

export default function App() {
  ...

  return (
    <WalletProvider value={walletProviders}>
      ...
    </WalletProvider>
  );
}

Note that some of the providers do not require static imports to be provided. This is usually the case of providers that are browser extensions.

Webpack 5

Note: Frameworks like next.js already include polyfills. This step is required if you're using create-react-app with webpack 5.

  1. Install react-app-rewired and the missing polyfills.

    yarn add --dev react-app-rewired crypto-browserify stream-browserify assert stream-http https-browserify os-browserify url buffer process
  2. Create config-overrides.js in the root of your project and add the following:

    const webpack = require("webpack");
       
    module.exports = function override(config) {
      const fallback = config.resolve.fallback || {};
      Object.assign(fallback, {
        crypto: require.resolve("crypto-browserify"),
        stream: require.resolve("stream-browserify"),
        assert: require.resolve("assert"),
        http: require.resolve("stream-http"),
        https: require.resolve("https-browserify"),
        os: require.resolve("os-browserify"),
        url: require.resolve("url"),
      });
      config.resolve.fallback = fallback;
      config.plugins = (config.plugins || []).concat([
        new webpack.ProvidePlugin({
          process: "process/browser",
          Buffer: ["buffer", "Buffer"],
        }),
      ]);
      return config;
    };
  3. Change your scripts in package.json to the following:

    "scripts": {
        "start": "react-app-rewired start",
        "build": "react-app-rewired build",
        "test": "react-app-rewired test",
        "eject": "react-scripts eject"
    },

Local Development

Install dependencies

yarn install

Demo in Storybook

yarn dev

To develop against a local version of use-wallet in your application, do the following:

Build the library

yarn build

Symlink the library

In the root of use-wallet directory, run:

yarn link

In the root of your application, run:

yarn link @txnlab/use-wallet

Symlink React

In the root of your application, run:

cd node_modules/react
yarn link

In the root of use-wallet directory, run:

yarn link react

License

See the LICENSE file for license rights and limitations (MIT)