<MultiSigSigner>
Live preview
import { MultiSigSigner } from "@cdr-kit/react";
// Default render — button → on click signs EIP-712 → shows the sig + copy button.
<MultiSigSigner uuid={7331} />
// With a custom caller (default = connected wallet) and 30-min deadline:
<MultiSigSigner
uuid={7331}
caller="0xBuyerWhoWillSubmit"
deadline={BigInt(Math.floor(Date.now() / 1000) + 1800)}
/>
// Render-prop for full custom UI:
<MultiSigSigner uuid={7331}>
{({ sign, signature, isLoading, error, onSign }) => (
signature
? <span>Sig: {signature}</span>
: <button disabled={isLoading} onClick={onSign}>
{isLoading ? "signing…" : "Approve read"}
</button>
)}
</MultiSigSigner>Props
| Prop | Type | Default | Description |
|---|---|---|---|
| uuidrequired | number | — | MultiSigCondition-gated vault uuid. |
| caller | Hex | — | Optional override — defaults to the connected wallet. The sig is bound to this address; only this caller can use it via accessAuxData (anyone else fails ecrecover). |
| deadline | bigint | — | Optional unix-seconds expiry. Default: 1 hour from when the user clicks Sign. The buyer's accessMultiSig call MUST pass the same deadline used at signing time. |
| children | (state) => ReactNode | — | Render-prop. Receives { sign, signature, isLoading, error, onSign }. onSign is a bound zero-arg helper that calls sign(...) with the component's caller+deadline. |
Submit threshold-many sigs
Once threshold-many signers have produced sigs, the buyer (or any caller) builds the combined accessAuxData and reads the vault. agent.accessMultiSig handles the abi-encoding; sigs must be ordered by recovered signer address ascending (the contract enforces a strict-ascending dedupe).
// Buyer side — once threshold-many sigs collected from different signers:
import { CdrAgent } from "@cdr-kit/agent";
const bytes = await agent.accessMultiSig({
uuid: 7331,
deadline, // MUST match every sig's deadline
sigs: [sigFromAlice, sigFromBob], // sorted by signer address ASC
});Epoch rotation invalidates in-flight sigs
The hook fetches the current epoch from getConfig(uuid) immediately before signing. If rotateSigners lands between sign and submit, the contract recomputes the digest with the new epoch — ecrecover returns a different address and the sig is rejected. The signer can re-sign against the new epoch if they still want to authorize the new set (use the "re-sign" button in the default render, or call sign() again).
Hook variant
Skip the component and use useSignMultiSigApproval(uuid) directly — returns { sign, signature, isLoading, error }. Useful when the sign trigger lives in a non-button surface (drag-and-drop, gesture, programmatic flow).