@futurekode/stablepay-react
v1.0.0
Published
Headless React SDK for stable token payments on Solana
Maintainers
Readme
@futurekode/stablepay-react
Headless React components and helpers for accepting stable tokens on Solana with built-in verification. USDC remains the default.
This package is the reusable payment component layer. It does not depend on the hosted Payflow dashboard or request-page product.
Install
npm install @futurekode/stablepay-reactUsage
Simple checkout
import {
StablePayProvider,
StablePayButton,
usePaymentVerification,
} from "@futurekode/stablepay-react";
export function Checkout() {
const { status, verify } = usePaymentVerification();
return (
<StablePayProvider to="YOUR_WALLET_ADDRESS">
<StablePayButton
amount={0.1}
reference="order-123"
metadata={{ requestId: "req_123", customerEmail: "[email protected]" }}
onSuccess={async (payload) => {
console.log(payload.metadata?.requestId);
await verify(payload);
}}
>
<button>
{status === "verifying"
? "Verifying..."
: status === "pending"
? "Confirming..."
: status === "confirmed"
? "Paid"
: "Pay 0.1 USDC"}
</button>
</StablePayButton>
</StablePayProvider>
);
}StablePayButton is the clearer alias for the payment button component. StablePay is still exported for compatibility.
Token presets
import { TOKENS, getTokenConfig } from "@futurekode/stablepay-react";
const usdc = TOKENS.USDC;
const usdt = getTokenConfig("USDT");Preflight checks
Use usePaymentPreflight to check wallet readiness before asking the user to sign.
import {
TOKENS,
StablePayButton,
StablePayProvider,
usePaymentPreflight,
} from "@futurekode/stablepay-react";
export function Checkout() {
const { check, loading, result } = usePaymentPreflight({
amount: 24,
to: "YOUR_WALLET_ADDRESS",
token: TOKENS.USDC,
});
return (
<StablePayProvider to="YOUR_WALLET_ADDRESS">
<button onClick={() => void check()}>
{loading ? "Checking..." : "Check wallet readiness"}
</button>
{result && <p>{result.message}</p>}
<StablePayButton amount={24} reference="invoice-1842" token={TOKENS.USDC}>
<button disabled={!result?.ok}>Pay 24.00 USDC</button>
</StablePayButton>
</StablePayProvider>
);
}runPaymentPreflight is also exported for non-hook usage.
Recipient token account creation
Set createRecipientTokenAccount if you want the payment transaction to create the recipient associated token account when it does not exist yet.
import { StablePayButton, TOKENS } from "@futurekode/stablepay-react";
<StablePayButton
amount={24}
reference="invoice-1842"
token={TOKENS.USDC}
createRecipientTokenAccount
>
<button>Pay 24.00 USDC</button>
</StablePayButton>;Error normalization
import { normalizeStablePayError, TOKENS } from "@futurekode/stablepay-react";
try {
// payment flow
} catch (error) {
const normalized = normalizeStablePayError(error, TOKENS.USDC);
console.log(normalized.code, normalized.message);
}Payment status and events
useStablePay exposes status, reset(), and lifecycle events for checkout-style flows.
import { TOKENS, useStablePay } from "@futurekode/stablepay-react";
export function CheckoutButton() {
const { pay, status, error, reset } = useStablePay();
return (
<>
<button
onClick={() =>
void pay({
amount: 24,
to: "YOUR_WALLET_ADDRESS",
reference: "invoice-1842",
token: TOKENS.USDC,
})
}
>
{status === "awaiting_wallet"
? "Connect wallet..."
: status === "preparing"
? "Preparing..."
: status === "submitting"
? "Opening wallet..."
: status === "confirming"
? "Confirming..."
: status === "confirmed"
? "Paid"
: "Pay 24.00 USDC"}
</button>
{error ? <p>{error.message}</p> : null}
{status === "failed" ? <button onClick={reset}>Try again</button> : null}
</>
);
}API
StablePayButton— clearer alias for the payment button componentuseStablePay— hook with payment status, reset, and lifecycle eventsusePaymentVerification— verify a submitted paymentusePaymentPreflight— wallet and payment readiness checksrunPaymentPreflight— non-hook preflight helperverifyPayment— verify a transaction against expected payment detailswaitForPaymentConfirmation— wait until a payment is confirmednormalizeStablePayError— map raw errors into developer-friendly messagesStableTokenConfig— token model for mint/decimals-aware integrations
token
StablePayButton accepts an optional token prop. If omitted, the package uses USDC_TOKEN_CONFIG.
import { StablePayButton, TOKENS } from "@futurekode/stablepay-react";
<StablePayButton amount={0.1} reference="order-123" token={TOKENS.USDC}>
<button>Pay 0.1 USDC</button>
</StablePayButton>;StablePay is still exported as a compatibility name for the same component. USDC compatibility helpers such as buildUsdcTransfer, parseUsdcPaymentFromTransaction, and getUsdcTokenAccountForWallet are also still exported, and USDC remains the default token when no token is provided.
metadata
StablePayButton accepts an optional metadata prop for app-side context.
<StablePayButton
amount={0.1}
reference="order-123"
metadata={{ requestId: "req_123", customerEmail: "[email protected]" }}
onSuccess={(payload) => {
console.log(payload.metadata?.requestId);
}}
>
<button>Pay 0.1 USDC</button>
</StablePayButton>metadata is:
- returned in the
onSuccesspayload - useful for request IDs, customer context, or analytics source data
- not sent on-chain
- not persisted anywhere by the package itself
