import { test } from '@substrate-system/tapzero' import { did, json } from '../src/index.js' import type { DidDocument, VerificationMethod, Service } from '../src/types.js' test('create a DID document', async t => { const doc = did({ host: 'example.com', publicKey: 'z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK' }) t.ok(doc, 'should return something') t.equal(doc.id, 'did:web:example.com', 'should have correct id') t.ok(Array.isArray(doc.verificationMethod), 'should have verificationMethod array') }) test('DID document has correct structure', async t => { const doc = did({ host: 'example.com', publicKey: 'z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK', service: [ { id: '#abc', type: 'abc123', serviceEndpoint: 'http://aaa.com' } ] }) // Verify service endpoint t.equal(doc.service?.length, 1, 'should have one service') const service = doc.service?.[0] t.equal(service?.id, '#abc', 'service should have correct id') t.equal( service?.type, 'abc123', 'service should have correct type' ) }) test('DID document verification method', async t => { const publicKey = 'z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK' const host = 'example.com' const doc = did({ host, publicKey }) t.equal(doc.verificationMethod?.length, 1, 'should have one verification method') const vm = doc.verificationMethod?.[0] t.equal(vm?.id, `did:web:${host}#main-key`, 'verification method should have correct id') t.equal(vm?.type, 'Multikey', 'verification method should be Multikey type') t.equal(vm?.controller, `did:web:${host}`, 'verification method should have correct controller') t.equal(vm?.publicKeyMultibase, publicKey, 'verification method should have correct public key') }) test('DID document type compatibility - basic structure', async t => { const doc: DidDocument = { id: 'did:web:example.com' } t.ok(doc, 'minimal DID document should be valid') t.equal(doc.id, 'did:web:example.com', 'should have required id field') }) test('DID document type compatibility - with context', async t => { const doc: DidDocument = { '@context': 'https://www.w3.org/ns/did/v1', id: 'did:web:example.com' } t.ok(doc, 'DID document with context should be valid') t.equal(doc['@context'], 'https://www.w3.org/ns/did/v1', 'should have correct context') }) test('DID document type compatibility - with multiple contexts', async t => { const doc: DidDocument = { '@context': [ 'https://www.w3.org/ns/did/v1', 'https://w3id.org/security/suites/jws-2020/v1' ], id: 'did:web:example.com' } t.ok(doc, 'DID document with multiple contexts should be valid') t.ok(Array.isArray(doc['@context']), 'context should be an array') }) test('verification method - publicKeyJwk format', async t => { const vm: VerificationMethod = { id: 'did:web:example.com#key-1', type: 'JsonWebKey2020', controller: 'did:web:example.com', publicKeyJwk: { kty: 'OKP', crv: 'Ed25519', x: 'VCpo2LMLhn6iWku8MKvSLg2ZAoC-nlOyPVQaO3FxVeQ' } } t.ok(vm, 'verification method with JWK should be valid') t.equal(vm.type, 'JsonWebKey2020', 'should have correct type') t.equal(vm.publicKeyJwk?.kty, 'OKP', 'JWK should have correct key type') }) test('verification method - publicKeyMultibase format', async t => { const vm: VerificationMethod = { id: 'did:web:example.com#key-1', type: 'Multikey', controller: 'did:web:example.com', publicKeyMultibase: 'z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK' } t.ok(vm, 'verification method with multibase should be valid') t.equal(vm.type, 'Multikey', 'should have correct type') t.ok(vm.publicKeyMultibase?.startsWith('z'), 'multibase key should start with z') }) test('service endpoint - single string endpoint', async t => { const service:Service = { id: '#service-1', type: 'LinkedDomains', serviceEndpoint: 'https://example.com' } t.ok(service, 'service with string endpoint should be valid') t.equal(typeof service.serviceEndpoint, 'string', 'endpoint should be a string') }) test('service endpoint - array of endpoints', async t => { const service: Service = { id: '#service-1', type: 'LinkedDomains', serviceEndpoint: ['https://example.com', 'https://example.org'] } t.ok(service, 'service with array endpoint should be valid') t.ok(Array.isArray(service.serviceEndpoint), 'endpoint should be an array') }) test('service endpoint - object endpoint', async t => { const service: Service = { id: '#service-1', type: 'MessagingService', serviceEndpoint: { uri: 'https://example.com/messages', accept: ['didcomm/v2'], routingKeys: ['did:example:somemediator#somekey'] } } t.ok(service, 'service with object endpoint should be valid') t.equal( typeof service.serviceEndpoint, 'object', 'endpoint should be an object' ) }) test('DID document - full example with all properties', async t => { const doc: DidDocument = { '@context': [ 'https://www.w3.org/ns/did/v1', 'https://w3id.org/security/suites/jws-2020/v1' ], id: 'did:web:example.com', alsoKnownAs: ['did:example:123'], controller: 'did:web:example.com', verificationMethod: [ { id: 'did:web:example.com#key-1', type: 'JsonWebKey2020', controller: 'did:web:example.com', publicKeyJwk: { kty: 'OKP', crv: 'Ed25519', x: 'VCpo2LMLhn6iWku8MKvSLg2ZAoC-nlOyPVQaO3FxVeQ' } } ], authentication: ['did:web:example.com#key-1'], assertionMethod: ['did:web:example.com#key-1'], keyAgreement: [ { id: 'did:web:example.com#key-2', type: 'JsonWebKey2020', controller: 'did:web:example.com', publicKeyJwk: { kty: 'OKP', crv: 'X25519', x: 'sB0bHZLYmC9V_FvhzgHF0P6p3wKgLnFMqVPLLTRwRnE' } } ], service: [ { id: '#bsky_fg', type: 'BskyFeedGenerator', serviceEndpoint: 'https://example.com' } ] } t.ok(doc, 'full DID document should be valid') t.equal(doc.id, 'did:web:example.com', 'should have correct id') t.ok(doc.verificationMethod?.length, 'should have verification methods') t.ok(doc.authentication?.length, 'should have authentication') t.ok(doc.service?.length, 'should have services') }) test('DID document - different host formats', async t => { const doc1 = did({ host: 'example.com', publicKey: 'z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK' }) const doc2 = did({ host: 'example.org', publicKey: 'z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK' }) t.equal(doc1.id, 'did:web:example.com', 'should handle example.com domain') t.equal(doc2.id, 'did:web:example.org', 'should handle example.org domain') }) test('json function returns canonical JSON string', async t => { const canonicalJson = json({ host: 'example.com', publicKey: 'z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK' }) t.equal(typeof canonicalJson, 'string', 'should return a string') t.ok(canonicalJson.length > 0, 'should return non-empty string') // Verify it's valid JSON const parsed = JSON.parse(canonicalJson) t.ok(parsed, 'should be valid JSON') t.equal(parsed.id, 'did:web:example.com', 'should have correct id') // Verify it's canonical format (compact, no whitespace) t.ok(!canonicalJson.includes('\n'), 'should not contain newlines') t.ok(!canonicalJson.includes(' '), 'should not contain extra spaces') }) test('json function produces deterministic output', async t => { const args = { host: 'example.com', publicKey: 'z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK' } const json1 = json(args) const json2 = json(args) t.equal(json1, json2, 'should produce identical output for same input') })