@smartledger/bsv 3.3.5 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +149 -20
  3. package/anchor-entry.js +1 -0
  4. package/bin/cli.js +349 -0
  5. package/bsv-anchor.min.js +12 -0
  6. package/bsv-covenant.min.js +8 -8
  7. package/bsv-didweb.min.js +12 -0
  8. package/bsv-gdaf.min.js +9 -9
  9. package/bsv-ltp.min.js +9 -9
  10. package/bsv-mnemonic.min.js +2 -2
  11. package/bsv-shamir.min.js +3 -3
  12. package/bsv-smartcontract.min.js +9 -9
  13. package/bsv-statuslist.min.js +18 -0
  14. package/bsv-vcjwt.min.js +12 -0
  15. package/bsv.bundle.js +9 -9
  16. package/bsv.min.js +8 -8
  17. package/build/webpack.anchor.config.js +17 -0
  18. package/build/webpack.didweb.config.js +17 -0
  19. package/build/webpack.statuslist.config.js +17 -0
  20. package/build/webpack.vcjwt.config.js +17 -0
  21. package/demos/browser-test.html +1 -1
  22. package/didweb-entry.js +1 -0
  23. package/docs/technical/roadmap.md +3 -3
  24. package/examples/legacy/README.md +11 -0
  25. package/index.js +39 -1
  26. package/lib/anchor/index.js +102 -0
  27. package/lib/browser-utxo-manager-es5.js +11 -4
  28. package/lib/browser-utxo-manager.js +15 -8
  29. package/lib/didweb/index.js +177 -0
  30. package/lib/ltp/claim.js +1 -0
  31. package/lib/ltp/obligation.js +1 -0
  32. package/lib/ltp/registry.js +2 -0
  33. package/lib/ltp/right.js +1 -0
  34. package/lib/statuslist/index.js +164 -0
  35. package/lib/transaction/transaction.js +1 -1
  36. package/lib/util/_.js +7 -1
  37. package/lib/vcjwt/index.js +189 -0
  38. package/package.json +19 -13
  39. package/statuslist-entry.js +1 -0
  40. package/vcjwt-entry.js +1 -0
  41. package/demos/gdaf_core_test.js +0 -131
  42. package/examples/scripts/custom_script_signature_test.js +0 -344
  43. package/tests/browser-compatibility/README.md +0 -35
  44. package/tests/browser-compatibility/test-cdn-vs-local.html +0 -186
  45. package/tests/browser-compatibility/test-pbkdf2.html +0 -51
  46. package/tests/bundle-completeness-test.html +0 -131
  47. package/tests/bundle-demo.html +0 -476
  48. package/tests/smartcontract-test.html +0 -239
  49. package/tests/standalone-modules-test.html +0 -260
  50. package/tests/test.html +0 -612
  51. package/tests/test_standalone_shamir.html +0 -83
  52. package/tests/unpkg-demo.html +0 -194
  53. package/utilities/blockchain-state.json +0 -118565
  54. /package/{lib/smart_contract/test_integration.js → examples/legacy/smart_contract_test_integration.js} +0 -0
  55. /package/{tests → examples/legacy}/test_builtin_verify.js +0 -0
  56. /package/{tests → examples/legacy}/test_debug_integration.js +0 -0
  57. /package/{tests → examples/legacy}/test_ecdsa_little.js +0 -0
  58. /package/{tests → examples/legacy}/test_shamir.js +0 -0
  59. /package/{tests → examples/legacy}/test_smartverify_der.js +0 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,54 @@ All notable changes to SmartLedger-BSV will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.4.1] - 2026-05-18
