Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
OneAuthClient – 1auth
Skip to content

Overview

OneAuthClient is the core class of the 1auth SDK. It handles all interactions with the passkey authentication system including:

  • User registration and authentication
  • Transaction signing with multiple UX modes
  • Cross-chain intent submission
  • Token swaps

Constructor

import { OneAuthClient } from '@rhinestone/1auth';
 
const client = new OneAuthClient({
  providerUrl: 'https://passkey.1auth.box',
  theme: {
    mode: 'dark',
    accent: '#6366f1',
  },
});

Config Options

OptionTypeRequiredDescription
providerUrlstringNoURL of the 1auth provider (defaults to https://passkey.1auth.box)
dialogUrlstringNoURL for the dialog UI (defaults to providerUrl)
redirectUrlstringNoRedirect target for redirect flow
themeThemeConfigNoUI customization options
blind_signingbooleanNoHide the 1auth signing review iframe for supported signing calls. The browser WebAuthn prompt still appears.
testnetsbooleanNoWhen true, operate on testnet chains only (default: false)

Authentication Methods

authWithModal

Opens a combined sign-in/sign-up modal:

const result = await client.authWithModal();
 
if (result.success) {
  console.log('User:', result.user?.username);
  console.log('Address:', result.user?.address); // typed `0x${string}`
}

authenticate

Authenticate with optional challenge signing:

const result = await client.authenticate({
  username: 'user@example.com',
  challenge: '0x...', // Optional: sign a challenge
});

Signing Methods

Multiple UX modes for transaction signing:

signWithModal

Full-screen modal with transaction details:

const result = await client.signWithModal({
  username: 'user@example.com',
  calls: [{ to: '0x...', data: '0x...' }],
  targetChain: 8453,
});

signWithPopup

Opens signing in a popup window:

const result = await client.signWithPopup({
  username: 'user@example.com',
  calls: [{ to: '0x...', data: '0x...' }],
  targetChain: 8453,
});

signWithEmbed

Embeds signing UI in your page:

const result = await client.signWithEmbed({
  username: 'user@example.com',
  calls: [{ to: '0x...', data: '0x...' }],
  targetChain: 8453,
  embed: {
    containerId: 'signing-container',
  },
});

blind_signing

Set blind_signing: true on the client to hide the 1auth review iframe for supported signing flows and start the passkey ceremony immediately. The browser's WebAuthn prompt is still shown.

const client = new OneAuthClient({
  providerUrl: 'https://passkey.1auth.box',
  blind_signing: true,
});
 
const result = await client.sendIntent({
  accountAddress: '0x...',
  targetChain: 8453,
  calls: [{ to: '0x...', data: '0x...' }],
});

Per-call options can override the client default:

await client.signTypedData({
  accountAddress: '0x...',
  domain,
  types,
  primaryType,
  message,
  blind_signing: false,
});

Blind signing applies to sendIntent, sendBatchIntent, signMessage, signTypedData, and signWithModal. It does not apply to signup, login, recovery, or permission-grant dialogs. See Blind Signing for security guidance and failure behavior.

Intent Execution

sendIntent

Submit cross-chain intents to the Rhinestone orchestrator.

const result = await client.sendIntent({
  username: 'user@example.com',
  targetChain: 8453,
  calls: [
    {
      to: '0x...',
      data: '0x...',
      value: parseEther('0.1'),
      label: 'Mint NFT', // Optional — shown in the sign dialog
      sublabel: '0.10 USDC',
      icon: 'https://your-app.example/nft.svg', // Optional fallback icon
    },
  ],
  closeOn: 'completed',
});
 
if (result.success) {
  console.log('TX Hash:', result.transactionHash);
}

Each call in calls is an IntentCall and accepts four optional UI fields:

FieldDescription
labelPrimary line in the sign dialog action card (e.g. "Mint NFT")
sublabelSecondary line under the label (e.g. "0.10 USDC")
iconFallback icon URL (SVG / square PNG / data: URL, ≤ 8 KB) shown when 1auth's built-in token registry can't resolve a logo. Built-in icons always win — USDC / ETH / MATIC etc. ignore icon.
abiOptional ABI used by the sign dialog to render an unverified human-readable decode of data (function name + args). Same trust model as label / sublabel / icon — the dialog renders the decoded preview behind an "Unverified" badge and always shows the raw to + selector alongside as ground truth. See Per-call ABIs.

With Token Requests (Output-First)

Use tokenRequests to specify what tokens you want to receive. The orchestrator determines the optimal path to deliver them from the user's assets across any chain.

import { parseUnits } from 'viem';
 
const result = await client.sendIntent({
  username: 'user@example.com',
  targetChain: 8453,
  calls: [{ to: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', data: '0x' }],
  tokenRequests: [
    {
      token: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
      amount: parseUnits('100', 6), // 100 USDC (bigint)
    },
  ],
  closeOn: 'completed',
});

This is ideal for swaps, cross-chain transfers, or any "output-first" operation.

Pass waitForHash: true if you need a transaction hash. Otherwise, rely on intentId + getIntentStatus.

grantPermissions

Grant a scoped SmartSession permission to an app-owned session key. 1auth opens the permission review, collects the user's passkey approval, and submits the install/enable transaction. Your app sends only the public sessionKeyAddress; keep the private key in your own signer.

import { definePermissions, OneAuthClient } from '@rhinestone/1auth';
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
import { parseUnits } from 'viem';
 
const oneAuth = new OneAuthClient({
  providerUrl: 'https://passkey.1auth.box',
  sponsorship: {
    accessTokenUrl: '/api/sponsorship/access-token',
    extensionTokenUrl: '/api/sponsorship/extension-token',
  },
});
 
const privateKey = generatePrivateKey();
const sessionKeyAddress = privateKeyToAccount(privateKey).address;
const now = Math.floor(Date.now() / 1000);
 
const permissions = definePermissions({
  address: MockUSD,
  name: 'MockUSD',
  abi: erc20Abi,
  functions: {
    mint: {
      policies: [
        { type: 'usage-limit', limit: 25n },
        { type: 'time-frame', validAfter: now, validUntil: now + 24 * 60 * 60 },
      ],
      params: {
        to: { condition: 'equal', value: accountAddress },
        amount: { condition: 'equal', value: parseUnits('0.1', 6) },
      },
    },
  },
});
 
const result = await oneAuth.grantPermissions({
  accountAddress,
  targetChains: [84532],
  sessionKeyAddress,
  ...permissions,
});

After this grant succeeds, the app can prepare and submit a matching MockUSD.mint(accountAddress, parseUnits('0.1', 6)) intent with its session key. That later mint does not open another 1auth user-signature dialog; the SmartSession validator enforces the to and amount constraints on-chain.

sendSwap

High-level token swap API:

const result = await client.sendSwap({
  username: 'user@example.com',
  fromToken: '0x...', // USDC
  toToken: '0x...',   // WETH
  amount: parseUnits('100', 6),
  targetChain: 8453,
});

Utility Methods

getIntentStatus

Poll for transaction completion:

const status = await client.getIntentStatus(intentId);
console.log(status.status); // 'pending' | 'completed' | 'failed'

getPasskeys

Fetch user's registered passkeys:

const { passkeys } = await client.getPasskeys('user@example.com');
passkeys.forEach(p => console.log(p.name, p.createdAt));

setTheme

Update theme at runtime:

client.setTheme({
  accent: '#10b981',
  mode: 'dark',
});

Error Handling

All methods return result objects with success/error info:

const result = await client.sendIntent({ ... });
 
if (!result.success) {
  console.error('Code:', result.error?.code);
  console.error('Message:', result.error?.message);
}

Supported Networks

1auth supports all chains in the Rhinestone orchestrator network. Query supported chains at runtime:

import { getSupportedChains, getAllSupportedChainsAndTokens } from '@rhinestone/1auth';
 
// Get all supported chain IDs
const chains = getSupportedChains();
 
// Get chains with their supported tokens
const chainsAndTokens = getAllSupportedChainsAndTokens();

Mainnet chains include Ethereum, Base, Arbitrum, Optimism, Polygon, and others. The targetChain parameter in sendIntent() and sendSwap() accepts any supported chain ID.

Transaction Lifecycle

When you call sendIntent(), the transaction progresses through these stages:

StatusDescription
pendingIntent created, waiting for quote
quotedQuote received from orchestrator
signedUser has signed with their passkey
submittedSubmitted to the Rhinestone orchestrator
claimedA solver has claimed the intent
preconfirmedPre-confirmation received (typically < 1 second)
filledTransaction filled on the target chain
completedFully confirmed on-chain
failedIntent failed
expiredIntent expired before execution

The closeOn option controls when sendIntent() resolves:

  • "preconfirmed" (default) — Resolves quickly, recommended for most use cases
  • "claimed" — Resolves at first solver claim (fastest, less certain)
  • "filled" — Resolves when the transaction hits the target chain
  • "completed" — Waits for full on-chain confirmation (slowest)

For a transaction hash, pass waitForHash: true or poll with getIntentStatus() after the intent resolves.

Notes

  • Create one client instance and reuse it
  • Use the closeOn parameter to control when promises resolve
  • The client handles all WebAuthn and passkey operations internally
  • signMessage and signTypedData require a passkey session (call authWithModal() first)
  • If you see 401 from /api/sign/options, your session cookie is missing or blocked