> ## Documentation Index
> Fetch the complete documentation index at: https://docs.walletconnect.network/llms.txt
> Use this file to discover all available pages before exploring further.

# Installation

WalletConnect App SDK is chain agnostic and provides seamless integration with several blockchain ecosystems. WalletConnect App SDK when combined with Universal Provider library enables compatibility across any blockchain protocol.

## Pre-requisites

This section is to inform you about the pre-requisites for integrating WalletConnect as an App with Vue

### Cloud Configuration

Create a new project on WalletConnect Dashboard at [https://dashboard.walletconnect.com](https://dashboard.walletconnect.com) and obtain a new project ID. You will need this project ID to initialize WalletConnect in your project (app).

<Info>
  **Don't have a project ID?**

  Head over to WalletConnect Dashboard and create a new project now!

  <Card title="Get started" href="https://dashboard.walletconnect.com/?utm_source=cloud_banner&utm_medium=docs&utm_campaign=backlinks" />
</Info>

### Allowlist

To help prevent malicious use of your project ID, you are strongly encouraged to set an allowlist of [origins](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin) where your project ID is used. You can manage your allowlist in the [WalletConnect Dashboard](https://dashboard.walletconnect.com) under the project settings.

The allowlist supports a list of origins in the format `[scheme://]<hostname[:port]>`. Using `localhost` (or `127.0.0.1`) is always permitted, and if the allowlist is empty, all origins are allowed. Updates take 15 minutes to apply.

Examples of possible origins in the allowlist:

* `example.com` - allows `https://example.com` or `http://example.com` but not `https://www.example.com`
* `https://example.com` - allows `https://example.com` but not `http://example.com`
* `https://*.example.com` - allows `https://www.example.com` but not `https://example.com`

<Warning>
  Requests from origins not in the allowlist will be denied. Make sure to add all domains where your app will be deployed.
</Warning>

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers
  ```

  ```bash Yarn theme={null}
  yarn add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers
  ```

  ```bash Bun theme={null}
  bun add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers
  ```

  ```bash pnpm theme={null}
  pnpm add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers
  ```
</CodeGroup>

## Implementation

Here is a sample implementation of WalletConnect App SDK with Vue. You can also check the example repository below.

<Card title="WalletConnect App SDK Vue Example" icon="github" href="https://github.com/reown-com/appkit-web-examples/tree/main/vue/vue-universal-connector">
  Check the WalletConnect App SDK Vue example
</Card>

For a quick integration of WalletConnect App SDK you can use the `UniversalConnector` class. Which simplifies the integration of WalletConnect App SDK by providing a single interface for all the blockchain protocols.

You can configure the Universal Connector with the networks you want to support.
For more information, please visit [RPC Reference](https://docs.reown.com/advanced/multichain/rpc-reference/cosmos-rpc) section from our docs.

We recommend creating a config file to establish a singleton instance for the Universal Connector:

<CodeGroup>
  ```tsx Generic Example theme={null}
  import type { AppKitNetwork } from '@reown/appkit/networks'
  import type { CustomCaipNetwork } from '@reown/appkit-common'
  import { UniversalConnector } from '@reown/appkit-universal-connector'

  // Get projectId from https://dashboard.walletconnect.com
  export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID

  if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") {
    throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.')
  }

  const suiMainnet: CustomCaipNetwork<'sui'> = {
    id: 784,
    chainNamespace: 'sui' as const,
    caipNetworkId: 'sui:mainnet',
    name: 'Sui',
    nativeCurrency: { name: 'SUI', symbol: 'SUI', decimals: 9 },
    rpcUrls: { default: { http: ['https://fullnode.mainnet.sui.io:443'] } }
  }

  export const networks = [suiMainnet] as [AppKitNetwork, ...AppKitNetwork[]]

  export async function getUniversalConnector() {
    const universalConnector = await UniversalConnector.init({
      projectId,
      metadata: {
        name: 'Universal Connector',
        description: 'Universal Connector',
        url: 'https://www.walletconnect.com',
        icons: ['https://www.walletconnect.com/icon.png']
      },
      networks: [
        {
          methods: ['sui_signPersonalMessage'],
          chains: [suiMainnet as CustomCaipNetwork],
          events: [],
          namespace: 'sui'
        }
      ]
    })

    return universalConnector
  }
  ```

  ```tsx Stacks Example theme={null}
  import type { AppKitNetwork } from '@reown/appkit/networks'
  import type { InferredCaipNetwork } from '@reown/appkit-common'
  import { UniversalConnector } from '@reown/appkit-universal-connector'

  // Get projectId from https://dashboard.walletconnect.com
  export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID

  if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") {
    throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.')
  }

  // you can configure your own network
  const stacksMainnet: InferredCaipNetwork = {
    id: 'stacks-mainnet',
    chainNamespace: 'stacks' as const,
    caipNetworkId: 'stacks:1',
    name: 'Stacks Mainnet',
    nativeCurrency: { name: 'STX', symbol: 'STX', decimals: 6 },
    rpcUrls: { default: { http: ['https://stacks-node-api.mainnet.stacks.co'] } } // Example Stacks Mainnet RPC URL
  }

  export const networks = [stacksMainnet] as [AppKitNetwork, ...AppKitNetwork[]]

  export async function getUniversalConnector() {
    const universalConnector = await UniversalConnector.init({
      projectId,
      metadata: {
        name: 'Universal Connector',
        description: 'Universal Connector',
        url: 'https://www.walletconnect.com',
        icons: ['https://www.walletconnect.com/icon.png']
      },
      networks: [
        {
          methods: ['stx_signMessage', 'stx_signTransaction', 'stx_getAccounts', 'stx_getAddresses', 'stx_callContract', 'stx_deployContract', 'sendTransfer', 'getAddresses'],
          chains: [stacksMainnet as InferredCaipNetwork],
          events: ['stx_chainChanged', 'stx_accountsChanged'],
          namespace: 'stacks'
        }
      ]
    })

    return universalConnector
  }
  ```

  ```tsx TON Example theme={null}
  import type { AppKitNetwork } from '@reown/appkit/networks'
  import type { CustomCaipNetwork } from '@reown/appkit-common'
  import { UniversalConnector } from '@reown/appkit-universal-connector'

  // Get projectId from https://dashboard.walletconnect.com
  export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID

  if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") {
    throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.')
  }

  const tonMainnet: CustomCaipNetwork<'ton'> = {
    id: -239,
    chainNamespace: 'ton' as const,
    caipNetworkId: 'ton:-239',
    name: 'TON',
    nativeCurrency: { name: 'TON', symbol: 'TON', decimals: 9 },
    rpcUrls: { default: { http: ['https://toncenter.com/api/v2/jsonRPC'] } }
  }

  export const networks = [tonMainnet] as [AppKitNetwork, ...AppKitNetwork[]]

  export async function getUniversalConnector() {
    const universalConnector = await UniversalConnector.init({
      projectId,
      metadata: {
        name: 'Universal Connector',
        description: 'Universal Connector',
        url: 'https://www.walletconnect.com',
        icons: ['https://www.walletconnect.com/icon.png']
      },
      networks: [
        {
          methods: ['ton_signData'],
          chains: [tonMainnet as CustomCaipNetwork],
          events: [],
          namespace: 'ton'
        }
      ]
    })

    return universalConnector
  }
  ```

  ```tsx TRON Example theme={null}
  import type { AppKitNetwork } from '@reown/appkit/networks'
  import type { CustomCaipNetwork } from '@reown/appkit-common'
  import { UniversalConnector } from '@reown/appkit-universal-connector'

  // Get projectId from https://dashboard.walletconnect.com
  export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID

  if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") {
    throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.')
  }

  const tronMainnet: CustomCaipNetwork<'tron'> = {
    id: '0x2b6653dc',
    chainNamespace: 'tron' as const,
    caipNetworkId: 'tron:0x2b6653dc',
    name: 'Tron Mainnet',
    nativeCurrency: { name: 'TRX', symbol: 'TRX', decimals: 6 },
    rpcUrls: { default: { http: ['https://api.trongrid.io'] } }
  }

  export const networks = [tronMainnet] as [AppKitNetwork, ...AppKitNetwork[]]

  export async function getUniversalConnector() {
    const universalConnector = await UniversalConnector.init({
      projectId,
      metadata: {
        name: 'Universal Connector',
        description: 'Universal Connector',
        url: 'https://www.walletconnect.com',
        icons: ['https://www.walletconnect.com/icon.png']
      },
      networks: [
        {
          methods: ['tron_signTransaction', 'tron_signMessage'],
          chains: [tronMainnet as CustomCaipNetwork],
          events: [],
          namespace: 'tron'
        }
      ]
    })

    return universalConnector
  }
  ```
</CodeGroup>

In de App.vue file you can add :

```tsx theme={null}
<script lang="ts">
import { ref, onMounted, watch } from 'vue'
import { UniversalConnector } from '@reown/appkit-universal-connector'
import { getUniversalConnector } from './config/index'