9
+
10
+ ### Fixed
11
+
12
+ - **Credential bundles now actually ship.** `bsv-didweb.min.js`, `bsv-vcjwt.min.js`, `bsv-statuslist.min.js`, and `bsv-anchor.min.js` were missing from the `files:` allowlist in 3.4.0, so they were never included in the published npm tarball even though the README advertised them.
13
+ - **`prepublishOnly` now builds every advertised bundle.** Previously it ran `npm run build`, which only produced 6 of the ~16 bundles. It now runs `npm run build-all`, so credential, covenant, ltp, gdaf, and other specialized bundles can't go out of sync with source at publish time.
14
+ - **CSPRNG-backed `Transaction.shuffleOutputs()`.** `lib/util/_.js` `_.shuffle` now draws entropy from `bsv.crypto.Random` (Node `crypto.randomBytes` / `window.crypto.getRandomValues`) instead of `Math.random`. Output ordering is a privacy primitive; a predictable PRNG defeated the purpose.
15
+ - **`Transaction._fromMultisigUtxo` returns a real error.** A reachable `throw new Error('@TODO')` for unsupported script types now throws `errors.Transaction.Input.UnsupportedScript` with the offending script in the message.
16
+ - **Module load failures surface in Node.** The `try/catch` blocks around optional modules (`DIDWeb`, `VcJwt`, `StatusList`, `Anchor`, `BrowserUTXOManager`) in `index.js` previously swallowed all errors. They now `console.warn` in Node and stay silent in the browser, so upgrade breakage is visible.
17
+
18
+ ### Changed
19
+
20
+ - **`tests/` no longer ships to npm consumers.** The directory of HTML demo pages and 5 orphan standalone scripts is removed from `package.json` `files:` and added to `.npmignore`.
21
+ - **`utilities/blockchain-state.json` (3.2MB) no longer ships.** Mock blockchain data added to `.npmignore`; not needed at install time.
22
+ - **Browser UTXO manager logs are gated.** `lib/browser-utxo-manager.js` and `lib/browser-utxo-manager-es5.js` info-level `console.log` calls now require `BSV_DEBUG=1` (Node) or `window.BSV_DEBUG = true` (browser). `console.warn`/`console.error` unchanged.
23
+ - **Orphan scripts moved out of `lib/` and `tests/`.** `lib/smart_contract/test_integration.js` (an integration script that called `process.exit`) plus 5 pre-mocha scripts from `tests/` moved to `examples/legacy/`.
24
+ - **`package-lock.json` is now committed.** Removed from `.gitignore` so `npm audit` and reproducible installs work.
25
+ - **Dead `files:` entries removed.** Seven file references in `package.json` `files:` pointed to files that don't exist; npm silently skipped them. Removed.
26
+
27
+ ### Notes
28
+
29
+ - No public API changes. All call sites continue to work.
30
+ - Dev-only vulnerabilities remain in `webpack 4` / `standard 12` / `mocha 8`; a toolchain upgrade is planned for 3.5.0 to address them without breaking downstream bundler integrations.
31
+
32
+ ## [3.4.0] - 2025-11-09
33
+
34
+ ### Added
35
+
36
+ - **DID:web module** (`bsv.DIDWeb`, `bsv-didweb.min.js`): W3C DID Core `did:web` method generation with both ES256 (NIST P-256) and ES256K (Bitcoin secp256k1) key types.
37
+ - **VC-JWT module** (`bsv.VcJwt`, `bsv-vcjwt.min.js`): W3C Verifiable Credentials issuance and verification as JWT (RFC 7515 / RFC 7519 compliant).
38
+ - **StatusList2021 module** (`bsv.StatusList`, `bsv-statuslist.min.js`): credential revocation supporting 100k credentials per list.
39
+ - **Anchor module** (`bsv.Anchor`, `bsv-anchor.min.js`): privacy-preserving SHA-256 hash-only anchoring helpers for BSV.
40
+ - **CLI tooling** (`bin/cli.js`): `didweb`, `vc`, `status`, `anchor` subcommands.
41
+ - Quickstart examples and updated module tables in the README.
42
+
43
+ ### Standards Compliance
44
+
45
+ - W3C Verifiable Credentials Data Model
46
+ - W3C DID Core (`did:web` method)
47
+ - RFC 7515 (JWS), RFC 7519 (JWT)
48
+ - StatusList2021 specification
49
+ - NIST P-256 and Bitcoin secp256k1 curves
50
+
51
+ ### Known Issues (fixed in 3.4.1)
52
+
53
+ - The four new credential bundles were not listed in `package.json` `files:`, so they did not ship to npm consumers despite being advertised in the README.
54
+ - `prepublishOnly` only built the core 6 bundles, not the credential set.
55
+
8
56
  ## [3.3.4] - 2025-10-31
9
57
 
10
58
  ### Fixed
package/README.md CHANGED
@@ -1,47 +1,176 @@
1
1
  # SmartLedger-BSV
2
2
 
3
- **🚀 Complete Bitcoin SV Development Framework with Legal Compliance, Digital Identity, and 12 Flexible Loading Options**
3
+ **🚀 Complete Bitcoin SV Development Framework with W3C Verifiable Credentials, DID:web, Legal Compliance, and 16 Flexible Loading Options**
4
4
 
