Skip to main content
The @txnlab/use-wallet-svelte package provides Svelte-specific bindings for use-wallet, including context management and reactive stores that enable seamless wallet integration in Svelte applications.

Installation

npm install @txnlab/use-wallet-svelte

Setup

Configure wallet context

Create a WalletManager instance and initialize the wallet context using useWalletContext. This is typically done in your root layout component.
<script lang="ts">
  import {
    NetworkId,
    WalletId,
    WalletManager,
    useWalletContext
  } from '@txnlab/use-wallet-svelte'

  const manager = new WalletManager({
    wallets: [
      WalletId.DEFLY,
      WalletId.PERA,
      WalletId.EXODUS,
      {
        id: WalletId.WALLETCONNECT,
        options: { projectId: 'YOUR_PROJECT_ID' }
      },
      WalletId.KMD
    ],
    defaultNetwork: NetworkId.TESTNET
  })

  useWalletContext(manager)

  let { children } = $props()
</script>

{@render children()}

Using the wallet hook

The useWallet function provides reactive access to wallet state and signing methods. Returned stores use Svelte’s reactive .current property.

Basic usage

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

  const { wallets, activeAddress } = useWallet()

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

<div>
  {#if activeAddress.current}
    <p>Connected: {activeAddress.current}</p>
  {:else}
    {#each wallets as wallet}
      <button
        onclick={() => handleConnect(wallet)}
        disabled={wallet.isConnected()}
      >
        Connect {wallet.metadata.name}
      </button>
    {/each}
  {/if}
</div>

Return values

The useWallet function returns reactive stores and methods:
interface UseWalletReturn {
  // Wallet state (reactive stores with .current)
  wallets: Wallet[]
  isReady: () => boolean
  algodClient: { current: algosdk.Algodv2 }
  activeWallet: () => Wallet | undefined
  activeWalletAccounts: { current: WalletAccount[] | undefined }
  activeWalletAddresses: { current: string[] | undefined }
  activeAccount: { current: WalletAccount | undefined }
  activeAddress: { current: string | undefined }

  // 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: { current: WalletAccount[] | undefined }
  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 lang="ts">
  import { useWallet } from '@txnlab/use-wallet-svelte'
  import algosdk from 'algosdk'

  const { activeAddress, algodClient, transactionSigner } = useWallet()
  let isSending = $state(false)

  async function sendTransaction() {
    const sender = activeAddress.current
    if (!sender) {
      throw new Error('No active account')
    }

    isSending = true

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

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

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

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

<button onclick={sendTransaction} disabled={!activeAddress.current || isSending}>
  {isSending ? 'Sending...' : 'Send Transaction'}
</button>

Network management

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

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

<div>
  <p>Current network: {activeNetwork.current}</p>
  <button onclick={() => setActiveNetwork('mainnet')}>
    Switch to MainNet
  </button>
  <button onclick={() => setActiveNetwork('testnet')}>
    Switch to TestNet
  </button>
</div>

Return values

interface UseNetworkReturn {
  activeNetwork: { current: string }
  networkConfig: Record<string, NetworkConfig>
  activeNetworkConfig: { current: NetworkConfig }
  setActiveNetwork: (networkId: 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 lang="ts">
  import { useWallet } from '@txnlab/use-wallet-svelte'

  const { activeWallet, activeAddress } = useWallet()

  function handleAccountChange(event) {
    const wallet = activeWallet()
    if (wallet) {
      wallet.setActiveAccount(event.target.value)
    }
  }
</script>

{#if activeWallet()?.isConnected()}
  <select value={activeAddress.current} onchange={handleAccountChange}>
    {#each activeWallet().accounts.current as account}
      <option value={account.address}>
        {account.address}
      </option>
    {/each}
  </select>
{/if}

Working with multiple wallets

Iterate through wallets and manage their connection states:
<script lang="ts">
  import { useWallet } from '@txnlab/use-wallet-svelte'

  const { wallets } = useWallet()

  async function handleConnect(wallet) {
    await wallet.connect()
  }

  async function handleDisconnect(wallet) {
    await wallet.disconnect()
  }
</script>

{#each wallets as wallet}
  <div class="wallet-group">
    <h4>
      {wallet.metadata.name}
      {#if wallet.isActive()}<span>[active]</span>{/if}
    </h4>
    <div class="wallet-buttons">
      <button
        onclick={() => handleConnect(wallet)}
        disabled={wallet.isConnected()}
      >
        Connect
      </button>
      <button
        onclick={() => handleDisconnect(wallet)}
        disabled={!wallet.isConnected()}
      >
        Disconnect
      </button>
      {#if !wallet.isActive()}
        <button
          onclick={() => wallet.setActive()}
          disabled={!wallet.isConnected()}
        >
          Set Active
        </button>
      {/if}
    </div>
  </div>
{/each}

Signing arbitrary data

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

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

  async function authenticate() {
    const address = activeAddress.current
    const wallet = activeWallet()

    if (!address || !wallet?.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>

<button
  onclick={authenticate}
  disabled={!activeWallet()?.canSignData}
>
  Authenticate
</button>

Accessing the wallet manager

For advanced use cases, access the wallet manager directly:
<script lang="ts">
  import { useWalletManager } from '@txnlab/use-wallet-svelte'

  const manager = useWalletManager()

  // Access manager methods and properties
  console.log('Network config:', manager.networkConfig)
  console.log('All wallets:', manager.wallets)
</script>

TypeScript support

The package includes full TypeScript definitions:
import type {
  Wallet,
  WalletAccount,
  WalletMetadata,
  SignMetadata,
  SignDataResponse
} from '@txnlab/use-wallet-svelte'

SvelteKit integration

For SvelteKit applications, initialize the wallet context in your root +layout.svelte file:
<!-- src/routes/+layout.svelte -->
<script lang="ts">
  import { browser } from '$app/environment'
  import {
    NetworkId,
    WalletId,
    WalletManager,
    useWalletContext
  } from '@txnlab/use-wallet-svelte'

  // Only initialize on client side
  if (browser) {
    const manager = new WalletManager({
      wallets: [
        WalletId.DEFLY,
        WalletId.PERA,
        {
          id: WalletId.WALLETCONNECT,
          options: { projectId: import.meta.env.VITE_WALLETCONNECT_PROJECT_ID }
        }
      ],
      defaultNetwork: NetworkId.TESTNET
    })

    useWalletContext(manager)
  }

  let { children } = $props()
</script>

{@render children()}

Next steps

Configuration

Learn about wallet and network configuration options

Wallets

Explore supported wallet providers and their options

Build docs developers (and LLMs) love