React SDK
npm install @tallypay/react @tallypay/core react react-dom<TallyPayProvider>
Section titled “<TallyPayProvider>”Wraps your app (or a subtree) with TallyPay context. All hooks require this provider as an ancestor.
import { TallyPayProvider } from "@tallypay/react";
function App() { return ( <TallyPayProvider network="eip155:8453" walletClient={walletClient} apiKey="tp_live_..." collectorUrl="http://127.0.0.1:8787" > {children} </TallyPayProvider> );}Props (TallyPayProviderProps)
| Prop | Type | Required | Description |
|---|---|---|---|
network | string | Yes | CAIP-2 network identifier (e.g. "eip155:8453"). |
walletClient | unknown | Yes | A viem WalletClient or similar signing interface. Currently stored in context for your signing logic. |
apiKey | string | No | TallyPay API key. Enables client-side beacons to the trace collector. |
collectorUrl | string | No | Override the collector URL for local dev. |
children | ReactNode | Yes | — |
useTallyPay()
Section titled “useTallyPay()”Read the provider context. Throws if used outside <TallyPayProvider>.
import { useTallyPay } from "@tallypay/react";
const { network, walletClient, apiKey } = useTallyPay();Returns TallyPayContext
| Property | Type | Description |
|---|---|---|
network | string | Network from provider. |
walletClient | unknown | Wallet client from provider. |
apiKey | string | undefined | API key from provider. |
collectorUrl | string | undefined | Collector URL from provider. |
usePayment(url, options?)
Section titled “usePayment(url, options?)”Declarative hook for a single payment flow. Manages the full lifecycle: idle → pending → signing → settling → complete / error.
import { usePayment } from "@tallypay/react";
function PremiumContent() { const { pay, status, receipt, error, traceId } = usePayment( "http://localhost:3000/api/premium", );
return ( <div> <button onClick={pay} disabled={status === "pending" || status === "signing"}> {status === "complete" ? "Paid" : "Pay $0.01"} </button> {error && <p>{error.message}</p>} {receipt?.txHash && <p>TX: {receipt.txHash}</p>} </div> );}Parameters
| Param | Type | Description |
|---|---|---|
url | string | The paywalled endpoint URL. |
options | RequestInit | Optional fetch init (headers, method, body). |
Returns UsePaymentResult
| Property | Type | Description |
|---|---|---|
pay | () => Promise<void> | Trigger the payment flow. |
status | PaymentStatus | "idle" | "pending" | "signing" | "settling" | "complete" | "error" |
receipt | { txHash?: string; traceId?: string } | null | Settlement receipt after success. |
error | Error | null | Error from the most recent attempt. |
traceId | string | null | Trace ID from the server’s 402 response. |
Beacons: If apiKey is set in the provider, the hook emits 402_RECEIVED and PAYMENT_ERROR beacons to the collector via navigator.sendBeacon.
usePaymentFetch()
Section titled “usePaymentFetch()”Returns a fetch wrapper (built on wrapFetch from @tallypay/core) that automatically handles 402 responses.
import { usePaymentFetch } from "@tallypay/react";
const payFetch = usePaymentFetch();const res = await payFetch("/api/premium");Requires a signing implementation wired to the walletClient from the provider.
<PaymentButton>
Section titled “<PaymentButton>”Pre-built button with status feedback. Wraps usePayment.
import { PaymentButton } from "@tallypay/react";
<PaymentButton url="http://localhost:3000/api/premium" label="Unlock content" className="btn btn-primary" onComplete={(receipt) => console.log("Paid!", receipt.txHash)} onError={(err) => console.error(err)}/>Props (PaymentButtonProps)
| Prop | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Paywalled endpoint URL. |
label | string | No | Override the button text. Default labels based on status: “Pay”, “Processing…”, “Sign payment…”, “Settling…”, “Paid”, “Failed — Retry”. |
className | string | No | CSS class for the <button>. |
requestInit | RequestInit | No | Fetch options for the request. |
onComplete | (receipt) => void | No | Called after successful payment. |
onError | (error) => void | No | Called on failure. |
The button sets data-tallypay-status on the <button> element (the current PaymentStatus value), so you can style states with CSS attribute selectors:
[data-tallypay-status="complete"] { background: green; }[data-tallypay-status="error"] { background: red; }Client beacons
Section titled “Client beacons”When apiKey is set in the provider, hooks emit lightweight beacons via navigator.sendBeacon to the TallyPay collector at each client-side lifecycle step:
| Event | When |
|---|---|
402_RECEIVED | Client received a 402 from the server |
PAYMENT_SIGNED | Client signed the authorization |
PAYMENT_SUBMITTED | Client retried with payment-signature |
PAYMENT_COMPLETE | Final response was 2xx |
PAYMENT_ERROR | Any client-side step failed |
This is the unique data. Facilitators only see verify + settle. Only TallyPay sees the full client funnel: how many 402s go unpaid, how long signing takes, whether the final response was received.
Next steps
Section titled “Next steps”- Wallet signing with viem — implement the signer
- Server middleware — the server half
- Express + React tutorial — end-to-end walkthrough