5
- [![Version](https://img.shields.io/badge/version-3.3.4-blue.svg)](https://www.npmjs.com/package/@smartledger/bsv)
5
+ [![Version](https://img.shields.io/badge/version-3.4.1-blue.svg)](https://www.npmjs.com/package/@smartledger/bsv)
6
6
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7
7
  [![BSV](https://img.shields.io/badge/BSV-Compatible-orange.svg)](https://bitcoinsv.com/)
8
8
  [![Modular](https://img.shields.io/badge/Loading-Modular-purple.svg)](#loading-options)
9
+ [![W3C](https://img.shields.io/badge/W3C-Compliant-blueviolet.svg)](#verifiable-credentials)
9
10
 
10
- The most comprehensive and flexible Bitcoin SV library available. Choose from 12 different distribution methods: standalone modules, complete bundle, or mix-and-match approach. Perfect for everything from simple transactions to complex DeFi protocols, smart contracts, legal tokenization, digital identity, and threshold cryptography.
11
+ The most comprehensive and flexible Bitcoin SV library available. **In v3.4.x**: Legally-recognizable DID:web + VC-JWT toolkit with ES256/ES256K support, StatusList2021 revocation, and BSV anchoring. Choose from 16 different distribution methods: standalone modules, complete bundle, or mix-and-match approach.
11
12
 
12
- ## 🎯 **12 Loading Options - Choose Your Approach**
13
+ > **v3.4.1 (bugfix)**: credential bundles now actually ship to npm consumers, `prepublishOnly` builds the full set, and `Transaction.shuffleOutputs()` uses a CSPRNG. See [CHANGELOG](./CHANGELOG.md#341---2026-05-18).
14
+
15
+ ## 🆕 **v3.4.x - Legally-Recognizable Credentials**
16
+
17
+ ### **Why This Matters**
18
+ - ✅ **W3C Standards**: Full VC-JWT and DID:web compliance for legal recognition
19
+ - ✅ **Enterprise Ready**: ES256 (P-256 NIST curve) for regulated industries
20
+ - ✅ **Blockchain Native**: ES256K (secp256k1) for BSV integration
21
+ - ✅ **Revocation Built-in**: StatusList2021 standard for credential management
22
+ - ✅ **Privacy Preserving**: Hash-only BSV anchoring (no PII on-chain)
23
+ - ✅ **CLI Tools**: Complete command-line interface for credential operations
24
+
25
+ ### **Quick Start - Issue Your First Verifiable Credential**
26
+
27
+ ```bash
28
+ # Install SmartLedger BSV v3.4.1
29
+ npm install @smartledger/bsv@3.4.1
30
+
31
+ # Initialize DID:web issuer (generates ES256 keys)
32
+ npx smartledger-bsv didweb init --domain example.com --alg ES256
33
+
34
+ # Issue a credential
35
+ npx smartledger-bsv vc issue \
36
+ --issuer did:web:example.com \
37
+ --subject did:example:alice \
38
+ --types "VerifiableCredential,DriversLicense" \
39
+ --claims '{"licenseNumber":"DL123456","class":"C"}' \
40
+ > credential.jwt
41
+
42
+ # Verify the credential
43
+ npx smartledger-bsv vc verify credential.jwt
44
+
45
+ # Anchor hash to BSV (privacy-preserving)
46
+ npx smartledger-bsv anchor hash credential.jwt
47
+
48
+ # Create revocation list
49
+ npx smartledger-bsv status create --issuer did:web:example.com > status-list.jwt
50
+
51
+ # Revoke a credential
52
+ npx smartledger-bsv status set --list status-list.jwt --index 42 --status revoked
53
+ ```
54
+
55
+ ### **Programmatic Usage**
56
+
57
+ ```javascript
58
+ const bsv = require('@smartledger/bsv')
59
+
60
+ // Generate DID:web issuer keys
61
+ const keys = await bsv.DIDWeb.generateIssuerKeys({ alg: 'ES256' })
62
+
63
+ // Build DID documents (.well-known/did.json and jwks.json)
64
+ const docs = bsv.DIDWeb.buildDidWebDocuments({
65
+ domain: 'example.com',
66
+ p256: { jwk: keys.publicJwk, kid: keys.kid },
67
+ controllerName: 'Example Corp'
68
+ })
69
+ // Deploy docs.didDocument to https://example.com/.well-known/did.json
70
+ // Deploy docs.jwks to https://example.com/.well-known/jwks.json
71
+
72
+ // Issue a Verifiable Credential as JWT
73
+ const result = await bsv.VcJwt.issueVcJwt({
74
+ issuerDid: docs.did,
75
+ subjectId: 'did:example:alice',
76
+ types: ['VerifiableCredential', 'AgeCredential'],
77
+ credentialSubject: {
78
+ ageOver: 18,
79
+ country: 'US'
80
+ },
81
+ privateJwk: keys.privateJwk,
82
+ alg: 'ES256',
83
+ kid: keys.kid
84
+ })
85
+
86
+ console.log('VC-JWT:', result.jwt)
87
+
88
+ // Verify the credential
89
+ const verification = await bsv.VcJwt.verifyVcJwt(result.jwt, {
90
+ didResolver: async (did) => {
91
+ // In production, fetch https://example.com/.well-known/jwks.json
92
+ return { jwks: docs.jwks }
93
+ },
94
+ expectedIssuerDid: docs.did
95
+ })
96
+
97
+ console.log('Valid:', verification.valid)
98
+
99
+ // Anchor hash to BSV (no PII on-chain)
100
+ const hash = bsv.Anchor.sha256Hex(result.jwt)
101
+ const anchorPayload = bsv.Anchor.buildAnchorPayload({
102
+ kind: 'VC_ANCHOR_SHA256',
103
+ hash: hash,
104
+ issuerDid: docs.did
105
+ })
106
+
107
+ // Include anchorPayload.json in OP_RETURN
108
+ // Later: verify with bsv.Anchor.verifyAnchorHash(originalData, anchorHash)
109
+
110
+ // Create revocation list (100k credentials)
111
+ const statusList = await bsv.StatusList.createStatusList({
112
+ issuerDid: docs.did,
113
+ privateJwk: keys.privateJwk
114
+ })
115
+
116
+ // Revoke a credential
117
+ const updated = await bsv.StatusList.updateStatusList({
118
+ listVcJwt: statusList.listVcJwt,
119
+ index: 42,
120
+ status: 'revoked',
121
+ privateJwk: keys.privateJwk
122
+ })
123
+
124
+ // Check revocation status
125
+ const status = bsv.StatusList.getCredentialStatusEntry({
126
+ listVcJwt: updated.listVcJwt,
127
+ index: 42
128
+ })
129
+
130
+ console.log('Status:', status) // 'revoked'
131
+ ```
132
+
133
+ ## 🎯 **16 Loading Options - Choose Your Approach**
13
134
 
14
135
  ### **Core Modules**
15
136
  | Module | Size | Use Case | CDN |
16
137
  |--------|------|----------|-----|
17
- | **bsv.min.js** | 449KB | Core BSV + SmartContract | `unpkg.com/@smartledger/bsv@3.3.4/bsv.min.js` |
18
- | **bsv.bundle.js** | 885KB | Everything in one file | `unpkg.com/@smartledger/bsv@3.3.4/bsv.bundle.js` |
138
+ | **bsv.min.js** | 937KB | Core BSV + SmartContract | `unpkg.com/@smartledger/bsv@3.4.1/bsv.min.js` |
139
+ | **bsv.bundle.js** | 937KB | Everything in one file | `unpkg.com/@smartledger/bsv@3.4.1/bsv.bundle.js` |
140
+
141
+ ### **🆕 W3C Verifiable Credentials (v3.4.x)**
142
+ | Module | Size | Use Case | CDN |
143
+ |--------|------|----------|-----|
144
+ | **🟢 bsv-didweb.min.js** | 419KB | **DID:web generation** | `unpkg.com/@smartledger/bsv@3.4.1/bsv-didweb.min.js` |
145
+ | **🟢 bsv-vcjwt.min.js** | 419KB | **VC-JWT issue/verify** | `unpkg.com/@smartledger/bsv@3.4.1/bsv-vcjwt.min.js` |
146
+ | **🟢 bsv-statuslist.min.js** | 487KB | **StatusList2021 revocation** | `unpkg.com/@smartledger/bsv@3.4.1/bsv-statuslist.min.js` |
147
+ | **🟢 bsv-anchor.min.js** | 418KB | **BSV anchoring (hash-only)** | `unpkg.com/@smartledger/bsv@3.4.1/bsv-anchor.min.js` |
19
148
 
20
149
  ### **Smart Contract & Development**
21
150
  | Module | Size | Use Case | CDN |
22
151
  |--------|------|----------|-----|
23
- | **bsv-smartcontract.min.js** | 451KB | Complete covenant framework | `unpkg.com/@smartledger/bsv@3.3.4/bsv-smartcontract.min.js` |
24
- | **bsv-covenant.min.js** | 32KB | Covenant operations | `unpkg.com/@smartledger/bsv@3.3.4/bsv-covenant.min.js` |
25
- | **bsv-script-helper.min.js** | 27KB | Custom script tools | `unpkg.com/@smartledger/bsv@3.3.4/bsv-script-helper.min.js` |
26
- | **bsv-security.min.js** | 290KB | Security enhancements | `unpkg.com/@smartledger/bsv@3.3.4/bsv-security.min.js` |
152
+ | **bsv-smartcontract.min.js** | 937KB | Complete covenant framework | `unpkg.com/@smartledger/bsv@3.4.1/bsv-smartcontract.min.js` |
153
+ | **bsv-covenant.min.js** | 913KB | Covenant operations | `unpkg.com/@smartledger/bsv@3.4.1/bsv-covenant.min.js` |
154
+ | **bsv-script-helper.min.js** | 26KB | Custom script tools | `unpkg.com/@smartledger/bsv@3.4.1/bsv-script-helper.min.js` |
155
+ | **bsv-security.min.js** | 26KB | Security enhancements | `unpkg.com/@smartledger/bsv@3.4.1/bsv-security.min.js` |
27
156
 
28
- ### **🆕 Legal & Compliance**
157
+ ### **Legal & Compliance**
29
158
  | Module | Size | Use Case | CDN |
30
159
  |--------|------|----------|-----|
31
- | **🟢 bsv-ltp.min.js** | 817KB | **Legal Token Protocol** | `unpkg.com/@smartledger/bsv@3.3.4/bsv-ltp.min.js` |
32
- | **🟢 bsv-gdaf.min.js** | 604KB | **Digital Identity & Attestation** | `unpkg.com/@smartledger/bsv@3.3.4/bsv-gdaf.min.js` |
160
+ | **bsv-ltp.min.js** | 1184KB | Legal Token Protocol | `unpkg.com/@smartledger/bsv@3.4.1/bsv-ltp.min.js` |
161
+ | **bsv-gdaf.min.js** | 1184KB | Digital Identity & Attestation | `unpkg.com/@smartledger/bsv@3.4.1/bsv-gdaf.min.js` |
33
162
 
34
- ### **🆕 Advanced Cryptography**
163
+ ### **Advanced Cryptography**
35
164
  | Module | Size | Use Case | CDN |
36
165
  |--------|------|----------|-----|
37
- | **🟢 bsv-shamir.min.js** | 433KB | **Threshold Cryptography** | `unpkg.com/@smartledger/bsv@3.3.4/bsv-shamir.min.js` |
166
+ | **bsv-shamir.min.js** | 432KB | Threshold Cryptography | `unpkg.com/@smartledger/bsv@3.4.1/bsv-shamir.min.js` |
38
167
 
39
168
  ### **Utilities**
40
169
  | Module | Size | Use Case | CDN |
41
170
  |--------|------|----------|-----|
42
- | **bsv-ecies.min.js** | 71KB | Encryption | `unpkg.com/@smartledger/bsv@3.3.4/bsv-ecies.min.js` |
43
- | **bsv-message.min.js** | 26KB | Message signing | `unpkg.com/@smartledger/bsv@3.3.4/bsv-message.min.js` |
44
- | **bsv-mnemonic.min.js** | 670KB | HD wallets | `unpkg.com/@smartledger/bsv@3.3.4/bsv-mnemonic.min.js` |
171
+ | **bsv-ecies.min.js** | 71KB | Encryption | `unpkg.com/@smartledger/bsv@3.4.1/bsv-ecies.min.js` |
172
+ | **bsv-message.min.js** | 26KB | Message signing | `unpkg.com/@smartledger/bsv@3.4.1/bsv-message.min.js` |
173
+ | **bsv-mnemonic.min.js** | 681KB | HD wallets | `unpkg.com/@smartledger/bsv@3.4.1/bsv-mnemonic.min.js` |
45
174
 
46
175
  ## ⚡ **2-Minute Quick Start**
47
176
 
@@ -52,10 +181,10 @@ Get started with Bitcoin SV development in under 2 minutes:
52
181
  npm install @smartledger/bsv
53
182
 
54
183
  # Or include in HTML
55
- <script src="https://unpkg.com/@smartledger/bsv@3.3.4/bsv.min.js"></script>
184
+ <script src="https://unpkg.com/@smartledger/bsv@3.4.1/bsv.min.js"></script>
56
185
  ```
57
186
 
58
- > **🔧 v3.3.4 Update:** Fixed critical browser compatibility issue with mnemonic generation. CDN users can now use HD wallet and mnemonic functionality without `createHmac` errors!
187
+ > **🔧 v3.4.x:** Legally-recognizable W3C Verifiable Credentials with DID:web + VC-JWT toolkit. ES256/ES256K support, StatusList2021 revocation, and privacy-preserving BSV anchoring. Complete CLI tooling included! v3.4.1 ensures these bundles ship to npm consumers; see CHANGELOG.
59
188
 
60
189
  **Basic Transaction (30 seconds):**
61
190
  ```javascript
@@ -0,0 +1 @@
1
+ module.exports = require('./lib/anchor')
package/bin/cli.js ADDED
@@ -0,0 +1,349 @@
1
+ #!/usr/bin/env node
2
+ 'use strict'
3
+
4
+ /**
5
+ * SmartLedger BSV CLI
6
+ * Command-line tools for DID:web, VC-JWT, and StatusList2021
7
+ */
8
+
9
+ var fs = require('fs')
10
+ var path = require('path')
11
+ var didweb = require('../lib/didweb')
12
+ var vcjwt = require('../lib/vcjwt')
13
+ var statuslist = require('../lib/statuslist')
14
+ var anchor = require('../lib/anchor')
15
+
16
+ var args = process.argv.slice(2)
17
+ var command = args[0]
18
+ var subcommand = args[1]
19
+
20
+ // Helper to parse command-line arguments
21
+ function parseArgs(args) {
22
+ var opts = {}
23
+ for (var i = 0; i < args.length; i++) {
24
+ if (args[i].startsWith('--')) {
25
+ var key = args[i].slice(2)
26
+ var value = args[i + 1]
27
+ opts[key] = value
28
+ i++
29
+ }
30
+ }
31
+ return opts
32
+ }
33
+
34
+ // Helper to read JSON file
35
+ function readJsonFile(filepath) {
36
+ var content = fs.readFileSync(filepath, 'utf8')
37
+ return JSON.parse(content)
38
+ }
39
+
40
+ // Helper to write JSON file
41
+ function writeJsonFile(filepath, data) {
42
+ fs.writeFileSync(filepath, JSON.stringify(data, null, 2))
43
+ }
44
+
45
+ async function main() {
46
+ if (!command) {
47
+ console.log('SmartLedger BSV CLI v3.4.0')
48
+ console.log('')
49
+ console.log('Usage:')
50
+ console.log(' smartledger-bsv didweb <subcommand> [options]')
51
+ console.log(' smartledger-bsv vc <subcommand> [options]')
52
+ console.log(' smartledger-bsv status <subcommand> [options]')
53
+ console.log(' smartledger-bsv anchor <subcommand> [options]')
54
+ console.log('')
55
+ console.log('DID:web Commands:')
56
+ console.log(' didweb init --domain <domain> [--alg ES256|ES256K]')
57
+ console.log(' didweb rotate --domain <domain> --key <key-file>')
58
+ console.log('')
59
+ console.log('VC Commands:')
60
+ console.log(' vc issue --issuer <did> --subject <did> --types <types> --claims <json>')
61
+ console.log(' vc verify <jwt-file>')
62
+ console.log('')
63
+ console.log('Status List Commands:')
64
+ console.log(' status create --issuer <did>')
65
+ console.log(' status set --list <file> --index <n> --status <revoked|suspended|valid>')
66
+ console.log(' status check --list <file> --index <n>')
67
+ console.log('')
68
+ console.log('Anchor Commands:')
69
+ console.log(' anchor hash <data-file>')
70
+ console.log(' anchor build --kind <type> --hash <hash> --issuer <did>')
71
+ process.exit(0)
72
+ }
73
+
74
+ var opts = parseArgs(args.slice(2))
75
+
76
+ try {
77
+ if (command === 'didweb') {
78
+ await handleDidWeb(subcommand, opts)
79
+ } else if (command === 'vc') {
80
+ await handleVc(subcommand, opts)
81
+ } else if (command === 'status') {
82
+ await handleStatus(subcommand, opts)
83
+ } else if (command === 'anchor') {
84
+ await handleAnchor(subcommand, opts)
85
+ } else {
86
+ console.error('Unknown command:', command)
87
+ process.exit(1)
88
+ }
89
+ } catch (error) {
90
+ console.error('Error:', error.message)
91
+ process.exit(1)
92
+ }
93
+ }
94
+
95
+ async function handleDidWeb(subcommand, opts) {
96
+ if (subcommand === 'init') {
97
+ if (!opts.domain) {
98
+ console.error('--domain is required')
99
+ process.exit(1)
100
+ }
101
+
102
+ var alg = opts.alg || 'ES256'
103
+ console.error('Generating ' + alg + ' keys for domain: ' + opts.domain)
104
+
105
+ // Generate keys
106
+ var keys = await didweb.generateIssuerKeys({ alg: alg })
107
+
108
+ // Build DID documents
109
+ var docs = didweb.buildDidWebDocuments({
110
+ domain: opts.domain,
111
+ p256: alg === 'ES256' ? { jwk: keys.publicJwk, kid: keys.kid } : undefined,
112
+ k1: alg === 'ES256K' ? { jwk: keys.publicJwk, kid: keys.kid } : undefined,
113
+ controllerName: opts.name || 'SmartLedger Issuer'
114
+ })
115
+
116
+ // Create .well-known directory
117
+ var wellKnownDir = path.join(process.cwd(), '.well-known')
118
+ if (!fs.existsSync(wellKnownDir)) {
119
+ fs.mkdirSync(wellKnownDir, { recursive: true })
120
+ }
121
+
122
+ // Write did.json
123
+ var didPath = path.join(wellKnownDir, 'did.json')
124
+ writeJsonFile(didPath, docs.didDocument)
125
+ console.error('✅ Created:', didPath)
126
+
127
+ // Write jwks.json
128
+ var jwksPath = path.join(wellKnownDir, 'jwks.json')
129
+ writeJsonFile(jwksPath, docs.jwks)
130
+ console.error('✅ Created:', jwksPath)
131
+
132
+ // Write private key to secure file
133
+ var keyPath = path.join(process.cwd(), 'issuer-key-' + keys.kid + '.json')
134
+ writeJsonFile(keyPath, {
135
+ kid: keys.kid,
136
+ alg: keys.alg,
137
+ privateJwk: keys.privateJwk,
138
+ publicJwk: keys.publicJwk,
139
+ did: docs.did
140
+ })
141
+ console.error('✅ Created private key:', keyPath)
142
+ console.error('⚠️ KEEP THIS FILE SECURE AND ENCRYPTED!')
143
+
144
+ console.error('')
145
+ console.error('DID:', docs.did)
146
+ console.error('')
147
+ console.error('Next steps:')
148
+ console.error('1. Host .well-known/did.json and .well-known/jwks.json at https://' + opts.domain)
149
+ console.error('2. Encrypt and securely store ' + keyPath)
150
+ console.error('3. Issue credentials with: smartledger-bsv vc issue ...')
151
+
152
+ } else if (subcommand === 'rotate') {
153
+ console.error('Key rotation coming soon')
154
+ } else {
155
+ console.error('Unknown didweb subcommand:', subcommand)
156
+ process.exit(1)
157
+ }
158
+ }
159
+
160
+ async function handleVc(subcommand, opts) {
161
+ if (subcommand === 'issue') {
162
+ if (!opts.issuer || !opts.subject || !opts.claims) {
163
+ console.error('--issuer, --subject, and --claims are required')
164
+ process.exit(1)
165
+ }
166
+
167
+ // Load issuer key
168
+ var keyFile = opts.key || 'issuer-key.json'
169
+ if (!fs.existsSync(keyFile)) {
170
+ console.error('Issuer key file not found:', keyFile)
171
+ console.error('Use --key to specify the key file')
172
+ process.exit(1)
173
+ }
174
+
175
+ var keyData = readJsonFile(keyFile)
176
+ var claims = JSON.parse(opts.claims)
177
+ var types = opts.types ? opts.types.split(',') : ['VerifiableCredential']
178
+
179
+ console.error('Issuing credential...')
180
+ console.error(' Issuer:', opts.issuer)
181
+ console.error(' Subject:', opts.subject)
182
+ console.error(' Types:', types.join(', '))
183
+
184
+ var result = await vcjwt.issueVcJwt({
185
+ issuerDid: opts.issuer,
186
+ subjectId: opts.subject,
187
+ types: types,
188
+ credentialSubject: claims,
189
+ privateJwk: keyData.privateJwk,
190
+ alg: keyData.alg || 'ES256',
191
+ kid: keyData.kid
192
+ })
193
+
194
+ console.log(result.jwt)
195
+ console.error('✅ Credential issued successfully')
196
+
197
+ } else if (subcommand === 'verify') {
198
+ var jwtFile = opts.jwt || args[2]
199
+ if (!jwtFile) {
200
+ console.error('JWT file required')
201
+ process.exit(1)
202
+ }
203
+
204
+ var jwt = fs.readFileSync(jwtFile, 'utf8').trim()
205
+
206
+ console.error('Verifying credential...')
207
+
208
+ // Simple resolver that reads from .well-known
209
+ var didResolver = async function(did) {
210
+ var domain = did.replace('did:web:', '').replace(/%3A/g, ':')
211
+ var jwksPath = path.join(process.cwd(), '.well-known', 'jwks.json')
212
+
213
+ if (fs.existsSync(jwksPath)) {
214
+ return readJsonFile(jwksPath)
215
+ }
216
+
217
+ throw new Error('Cannot resolve DID: ' + did)
218
+ }
219
+
220
+ var result = await vcjwt.verifyVcJwt(jwt, { didResolver: didResolver })
221
+
222
+ if (result.valid) {
223
+ console.error('✅ Credential is VALID')
224
+ console.log(JSON.stringify(result.payload, null, 2))
225
+ } else {
226
+ console.error('❌ Credential is INVALID')
227
+ console.error('Error:', result.error)
228
+ process.exit(1)
229
+ }
230
+
231
+ } else {
232
+ console.error('Unknown vc subcommand:', subcommand)
233
+ process.exit(1)
234
+ }
235
+ }
236
+
237
+ async function handleStatus(subcommand, opts) {
238
+ if (subcommand === 'create') {
239
+ if (!opts.issuer) {
240
+ console.error('--issuer is required')
241
+ process.exit(1)
242
+ }
243
+
244
+ var keyFile = opts.key || 'issuer-key.json'
245
+ if (!fs.existsSync(keyFile)) {
246
+ console.error('Issuer key file not found:', keyFile)
247
+ process.exit(1)
248
+ }
249
+
250
+ var keyData = readJsonFile(keyFile)
251
+
252
+ console.error('Creating status list...')
253
+
254
+ var result = await statuslist.createStatusList({
255
+ issuerDid: opts.issuer,
256
+ privateJwk: keyData.privateJwk
257
+ })
258
+
259
+ console.log(result.listVcJwt)
260
+ console.error('✅ Status list created')
261
+ console.error('List ID:', result.listId)
262
+
263
+ } else if (subcommand === 'set') {
264
+ if (!opts.list || opts.index === undefined || !opts.status) {
265
+ console.error('--list, --index, and --status are required')
266
+ process.exit(1)
267
+ }
268
+
269
+ var listJwt = fs.readFileSync(opts.list, 'utf8').trim()
270
+ var keyFile = opts.key || 'issuer-key.json'
271
+ var keyData = readJsonFile(keyFile)
272
+
273
+ console.error('Updating status list...')
274
+ console.error(' Index:', opts.index)
275
+ console.error(' Status:', opts.status)
276
+
277
+ var result = await statuslist.updateStatusList({
278
+ listVcJwt: listJwt,
279
+ index: parseInt(opts.index),
280
+ status: opts.status,
281
+ privateJwk: keyData.privateJwk
282
+ })
283
+
284
+ console.log(result.listVcJwt)
285
+ console.error('✅ Status list updated')
286
+
287
+ } else if (subcommand === 'check') {
288
+ if (!opts.list || opts.index === undefined) {
289
+ console.error('--list and --index are required')
290
+ process.exit(1)
291
+ }
292
+
293
+ var listJwt = fs.readFileSync(opts.list, 'utf8').trim()
294
+
295
+ var status = statuslist.getCredentialStatusEntry({
296
+ listVcJwt: listJwt,
297
+ index: parseInt(opts.index)
298
+ })
299
+
300
+ console.log(status)
301
+ console.error('Status at index', opts.index + ':', status)
302
+
303
+ } else {
304
+ console.error('Unknown status subcommand:', subcommand)
305
+ process.exit(1)
306
+ }
307
+ }
308
+
309
+ async function handleAnchor(subcommand, opts) {
310
+ if (subcommand === 'hash') {
311
+ var dataFile = args[2]
312
+ if (!dataFile) {
313
+ console.error('Data file required')
314
+ process.exit(1)
315
+ }
316
+
317
+ var data = fs.readFileSync(dataFile)
318
+ var hash = anchor.sha256Hex(data)
319
+
320
+ console.log(hash)
321
+ console.error('SHA-256 hash:', hash)
322
+
323
+ } else if (subcommand === 'build') {
324
+ if (!opts.kind || !opts.hash || !opts.issuer) {
325
+ console.error('--kind, --hash, and --issuer are required')
326
+ process.exit(1)
327
+ }
328
+
329
+ var payload = anchor.buildAnchorPayload({
330
+ kind: opts.kind,
331
+ hash: opts.hash,
332
+ issuerDid: opts.issuer,
333
+ issuedAt: opts.timestamp
334
+ })
335
+
336
+ console.log(payload.json)
337
+ console.error('✅ Anchor payload created')
338
+ console.error('Size:', payload.json.length, 'bytes')
339
+
340
+ } else {
341
+ console.error('Unknown anchor subcommand:', subcommand)
342
+ process.exit(1)
343
+ }
344
+ }
345
+
346
+ main().catch(function(error) {
347
+ console.error('Fatal error:', error)
348
+ process.exit(1)
349
+ })