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

PayButton

One-click payment button with built-in authentication. Users click, authenticate with their passkey, and the transaction executes.

Usage

import { PayButton } from '@rhinestone/1auth/react';
 
<PayButton
  client={client}
  intent={{
    targetChain: 8453,
    calls: [{ to: '0x...', value: parseEther('0.01') }],
  }}
  onSuccess={(result) => console.log('Paid:', result.transactionHash)}
  onError={(error) => console.error(error)}
/>

Props

PropTypeRequiredDescription
clientOneAuthClientYesSDK client instance
intentIntentParamsYesTransaction parameters
onSuccess(result) => voidNoCalled on successful transaction
onError(error) => voidNoCalled on error
childrenReactNodeNoButton text (default: "Pay with 1auth")
classNamestringNoCustom CSS class
disabledbooleanNoDisabled state

IntentParams

interface IntentParams {
  targetChain: number;           // Chain ID to execute on
  calls: IntentCall[];           // Array of calls to execute
  tokenRequests?: TokenRequest[]; // Optional: tokens to receive (output-first)
}
 
interface IntentCall {
  to: `0x${string}`;             // Target contract address
  value?: bigint;                // ETH value to send
  data?: `0x${string}`;          // Encoded calldata
}
 
interface TokenRequest {
  token: string;                 // ERC-20 token contract address
  amount: bigint;                // Amount in base units
}

Examples

Simple Payment

<PayButton
  client={client}
  intent={{
    targetChain: 8453,
    calls: [{
      to: '0xRecipientAddress',
      value: parseEther('0.01')
    }],
  }}
>
  Pay $10
</PayButton>

Contract Interaction

<PayButton
  client={client}
  intent={{
    targetChain: 8453,
    calls: [{
      to: contractAddress,
      data: encodeFunctionData({
        abi: contractAbi,
        functionName: 'mint',
        args: [tokenId],
      }),
      value: parseEther('0.05'),
    }],
  }}
  onSuccess={(result) => {
    toast.success('NFT minted!');
    router.push(`/nft/${tokenId}`);
  }}
>
  Mint NFT
</PayButton>

Custom Styling

<PayButton
  client={client}
  intent={intent}
  className="bg-purple-600 hover:bg-purple-700 text-white px-6 py-3 rounded-lg"
>
  Complete Purchase
</PayButton>

ERC20 Payment with tokenRequests

For payments in ERC20 tokens (like USDC), use tokenRequests to tell the orchestrator what tokens are needed. This enables cross-chain funding - users can pay even if their funds are on a different chain.

import { encodeFunctionData, parseUnits } from 'viem';
 
const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
const amount = parseUnits('10', 6); // 10 USDC
 
const transferData = encodeFunctionData({
  abi: erc20Abi,
  functionName: 'transfer',
  args: [merchantAddress, amount],
});
 
<PayButton
  client={client}
  intent={{
    targetChain: 8453, // Base
    calls: [{
      to: USDC_BASE,
      data: transferData,
      label: 'Pay Merchant',
      sublabel: '10 USDC',
    }],
    tokenRequests: [{
      token: USDC_BASE,
      amount: amount,
    }],
  }}
  onSuccess={(result) => toast.success('Payment complete!')}
>
  Pay 10 USDC
</PayButton>

Chain Abstraction

The user can pay from any chain they have funds on. If their balance is on Arbitrum but targetChain is Base, 1auth automatically bridges the assets. Users see a unified balance and never worry about which chain they're on.