export default {
  name: "App",
  setup() {
    const universalConnector = ref<UniversalConnector>()
    const session = ref<any>()

    onMounted(async () => {
      const connector = await getUniversalConnector()
      universalConnector.value = connector
    })

    watch(() => universalConnector.value?.provider.session, (newSession) => {
      session.value = newSession
    })
    return {
      universalConnector,
      session
    }
  }
};
</script>
```

## Trigger the modal

To open the WalletConnect modal you need to call the `connect` function from the Universal Connector.

```tsx theme={null}
<template>
  <div>
    <button @click="handleConnect">Open</button>
  </div>
</template>

...
    
async handleConnect() {
      if (!universalConnector) {
        return
      }
  
      const { session: providerSession } = await universalConnector.connect()
    }
```

## Smart Contract Interaction

<Tabs>
  <Tab title="Wagmi">
    [Wagmi actions](https://wagmi.sh/core/api/actions/readContract) can help us interact with wallets and smart contracts:

    ```html theme={null}
    <script setup lang="ts">
      import { readContract } from "@wagmi/core";
      import { USDTAbi } from "../abi/USDTAbi";

      const USDTAddress = "0x...";

      const data = readContract({
        abi: USDTAbi,
        address: USDTAddress,
        functionName: "symbol",
      });
    </script>
    ```

    Read more about Wagmi actions for smart contract interaction [here](https://wagmi.sh/core/actions/readContract).
  </Tab>

  <Tab title="Ethers">
    [Ethers](https://docs.ethers.org/v6/) can help us interact with wallets and smart contracts:

    ```html theme={null}
    <script setup lang="ts">
      import { useAppKitProvider, useAppKitAccount } from "@reown/appkit/vue";
      import { BrowserProvider, Contract, formatUnits } from "ethers";

      const USDTAddress = "0x617f3112bf5397D0467D315cC709EF968D9ba546";

      // The ERC-20 Contract ABI, which is a common contract interface
      // for tokens (this is the Human-Readable ABI format)
      const USDTAbi = [
        "function name() view returns (string)",
        "function symbol() view returns (string)",
        "function balanceOf(address) view returns (uint)",
        "function transfer(address to, uint amount)",
        "event Transfer(address indexed from, address indexed to, uint amount)",
      ];

      function Components() {
        const { address, isConnected } = useAppKitAccount();
        const { walletProvider } = useAppKitProvider("eip155");

        async function getBalance() {
          if (!isConnected) throw Error("User disconnected");

          const ethersProvider = new BrowserProvider(walletProvider);
          const signer = await ethersProvider.getSigner();
          // The Contract object
          const USDTContract = new Contract(USDTAddress, USDTAbi, signer);
          const USDTBalance = await USDTContract.balanceOf(address);

          console.log(formatUnits(USDTBalance, 18));
        }
        return <button onClick={getBalance}>Get User Balance</button>;
      }
    </script>
    ```
  </Tab>

  <Tab title="Solana">
    [@Solana/web3.js](https://solana.com/docs/clients/javascript) library allows for seamless interaction with wallets and smart contracts on the Solana blockchain.

    For a practical example of how it works, you can refer to our [lab dApp](https://lab.reown.com/appkit/?name=solana).

    ```tsx theme={null}
    import { ref } from 'vue';
    import {
      SystemProgram,
      PublicKey,
      Keypair,
      Transaction,
      TransactionInstruction,
      LAMPORTS_PER_SOL
    } from '@solana/web3.js';
    import { useAppKitAccount, useAppKitProvider } from '@reown/appkit/vue'
    import { useAppKitConnection, type Provider } from '@reown/appkit-adapter-solana/vue'

    export default {
      setup() {
        const counterMessage = ref('');
        const { address } = useAppKitAccount();
        const { connection } = useAppKitConnection()
        const { walletProvider } = useAppKitProvider<Provider>('solana')

        function deserializeCounterAccount(data) {
          if (data?.byteLength !== 8) {
            throw Error('Need exactly 8 bytes to deserialize counter');
          }

          return {
            count: Number(data[0])
          };
        }

        async function onIncrementCounter() {
          try {
            const PROGRAM_ID = new PublicKey('Cb5aXEgXptKqHHWLifvXu5BeAuVLjojQ5ypq6CfQj1hy');

            const counterKeypair = Keypair.generate();
            const counter = counterKeypair.publicKey;

            const balance = await connection.getBalance(walletProvider.publicKey);
            if (balance < LAMPORTS_PER_SOL / 100) {
              throw Error('Not enough SOL in wallet');
            }

            const COUNTER_ACCOUNT_SIZE = 8;
            const allocIx = SystemProgram.createAccount({
              fromPubkey: walletProvider.publicKey,
              newAccountPubkey: counter,
              lamports: await connection.getMinimumBalanceForRentExemption(COUNTER_ACCOUNT_SIZE),
              space: COUNTER_ACCOUNT_SIZE,
              programId: PROGRAM_ID
            });

            const incrementIx = new TransactionInstruction({
              programId: PROGRAM_ID,
              keys: [
                {
                  pubkey: counter,
                  isSigner: false,
                  isWritable: true
                }
              ],
              data: Buffer.from([0x0])
            });

            const tx = new Transaction().add(allocIx).add(incrementIx);

            tx.feePayer = walletProvider.publicKey;
            tx.recentBlockhash = (await connection.getLatestBlockhash('confirmed')).blockhash;

            await walletProvider.signAndSendTransaction(tx, [counterKeypair]);

            const counterAccountInfo = await connection.getAccountInfo(counter, {
              commitment: 'confirmed'
            });

            if (!counterAccountInfo) {
              throw new Error('Expected counter account to have been created');
            }

            const counterAccount = deserializeCounterAccount(counterAccountInfo?.data);

            if (counterAccount.count !== 1) {
              throw new Error('Expected count to have been 1');
            }

            counterMessage.value = `[alloc+increment] count is: ${counterAccount.count}`;
          } catch (error) {
            console.error(error);
            counterMessage.value = `Error: ${error.message}`;
          }
        }

        return {
          onIncrementCounter,
          counterMessage
        };
      }
    };
    ```
  </Tab>
</Tabs>
