Examples
React verification button
A complete component: detects the extension, launches verification, follows the flow, and reports the outcome.
KeyringVerification.tsx
import { useEffect, useRef, useState } from "react";
import {
KeyringConnect,
type ExtensionSDKConfig,
type ExtensionState,
} from "@keyringnetwork/keyring-connect-sdk";
type Phase = "checking" | "ready" | "verifying" | "verified" | "failed";
export function KeyringVerification({ wallet }: { wallet: string }) {
const [phase, setPhase] = useState<Phase>("checking");
const [message, setMessage] = useState<string>();
const unsubscribe = useRef<() => void>();
useEffect(() => {
KeyringConnect.isKeyringConnectInstalled().then(() => setPhase("ready"));
return () => unsubscribe.current?.();
}, []);
const config: ExtensionSDKConfig = {
name: "Example dApp",
app_url: window.location.origin,
logo_url: "https://example.com/logo.png",
policy_id: 7,
credential_config: { chain_id: 1, wallet_address: wallet },
};
async function verify() {
setPhase("verifying");
try {
await KeyringConnect.launchExtension(config);
unsubscribe.current = KeyringConnect.subscribeToExtensionState(
(state) => {
if (!state) return;
if (state.status === "prove_success") {
unsubscribe.current?.();
setPhase("verified");
}
if (state.status === "prove_error" || state.status === "error") {
setMessage(state.error);
setPhase("failed");
}
},
);
} catch (error) {
setMessage(error instanceof Error ? error.message : String(error));
setPhase("failed");
}
}
if (phase === "checking") return <button disabled>Checking…</button>;
if (phase === "verified") return <p>Verification complete.</p>;
return (
<div>
<button onClick={verify} disabled={phase === "verifying"}>
{phase === "verifying" ? "Verifying…" : "Verify with Keyring"}
</button>
{phase === "failed" ? <p role="alert">{message}</p> : null}
</div>
);
}Returning-user shortcut
A user who already holds a valid credential needs no new proof. Check the
extension’s user object before launching:
const state = await KeyringConnect.getExtensionState();
if (state?.user?.credential_status === "valid") {
// already compliant on chain; skip verification
} else {
await KeyringConnect.launchExtension(config);
}For the on-chain half of the integration, continue with gating with checkCredential.
Last verified on