// Modals — signing approval, rotate key, new key, generic confirm const SigningModal = ({ onClose, style = "drawer" }) => { const [stage, setStage] = useStateS("review"); // review → authenticate → broadcasting → done const [expanded, setExpanded] = useStateS(false); const W = style === "drawer" ? 620 : 560; const Container = ({ children }) => style === "drawer" ? (
{children}
) : (
{children}
); const headerIcon = (
); return ( <>
{headerIcon}
{stage === "review" && "Step 1 of 3 · Review"} {stage === "authenticate" && "Step 2 of 3 · Authenticate"} {stage === "broadcasting" && "Step 3 of 3 · Broadcasting"} {stage === "done" && "Confirmed"}
{stage === "review" && "Sign transfer · 1.20 ETH"} {stage === "authenticate" && "Confirm with passkey"} {stage === "broadcasting" && "Broadcasting to Ethereum"} {stage === "done" && "Signed and broadcast"}
{stage === "review" && "Review the payload. Signing produces a signature; broadcast happens in the next step."} {stage === "authenticate" && "Touch ID or your security key is required to release the signature."} {stage === "broadcasting" && "Waiting for the first block confirmation."} {stage === "done" && "Receipt recorded in the audit log."}
{stage === "review" && (
0x9a4c…e21f 0xf2c3…9a11 1.20 ETH ≈ $3,942.00 0.00042 ETH · priority medium #1,284
Policy payments_v3 passed
Within daily cap (8 / 250 ETH). Recipient on allowlist. Requires 1 approver — you.
{expanded && (
tx.jsonEIP-1559
                    
                  
)}
)} {stage === "authenticate" && (
Touch the sensor to confirm
Lena's MacBook Pro · Touch ID
setStage("review")}>Cancel }>Use security key
)} {stage === "broadcasting" && (
{[ { t: "Signed", done: true, note: "sig 0x4f1a… produced" }, { t: "Submitted to mempool", done: true, note: "0.4s" }, { t: "Block confirmed", done: false, note: "waiting (12s avg)" }, { t: "Webhook delivered", done: false, note: "signing.confirmed → alerts.policy" }, ].map((s, i) => (
{s.done ? :
}
{s.t}
{s.note}
))}
)}
{stage === "review" && <> }>Reject
Cancel setStage("authenticate")} icon={}>Sign } {stage === "authenticate" && <> Waiting for passkey…
setStage("broadcasting")}>Simulate pass } {stage === "broadcasting" && <> Do not close — webhook pending
Background it }
); }; const RotateModal = ({ onClose, pattern = "type-to-confirm" }) => { const [confirm, setConfirm] = useStateS(""); const targetText = "rotate sk_live_a94f"; const valid = confirm === targetText; return ( <>
Rotate production API key?
The old secret stops working in 10 minutes. Any deployment still using it will start failing with 401 invalid_key.
What happens when you rotate
  • A new secret is revealed once — we'll copy it to your clipboard.
  • Old secret enters a 10-minute overlap window, then is revoked.
  • Event key.rotated is emitted to alerts.security.
  • Reversible during the overlap by clicking Undo.
{pattern === "type-to-confirm" && ( Type {targetText} to confirm}> setConfirm(e.target.value)}/> )} {pattern === "passkey-step" && ( You'll be asked to touch your passkey before the rotation commits. )} {pattern === "armed-commit" && ( Click Arm, then Rotate now. You'll have 5 seconds to undo with the toast at the bottom-right. )}
Cancel
{pattern === "type-to-confirm" && ( Rotate key )} {pattern === "passkey-step" && ( }>Verify & rotate )} {pattern === "armed-commit" && ( Arm )}
); }; const NewKeyModal = ({ onClose }) => ( <>
Create API key
Give it a label, pick its environment, and grant only the scopes it needs.
{}} options={[ { value: "dev", label: "Dev" }, { value: "staging", label: "Staging" }, { value: "prod", label: "Production" }, ]}/>
{["wallets:write","signing:write","audit:read","webhooks:read","admin:write"].map(s => ( ))}
Cancel
Create key
); Object.assign(window, { SigningModal, RotateModal, NewKeyModal });