Repository navigation
SDK Overview and Setup
- Introduction
- Project Structure
- Core Components
- Architecture Overview
- Detailed Component Analysis
- Dependency Analysis
- Performance Considerations
- Troubleshooting Guide
- Conclusion
This document explains the Sigvara TypeScript SDK, its purpose, installation, configuration, and core concepts for interacting with the Sigvara protocol smart contracts. The SDK provides:
- Agent identity management using
did:sigvaraidentifiers and Ed25519 keys - Cryptographic challenge-response authentication between agents
- On-chain reads for identity, reputation, stake, and threshold checks
- A gate that turns identity verification and reputation into a single admission decision
The repository also documents the broader protocol: ERC-8004-based agent identity, computed reputation, staked accountability, slashing, and an oracle-driven scoring system.
This page describes the SDK in 1.0.0-alpha.15, published to npm on 3 November 2026. New since 1.0.0-alpha.14: sigvara-mcp, a read-only MCP trust server for an agent's MCP host (see MCP Gated Tools), the evidence-root functions evidenceLeaf, evidenceRoot and matchEvidenceRoot, and reads on SigvaraVerifier for a trust check, verifyEvidence and getEvidenceRoot among them. New since 1.0.0-alpha.13: profile: 'production' on SigvaraGate, which makes the constructor refuse to build the gate until instances and maxScoreAgeSeconds are both set. New since 1.0.0-alpha.12: atomicNonceStore; the gate's instances setting, with which a gate set to 'multiple' refuses to start without a nonce store with an atomic consume(); and signPaymentOutcome and verifyPaymentOutcome, which sign and check a payer's statement of whether one payment's work was delivered. New since 1.0.0-alpha.11: the agent's signChallenge is removed, so a call does not compile in TypeScript and throws in JavaScript, and signChallengeFor is the way to sign. New since 1.0.0-alpha.10: verifySignature requires the expected audience (see the changelog). These items are new since 1.0.0-alpha.9 (listed in the changelog): signChallengeFor, the 30 second read timeout, the parallel status and score read, the gate also checking the bond held now, the optional maxScoreAgeSeconds limit and its stale_score refusal, the refusal of a challenge dated in the future, the checks on a gate's threshold, ttlSeconds and maxScoreAgeSeconds, and the agent keeping its secret key in a private field.
Section sources
At a high level, the SDK lives under packages/sdk. Its public API is re-exported from the package entry point, while domain modules implement agent identity, verification, gating, challenges, DID helpers, key utilities, types, and contract interaction.
graph TB
Entry["packages/sdk/src/index.ts<br/>Public exports"] --> Agent["agent.ts<br/>Agent identity + signing"]
Entry --> Verifier["verifier.ts<br/>On-chain reads + registration"]
Entry --> Gate["gate.ts<br/>Admission decision"]
Entry --> Types["types.ts<br/>Shared types"]
Verifier --> Abis["abis.ts (ABI bindings)"]
Verifier --> Did["did.ts (DID helpers)"]
Verifier --> Challenge["challenge.ts (payload handling)"]
Verifier --> Keys["keys.ts (key encoding)"]
Diagram sources
Section sources
-
Agent: Generates and holds an Ed25519 keypair, derives the agent’s DID and on-chain
didHash, signs challenges, and exposes the bytes32 public key used during registration. - Verifier: Connects to an RPC provider, reads identity and reputation data, verifies signatures against on-chain public keys, builds W3C-compliant DID Documents, and registers agents when called by an operator.
- Gate: Issues signed challenges, enforces nonce replay protection, validates proofs before it reads status or score (checking a proof costs one read of the agent's registered key), checks agent status and the bond held now, compares the matured score against a threshold (and, if you set a limit, how old it is), and returns a structured result with a reason code.
- Types: Shared interfaces for contract addresses, agent identity, reputation data, challenge payloads, verifier configuration, and DID documents.
Key responsibilities:
- Identity:
SigvaraAgentand DID helpers - Authentication: challenge generation, signing, and verification
- Reputation: reading factors, total score, and threshold checks
- Stake: deposit helper for moving an agent from pending to active
- Gating: end-to-end admission logic with replay protection
Section sources
The SDK sits between your application and the Sigvara protocol contracts. It does not compute reputation itself; it reads on-chain state and performs local cryptographic operations. The one exception is sigvara-mcp's sigvara_verify_evidence, which also fetches an oracle's public /evidence list to check it against the chain.
graph TB
App["Your Application"] --> SDK["@sigvara/protocol-sdk"]
SDK --> Provider["ethers JsonRpcProvider"]
Provider --> RPC["RPC Endpoint"]
RPC --> Contracts
subgraph Contracts["Sigvara Contracts"]
Identity["SigvaraIdentity"]
Reputation["SigvaraReputation"]
Staking["SigvaraStaking"]
end
SDK --> Identity
SDK --> Reputation
SDK --> Staking
Diagram sources
- Install via npm or yarn:
npm install @sigvara/protocol-sdkyarn add @sigvara/protocol-sdk
- Runtime dependencies:
-
ethersv6 tweetnacl
-
- Node.js requirement:
- Node 18 or newer
For web applications, you can bundle the SDK with your frontend toolchain. There is no separate CDN distribution declared in the package metadata; include it as a normal npm dependency and let your bundler resolve it.
Section sources
- Node.js: 18+
- Browser support: depends on your bundler and polyfills. The SDK builds as CommonJS and imports Node's
cryptofor random bytes (challenge.ts), so a browser bundle needs acryptoshim or fallback as well asethersandtweetnacl. - Network access: required for RPC calls unless you are only performing local cryptographic operations.
Section sources
You need three things:
- RPC endpoint URL
- Contract addresses for identity, reputation, and staking
- Chain ID
Example environment variables commonly used in quickstart guides:
RPC_URL=https://rpc.testnet.arc.io- Testnet contract addresses for Arc testnet chain ID
5042002
These values are passed into SigvaraVerifier and SigvaraGate configuration objects. Both also take an optional timeoutMs, a positive number of milliseconds that one chain read may take before it is abandoned. It defaults to 30000 (alpha.9 uses ethers' own default, which is five minutes).
Section sources
The SDK exposes:
- Classes:
SigvaraAgent,SigvaraVerifier,SigvaraGate - Functions:
registerAgent,depositStake,atomicNonceStore,generateChallenge,signChallenge,verifyChallenge,parseChallengePayload,isChallengeExpired - Payment outcomes (from 1.0.0-alpha.13):
signPaymentOutcome,verifyPaymentOutcomeandpaymentOutcomeDomain, the constantsPAYMENT_OUTCOME_TYPES,OUTCOME_DELIVERED,OUTCOME_NOT_DELIVEREDandMAX_OUTCOME_DEADLINE_SECONDS, and their types - DID helpers:
computeDidHash,formatDid,parseDid - Key utilities: base58/hex conversion, seed/keypair helpers, bytes32/public-key conversions
- Evidence roots (from 1.0.0-alpha.15):
evidenceLeaf,evidenceLayers,evidenceRoot,evidenceProof,matchEvidenceRootandoutcomeCode - Types:
ContractAddresses,AgentIdentity,ReputationData,Challenge,ParsedChallenge,VerifierConfig,DidDocument,VerificationMethod,AgentStatus, and from 1.0.0-alpha.15SlashState,PendingScore,PendingWithdrawal,SlashProposal,EvidenceRecordandRootMatch
Import from the package root rather than internal files. The exception is the trust server: createTrustServer and serveStdio are only in @sigvara/protocol-sdk/dist/mcp, kept out of the main entry because they use Node's readline. The two newer constants, MAX_FUTURE_SKEW_SECONDS (60, in challenge.ts) and DEFAULT_RPC_TIMEOUT_MS (30000, in verifier.ts), are exported from their modules but not re-exported from the package root.
Section sources
An agent has:
- An Ethereum address used as part of the DID
- An Ed25519 keypair generated off-chain
- A DID string:
did:sigvara:<chainId>:<address> - A
didHashderived on-chain at registration
Use SigvaraAgent.generate to create a new agent, then register it on-chain with an operator wallet. The agent must prove control of its Ethereum address during registration.
flowchart TD
Start(["Create Agent"]) --> Generate["Generate Ed25519 keypair"]
Generate --> DID["Derive did:sigvara DID"]
DID --> Hash["Compute didHash"]
Hash --> Register["Operator calls registerAgent()"]
Register --> Pending["Agent becomes PendingBond"]
Pending --> Stake["Deposit stake >= minimumStake"]
Stake --> Active["Agent becomes Active"]
Diagram sources
Section sources
The SDK handles:
- Ed25519 keypair generation
- Signing challenge payloads
- Verifying signatures against on-chain public keys
- Converting between hex, bytes32, base58, and multibase representations
Challenge-response flow:
- Verifier issues a challenge payload bound to the prover’s DID and an audience.
- Prover signs the payload with its Ed25519 private key.
signChallengeFor(payload, audience)does this only if the payload is a v2 challenge naming the prover and exactly the audience the prover passes, and otherwise throws and signs nothing. The agent'ssignChallenge(payload)signed whatever it was handed and is removed in 1.0.0-alpha.12 (alpha.9 has onlysignChallenge, so on alpha.9 check the audience yourself before you sign). - Verifier resolves the public key from the identity contract and verifies the signature.
- Verifier may additionally check reputation thresholds.
sequenceDiagram
participant V as "Verifier"
participant A as "Agent"
participant I as "Identity Contract"
participant R as "Reputation Contract"
V->>A : Issue challenge payload
A->>A : Sign payload with Ed25519 key
A-->>V : Return signature
V->>I : Resolve public key
I-->>V : Public key
V->>V : Verify signature
V->>R : Check meetsThreshold()
R-->>V : Boolean
Diagram sources
Section sources
The SDK reads:
- Raw six-factor reputation data
- Matured total score
- Threshold checks
- Stake and minimum-stake information
Important distinction:
- Earned score: what the oracle finalized
- Total score: the matured score used by
meetsThreshold
Use getTotalScore when you only need the number compared against a threshold. Use getReputation when you need factor breakdowns.
Section sources
SigvaraGate combines identity proof, replay protection, status checks, and reputation into one decision. It returns:
-
ok: whether the agent is admitted -
reason: one ofbad_proof,replayed,not_active,stale_score(only whenmaxScoreAgeSecondsis set),below_threshold -
score: the agent’s on-chain score when available -
threshold: the configured threshold -
did: the agent’s DID
Nonce handling:
- Default store is per process
- For multiple instances, provide a shared
NonceStorewith atomicconsumesemantics and setinstances: 'multiple', which refuses to start the gate without one.atomicNonceStore(setIfAbsent)builds such a store from any atomic insert-if-absent, such as a RedisSET NX(both from 1.0.0-alpha.13)
Construction and reads (new in 1.0.0-alpha.10):
-
new SigvaraGate(...)throws whenthresholdis not a finite number of 0 or more, orttlSecondsormaxScoreAgeSecondsis not a positive number. ANaNthreshold, such asNumber(process.env.X)withXunset, would otherwise admit every active agent that can prove its key - The status, the bond held now and the score are read together once the proof and the nonce have passed, so an admit costs two round trips and not three. Standing is still named before score. An agent whose bond is under the minimum in force now is refused as
not_active -
maxScoreAgeSeconds(optional, off by default) refuses a score written longer ago than that, or never, asstale_score, after standing and before the number. It costs one more read per admit
Deployment settings:
-
instances(from 1.0.0-alpha.13) says how many processes serve the gate. It defaults to'single';'multiple'makes the constructor throw unless thenonceStorehas aconsume(), which must be atomic and shared by every instance -
profile: 'production'(from 1.0.0-alpha.14) makes the constructor throw untilinstancesandmaxScoreAgeSecondsare both set, and names everything missing in one error. Any otherprofilevalue throws too, so'prod'read from an environment variable does not build an unchecked gate
flowchart TD
Start(["admit(did, challenge, signature)"]) --> Parse["Parse signed payload"]
Parse --> Verify["Verify signature + audience + expiry"]
Verify --> |Invalid| BadProof["Return bad_proof"]
Verify --> Nonce["Check nonce uniqueness"]
Nonce --> |Seen| Replayed["Return replayed"]
Nonce --> Status["Check isActive() and hasMinimumStake()"]
Status --> |False| NotActive["Return not_active"]
Status --> Score["Read getTotalScore()"]
Score --> Fresh{"Score too old? Only if maxScoreAgeSeconds is set"}
Fresh --> |Yes| Stale["Return stale_score"]
Fresh --> |No| Threshold{"Score >= threshold?"}
Threshold --> |No| Below["Return below_threshold"]
Threshold --> |Yes| Admit["Return ok=true"]
Diagram sources
Section sources
- Install the SDK and ethers:
npm install @sigvara/protocol-sdk ethers
- Configure environment variables:
OPERATOR_PRIVATE_KEYRPC_URL=https://rpc.testnet.arc.io
- Set testnet contract addresses for chain ID
5042002. - Generate an Ed25519 keypair with
SigvaraAgent.generate. - Register the agent with
registerAgent. - Deposit stake with
depositStaketo move the agent fromPendingBondtoActive. - Read identity and reputation with
SigvaraVerifier.
Section sources
- Add
@sigvara/protocol-sdkto your project dependencies. - Configure an RPC endpoint and contract addresses in your app settings.
- Use
SigvaraAgentfor client-side signing if your agent runs in the browser. - Use
SigvaraVerifierorSigvaraGateon the server side for secure verification and reputation checks. - If running verification in the browser, ensure your bundler supports
ethersandtweetnacland provides acryptomodule for Node'srandomBytes.
Note: The package metadata does not declare a CDN entry point; treat it as a normal npm module.
Section sources
- Install the SDK and ethers in your React project.
- Store RPC endpoints and contract addresses in environment variables.
- Create a verifier instance for on-chain reads.
- For agent-facing flows, generate and sign challenges in the browser using
SigvaraAgent. - For admission decisions, prefer server-side verification with
SigvaraGateto keep nonces and secrets safe. - If you need client-side gating, provide a distributed nonce store implementation through the
NonceStoreinterface.
Section sources
The SDK does not expose gas-specific configuration options. Gas behavior is controlled by:
- Your signer/provider configuration
- Contract-level parameters such as minimum stake and maturity
- Transaction submission strategy in your application
Optimization tips:
- Batch operations where possible
- Cache contract instances and network info
- Avoid unnecessary reads by using
getTotalScoreinstead of full reputation tuples when only the threshold matters
Section sources
- Node.js version too old:
- Requirement: Node 18+
- Missing RPC endpoint:
- Provide a valid RPC URL for the target network
- Wrong contract addresses:
- Use the addresses matching your selected chain ID
- Using mainnet vs testnet incorrectly:
- Arc testnet uses chain ID
5042002; mainnet configuration differs
- Arc testnet uses chain ID
- Replay attacks:
- Always use
SigvaraGateor implement a shared nonce store with atomicconsume
- Always use
- Audience mismatch:
- Pass the same stable audience value to challenge generation and verification
- Signature width or encoding errors:
- The verifier rejects malformed signatures early; ensure clients send base58-encoded Ed25519 signatures within expected length bounds
- A request that hangs on a dead RPC:
- A read gives up after 30 seconds and
timeoutMschanges that. On alpha.9 ethers waits five minutes
- A read gives up after 30 seconds and
Section sources
The SDK depends on:
-
ethersfor RPC connectivity, contract interactions, and signing -
tweetnaclfor Ed25519 cryptography
Internal module relationships:
-
index.tsre-exports the public surface -
agent.tsdepends on key utilities, DID helpers, and challenge functions -
verifier.tsdepends on ABIs, DID helpers, challenge functions, key utilities, and types -
gate.tsdepends onverifier.tsand challenge functions -
types.tsis consumed across modules
graph LR
Index["index.ts"] --> Agent["agent.ts"]
Index --> Verifier["verifier.ts"]
Index --> Gate["gate.ts"]
Agent --> Keys["keys.ts"]
Agent --> Did["did.ts"]
Agent --> Challenge["challenge.ts"]
Verifier --> Abis["abis.ts"]
Verifier --> Did
Verifier --> Challenge
Verifier --> Keys
Verifier --> Types["types.ts"]
Gate --> Verifier
Gate --> Challenge
Diagram sources
Section sources
- Prefer
getTotalScorewhen you only need the matured score for threshold checks. - Avoid reading the full reputation tuple unless you need factor breakdowns.
- Use a shared nonce store with atomic
consumein multi-instance deployments to avoid race conditions. - Cache provider and contract instances where appropriate.
- Keep challenge TTLs reasonable to limit nonce storage growth.
- Registration fails because the agent did not sign:
- Ensure the agent address signs the registration digest returned by the identity contract.
- Agent remains
PendingBond:- Deposit at least
minimumStaketo activate the agent.
- Deposit at least
- Signature verification fails:
- Confirm the payload names the correct DID and audience.
- Confirm the signature is base58-encoded and within expected length bounds.
- Confirm the challenge has not expired. A payload dated more than 60 seconds ahead of the verifier's clock is refused as well.
- Gate returns
replayed:- Issue a fresh challenge; do not reuse a previous response.
- Implement a shared nonce store if running multiple instances, and set
instances: 'multiple'so the gate refuses to start without one.
-
new SigvaraGate(...)throws:- Read the message. It names a
threshold,ttlSecondsormaxScoreAgeSecondsthat is not a usable number, aninstancesorprofilevalue it does not accept,instances: 'multiple'with noconsume()on thenonceStore, or, withprofile: 'production', each setting still missing.
- Read the message. It names a
- Gate returns
not_active:- The agent is unbonded (or bonded below the minimum stake in force now), suspended, or slashed. Fix the standing issue before adjusting reputation.
- Gate returns
stale_score(only whenmaxScoreAgeSecondsis set):- The score was written longer ago than the limit, or never. Check that the oracle is running and finalizing; the number itself is not the problem.
- Gate returns
below_threshold:- Increase verified activity and reputation over time; the matured score climbs toward the earned score.
Section sources
The Sigvara TypeScript SDK is a focused client library for agent identity, cryptographic authentication, and reputation-aware admission decisions. Install it as a normal npm package, configure an RPC endpoint and contract addresses for your chosen network, and use the provided classes to manage agents, verify signatures, read reputation, and gate access. For production deployments, pay special attention to nonce replay protection, audience binding, and correct network configuration.
- Agent Registration and Lifecycle
- Contract Overview and Architecture
- Economic Security Model and Incentives
- Evidence Verification and Merkle Proofs
- Key Management and Rotation
- Maturity Mechanism and Score Release
- Proposal Workflow and Challenge System
- Score Storage and Data Model
- SigvaraIdentity Contract
- SigvaraOracleBond Contract
- SigvaraReputation Contract
- SigvaraStaking Contract
- Slashing Lifecycle and Dispute Resolution
- Stake Management Functions
- Status Management and Control
- Token and Fee Contracts
- Unbonding Period and Withdrawal Security
- Anti-Manipulation and Security Measures
- Community Flag Processing
- Evidence Sources and Verification
- External Trust Integration
- Merkle Proof System
- Oracle Score Computation
- Payment-Backed Attestations
- Scoring Model and Formulas
- Agent Creation and Key Management
- Agent Operations
- Agent Registration Workflow
- Challenge-Response Authentication
- Gate Access Control
- Integration Patterns and Examples
- SDK Overview and Setup
- Verifier Functions