Skip to content

Commit eb166ba

Browse files
Add working JS examples for DID resolution and VC verification
Provides starter code for Issue #4 contributors: - did-resolution.js: keypair gen, 3 DID modes, document creation, offline resolution - vc-verification.js: self-signed VC, DataIntegrityProof, tamper detection - README with setup instructions and learning objectives - Both examples tested and passing against @trailprotocol/core@0.1.0 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 30e25c3 commit eb166ba

6 files changed

Lines changed: 298 additions & 0 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ dist/
44
*.tsbuildinfo
55
.env
66
.env.*
7+
examples/js/node_modules/

examples/js/README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# TRAIL Protocol - JavaScript Examples
2+
3+
Working examples showing how to use `did:trail` with Node.js.
4+
5+
## Prerequisites
6+
7+
- Node.js 18+ (uses built-in `crypto` module)
8+
- npm
9+
10+
## Setup
11+
12+
```bash
13+
cd examples/js
14+
npm install
15+
```
16+
17+
## Examples
18+
19+
### DID Resolution (`did-resolution.js`)
20+
21+
Creates DIDs in all three modes (self, org, agent), builds DID Documents, and resolves a self-issued DID offline.
22+
23+
```bash
24+
node did-resolution.js
25+
```
26+
27+
**What you'll learn:**
28+
- Ed25519 keypair generation
29+
- The three DID modes and their trust tiers
30+
- DID Document structure (W3C DID Core 1.0)
31+
- Offline resolution for self-mode DIDs
32+
33+
### VC Verification (`vc-verification.js`)
34+
35+
Issues a self-signed Verifiable Credential with a DataIntegrityProof, then verifies it - including a tamper detection test.
36+
37+
```bash
38+
node vc-verification.js
39+
```
40+
41+
**What you'll learn:**
42+
- Verifiable Credentials 2.0 structure
43+
- DataIntegrityProof with `eddsa-jcs-2023` cryptosuite
44+
- JSON Canonicalization (JCS, RFC 8785)
45+
- Cryptographic verification and tamper detection
46+
47+
## Reference
48+
49+
- [`@trailprotocol/core`](https://www.npmjs.com/package/@trailprotocol/core) - Full API reference
50+
- [TRAIL DID Method Spec](../../did-method-spec.md) - Specification v1.1.0
51+
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - How to contribute

examples/js/did-resolution.js

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* TRAIL Protocol - DID Resolution Example
5+
*
6+
* Demonstrates how to:
7+
* 1. Generate an Ed25519 keypair
8+
* 2. Create did:trail DIDs (self, org, agent)
9+
* 3. Build DID Documents
10+
* 4. Resolve a did:trail DID offline (self-mode)
11+
*
12+
* Prerequisites:
13+
* npm install @trailprotocol/core
14+
*
15+
* Run:
16+
* node did-resolution.js
17+
*/
18+
19+
const {
20+
generateKeyPair,
21+
createSelfDid,
22+
createOrgDid,
23+
createAgentDid,
24+
createDidDocument,
25+
TrailResolver,
26+
} = require('@trailprotocol/core');
27+
28+
async function main() {
29+
// -------------------------------------------------------
30+
// Step 1: Generate an Ed25519 keypair
31+
// -------------------------------------------------------
32+
const keys = generateKeyPair();
33+
console.log('=== Key Generation ===');
34+
console.log('Public key (multibase):', keys.publicKeyMultibase);
35+
console.log('Public key (JWK):', JSON.stringify(keys.publicKeyJwk, null, 2));
36+
console.log();
37+
38+
// -------------------------------------------------------
39+
// Step 2: Create DIDs in all three modes
40+
// -------------------------------------------------------
41+
42+
// Self DID (Tier 0) - no registry needed, local trust only
43+
const selfDid = createSelfDid(keys.publicKeyMultibase);
44+
console.log('=== DID Creation ===');
45+
console.log('Self DID: ', selfDid);
46+
47+
// Org DID (Tier 1) - for organizations with KYB attestation
48+
const orgDid = createOrgDid('Acme Corporation', keys.publicKeyMultibase);
49+
console.log('Org DID: ', orgDid);
50+
51+
// Agent DID (Tier 2) - for AI agents with full trust chain
52+
const agentDid = createAgentDid('Sales Assistant', keys.publicKeyMultibase);
53+
console.log('Agent DID:', agentDid);
54+
console.log();
55+
56+
// -------------------------------------------------------
57+
// Step 3: Build DID Documents
58+
// -------------------------------------------------------
59+
console.log('=== DID Documents ===');
60+
61+
// Self DID Document - simplest form
62+
const selfDoc = createDidDocument(selfDid, keys, { mode: 'self' });
63+
console.log('Self DID Document:');
64+
console.log(JSON.stringify(selfDoc, null, 2));
65+
console.log();
66+
67+
// Agent DID Document - with parent organization reference
68+
const agentDoc = createDidDocument(agentDid, keys, {
69+
mode: 'agent',
70+
parentOrganization: orgDid,
71+
aiSystemType: 'agent',
72+
});
73+
console.log('Agent DID Document:');
74+
console.log(JSON.stringify(agentDoc, null, 2));
75+
console.log();
76+
77+
// -------------------------------------------------------
78+
// Step 4: Resolve a self DID (offline resolution)
79+
// -------------------------------------------------------
80+
// Self-mode DIDs can be resolved without a registry because
81+
// the public key is embedded in the DID itself.
82+
console.log('=== DID Resolution ===');
83+
const resolver = new TrailResolver();
84+
const result = await resolver.resolve(selfDid);
85+
86+
console.log('Resolution result:');
87+
console.log(' DID:', result.didDocument.id);
88+
console.log(' Content-Type:', result.didResolutionMetadata.contentType);
89+
console.log(' Verification Method:', result.didDocument.verificationMethod[0].type);
90+
console.log(' Trust Tier:', result.didDocument['trail:trailTrustTier']);
91+
console.log();
92+
93+
// TODO: Add registry-based resolution for org/agent DIDs
94+
// (requires a running TRAIL Registry instance)
95+
96+
console.log('Done. All examples completed successfully.');
97+
}
98+
99+
main().catch(console.error);

examples/js/package-lock.json

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/js/package.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "trail-examples-js",
3+
"version": "1.0.0",
4+
"private": true,
5+
"description": "TRAIL Protocol usage examples for Node.js",
6+
"scripts": {
7+
"did-resolution": "node did-resolution.js",
8+
"vc-verification": "node vc-verification.js"
9+
},
10+
"dependencies": {
11+
"@trailprotocol/core": "^0.1.0"
12+
},
13+
"engines": {
14+
"node": ">=18.0.0"
15+
}
16+
}

