Skip to main content
The @txnlab/use-wallet-vue package provides Vue-specific bindings for use-wallet, including a plugin and composables that enable reactive wallet integration in Vue 3 applications.

Installation

npm install @txnlab/use-wallet-vue

Setup

Install the plugin

Install the WalletManagerPlugin when creating your Vue app. This makes the wallet manager available throughout your application.
import { createApp } from 'vue'
import {
  NetworkId,
  WalletId,
  WalletManagerPlugin
} from '@txnlab/use-wallet-vue'
import App from './App.vue'

const app = createApp(App)

app.use(WalletManagerPlugin, {
  wallets: [
    WalletId.DEFLY,
    WalletId.PERA,
    WalletId.EXODUS,
    {
      id: WalletId.WALLETCONNECT,
      options: { projectId: 'YOUR_PROJECT_ID' }
    },
    WalletId.KMD
  ],
  defaultNetwork: NetworkId.TESTNET
})

app.mount('#app')

Using the wallet composable

The useWallet composable provides reactive access to wallet state and signing methods.

Basic usage

<script setup lang="ts">
import { useWallet } from '@txnlab/use-wallet-vue'

const { wallets, activeAddress } = useWallet()

const handleConnect = async (wallet) => {
  await wallet.connect()
}
</script>

<template>
  <div>
    <p v-if="activeAddress">Connected: {{ activeAddress }}</p>
    <div v-else>
      <button
        v-for="wallet in wallets"
        :key="wallet.id"
        @click="handleConnect(wallet)"
        :disabled="wallet.isConnected"
      >
        Connect {{ wallet.metadata.name }}
      </button>
    </div>
  </div>
</template>

Return values

The useWallet composable returns computed refs and methods:
interface UseWalletReturn {
  // Wallet state (computed refs)
  wallets: ComputedRef<Wallet[]>
  isReady: ComputedRef<boolean>
  activeWallet: ComputedRef<Wallet | null>
  activeWalletAccounts: ComputedRef<WalletAccount[] | null>
  activeWalletAddresses: ComputedRef<string[] | null>
  activeAccount: ComputedRef<WalletAccount | null>
  activeAddress: ComputedRef<string | null>

  // Algod client
  algodClient: ComputedRef<algosdk.Algodv2>

  // Signing methods
  signTransactions: (txnGroup: Transaction[] | Uint8Array[], indexesToSign?: number[]) => Promise<(Uint8Array | null)[]>
  transactionSigner: (txnGroup: Transaction[], indexesToSign: number[]) => Promise<Uint8Array[]>
  signData: (data: string, metadata: SignMetadata) => Promise<SignDataResponse>
  withPrivateKey: <T>(callback: (secretKey: Uint8Array) => Promise<T>) => Promise<T>
}

Wallet interface

Each wallet object has the following properties:
interface Wallet {
  id: WalletId
  walletKey: WalletKey
  metadata: WalletMetadata
  accounts: WalletAccount[]
  activeAccount: WalletAccount | null
  isConnected: boolean
  isActive: boolean
  canSignData: boolean
  canUsePrivateKey: boolean
  connect: (args?: Record<string, any>) => Promise<WalletAccount[]>
  disconnect: () => Promise<void>
  setActive: () => void
  setActiveAccount: (address: string) => void
}

Signing transactions

The transactionSigner method is compatible with the Algorand SDK’s AtomicTransactionComposer.
<script setup lang="ts">
import { useWallet } from '@txnlab/use-wallet-vue'
import algosdk from 'algosdk'
import { ref } from 'vue'

const { activeAddress, algodClient, transactionSigner } = useWallet()
const isSending = ref(false)

const sendTransaction = async () => {
  if (!activeAddress.value) {
    throw new Error('No active account')
  }

  isSending.value = true

  try {
    const atc = new algosdk.AtomicTransactionComposer()
    const suggestedParams = await algodClient.value.getTransactionParams().do()

    const transaction = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
      sender: activeAddress.value,
      receiver: activeAddress.value,
      amount: 0,
      suggestedParams
    })

    atc.addTransaction({ txn: transaction, signer: transactionSigner })

    const result = await atc.execute(algodClient.value, 4)
    console.log('Transaction sent:', result.txIDs)
  } finally {
    isSending.value = false
  }
}
</script>

