// Overview + Integration handoff screens
const OverviewScreen = ({ setRoute, openModal }) => {
const steps = [
{ key: "proj", label: "Create project", done: true, desc: "Ledger Payments" },
{ key: "env", label: "Configure environments", done: true, desc: "dev · staging · prod" },
{ key: "keys", label: "Issue API credentials", done: true, desc: "3 active keys" },
{ key: "oidc", label: "Register OIDC client", done: true, desc: "Sign in with Swop — Web" },
{ key: "policy", label: "Attach signing policy", done: false, desc: "Required before prod traffic" },
{ key: "webhook", label: "Verify webhook endpoint", done: false, desc: "Ingest events at scale" },
];
const completed = steps.filter(s => s.done).length;
const pct = Math.round((completed / steps.length) * 100);
return (
<>
Overview
Monitor integration health, pending actions, and traffic across Ledger Payments.
}>Docs
} onClick={() => setRoute("handoff")}>Integrate
setRoute("handoff")}>Open handoff →}
>
{pct}%
Ready for staging traffic
{steps.map((s, i) => (
{s.done ? : {i + 1} }
{!s.done &&
Continue }
))}
setRoute("signing")}>All →}>
Sign transfer · 1.20 ETH
wlt_7bf24xA → 0xf2c3…9a11 · 3m ago
openModal("sign")}>Review
Policy change · daily cap +50%
Requested by Omar Vega · 12m ago
Review
{["prod", "staging", "dev"].map(e => (
{e === "prod" ? "Production" : e === "staging" ? "Staging" : "Development"}
{e === "prod" ? "842 req/min · 0 err" : e === "staging" ? "41 req/min · 1 err" : "idle"}
))}
setRoute("audit")}>Audit log →} bodyClass="pad-0">
{AUDIT_EVENTS.slice(0, 5).map(e => (
{e.t}
{e.who === "system" ? system : {e.who} }
{e.action}
{e.target}
{e.meta}
))}
>
);
};
// --- Integration handoff — the hero flow
const HandoffScreen = ({ setRoute, openModal, tweaks }) => {
const [step, setStep] = useStateS(2); // pretend user is mid-flow
const total = 5;
const steps = [
{ key: "proj", label: "Project", desc: "Ledger Payments · prj_7QkA2vN" },
{ key: "env", label: "Environments", desc: "dev · staging · prod" },
{ key: "keys", label: "API credentials", desc: "Server key + webhook secret" },
{ key: "oidc", label: "OIDC client", desc: "Hosted auth + Sign in with Swop" },
{ key: "sdk", label: "SDK snippet", desc: "Ship to a real login" },
];
return (
<>
Developer handoff
Ship Swivy in under 10 minutes.
A guided path from a fresh project to your first authenticated, wallet-backed user — with credentials, policy scaffolding, and SDK snippets ready to paste.
}>Export as runbook
{/* Stepper rail */}
{steps.map((s, i) => (
setStep(i)} style={{
display: "grid", gridTemplateColumns: "24px 1fr", gap: 10, padding: "10px 8px",
borderRadius: 8, textAlign: "left", alignItems: "flex-start",
background: step === i ? "var(--bg-sunken)" : "transparent",
}}>
{i < step ? : i + 1}
))}
Production gate
Prod environment unlocks after passkey step-up and a review by an Owner.
{step === 0 &&
setStep(1)}/>}
{step === 1 && setStep(2)}/>}
{step === 2 && setStep(3)} openModal={openModal} tweaks={tweaks}/>}
{step === 3 && setStep(4)} tweaks={tweaks}/>}
{step === 4 && setRoute("overview")} tweaks={tweaks}/>}
setStep(Math.max(0, step - 1))} disabled={step === 0}>← Previous
Step {step + 1} of {total}
{step < total - 1 && setStep(step + 1)}>Continue → }
{step === total - 1 && setRoute("overview")}>Finish ✓ }
>
);
};
const StepProject = ({ onNext }) => (
);
const StepEnv = ({ onNext }) => (
{[
{ e: "dev", desc: "Sandbox keys · test data · no rate limits", ok: true },
{ e: "staging", desc: "Production-shaped · forked chain state", ok: true },
{ e: "prod", desc: "Live keys · real assets · passkey step-up", ok: false },
].map(x => (
{x.e === "prod" ? "Production" : x.e === "staging" ? "Staging" : "Development"}
{x.desc}
{x.ok ?
Provisioned :
Locked }
))}
);
const StepKeys = ({ onNext, openModal, tweaks }) => {
const [revealed, setRevealed] = useStateS(false);
const fakeKey = "sk_live_a94fE3rT8vNq91KpMnBxYzC2hA5jK0sL";
return (
<>
} onClick={() => openModal("rotate")}>Rotate}
>
Server secret
Use from your backend only. Never ship to a client.
One-time reveal
{revealed ? fakeKey : "•".repeat(40)}
: } onClick={() => setRevealed(v => !v)}>
{revealed ? "Hide" : "Reveal"}
}>Copy
Reveal required passkey — Touch ID · Lena Osei · {new Date().toLocaleTimeString()}
}>Copy
{[
{ k: "wallets:write", d: "Create wallets, rotate keys, attach policies", on: true },
{ k: "signing:write", d: "Request signatures; execution is policy-gated", on: true },
{ k: "audit:read", d: "Read audit events and export compliance reports", on: true },
{ k: "webhooks:read", d: "Subscribe to event stream", on: false },
{ k: "admin:write", d: "Create projects, invite members, change billing", on: false },
].map(s => (
))}
>
);
};
const StepOidc = ({ onNext, tweaks }) => (
<>
https://auth.swivy.dev/o/prj_7QkA2vN
/authorize
/token
/.well-known/jwks.json
/userinfo
>
);
const StepSdk = ({ onDone, tweaks }) => {
const tsCode = `import { createSwivy } from "@swivy/sdk";
const swivy = createSwivy({
projectId: "prj_7QkA2vN",
environment: "staging",
authMethods: ["email", "passkey"],
// Chain defaults — override per-call if needed
defaultChain: "ETH",
});
export async function handleLogin() {
const session = await swivy.auth.loginWithEmail({
email: "user@example.com",
});
// Identity first, wallet second.
const wallet = await swivy.wallets.getOrCreate({
chain: "ETH",
});
return { session, wallet };
}`;
const curlCode = `curl https://api.swivy.dev/v1/wallets \\
-H "Authorization: Bearer sk_live_a94f..." \\
-H "Swivy-Environment: staging" \\
-H "Content-Type: application/json" \\
-d '{
"owner": "user_29Kxa",
"chain": "ETH"
}'`;
const reactCode = `import { SwivyProvider, useSwivy } from "@swivy/react";
export default function App() {
return (
);
}
function Checkout() {
const { user, signAndSend } = useSwivy();
return (
signAndSend({ to: "0x…", value: "0.1" })}>
Pay with {user.email}
);
}`;
return (
<>
{[
{ t: "Starter repo", d: "Next.js + Swivy preconfigured", i:
},
{ t: "Postman collection", d: "50 endpoints, realistic payloads", i: },
{ t: "Slack handoff", d: "Invite your devs to #swivy-ledger", i: },
].map((x, i) => (
{x.d}
))}
>
);
};
Object.assign(window, { OverviewScreen, HandoffScreen });