StrimzStrimz
SDKs

@strimz/sdk-react

React provider, components, and hooks for browser-side Strimz integrations.

The React SDK gives you a provider, hooks, and components that open Strimz hosted checkout, for a payment session or a subscription plan, from your own page. It uses publishable keys (pk_test_… and pk_live_…), which are safe to ship in a browser bundle. A publishable key grants no access: the SDK reads test or live mode from its prefix and calls only the public /v1/checkout and /v1/tokens routes, which answer browsers on any origin. See Calling Strimz from a browser.

Install

pnpm add @strimz/sdk-react

Provider

Wrap your app once:

app/layout.tsx
'use client'
import { StrimzProvider } from '@strimz/sdk-react'
 
export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <StrimzProvider publishableKey={process.env.NEXT_PUBLIC_STRIMZ_PUBLISHABLE_KEY!}>
      {children}
    </StrimzProvider>
  )
}

StrimzProvider takes a publishable key, never a secret key. Write operations, such as creating a payment session, go through your own backend with the server-side StrimzClient, which refuses to start in a browser (see Create sessions on your server). The provider also accepts apiBaseUrl to override the API base URL and checkoutOrigin to override the hosted-checkout origin (default https://checkout.strimz.finance). It takes an origin only: a path, query or hash throws.

<StrimzPayButton />

Drop-in checkout button for an existing session:

'use client'
import { useRouter } from 'next/navigation'
import { toast } from 'sonner'
import { StrimzPayButton } from '@strimz/sdk-react'
 
export function Checkout({ session }: { session: { id: string } }) {
  const router = useRouter()
  return (
    <StrimzPayButton
      sessionId={session.id}
      onSuccess={(txHash) => router.push(`/thanks?tx=${txHash ?? ''}`)}
      onError={(err) => toast.error(err.message)}
    />
  )
}

The button opens Strimz hosted checkout for the session, in a popup by default or as a full-page redirect with mode="redirect". The hosted checkout uses Reown AppKit to connect a wallet. It then prompts the customer for two typed-data signatures. The first is an EIP-3009 ReceiveWithAuthorization that authorises USDC (or EURC) to move. The second is a Strimz PayIntent that binds the payment to this specific merchant, amount, and session. onSuccess receives the on-chain transaction hash when the checkout reports success. Treat it as a UI signal only: your webhook is the source of truth for fulfilment.

The PayIntent signature is what stops an intercepted EIP-3009 auth from being replayed to a different merchant. Same story on subscriptions: the wallet prompts once for the EIP-2612 permit and once for a SubscriptionIntent that pins the plan.

<StrimzCheckoutEmbed />

For a full embedded checkout (no redirect):

<StrimzCheckoutEmbed
  sessionId={session.id}
  className="rounded-xl border"
  onSuccess={(txHash) => router.push(`/thanks?tx=${txHash ?? ''}`)}
/>

Renders the hosted checkout inline in an iframe. Useful for cart-style flows where you don't want to lose the buyer's context.

PropTypeDefaultDescription
sessionIdstringrequiredThe payment session to pay.
heightnumber | string600Iframe height.
theme'light' | 'dark'payer's preferencePins the embedded checkout to light or dark. Omit it to follow the payer's system.
onSuccess(txHash?: string) => voidCalled with the transaction hash after a successful payment.
onCancel() => voidCalled when the payer cancels.
onError(error: Error) => voidCalled with a StrimzCheckoutError when the checkout reports an error.
classNamestringClass name for the iframe wrapper.
styleReact.CSSPropertiesInline style for the iframe wrapper.

Checkout results

The popup and the embed report back to your page with onSuccess(txHash), onCancel() and onError(error). Neither one navigates, so the session's successUrl and cancelUrl only apply to the full-page redirect. In the popup, onCancel also fires when the payer closes the window.

error is a StrimzCheckoutError with code (load_failed, merchant_not_ready or payment_reverted), sessionId and message. A failure the payer can retry stays inside the checkout and is not reported.

Your page only accepts a message from the checkout origin, from its own popup or iframe, and for the session it opened. These callbacks need version 0.3.0 or later; earlier versions never receive a result.

Subscription plans

<StrimzSubscribeButton /> and <StrimzSubscriptionEmbed /> open the hosted checkout for a plan instead of a payment session. There's no session to create: pass the plan id.

'use client'
import { useRouter } from 'next/navigation'
import { toast } from 'sonner'
import { StrimzSubscribeButton } from '@strimz/sdk-react'
 
export function Subscribe({ planId }: { planId: string }) {
  const router = useRouter()
  return (
    <StrimzSubscribeButton
      planId={planId}
      onSuccess={({ subscriptionId }) => router.push(`/welcome?sub=${subscriptionId ?? ''}`)}
      onError={(err) => toast.error(err.message)}
    />
  )
}
<StrimzSubscriptionEmbed planId={planId} className="rounded-xl border" onSuccess={onSubscribed} />

The button takes the same mode, theme, size and label props as <StrimzPayButton />. The embed takes the same height (default 640), theme, className and style props as <StrimzCheckoutEmbed />.

  • onSuccess({ subscriptionId, txHash }) fires once Strimz has recorded the subscription. The checkout waits up to 30 seconds for that. If it takes longer, subscriptionId is null and the subscription.created webhook carries it.
  • onCancel() fires when the payer cancels, or closes the popup.
  • onError(error) gets a StrimzSubscriptionError with code (load_failed, merchant_not_ready, payment_reverted or already_subscribed), planId and message. already_subscribed means the connected wallet already has a live subscription to the plan.

As with payments, your page only accepts a message from the checkout origin, from its own popup or iframe, and for the plan it opened. Treat onSuccess as a UI signal and confirm with the webhook. These components need version 0.4.0 or later.

Hooks

The package exports four hooks. All of them must be used inside <StrimzProvider>.

  • useStrimzSession(sessionId, { pollIntervalMs? }) reads a payment session with the publishable key and polls until it reaches a terminal state (confirmed, failed, expired, or cancelled). It returns { session, loading, error, refresh }.
  • useStrimzCheckout({ mode?, onSuccess?, onCancel?, onError? }) is the imperative opener behind <StrimzPayButton />. It returns { open(sessionId), close(), status }.
  • useStrimzSubscribe({ mode?, onSuccess?, onCancel?, onError? }) is the opener behind <StrimzSubscribeButton />. It returns { open(planId), close(), status }.
  • useStrimzClient() returns the provider's StrimzBrowserClient.
'use client'
import { useStrimzSession } from '@strimz/sdk-react'
 
function PaymentStatus({ sessionId }: { sessionId: string }) {
  const { session, loading, error } = useStrimzSession(sessionId)
  if (error) return <p>Could not load the payment: {error.message}</p>
  if (loading && !session) return <p>Loading…</p>
  return <p>Status: {session?.status}</p>
}

The hooks have no TanStack Query dependency.

Source

github.com/StrimzLab/strimz/tree/main/packages/sdk-react

On this page