<template>
  <button @click="sendTransaction" :disabled="!activeAddress || isSending">
    {{ isSending ? 'Sending...' : 'Send Transaction' }}
  </button>
</template>

Network management

The useNetwork composable provides methods for managing network configuration.
<script setup lang="ts">
import { useNetwork } from '@txnlab/use-wallet-vue'

const { activeNetwork, setActiveNetwork } = useNetwork()
</script>

<template>
  <div>
    <p>Current network: {{ activeNetwork }}</p>
    <button @click="setActiveNetwork('mainnet')">
      Switch to MainNet
    </button>
    <button @click="setActiveNetwork('testnet')">
      Switch to TestNet
    </button>
  </div>
</template>

Return values

interface UseNetworkReturn {
  activeNetwork: Ref<string>
  networkConfig: Record<string, NetworkConfig>
  activeNetworkConfig: ComputedRef<NetworkConfig>
  setActiveNetwork: (networkId: string) => Promise<void>
  updateAlgodConfig: (networkId: string, config: Partial<AlgodConfig>) => void
  resetNetworkConfig: (networkId: string) => void
}

Managing accounts

Switch between accounts for a connected wallet:
<script setup lang="ts">
import { useWallet } from '@txnlab/use-wallet-vue'

const { activeWallet } = useWallet()

const handleAccountChange = (event: Event) => {
  const target = event.target as HTMLSelectElement
  activeWallet.value?.setActiveAccount(target.value)
}
</script>

<template>
  <select
    v-if="activeWallet?.isConnected"
    :value="activeWallet.activeAccount?.address"
    @change="handleAccountChange"
  >
    <option
      v-for="account in activeWallet.accounts"
      :key="account.address"
      :value="account.address"
    >
      {{ account.address }}
    </option>
  </select>
</template>

Signing arbitrary data

For wallets that support it, you can sign arbitrary data for authentication:
<script setup lang="ts">
import { useWallet, ScopeType } from '@txnlab/use-wallet-vue'

const { activeAddress, signData, activeWallet } = useWallet()

const authenticate = async () => {
  if (!activeAddress.value || !activeWallet.value?.canSignData) {
    throw new Error('Wallet does not support data signing')
  }

  const message = { domain: window.location.host, timestamp: Date.now() }
  const data = btoa(JSON.stringify(message))
  const metadata = { scope: ScopeType.AUTH, encoding: 'base64' }

  const response = await signData(data, metadata)
  console.log('Signature:', response)
}
</script>

<template>
  <button
    @click="authenticate"
    :disabled="!activeWallet?.canSignData"
  >
    Authenticate
  </button>
</template>

Options API support

While the Composition API is recommended, you can use the plugin with the Options API:
<script>
export default {
  inject: ['walletManager', 'algodClient'],
  computed: {
    wallets() {
      return Array.from(this.walletManager.wallets.values())
    }
  },
  methods: {
    async connectWallet(wallet) {
      await wallet.connect()
    }
  }
}
</script>

TypeScript support

The package includes full TypeScript definitions. All composables are fully typed:
import type {
  Wallet,
  WalletAccount,
  WalletMetadata,
  SignMetadata,
  SignDataResponse
} from '@txnlab/use-wallet-vue'

Nuxt integration

For Nuxt applications, create a plugin to initialize the wallet manager:
// plugins/wallet.client.ts
import { WalletManagerPlugin, NetworkId, WalletId } from '@txnlab/use-wallet-vue'

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(WalletManagerPlugin, {
    wallets: [
      WalletId.DEFLY,
      WalletId.PERA,
      {
        id: WalletId.WALLETCONNECT,
        options: { projectId: process.env.WALLETCONNECT_PROJECT_ID }
      }
    ],
    defaultNetwork: NetworkId.TESTNET
  })
})

Next steps

Configuration

Learn about wallet and network configuration options

Wallets

Explore supported wallet providers and their options

Build docs developers (and LLMs) love