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

# Quickstart

> Create a smart account and send a crosschain transaction

Create a smart account and send a crosschain transaction.

By the end you'll have an account deployed on two chains and a USDC transfer that crossed between them, funded entirely with ETH.

## Prerequisites

You'll need a funding account with some testnet ETH on Base Sepolia. Get testnet ETH from [QuickNode](https://faucet.quicknode.com/drip) or [Alchemy](https://www.alchemy.com/faucets).

Install the SDK:

<CodeGroup>
  ```bash npm theme={null}
  npm install viem @rhinestone/sdk@beta
  ```

  ```bash pnpm theme={null}
  pnpm add viem @rhinestone/sdk@beta
  ```

  ```bash bun theme={null}
  bun install viem @rhinestone/sdk@beta
  ```
</CodeGroup>

<Steps>
  <Step title="Create an account">
    Create a smart account with a single ECDSA owner:

    ```ts theme={null}
    import { RhinestoneSDK } from '@rhinestone/sdk'
    import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
    import { baseSepolia, arbitrumSepolia } from 'viem/chains'
    import {
      createPublicClient,
      createWalletClient,
      encodeFunctionData,
      erc20Abi,
      type Hex,
      http,
      parseEther,
      parseUnits,
    } from 'viem'

    const fundingPrivateKey = process.env.FUNDING_PRIVATE_KEY
    if (!fundingPrivateKey) {
      throw new Error('FUNDING_PRIVATE_KEY is not set')
    }

    const sourceChain = baseSepolia
    const targetChain = arbitrumSepolia

    // You can use an existing PK here
    const privateKey = generatePrivateKey()
    console.log(`Owner private key: ${privateKey}`)
    const account = privateKeyToAccount(privateKey)

    const rhinestone = new RhinestoneSDK({
      apiKey: process.env.RHINESTONE_API_KEY,
    })
    const rhinestoneAccount = await rhinestone.createAccount({
      owners: {
        type: 'ecdsa',
        accounts: [account],
      },
    })
    const address = rhinestoneAccount.getAddress()
    console.log(`Smart account address: ${address}`)
    ```

    You'll see a deterministic address printed:

    ```txt theme={null}
    Smart account address: 0x...
    ```

    Nothing is onchain yet: the account is deployed lazily on first use, on each chain it touches.
  </Step>

  <Step title="Fund the account">
    Send ETH to the smart account on the source chain. This is the only token you fund:

    ```ts theme={null}
    const publicClient = createPublicClient({
      chain: sourceChain,
      transport: http(),
    })
    const fundingAccount = privateKeyToAccount(fundingPrivateKey as Hex)
    const fundingClient = createWalletClient({
      account: fundingAccount,
      chain: sourceChain,
      transport: http(),
    })

    const txHash = await fundingClient.sendTransaction({
      to: address,
      value: parseEther('0.001'),
    })
    await publicClient.waitForTransactionReceipt({ hash: txHash })
    ```
  </Step>

  <Step title="Send a crosschain transaction">
    Transfer USDC on the target chain, sourced from the ETH you funded on the source chain:

    ```ts theme={null}
    const usdcAmount = parseUnits('0.1', 6)

    const prepared = await rhinestoneAccount.prepareTransaction({
      sourceChains: [sourceChain],
      targetChain,
      calls: [
        {
          to: 'USDC',
          value: 0n,
          data: encodeFunctionData({
            abi: erc20Abi,
            functionName: 'transfer',
            args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', usdcAmount],
          }),
        },
      ],
      tokenRequests: [
        {
          address: 'USDC',
          amount: usdcAmount,
        },
      ],
    })
    const signed = await rhinestoneAccount.signTransaction(prepared)
    const transaction = await rhinestoneAccount.submitTransaction(signed)
    console.log('Transaction', transaction)

    const transactionResult = await rhinestoneAccount.waitForExecution(transaction)
    console.log('Result', transactionResult)
    ```

    `submitTransaction` returns an intent handle; `waitForExecution` polls until every chain's operation reaches a terminal state:

    ```txt theme={null}
    Transaction {
      type: 'intent',
      id: '0x9c…',
      traceId: '…',
      sourceChains: [ 84532 ],
      targetChain: 421614
    }
    Result {
      status: 'COMPLETED',
      accountAddress: '0x5fA3…42c1',
      operations: [
        { chain: 84532, status: 'COMPLETED', txHash: '0x…', timestamp: 1750000000 },
        { chain: 421614, status: 'COMPLETED', txHash: '0x…', timestamp: 1750000002 }
      ]
    }
    ```

    Your ETH on Base Sepolia landed as USDC on Arbitrum Sepolia in a single atomic operation: no bridging, swapping, or gas tokens to manage.
  </Step>
</Steps>

<Info>
  **Building a browser app?** Use the [Reown + Rhinestone example](https://github.com/rhinestonewtf/e2e-examples/tree/main/reown) to get wallet connection working with MetaMask or any WalletConnect-compatible wallet.
</Info>

## Next steps

<CardGroup cols={3}>
  <Card title="Sponsor fees" icon="fuel" href="./tutorials/sponsor-fees">
    Cover gas, bridging, and swap fees for your users across any chain.
  </Card>

  <Card title="Smart account setup" icon="settings" href="./core/create-account">
    Configure signers: passkeys, embedded wallets, multisig, and more.
  </Card>

  <Card title="Smart Sessions" icon="key" href="./smart-sessions/overview">
    Add session keys for one-click UX and automated transactions.
  </Card>
</CardGroup>
