Skip to content

TypeScript SDK Testing Strategy

RunTimeAdmin edited this page Oct 23, 2026 · 31 revisions

TypeScript SDK Testing Strategy

**Referenced Files in This Document** - [packages/sdk/package.json](https://github.com/RunTimeAdmin/Sigvara/blob/main/packages/sdk/package.json) - [packages/sdk/vitest.config.ts](https://github.com/RunTimeAdmin/Sigvara/blob/main/packages/sdk/vitest.config.ts) - [packages/sdk/src/index.ts](https://github.com/RunTimeAdmin/Sigvara/blob/main/packages/sdk/src/index.ts) - [packages/sdk/src/agent.ts](https://github.com/RunTimeAdmin/Sigvara/blob/main/packages/sdk/src/agent.ts) - [packages/sdk/src/challenge.ts](https://github.com/RunTimeAdmin/Sigvara/blob/main/packages/sdk/src/challenge.ts) - [packages/sdk/src/verifier.ts](https://github.com/RunTimeAdmin/Sigvara/blob/main/packages/sdk/src/verifier.ts) - [packages/sdk/test/agent.test.ts](https://github.com/RunTimeAdmin/Sigvara/blob/main/packages/sdk/test/agent.test.ts) - [packages/sdk/test/challenge.test.ts](https://github.com/RunTimeAdmin/Sigvara/blob/main/packages/sdk/test/challenge.test.ts) - [packages/sdk/test/verifier.test.ts](https://github.com/RunTimeAdmin/Sigvara/blob/main/packages/sdk/test/verifier.test.ts) - [packages/sdk/test/integration.test.ts](https://github.com/RunTimeAdmin/Sigvara/blob/main/packages/sdk/test/integration.test.ts) - [packages/sdk/test/did.test.ts](https://github.com/RunTimeAdmin/Sigvara/blob/main/packages/sdk/test/did.test.ts)

Table of Contents

  1. Introduction
  2. Project Structure
  3. Core Components
  4. Architecture Overview
  5. Detailed Component Analysis
  6. Dependency Analysis
  7. Performance Considerations
  8. Troubleshooting Guide
  9. Conclusion

Introduction

This document explains the testing strategy for the Sigvara TypeScript SDK using Vitest. It covers unit tests for agent operations, cryptographic challenge-response flows, and verifier utilities; mocking strategies for blockchain interactions; integration test patterns for end-to-end workflows; fixtures and environment configuration; and guidance for edge cases, error handling, and performance validation. The goal is to make the testing approach clear and reproducible for both new and experienced contributors.

Project Structure

The SDK lives under packages/sdk with a focused set of source modules and corresponding test files:

  • Source modules include agent identity, challenge generation/signing/verification, DID helpers, and a verifier that interacts with on-chain contracts.
  • Tests are organized by feature: agent behavior, challenge protocol, verifier pre-chain guards, DID utilities, and an integration suite that runs against a live EVM when environment variables are provided.
graph TB
subgraph "SDK Package"
A["src/index.ts"]
B["src/agent.ts"]
C["src/challenge.ts"]
D["src/verifier.ts"]
T1["test/agent.test.ts"]
T2["test/challenge.test.ts"]
T3["test/verifier.test.ts"]
T4["test/integration.test.ts"]
T5["test/did.test.ts"]
end
A --> B
A --> C
A --> D
T1 --> B
T1 --> C
T2 --> C
T3 --> D
T4 --> A
T5 --> D
Loading

Diagram sources

Section sources

Core Components

  • SigvaraAgent: Encapsulates Ed25519 key material, DID derivation, challenge issuance, and signing. Provides a static factory to generate agents without exposing low-level crypto directly.
  • Challenge module: Implements v1 and v2 challenge payloads, signature creation/verification, parsing, and expiration checks. v2 binds the audience to prevent relay attacks.
  • SigvaraVerifier: Interacts with Identity, Reputation, and Staking contracts via ethers. Validates signatures, enforces pre-chain guards (payload format, DID binding, audience binding, TTL, signature width), and builds W3C-compliant DID Documents.
  • Integration harness: Optional end-to-end tests that register an agent and exercise identity, reputation, and challenge-response flows against a live network when environment variables are present.

Key responsibilities and relationships:

  • Agent uses challenge and keys utilities to issue and sign challenges.
  • Verifier composes challenge verification with on-chain reads to resolve public keys and reputation data.
  • Index re-exports core APIs for consumers and tests.

Section sources

Architecture Overview

The SDK’s testing architecture separates concerns into unit tests for pure logic and optional integration tests for on-chain behavior.

sequenceDiagram
participant Test as "Vitest Test"
participant Agent as "SigvaraAgent"
participant Challenge as "challenge.ts"
participant Verifier as "SigvaraVerifier"
participant Chain as "EVM Contracts"
Test->>Agent : issueChallenge(peerDid)
Agent->>Challenge : generateChallenge(proverDid, audience, ttl)
Challenge-->>Agent : { payload, nonce, timestamp }
Test->>Agent : signChallenge(payload)
Agent->>Challenge : signChallenge(payload, secretKey)
Challenge-->>Agent : base58(signature)
Test->>Verifier : verifySignature(did, payload, signature)
Verifier->>Verifier : parseChallengePayload()
Verifier->>Verifier : isChallengeExpired()
Verifier->>Chain : getIdentity(didHash)
Chain-->>Verifier : { ed25519PubKey, status }
Verifier->>Challenge : verifyChallenge(payload, signature, publicKey)
Challenge-->>Verifier : boolean
Verifier-->>Test : boolean
Loading

Diagram sources

Detailed Component Analysis

Agent Operations Testing

  • Identity assertions: Tests validate DID derivation, didHash computation, and public key bytes32 formatting.
  • Challenge issuance: Ensures peer DID inclusion and unique nonces per issued challenge.
  • A2A sign/verify flow: Demonstrates full round-trip where one agent issues a challenge to another, the target signs it, and the signature verifies against the correct public key. Also validates failure paths with wrong keys and freshness checks.
  • Static factory: Confirms deterministic keypair reconstruction, uniqueness across calls, and successful challenge signing from generated agents.

Mocking strategy:

  • Uses tweetnacl directly within tests to construct deterministic or random keypairs for predictable outcomes.
  • No blockchain dependencies are required for these unit tests.
flowchart TD
Start(["Agent Unit Tests"]) --> MakeAgent["Create SigvaraAgent with seed/keypair"]
MakeAgent --> Issue["issueChallenge(peerDid)"]
Issue --> Sign["signChallenge(payload)"]
Sign --> Verify["verifyChallenge(payload, signature, publicKey)"]
Verify --> CheckFreshness{"isChallengeExpired(payload)?"}
CheckFreshness --> |No| Pass["Pass"]
CheckFreshness --> |Yes| Fail["Fail"]
Loading

Diagram sources

Section sources

Cryptographic Functions and Challenge Protocol

  • Payload structure: v2 uses newline-delimited fields including prover DID, audience, nonce, and timestamp; v1 remains supported for backward compatibility.
  • Signature encoding: Base58-encoded Ed25519 signatures; length and alphabet constraints are enforced.
  • Audience binding: Prevents relay attacks by ensuring the signed payload names the intended verifier or agent.
  • Expiration: Parses timestamps and treats malformed payloads as expired to fail safely.

Testing highlights:

  • Valid signature verification and rejection with wrong keys or tampered payloads.
  • Audience binding scenarios, including DID audiences and colon-bearing URLs.
  • Backward compatibility with v1 payloads and safe handling of unparseable inputs.
flowchart TD
Gen["generateChallenge(proverDid, audience, ttl)"] --> Validate["Validate audience and no newlines"]
Validate --> Build["Build newline-delimited payload"]
Build --> Sign["signChallenge(payload, secretKey)"]
Sign --> Verify["verifyChallenge(payload, signature, publicKey)"]
Verify --> Parse["parseChallengePayload(payload)"]
Parse --> Expire["isChallengeExpired(payload, maxAgeSeconds)"]
Loading

Diagram sources

Section sources

Verifier Utilities and Pre-Chain Guards

  • Pre-chain validation: Rejects malformed payloads, mismatched prover DID, expired challenges, and out-of-range signature lengths before any RPC call.
  • On-chain resolution: Reads identity to obtain Ed25519 public key and status, then performs cryptographic verification.
  • Error handling: Converts invalid input errors (e.g., bad base58 alphabet) into false results rather than throwing, preventing gate crashes.

Testing highlights:

  • Short-circuit behavior verified by pointing at an unreachable RPC; failures occur before chain access.
  • Width guard boundaries tested with minimal and maximal base58 lengths.
  • Audience binding enforcement when expectedAudience is provided.
sequenceDiagram
participant Test as "verifier.test.ts"
participant V as "SigvaraVerifier.verifySignature"
participant P as "parseChallengePayload"
participant E as "isChallengeExpired"
participant I as "getIdentity"
participant C as "verifyChallenge"
Test->>V : verifySignature(did, payload, sig)
V->>P : parse(payload)
P-->>V : parsed
V->>E : isChallengeExpired(payload)
E-->>V : boolean
V->>I : getIdentity(did)
I-->>V : identity
V->>C : verifyChallenge(payload, sig, publicKey)
C-->>V : boolean
V-->>Test : boolean
Loading

Diagram sources

Section sources

DID Utilities

  • Formatting and parsing: Ensures canonical DID strings and robust parsing with meaningful errors.
  • Hashing: Deterministic bytes32 hashing dependent on address and chain ID.

Tests cover:

  • Lowercasing normalization.
  • Invalid format exceptions.
  • Determinism and cross-chain differentiation.

Section sources

Integration Test Patterns

  • Environment gating: Tests skip automatically unless all required environment variables are set.
  • Setup: Creates a verifier connected to a live RPC, registers an agent if not already registered, and derives DID and public key.
  • Scenarios:
    • Identity queries return active status and registration metadata.
    • Challenge-response authentication succeeds for valid signatures and fails for tampered payloads.
    • DID Document construction yields W3C-compliant structures.
    • Reputation checks return bounded scores and threshold evaluation.

Setup and teardown:

  • Uses beforeAll to initialize shared state and perform one-time registration.
  • Each scenario sets explicit timeouts appropriate for network latency.
flowchart TD
EnvCheck{"Env vars present?"}
EnvCheck --> |No| Skip["Skip integration suite"]
EnvCheck --> |Yes| Init["Init verifier + operator wallet"]
Init --> Register["registerAgent(operator, agentAddress, pubKey, identityAddr)"]
Register --> Run["Run identity, challenge-response, DID doc, reputation tests"]
Loading

Diagram sources

Section sources

Dependency Analysis

The SDK’s internal dependencies and their test coverage are summarized below.

graph LR
Index["src/index.ts"] --> Agent["src/agent.ts"]
Index --> Challenge["src/challenge.ts"]
Index --> Verifier["src/verifier.ts"]
Agent --> Challenge
Verifier --> Challenge
Verifier --> Did["did helpers (via index)"]
Verifier --> Abi["abis (ethers contracts)"]
T_Agent["test/agent.test.ts"] --> Agent
T_Challenge["test/challenge.test.ts"] --> Challenge
T_Verifier["test/verifier.test.ts"] --> Verifier
T_Integration["test/integration.test.ts"] --> Index
Loading

Diagram sources

Section sources

Performance Considerations

  • Avoid unnecessary RPC calls: Verifier.pre-chain guards reject invalid inputs early, preventing expensive contract reads. Tests confirm this short-circuit behavior by targeting an unreachable RPC.
  • Reuse provider and contracts: Verifier lazily caches contract instances to avoid repeated ABI parsing and object creation.
  • Efficient reputation queries: getTotalScore provides a single RPC read when only the total score is needed, avoiding tuple decoding overhead.
  • Deterministic randomness: Use fixed seeds in tests to ensure repeatable outcomes and reduce variance in timing-sensitive checks.

Troubleshooting Guide

Common issues and resolutions:

  • Malformed challenge payload: Ensure payloads start with the correct version header and contain required fields. Tests assert strict prefix validation and field parsing.
  • Wrong audience binding: When expectedAudience is provided, only v2 payloads with matching audience pass. For agent-to-agent auth, use the issuer’s DID as the audience.
  • Expired challenges: Verify timestamps and TTL settings. Unparseable payloads are treated as expired to fail safely.
  • Signature width errors: Base58-encoded signatures must be between 64 and 88 characters. Out-of-range values are rejected before chain access.
  • Network connectivity: Integration tests require valid environment variables; otherwise, they are skipped. Ensure RPC URL, addresses, and operator private key are set correctly.

Section sources

Conclusion

The SDK’s testing strategy combines isolated unit tests for cryptographic and identity logic with optional integration tests for end-to-end workflows. By enforcing pre-chain guards, audience binding, and strict payload formats, the verifier minimizes attack surface and reduces unnecessary blockchain calls. Tests leverage deterministic keypairs, environment-gated integration suites, and targeted mocks to provide reliable, fast feedback while covering critical security properties such as replay protection and signature validity.

Overview

Clone this wiki locally