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

# Quickstart: Send tokens across wallets on the same blockchain

> Use the App Kit SDK to send tokens from one wallet to another on the same blockchain

This quickstart walks you through sending tokens from one wallet to another on
the same blockchain. The example in this quickstart sends USDC on Arc Testnet,
but you can use another
[supported token or blockchain](/app-kit/references/supported-blockchains).

<Tabs>
  <Tab title="Browser wallet">
    Use this flow to send USDC from a browser wallet. The wallet runs in the
    browser, and the user signs transactions in the wallet extension, so connect the
    wallet first and call `kit.send()` only after the wallet is available.

    This example uses the
    [Viem adapter](https://www.npmjs.com/package/@circle-fin/adapter-viem-v2) to
    send USDC on an EVM-compatible blockchain in an existing browser app. The sample
    configuration uses Arc Testnet, but you can use any
    [supported EVM chain and token](/app-kit/references/supported-blockchains).

    ## Prerequisites

    Before you begin, ensure that you have:

    * Installed [Node.js v22+](https://nodejs.org/).
    * Installed a browser wallet such as [MetaMask](https://metamask.io/) and added
      the
      [Arc Testnet](https://docs.arc.network/arc/references/connect-to-arc#wallet-setup)
      network.
    * Funded your wallet with testnet USDC from the
      [Circle Faucet](https://faucet.circle.com/).

    ## Step 1. Set up the project

    ### 1.1. Create the project and install dependencies

    Create a new directory, install the App Kit packages, and add local browser demo
    tooling:

    ```bash Shell theme={null}
    # Set up your directory and initialize a Node.js project
    mkdir app-kit-send-browser-wallet
    cd app-kit-send-browser-wallet
    npm init -y
    npm pkg set type=module

    # Install App Kit packages
    npm install @circle-fin/app-kit @circle-fin/adapter-viem-v2 viem

    # Install TypeScript and a local Vite dev server for the browser demo
    npm install --save-dev typescript vite
    ```

    ### 1.2. Configure TypeScript (optional)

    <Info>
      This step is optional. It helps prevent missing types in your IDE or editor.
    </Info>

    Create a `tsconfig.json` file:

    ```bash Shell theme={null}
    npx tsc --init
    ```

    Then, update the `tsconfig.json` file:

    ```bash Shell theme={null}
    cat <<'EOF' > tsconfig.json
    {
      "compilerOptions": {
        "target": "ESNext",
        "module": "ESNext",
        "moduleResolution": "bundler",
        "strict": true,
        "types": ["node"]
      }
    }
    EOF
    ```

    ## Step 2. Connect a browser wallet

    This step shows the core browser wallet integration flow: discover an
    [`EIP-6963`](https://eips.ethereum.org/EIPS/eip-6963) provider, create an App
    Kit adapter from the selected provider, and pass that adapter into an App Kit
    SDK method.

    The snippets below keep wallet discovery, wallet connection, and adapter setup
    in small helper functions for readability.

    ### 2.1. Discover a browser wallet with `EIP-6963`

    <Info>
      This pattern is standards-based. The example uses MetaMask as the selected
      wallet, but the discovery flow works with any wallet that announces an
      `EIP-6963` provider.
    </Info>

    ```typescript TypeScript theme={null}
    import type { EIP1193Provider } from "viem";

    type EIP6963ProviderInfo = {
      uuid: string;
      name: string;
      icon: string;
      rdns: string;
    };

    type EIP6963ProviderDetail = {
      info: EIP6963ProviderInfo;
      provider: EIP1193Provider;
    };

    declare global {
      interface WindowEventMap {
        "eip6963:announceProvider": CustomEvent<EIP6963ProviderDetail>;
      }
    }

    async function discoverBrowserWallets(): Promise<EIP6963ProviderDetail[]> {
      const providers = new Map<string, EIP6963ProviderDetail>();

      const handleProviderAnnouncement = (
        event: WindowEventMap["eip6963:announceProvider"],
      ) => {
        providers.set(event.detail.info.uuid, event.detail);
      };

      window.addEventListener(
        "eip6963:announceProvider",
        handleProviderAnnouncement,
      );
      window.dispatchEvent(new Event("eip6963:requestProvider"));

      await new Promise((resolve) => window.setTimeout(resolve, 250));
      window.removeEventListener(
        "eip6963:announceProvider",
        handleProviderAnnouncement,
      );

      return [...providers.values()];
    }
    ```

    ### 2.2. Connect the wallet and request account access

    After you select a provider, request account access before attempting to bridge.
    This should happen in a user-triggered action such as a `Connect wallet` button.

    ```typescript TypeScript theme={null}
    async function connectWallet(provider: EIP1193Provider) {
      await provider.request({
        method: "eth_requestAccounts",
        params: undefined, // Required by the provider type even though this method has no params.
      });

      const accounts = (await provider.request({
        method: "eth_accounts",
        params: undefined, // Required by the provider type even though this method has no params.
      })) as string[];

      return {
        connectedAddress: accounts[0] ?? null,
      };
    }
    ```

    <Tip>
      Keep wallet connection and bridging as separate user actions. This avoids
      overlapping wallet permission or chain-switch requests while a previous wallet
      prompt is still pending.
    </Tip>

    ### 2.3. Create a Viem adapter from the selected wallet provider

    Use the discovered provider to request account access, then create the App Kit
    adapter that signs bridge transactions in the browser:

    ```typescript TypeScript theme={null}
    import { createViemAdapterFromProvider } from "@circle-fin/adapter-viem-v2";

    async function connectBrowserWallet() {
      const providers = await discoverBrowserWallets();
      const selectedWallet =
        providers.find(
          ({ info }) => info.rdns === "io.metamask" || info.name === "MetaMask",
        ) ?? providers[0];

      if (!selectedWallet) {
        throw new Error("No EIP-6963 browser wallet found");
      }

      const { connectedAddress } = await connectWallet(selectedWallet.provider);

      const adapter = await createViemAdapterFromProvider({
        provider: selectedWallet.provider,
      });

      return {
        adapter,
        connectedAddress,
        walletName: selectedWallet.info.name,
      };
    }
    ```

    <Tip>
      If multiple EVM wallets are installed, explicitly choose the wallet you want to
      use instead of relying on the first announced provider. The browser demo used to
      validate this quickstart prefers MetaMask when it is available.
    </Tip>

    ## Step 3. Send USDC

    ### 3.1. Call `kit.send()`

    This is the only App Kit-specific send call you need after the wallet is
    connected:

    ```typescript TypeScript theme={null}
    import { AppKit } from "@circle-fin/app-kit";
    import type { SendParams } from "@circle-fin/app-kit";

    const kit = new AppKit();

    async function sendUSDCWithBrowserWallet() {
      const { adapter, connectedAddress, walletName } =
        await connectBrowserWallet();

      const sendParams: SendParams = {
        from: { adapter, chain: "Arc_Testnet" },
        to: "RECIPIENT_ADDRESS",
        amount: "1.00",
        token: "USDC",
      };

      const estimate = await kit.estimateSend(sendParams);
      const result = await kit.send(sendParams);

      console.log(`Submitted send with ${walletName}`, {
        connectedAddress,
        estimate,
        result,
      });
      return result;
    }
    ```

    <Info>
      Using another
      [token](/app-kit/references/supported-blockchains#supported-tokens) or
      [blockchain](/app-kit/references/supported-blockchains)? Change the `token` and
      `chain` values in `kit.send()` and ensure the connected wallet holds enough
      funds to complete the transfer.
    </Info>

    ### 3.2. Verify the transaction

    After `kit.send()` resolves, inspect the returned result. Use the transaction
    explorer URL to verify the amount and recipient on the blockchain.

    The following is an example of how the result of a successful send might look in
    the browser console. The values are used in this example only and are not a real
    transaction:

    ```text Browser console theme={null}
    {
      name: "transfer",
      state: "success",
      txHash: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
      explorerUrl: "https://testnet.arcscan.app/tx/0x1234567890abcdef...",
    }
    ```
  </Tab>

  <Tab title="Circle Wallets">
    Send USDC from a developer-controlled wallet using the Circle Wallets adapter.
    The example uses Arc Testnet, but you can use any blockchain the Circle Wallets
    adapter [supports](/app-kit/references/supported-blockchains).

    ## Prerequisites

    Before you begin, ensure that you have:

    * Installed [Node.js v22+](https://nodejs.org/).
    * Obtained a
      [Circle API Key](https://developers.circle.com/w3s/circle-developer-account#creating-an-api-key-for-developer-services)
      and
      [Entity Secret](https://developers.circle.com/wallets/dev-controlled/register-entity-secret)
      from the
      [Circle Console](https://developers.circle.com/w3s/circle-developer-account).
    * Created a developer-controlled wallet on Arc Testnet using the Circle Console.
    * Funded your Arc Testnet wallet with testnet USDC from the
      [Circle Faucet](https://faucet.circle.com/).

    ## Step 1. Set up the project

    ### 1.1. Create the project and install dependencies

    Create a new directory and install the App Kit SDK with the Circle Wallets
    adapter and supporting tools:

    ```bash theme={null}
    # Set up your directory and initialize a Node.js project
    mkdir app-kit-send-circle-wallets
    cd app-kit-send-circle-wallets
    npm init -y
    npm pkg set type=module

    # Set up module type and start command
    npm pkg set scripts.start="tsx --env-file=.env index.ts"

    # Install runtime dependencies
    npm install @circle-fin/app-kit @circle-fin/adapter-circle-wallets tsx

    # Install dev dependencies
    npm install --save-dev typescript @types/node
    ```

    ### 1.2. Configure TypeScript (optional)

    <Info>
      This step is optional. It helps prevent missing types in your IDE or editor.
    </Info>

    Create a `tsconfig.json` file:

    ```bash Shell theme={null}
    npx tsc --init
    ```

    Then, update the `tsconfig.json` file:

    ```bash Shell theme={null}
    cat <<'EOF' > tsconfig.json
    {
      "compilerOptions": {
        "target": "ESNext",
        "module": "ESNext",
        "moduleResolution": "bundler",
        "strict": true,
        "types": ["node"]
      }
    }
    EOF
    ```

    ### 1.3. Set environment variables

    Create an `.env` file in the project directory:

    ```bash Shell theme={null}
    touch .env
    ```

    Add your credentials. Replace `YOUR_API_KEY` with your Circle Developer API key,
    `YOUR_ENTITY_SECRET` with your entity secret. You can fetch the address from the
    [Circle Developer Console](https://developers.circle.com/w3s/circle-developer-account)
    or the
    [list wallets](https://developers.circle.com/api-reference/wallets/developer-controlled-wallets/get-wallets)
    endpoint:

    ```text .env theme={null}
    CIRCLE_API_KEY=YOUR_API_KEY
    CIRCLE_ENTITY_SECRET=YOUR_ENTITY_SECRET
    ```

    <Tip>
      Edit `.env` files in your IDE or editor so credentials are not leaked to your
      shell history.
    </Tip>

    ## Step 2. Send USDC

    ### 2.1. Create the script

    Create an `index.ts` file in the project directory and add the following code.
    This code sends 1.00 USDC from your Circle Wallets-controlled Arc Testnet wallet
    to a recipient on Arc Testnet:

    <Info>
      Using another
      [token](/app-kit/references/supported-blockchains#supported-tokens) or
      [blockchain](/app-kit/references/supported-blockchains)? Change the `token` and
      `chain` values in `kit.send()` and ensure the source wallet has enough funds to
      complete the transfer.
    </Info>

    ```typescript TypeScript theme={null}
    import { AppKit } from "@circle-fin/app-kit";
    import { createCircleWalletsAdapter } from "@circle-fin/adapter-circle-wallets";
    import type { SendParams } from "@circle-fin/app-kit";

    const kit = new AppKit();

    const sourceWalletAddress = "YOUR_SOURCE_WALLET_ADDRESS";
    const recipientAddress = "RECIPIENT_ADDRESS";

    const adapter = createCircleWalletsAdapter({
      apiKey: process.env.CIRCLE_API_KEY!,
      entitySecret: process.env.CIRCLE_ENTITY_SECRET!,
    });

    const sendParams: SendParams = {
      from: {
        adapter,
        chain: "Arc_Testnet",
        address: sourceWalletAddress,
      },
      to: recipientAddress,
      amount: "1.00",
      token: "USDC",
    };

    const estimate = await kit.estimateSend(sendParams);
    const result = await kit.send(sendParams);

    console.dir({ estimate, result }, { depth: null, colors: true });
    ```

    ### 2.2. Run the script

    Save the `index.ts` file and run the script in your terminal:

    ```bash Shell theme={null}
    npm run start
    ```

    ### 2.3. Verify the transaction

    After the script finishes, inspect the returned result in the terminal output.
    Use the transaction explorer URL to verify the amount and recipient on the
    blockchain.

    The following is an example of how the result of a successful send might look in
    the terminal output. The values are used in this example only and are not a real
    transaction:

    ```text Terminal output theme={null}
    {
      estimate: { gas: 406817n, fee: '8138073262135265', gasPrice: 20004260545n },
      result: {
        name: 'send',
        state: 'success',
        txHash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
        explorerUrl: 'https://testnet.arcscan.app/tx/0x1234567890abcdef123456789...'
      }
    }
    ```
  </Tab>
</Tabs>