examples/js/vc-verification.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* TRAIL Protocol - Verifiable Credential Example
5+
*
6+
* Demonstrates how to:
7+
* 1. Create a self-signed Verifiable Credential (VC 2.0)
8+
* 2. Inspect the DataIntegrityProof (eddsa-jcs-2023)
9+
* 3. Verify the credential cryptographically
10+
* 4. Detect tampering (negative test)
11+
*
12+
* Prerequisites:
13+
* npm install @trailprotocol/core
14+
*
15+
* Run:
16+
* node vc-verification.js
17+
*/
18+
19+
const {
20+
generateKeyPair,
21+
createSelfDid,
22+
createSelfSignedCredential,
23+
verifyCredential,
24+
} = require('@trailprotocol/core');
25+
26+
async function main() {
27+
// -------------------------------------------------------
28+
// Step 1: Setup - generate keys and create a DID
29+
// -------------------------------------------------------
30+
const issuerKeys = generateKeyPair();
31+
const issuerDid = createSelfDid(issuerKeys.publicKeyMultibase);
32+
33+
console.log('=== Setup ===');
34+
console.log('Issuer DID:', issuerDid);
35+
console.log();
36+
37+
// -------------------------------------------------------
38+
// Step 2: Issue a self-signed Verifiable Credential
39+
// -------------------------------------------------------
40+
// createSelfSignedCredential(issuerDid, subjectDid, claims, privateKeyBytes)
41+
//
42+
// This creates a VC 2.0 credential with a DataIntegrityProof
43+
// using the eddsa-jcs-2023 cryptosuite (Ed25519 + JCS RFC 8785).
44+
// For self-signed VCs, issuer and subject are the same DID.
45+
const credential = createSelfSignedCredential(
46+
issuerDid,
47+
issuerDid, // subject = issuer (self-signed)
48+
{
49+
type: 'TrailTrustAttestation',
50+
aiSystemType: 'agent',
51+
capabilities: ['text-generation', 'tool-use'],
52+
},
53+
issuerKeys.privateKeyBytes
54+
);
55+
56+
console.log('=== Issued Credential ===');
57+
console.log(JSON.stringify(credential, null, 2));
58+
console.log();
59+
60+
// -------------------------------------------------------
61+
// Step 3: Inspect the proof
62+
// -------------------------------------------------------
63+
console.log('=== Proof Details ===');
64+
console.log(' Type:', credential.proof.type);
65+
console.log(' Cryptosuite:', credential.proof.cryptosuite);
66+
console.log(' Verification Method:', credential.proof.verificationMethod);
67+
console.log(' Created:', credential.proof.created);
68+
console.log(' Proof Purpose:', credential.proof.proofPurpose);
69+
console.log(' Proof Value (first 40 chars):', credential.proof.proofValue.substring(0, 40) + '...');
70+
console.log();
71+
72+
// -------------------------------------------------------
73+
// Step 4: Verify the credential
74+
// -------------------------------------------------------
75+
// verifyCredential(vc, publicKeyBytes) checks:
76+
// - Required VC fields (@context, type, issuer, issuanceDate, credentialSubject)
77+
// - DataIntegrityProof signature validity
78+
console.log('=== Verification ===');
79+
const result = verifyCredential(credential, issuerKeys.publicKeyBytes);
80+
console.log('Credential valid:', result.valid);
81+
console.log('Errors:', result.errors.length === 0 ? 'none' : result.errors);
82+
console.log();
83+
84+
// -------------------------------------------------------
85+
// Step 5: Tamper detection (negative test)
86+
// -------------------------------------------------------
87+
// Modify the credential and verify again - should fail
88+
// because the signature no longer matches the content.
89+
console.log('=== Tamper Detection ===');
90+
const tampered = JSON.parse(JSON.stringify(credential));
91+
tampered.credentialSubject.trailTrustTier = 2; // Attacker tries to upgrade trust tier
92+
93+
const tamperedResult = verifyCredential(tampered, issuerKeys.publicKeyBytes);
94+
console.log('Tampered credential valid:', tamperedResult.valid, '(expected: false)');
95+
console.log('Errors:', tamperedResult.errors);
96+
console.log();
97+
98+
console.log('Done. All examples completed successfully.');
99+
}
100+
101+
main().catch(console.error);

0 commit comments

Comments
 (0)