@orangecheck/agent-signer
High-level API for producing OC Agent envelopes from a BIP-322-capable signer.
Three functions:
createDelegation(input) | Principal signs a scoped grant for an agent address. |
signAsAgent(input) | Agent produces an agent-action envelope over content, citing the delegation. |
revoke(input) | Principal (or agent, if authorized) burns the delegation. |
The signer layer wraps @orangecheck/agent-core: canonical messages, scope canonicalization, envelope ids, and verification are delegated to the core package. This module handles wallet plumbing, default timestamps and nonces, and input validation.
Nothing here touches the network — OpenTimestamps submission and Nostr publication are separate steps. If you already have an OTS proof, pass it in via the ots field; otherwise the resulting envelope has ots: null and the caller submits to a calendar out of band.
Install
npm i @orangecheck/agent-signer
Quickstart
import {
createDelegation,
signAsAgent,
revoke,
} from '@orangecheck/agent-signer';
const principal = {
address: 'bc1qprincipal…',
signMessage: async (msg: string) => wallet.signMessage(msg),
};
const agent = {
address: 'bc1qagent…',
signMessage: async (msg: string) => agentKey.signBip322(msg),
};
const delegation = await createDelegation({
principal,
agentAddress: agent.address,
scopes: [
'lock:seal(recipient=bc1qalice)',
'stamp:sign(mime=text/markdown)',
],
bond: { sats: 500_000, attestation_id: '22…22' },
ttlMs: 7 * 24 * 60 * 60 * 1000,
});
const action = await signAsAgent({
agent,
delegation,
content: new TextEncoder().encode('hello world'),
mime: 'text/plain',
scopeExercised: 'lock:seal(recipient=bc1qalice)',
});
const revocation = await revoke({
signer: principal,
delegation,
reason: 'key rotated',
});
API
createDelegation(input)
interface CreateDelegationInput {
principal: SignerRef;
agentAddress: string;
scopes: string[];
bond?: { sats: number; attestation_id: string } | null;
issuedAt?: Date;
ttlMs?: number;
expiresAt?: Date;
nonce?: string;
revocationHolders?: ('principal' | 'agent')[];
revocationRef?: string | null;
scopeMode?: 'strict' | 'permissive';
}
Returns a DelegationEnvelope. The principal's signMessage is called exactly once with the ASCII hex of the envelope id.
signAsAgent(input)
interface SignAsAgentInput {
agent: SignerRef;
delegation: DelegationEnvelope;
content: Uint8Array | { hash: string; length: number };
mime: string;
scopeExercised: string;
ref?: string | null;
signedAt?: Date;
ots?: ActionOts | null;
}
Returns an ActionEnvelope — a strict extension of an OC Stamp envelope, so any stamp verifier reads it as a valid stamp.
revoke(input)
interface RevokeInput {
signer: SignerRef;
delegation: DelegationEnvelope;
reason?: string;
signedAt?: Date;
ots?: ActionOts | null;
}
Returns a RevocationEnvelope. The function throws if the signer isn't authorized to revoke per delegation.revocation.holders.
Verification
Re-exports verifyDelegation, verifyAction, and verifyRevocation from @orangecheck/agent-core for convenience. See that package's README for full details.
Companion packages
License
MIT. See LICENSE.