Skip to main content
If your users already have an EOA, you can connect it directly to the Rhinestone SDK and start sending intents straight away. No deployment, no migration, no smart account setup required. The SDK handles the orchestration layer for you — you write the same sendTransaction call as any other account type, and the Rhinestone Orchestrator takes care of routing, bridging, and settlement. The result is significantly better DX than calling the raw API yourself. This is the right choice when:
  • Your users have existing EOAs with assets they want to keep at their current address
  • You want intent support without requiring users to migrate to a smart account
  • You need the simplest possible integration path
Plain EOAs do not support modules, session keys, gas sponsorship, or multisig. If you need those features, use EIP-7702 to add smart account capabilities to an existing EOA, or create a new smart account.

Setup

Pass type: 'eoa' in the account config and provide the EOA as the signer. The EOA address is used directly — no separate smart account address is derived.
import { RhinestoneSDK } from '@rhinestone/sdk'
import { privateKeyToAccount } from 'viem/accounts'
import { arbitrum, base } from 'viem/chains'
import { encodeFunctionData, erc20Abi, parseUnits } from 'viem'

const eoaAccount = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`)

const rhinestone = new RhinestoneSDK({
  apiKey: process.env.RHINESTONE_API_KEY as string,
})

const account = await rhinestone.createAccount({
  account: { type: 'eoa' },
  eoa: eoaAccount,
})

Send an intent

Once the account is created, the transaction API is identical to any other account type.
const recipientAddress = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'

const result = await account.sendTransaction({
  sourceChains: [arbitrum],
  targetChain: base,
  calls: [
    {
      to: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
      data: encodeFunctionData({
        abi: erc20Abi,
        functionName: 'transfer',
        args: [recipientAddress, parseUnits('10', 6)],
      }),
    },
  ],
  tokenRequests: [
    {
      address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
      amount: parseUnits('10', 6),
    },
  ],
})

const status = await account.waitForExecution(result)
The Orchestrator handles token sourcing, bridging, and gas — your code stays the same regardless of which chain the user’s funds are on.

Next steps

EIP-7702

Add smart account features to an existing EOA without changing its address.

Create a smart account

Start fresh with a full smart account: modules, session keys, gas sponsorship.