smartledger-bsv 3.3.5 → 3.4.4

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 (126) hide show
  1. package/CHANGELOG.md +400 -0
  2. package/README.md +235 -80
  3. package/SECURITY.md +88 -0
  4. package/anchor-entry.js +1 -0
  5. package/bin/cli.js +354 -0
  6. package/bsv-anchor.min.js +12 -0
  7. package/bsv-covenant.min.js +8 -8
  8. package/bsv-didweb.min.js +12 -0
  9. package/bsv-gdaf.min.js +9 -9
  10. package/bsv-ltp.min.js +9 -9
  11. package/bsv-mnemonic.min.js +2 -2
  12. package/bsv-shamir.min.js +3 -3
  13. package/bsv-smartcontract.min.js +9 -9
  14. package/bsv-statuslist.min.js +18 -0
  15. package/bsv-vcjwt.min.js +12 -0
  16. package/bsv.bundle.js +9 -9
  17. package/bsv.d.ts +486 -9
  18. package/bsv.min.js +8 -8
  19. package/build/webpack.anchor.config.js +17 -0
  20. package/build/webpack.didweb.config.js +17 -0
  21. package/build/webpack.statuslist.config.js +17 -0
  22. package/build/webpack.vcjwt.config.js +17 -0
  23. package/didweb-entry.js +1 -0
  24. package/docs/COVENANT_DEVELOPMENT_RESOLVED.md +2 -2
  25. package/docs/MODULE_REFERENCE_COMPLETE.md +61 -58
  26. package/docs/advanced/LEGAL_TOKEN_PROTOCOL.md +3 -3
  27. package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
  28. package/docs/getting-started/INSTALLATION.md +30 -30
  29. package/docs/getting-started/QUICK_START.md +18 -18
  30. package/docs/migration/FROM_BSV_1_5_6.md +16 -10
  31. package/docs/technical/roadmap.md +3 -3
  32. package/gdaf-entry.js +1 -2
  33. package/index.js +68 -9
  34. package/lib/anchor/index.js +102 -0
  35. package/lib/browser-utxo-manager-es5.js +11 -4
  36. package/lib/browser-utxo-manager.js +15 -8
  37. package/lib/didweb/index.js +177 -0
  38. package/lib/ltp/claim.js +1 -0
  39. package/lib/ltp/obligation.js +1 -0
  40. package/lib/ltp/registry.js +2 -0
  41. package/lib/ltp/right.js +1 -0
  42. package/lib/smart_contract/covenant.js +10 -1
  43. package/lib/smartutxo.js +20 -12
  44. package/lib/statuslist/index.js +164 -0
  45. package/lib/transaction/transaction.js +8 -1
  46. package/lib/util/_.js +7 -1
  47. package/lib/vcjwt/index.js +189 -0
  48. package/ltp-entry.js +1 -2
  49. package/package.json +21 -15
  50. package/statuslist-entry.js +1 -0
  51. package/utilities/blockchain-state.js +32 -23
  52. package/vcjwt-entry.js +1 -0
  53. package/demos/README.md +0 -188
  54. package/demos/architecture_demo.js +0 -247
  55. package/demos/browser-test.html +0 -1208
  56. package/demos/bsv_wallet_demo.js +0 -242
  57. package/demos/complete_ltp_demo.js +0 -511
  58. package/demos/debug_tools_demo.js +0 -87
  59. package/demos/demo_features.js +0 -123
  60. package/demos/easy_interface_demo.js +0 -109
  61. package/demos/ecies_demo.js +0 -182
  62. package/demos/gdaf_core_test.js +0 -131
  63. package/demos/gdaf_demo.js +0 -237
  64. package/demos/ltp_demo.js +0 -361
  65. package/demos/ltp_primitives_demo.js +0 -403
  66. package/demos/message_demo.js +0 -209
  67. package/demos/preimage_separation_demo.js +0 -383
  68. package/demos/script_helper_demo.js +0 -289
  69. package/demos/security_demo.js +0 -287
  70. package/demos/shamir_demo.js +0 -121
  71. package/demos/simple_demo.js +0 -204
  72. package/demos/simple_p2pkh_demo.js +0 -169
  73. package/demos/simple_utxo_preimage_demo.js +0 -196
  74. package/demos/smart_contract_demo.html +0 -1347
  75. package/demos/smart_contract_demo.js +0 -910
  76. package/demos/utxo_generator_demo.js +0 -244
  77. package/demos/validation_pipeline_demo.js +0 -155
  78. package/demos/web3keys.html +0 -740
  79. package/examples/README.md +0 -200
  80. package/examples/basic/transaction-creation.js +0 -534
  81. package/examples/basic/transaction_signature_api_gap.js +0 -178
  82. package/examples/complete_workflow_demo.js +0 -783
  83. package/examples/covenants/advanced_covenant_demo.js +0 -219
  84. package/examples/covenants/covenant_interface_demo.js +0 -270
  85. package/examples/covenants/covenant_manual_signature_resolved.js +0 -212
  86. package/examples/covenants/covenant_signature_template.js +0 -117
  87. package/examples/covenants2/covenant_bidirectional_example.js +0 -262
  88. package/examples/covenants2/covenant_utils_demo.js +0 -120
  89. package/examples/covenants2/preimage_covenant_utils.js +0 -287
  90. package/examples/covenants2/production_integration.js +0 -256
  91. package/examples/data/covenant_utxos.json +0 -28
  92. package/examples/data/utxos.json +0 -26
  93. package/examples/definitive_working_demo.js +0 -261
  94. package/examples/final_working_contracts.js +0 -338
  95. package/examples/preimage/README.md +0 -178
  96. package/examples/preimage/extract_preimage_bidirectional.js +0 -421
  97. package/examples/preimage/generate_sample_preimage.js +0 -208
  98. package/examples/preimage/generate_sighash_examples.js +0 -152
  99. package/examples/preimage/parse_preimage.js +0 -117
  100. package/examples/preimage/test_preimage_extractor.js +0 -53
  101. package/examples/preimage/test_varint_extraction.js +0 -95
  102. package/examples/scripts/custom_script_helper_example.js +0 -273
  103. package/examples/scripts/custom_script_signature_test.js +0 -344
  104. package/examples/scripts/script_interpreter.js +0 -193
  105. package/examples/smart_contract/complete_workflow_demo.js +0 -343
  106. package/examples/smart_contract/covenant_builder_demo.js +0 -176
  107. package/examples/smart_contract/script_testing_integration.js +0 -198
  108. package/examples/smart_contract_templates.js +0 -718
  109. package/examples/working_smart_contracts.js +0 -348
  110. package/lib/smart_contract/test_integration.js +0 -269
  111. package/tests/browser-compatibility/README.md +0 -35
  112. package/tests/browser-compatibility/test-cdn-vs-local.html +0 -186
  113. package/tests/browser-compatibility/test-pbkdf2.html +0 -51
  114. package/tests/bundle-completeness-test.html +0 -131
  115. package/tests/bundle-demo.html +0 -476
  116. package/tests/smartcontract-test.html +0 -239
  117. package/tests/standalone-modules-test.html +0 -260
  118. package/tests/test.html +0 -612
  119. package/tests/test_builtin_verify.js +0 -117
  120. package/tests/test_debug_integration.js +0 -71
  121. package/tests/test_ecdsa_little.js +0 -70
  122. package/tests/test_shamir.js +0 -221
  123. package/tests/test_smartverify_der.js +0 -110
  124. package/tests/test_standalone_shamir.html +0 -83
  125. package/tests/unpkg-demo.html +0 -194
  126. package/utilities/blockchain-state.json +0 -118565
package/index.js CHANGED
@@ -2,17 +2,30 @@
2
2
 
3
3
  var bsv = module.exports
4
4
 
5
- // Initialize dependencies first to avoid circular dependency issues
5
+ // Initialize dependencies first to avoid circular dependency issues.
6
+ //
7
+ // `bn.js`, `bs58`, and `elliptic` are declared runtime deps in
8
+ // package.json. In Node they MUST be installed — silently swallowing
9
+ // a require() failure here used to mask broken installs behind cryptic
10
+ // downstream errors in lib/crypto/bn.js etc. We now let those throw in
11
+ // Node so the failure points at the real cause (`npm install` is broken).
12
+ // In a browser context the bundler is expected to inline these; if it
13
+ // somehow didn't, we tolerate the absence rather than block the whole
14
+ // library load.
6
15
  bsv.deps = bsv.deps || {}
7
- try {
16
+ bsv.deps._ = require('./lib/util/_')
17
+ bsv.deps.Buffer = (typeof Buffer !== 'undefined') ? Buffer : null
18
+
19
+ if (typeof window === 'undefined') {
20
+ // Node — hard require; failure means broken install.
8
21
  bsv.deps.bnjs = require('bn.js')
9
22
  bsv.deps.bs58 = require('bs58')
10
- bsv.deps.Buffer = (typeof Buffer !== 'undefined') ? Buffer : null
11
23
  bsv.deps.elliptic = require('elliptic')
12
- bsv.deps._ = require('./lib/util/_')
13
- } catch (e) {
14
- // Handle browser environment gracefully
15
- console.warn('Some dependencies may not be available in browser environment:', e.message)
24
+ } else {
25
+ // Browser bundler-resolved; tolerate absence individually.
26
+ try { bsv.deps.bnjs = require('bn.js') } catch (e) { /* polyfilled by bundler */ }
27
+ try { bsv.deps.bs58 = require('bs58') } catch (e) { /* polyfilled by bundler */ }
28
+ try { bsv.deps.elliptic = require('elliptic') } catch (e) { /* polyfilled by bundler */ }
16
29
  }
17
30
 
18
31
  // module information
@@ -29,7 +42,15 @@ bsv.versionGuard = function (version) {
29
42
  bsv.versionGuard(global._bsv)
30
43
  global._bsv = bsv.version
31
44
 
32
- // SmartLedger security information
45
+ // SmartLedger security information.
46
+ // NOTE: these properties advertise that hardening *helpers* ship in this
47
+ // package (`bsv.SmartVerify`, `bsv.EllipticFixed`, `signature.toCanonical()`,
48
+ // etc.). They are NOT automatically wired into the default verify path:
49
+ // `transaction.verify()`, `signature.verify()`, and `Message().verify()` go
50
+ // through `lib/crypto/ecdsa.js`, which uses BSV's own pure-JS ECDSA and does
51
+ // not route through `SmartVerify` or `EllipticFixed`. To get the strict
52
+ // input validation, call `bsv.SmartVerify.smartVerify(...)` explicitly.
53
+ // See the Security section of README.md.
33
54
  bsv.isHardened = true
34
55
  bsv.hardenedBy = 'SmartLedger'
35
56
  bsv.baseVersion = 'v1.5.6'
@@ -119,7 +140,9 @@ try {
119
140
  try {
120
141
  bsv.BrowserUTXOManager = require('./lib/browser-utxo-manager-es5')
121
142
  } catch (e) {
122
- // BrowserUTXOManager not available
143
+ if (typeof window === 'undefined') {
144
+ console.warn('[bsv] BrowserUTXOManager failed to load:', e.message)
145
+ }
123
146
  }
124
147
 
125
148
  // Node.js specific tools (advanced development tools)
@@ -136,6 +159,42 @@ if (typeof window === 'undefined' && typeof require === 'function') {
136
159
  // Global Digital Attestation Framework (GDAF)
137
160
  bsv.GDAF = require('./lib/gdaf')
138
161
 
162
+ // DID:web Module (W3C standards-based DIDs)
163
+ try {
164
+ bsv.DIDWeb = require('./lib/didweb')
165
+ } catch (e) {
166
+ if (typeof window === 'undefined') {
167
+ console.warn('[bsv] DIDWeb module failed to load:', e.message)
168
+ }
169
+ }
170
+
171
+ // VC-JWT Module (W3C Verifiable Credentials)
172
+ try {
173
+ bsv.VcJwt = require('./lib/vcjwt')
174
+ } catch (e) {
175
+ if (typeof window === 'undefined') {
176
+ console.warn('[bsv] VcJwt module failed to load:', e.message)
177
+ }
178
+ }
179
+
180
+ // StatusList2021 Module (Credential revocation)
181
+ try {
182
+ bsv.StatusList = require('./lib/statuslist')
183
+ } catch (e) {
184
+ if (typeof window === 'undefined') {
185
+ console.warn('[bsv] StatusList module failed to load:', e.message)
186
+ }
187
+ }
188
+
189
+ // Anchor Module (BSV hash anchoring)
190
+ try {
191
+ bsv.Anchor = require('./lib/anchor')
192
+ } catch (e) {
193
+ if (typeof window === 'undefined') {
194
+ console.warn('[bsv] Anchor module failed to load:', e.message)
195
+ }
196
+ }
197
+
139
198
  // GDAF Direct Access Methods (for easier developer experience)
140
199
  bsv.createDID = function(publicKey) {
141
200
  var gdaf = new bsv.GDAF()
@@ -0,0 +1,102 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * BSV Anchor Module
5
+ * Hash anchoring helpers for on-chain evidence (no PII)
6
+ */
7
+
8
+ var crypto = require('crypto')
9
+
10
+ // SHA-256 hex hash
11
+ function sha256Hex(data) {
12
+ var buffer
13
+ if (typeof data === 'string') {
14
+ buffer = Buffer.from(data, 'utf8')
15
+ } else if (Buffer.isBuffer(data)) {
16
+ buffer = data
17
+ } else if (data instanceof Uint8Array) {
18
+ buffer = Buffer.from(data)
19
+ } else {
20
+ throw new Error('Data must be string, Buffer, or Uint8Array')
21
+ }
22
+
23
+ return crypto.createHash('sha256').update(buffer).digest('hex')
24
+ }
25
+
26
+ // Build anchor payload for OP_RETURN
27
+ function buildAnchorPayload(params) {
28
+ if (!params.kind || !params.hash || !params.issuerDid) {
29
+ throw new Error('kind, hash, and issuerDid are required')
30
+ }
31
+
32
+ var validKinds = ['VC_ANCHOR_SHA256', 'STATUSLIST_SHA256', 'PRESENTATION_SHA256']
33
+ if (validKinds.indexOf(params.kind) === -1) {
34
+ throw new Error('Invalid kind. Must be one of: ' + validKinds.join(', '))
35
+ }
36
+
37
+ // Validate hash format (64 hex characters)
38
+ if (!/^[a-fA-F0-9]{64}$/.test(params.hash)) {
39
+ throw new Error('Invalid hash format. Must be 64 hex characters')
40
+ }
41
+
42
+ var payload = {
43
+ protocol: 'SmartLedger',
44
+ version: '1.0',
45
+ type: params.kind,
46
+ hash: params.hash,
47
+ issuer: params.issuerDid,
48
+ timestamp: params.issuedAt || new Date().toISOString()
49
+ }
50
+
51
+ return {
52
+ json: JSON.stringify(payload)
53
+ }
54
+ }
55
+
56
+ // Verify anchor hash against original data
57
+ function verifyAnchorHash(originalData, anchorHash) {
58
+ var computed = sha256Hex(originalData)
59
+ return computed === anchorHash
60
+ }
61
+
62
+ // Extract anchor info from OP_RETURN data
63
+ function parseAnchorPayload(opReturnData) {
64
+ try {
65
+ var parsed = JSON.parse(opReturnData)
66
+
67
+ if (parsed.protocol !== 'SmartLedger') {
68
+ return { valid: false, error: 'Invalid protocol' }
69
+ }
70
+
71
+ var validTypes = ['VC_ANCHOR_SHA256', 'STATUSLIST_SHA256', 'PRESENTATION_SHA256']
72
+ if (validTypes.indexOf(parsed.type) === -1) {
73
+ return { valid: false, error: 'Invalid anchor type' }
74
+ }
75
+
76
+ if (!/^[a-fA-F0-9]{64}$/.test(parsed.hash)) {
77
+ return { valid: false, error: 'Invalid hash format' }
78
+ }
79
+
80
+ return {
81
+ valid: true,
82
+ protocol: parsed.protocol,
83
+ version: parsed.version,
84
+ type: parsed.type,
85
+ hash: parsed.hash,
86
+ issuer: parsed.issuer,
87
+ timestamp: parsed.timestamp
88
+ }
89
+ } catch (error) {
90
+ return {
91
+ valid: false,
92
+ error: 'Failed to parse anchor payload: ' + error.message
93
+ }
94
+ }
95
+ }
96
+
97
+ module.exports = {
98
+ sha256Hex: sha256Hex,
99
+ buildAnchorPayload: buildAnchorPayload,
100
+ verifyAnchorHash: verifyAnchorHash,
101
+ parseAnchorPayload: parseAnchorPayload
102
+ }
@@ -5,6 +5,13 @@
5
5
  * Lightweight UTXO management for browser environments with configurable storage
6
6
  */
7
7
 
8
+ // Set window.BSV_DEBUG = true (browser) or BSV_DEBUG=1 (Node) to enable info logs.
9
+ var debug = function () {
10
+ var enabled = (typeof process !== 'undefined' && process.env && process.env.BSV_DEBUG) ||
11
+ (typeof window !== 'undefined' && window.BSV_DEBUG)
12
+ if (enabled) console.log.apply(console, arguments)
13
+ }
14
+
8
15
  var STORAGE_TYPES = {
9
16
  MEMORY: 'memory',
10
17
  SESSION: 'session',
@@ -75,7 +82,7 @@ BrowserUTXOManager.prototype.loadFromStorage = function() {
75
82
  this.metadata = parsed.metadata
76
83
  }
77
84
 
78
- console.log('✅ BrowserUTXOManager: Loaded ' + this.utxos.size + ' UTXOs from ' + this.options.storage + ' storage')
85
+ debug('✅ BrowserUTXOManager: Loaded ' + this.utxos.size + ' UTXOs from ' + this.options.storage + ' storage')
79
86
  } catch (e) {
80
87
  console.error('Failed to load UTXOs from storage:', e)
81
88
  }
@@ -96,7 +103,7 @@ BrowserUTXOManager.prototype.saveToStorage = function() {
96
103
  }
97
104
 
98
105
  storage.setItem(this.options.storageKey, JSON.stringify(data))
99
- console.log('💾 BrowserUTXOManager: Saved ' + this.utxos.size + ' UTXOs to ' + this.options.storage + ' storage')
106
+ debug('💾 BrowserUTXOManager: Saved ' + this.utxos.size + ' UTXOs to ' + this.options.storage + ' storage')
100
107
  } catch (e) {
101
108
  console.error('Failed to save UTXOs to storage:', e)
102
109
  }
@@ -110,7 +117,7 @@ BrowserUTXOManager.prototype.addUTXO = function(utxo) {
110
117
  var key = utxo.txid + ':' + utxo.vout
111
118
 
112
119
  if (this.utxos.has(key)) {
113
- console.log('⚠️ UTXO already exists: ' + key)
120
+ debug('⚠️ UTXO already exists: ' + key)
114
121
  return false
115
122
  }
116
123
 
@@ -298,7 +305,7 @@ BrowserUTXOManager.prototype.importData = function(jsonData, merge) {
298
305
  })
299
306
  }
300
307
 
301
- console.log('✅ BrowserUTXOManager: Imported ' + (data.utxos && data.utxos.length || 0) + ' UTXOs')
308
+ debug('✅ BrowserUTXOManager: Imported ' + (data.utxos && data.utxos.length || 0) + ' UTXOs')
302
309
  return true
303
310
  } catch (e) {
304
311
  console.error('Failed to import UTXO data:', e)
@@ -5,6 +5,13 @@
5
5
  * Lightweight UTXO management for browser environments with configurable storage
6
6
  */
7
7
 
8
+ // Set window.BSV_DEBUG = true (browser) or BSV_DEBUG=1 (Node) to enable info logs.
9
+ var debug = function () {
10
+ var enabled = (typeof process !== 'undefined' && process.env && process.env.BSV_DEBUG) ||
11
+ (typeof window !== 'undefined' && window.BSV_DEBUG)
12
+ if (enabled) console.log.apply(console, arguments)
13
+ }
14
+
8
15
  /**
9
16
  * Storage types available for browser UTXO management
10
17
  */
@@ -127,7 +134,7 @@ function BrowserUTXOManager(options) {
127
134
  }
128
135
 
129
136
  this._updateMetadata()
130
- console.log(`✅ BrowserUTXOManager: Loaded ${this.utxos.size} UTXOs from ${this.options.storage} storage`)
137
+ debug(`✅ BrowserUTXOManager: Loaded ${this.utxos.size} UTXOs from ${this.options.storage} storage`)
131
138
 
132
139
  } catch (error) {
133
140
  console.error('BrowserUTXOManager: Error loading from storage:', error.message)
@@ -163,7 +170,7 @@ function BrowserUTXOManager(options) {
163
170
  })
164
171
 
165
172
  storage.setItem(this.options.storageKey, JSON.stringify(data))
166
- console.log(`💾 BrowserUTXOManager: Saved ${this.utxos.size} UTXOs to ${this.options.storage} storage`)
173
+ debug(`💾 BrowserUTXOManager: Saved ${this.utxos.size} UTXOs to ${this.options.storage} storage`)
167
174
 
168
175
  } catch (error) {
169
176
  console.error('BrowserUTXOManager: Error saving to storage:', error.message)
@@ -186,7 +193,7 @@ function BrowserUTXOManager(options) {
186
193
 
187
194
  // Check if already exists
188
195
  if (this.utxos.has(key)) {
189
- console.log(`⚠️ UTXO already exists: ${key}`)
196
+ debug(`⚠️ UTXO already exists: ${key}`)
190
197
  return false
191
198
  }
192
199
 
@@ -217,7 +224,7 @@ function BrowserUTXOManager(options) {
217
224
  this.saveToStorage()
218
225
  }
219
226
 
220
- console.log(`✅ UTXO added: ${key} (${utxo.satoshis} sats)`)
227
+ debug(`✅ UTXO added: ${key} (${utxo.satoshis} sats)`)
221
228
  return true
222
229
 
223
230
  } catch (error) {
@@ -305,7 +312,7 @@ function BrowserUTXOManager(options) {
305
312
  }
306
313
  }
307
314
 
308
- console.log(`❌ UTXO spent: ${key} in ${spentUTXO.spentInTx}`)
315
+ debug(`❌ UTXO spent: ${key} in ${spentUTXO.spentInTx}`)
309
316
  })
310
317
 
311
318
  this._updateMetadata()
@@ -446,11 +453,11 @@ function BrowserUTXOManager(options) {
446
453
  const storage = this._getStorage()
447
454
  if (storage) {
448
455
  storage.removeItem(this.options.storageKey)
449
- console.log(`🔄 Cleared ${this.options.storage} storage`)
456
+ debug(`🔄 Cleared ${this.options.storage} storage`)
450
457
  }
451
458
  }
452
459
 
453
- console.log('🔄 BrowserUTXOManager reset complete')
460
+ debug('🔄 BrowserUTXOManager reset complete')
454
461
  }
455
462
 
456
463
  /**
@@ -513,7 +520,7 @@ function BrowserUTXOManager(options) {
513
520
  this.saveToStorage()
514
521
  }
515
522
 
516
- console.log('✅ BrowserUTXOManager: Imported ' + (data.utxos && data.utxos.length || 0) + ' UTXOs')
523
+ debug('✅ BrowserUTXOManager: Imported ' + (data.utxos && data.utxos.length || 0) + ' UTXOs')
517
524
  return true
518
525
 
519
526
  } catch (error) {
@@ -0,0 +1,177 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * DID:web Module
5
+ * Legally-recognizable DID (did:web) generation and management
6
+ * Supports ES256 (P-256) and ES256K (secp256k1) keys
7
+ */
8
+
9
+ var crypto = require('crypto')
10
+
11
+ // Generate issuer keys (ES256 or ES256K)
12
+ async function generateIssuerKeys(opts) {
13
+ opts = opts || {}
14
+ var alg = opts.alg || 'ES256'
15
+ var kid = opts.kid || 'key-' + Date.now()
16
+
17
+ if (alg !== 'ES256' && alg !== 'ES256K') {
18
+ throw new Error('Invalid algorithm. Must be ES256 or ES256K')
19
+ }
20
+
21
+ var keyPair
22
+ if (alg === 'ES256') {
23
+ // P-256 (NIST curve)
24
+ keyPair = crypto.generateKeyPairSync('ec', {
25
+ namedCurve: 'P-256',
26
+ publicKeyEncoding: { type: 'spki', format: 'pem' },
27
+ privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
28
+ })
29
+ } else {
30
+ // secp256k1
31
+ keyPair = crypto.generateKeyPairSync('ec', {
32
+ namedCurve: 'secp256k1',
33
+ publicKeyEncoding: { type: 'spki', format: 'pem' },
34
+ privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
35
+ })
36
+ }
37
+
38
+ // Convert to JWK format
39
+ var publicJwk = crypto.createPublicKey(keyPair.publicKey).export({ format: 'jwk' })
40
+ var privateJwk = crypto.createPrivateKey(keyPair.privateKey).export({ format: 'jwk' })
41
+
42
+ // Add required JWK fields
43
+ publicJwk.kid = kid
44
+ publicJwk.alg = alg
45
+ publicJwk.use = 'sig'
46
+ publicJwk.kty = 'EC'
47
+
48
+ privateJwk.kid = kid
49
+ privateJwk.alg = alg
50
+ privateJwk.use = 'sig'
51
+ privateJwk.kty = 'EC'
52
+
53
+ return {
54
+ privateJwk: privateJwk,
55
+ publicJwk: publicJwk,
56
+ kid: kid,
57
+ alg: alg
58
+ }
59
+ }
60
+
61
+ // Build did:web documents (did.json and jwks.json)
62
+ function buildDidWebDocuments(params) {
63
+ if (!params.domain) {
64
+ throw new Error('domain is required')
65
+ }
66
+
67
+ var domain = params.domain
68
+ var did = 'did:web:' + domain.replace(/:/g, '%3A')
69
+
70
+ var verificationMethods = []
71
+ var publicKeys = []
72
+
73
+ // Add P-256 key if provided
74
+ if (params.p256) {
75
+ var p256Method = {
76
+ id: did + '#' + params.p256.kid,
77
+ type: 'JsonWebKey2020',
78
+ controller: did,
79
+ publicKeyJwk: params.p256.jwk
80
+ }
81
+ verificationMethods.push(p256Method)
82
+ publicKeys.push(params.p256.jwk)
83
+ }
84
+
85
+ // Add secp256k1 key if provided
86
+ if (params.k1) {
87
+ var k1Method = {
88
+ id: did + '#' + params.k1.kid,
89
+ type: 'JsonWebKey2020',
90
+ controller: did,
91
+ publicKeyJwk: params.k1.jwk
92
+ }
93
+ verificationMethods.push(k1Method)
94
+ publicKeys.push(params.k1.jwk)
95
+ }
96
+
97
+ if (verificationMethods.length === 0) {
98
+ throw new Error('At least one key (p256 or k1) must be provided')
99
+ }
100
+
101
+ // Build DID Document
102
+ var didDocument = {
103
+ '@context': [
104
+ 'https://www.w3.org/ns/did/v1',
105
+ 'https://w3id.org/security/suites/jws-2020/v1'
106
+ ],
107
+ id: did,
108
+ verificationMethod: verificationMethods,
109
+ authentication: verificationMethods.map(function(vm) { return vm.id }),
110
+ assertionMethod: verificationMethods.map(function(vm) { return vm.id })
111
+ }
112
+
113
+ if (params.controllerName) {
114
+ didDocument.controller = params.controllerName
115
+ }
116
+
117
+ // Build JWKS
118
+ var jwks = {
119
+ keys: publicKeys
120
+ }
121
+
122
+ return {
123
+ did: did,
124
+ didDocument: didDocument,
125
+ jwks: jwks
126
+ }
127
+ }
128
+
129
+ // Rotate issuer key
130
+ function rotateIssuerKey(params) {
131
+ if (!params.domain || !params.newKey) {
132
+ throw new Error('domain and newKey are required')
133
+ }
134
+
135
+ var domain = params.domain
136
+ var did = 'did:web:' + domain.replace(/:/g, '%3A')
137
+ var keepOldForDays = params.keepOldForDays || 30
138
+
139
+ // Create verification method for new key
140
+ var newMethod = {
141
+ id: did + '#' + params.newKey.kid,
142
+ type: 'JsonWebKey2020',
143
+ controller: did,
144
+ publicKeyJwk: params.newKey.jwk
145
+ }
146
+
147
+ // Build updated DID Document with new key as primary
148
+ var didDocument = {
149
+ '@context': [
150
+ 'https://www.w3.org/ns/did/v1',
151
+ 'https://w3id.org/security/suites/jws-2020/v1'
152
+ ],
153
+ id: did,
154
+ verificationMethod: [newMethod],
155
+ authentication: [newMethod.id],
156
+ assertionMethod: [newMethod.id],
157
+ rotationInfo: {
158
+ rotatedAt: new Date().toISOString(),
159
+ gracePeriodDays: keepOldForDays
160
+ }
161
+ }
162
+
163
+ var jwks = {
164
+ keys: [params.newKey.jwk]
165
+ }
166
+
167
+ return {
168
+ didDocument: didDocument,
169
+ jwks: jwks
170
+ }
171
+ }
172
+
173
+ module.exports = {
174
+ generateIssuerKeys: generateIssuerKeys,
175
+ buildDidWebDocuments: buildDidWebDocuments,
176
+ rotateIssuerKey: rotateIssuerKey
177
+ }
package/lib/ltp/claim.js CHANGED
@@ -691,6 +691,7 @@ var ClaimValidator = {
691
691
  * @private
692
692
  */
693
693
  _generateBatchId: function() {
694
+ // Non-security: identifier collision avoidance only
694
695
  var data = 'batch_' + Date.now() + '_' + Math.random()
695
696
  return Hash.sha256(Buffer.from(data)).toString('hex').substring(0, 16)
696
697
  },
@@ -929,6 +929,7 @@ var ObligationToken = {
929
929
  * @private
930
930
  */
931
931
  _generateUUID: function() {
932
+ // Non-security: identifier collision avoidance only (not RFC 4122 v4 random)
932
933
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
933
934
  var r = Math.random() * 16 | 0
934
935
  var v = c === 'x' ? r : (r & 0x3 | 0x8)
@@ -552,6 +552,7 @@ var LTPRegistry = {
552
552
  * @private
553
553
  */
554
554
  _generateRegistryId: function() {
555
+ // Non-security: identifier collision avoidance only
555
556
  var data = 'reg_' + Date.now() + '_' + Math.random()
556
557
  return 'reg_' + Hash.sha256(Buffer.from(data)).toString('hex').substring(0, 16)
557
558
  },
@@ -685,6 +686,7 @@ var LTPRegistry = {
685
686
  * @private
686
687
  */
687
688
  _generateAuditId: function() {
689
+ // Non-security: identifier collision avoidance only
688
690
  var data = 'audit_' + Date.now() + '_' + Math.random()
689
691
  return 'audit_' + Hash.sha256(Buffer.from(data)).toString('hex').substring(0, 12)
690
692
  },
package/lib/ltp/right.js CHANGED
@@ -752,6 +752,7 @@ var RightToken = {
752
752
  * @private
753
753
  */
754
754
  _generateUUID: function() {
755
+ // Non-security: identifier collision avoidance only (not RFC 4122 v4 random)
755
756
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
756
757
  var r = Math.random() * 16 | 0
757
758
  var v = c === 'x' ? r : (r & 0x3 | 0x8)
@@ -26,6 +26,15 @@ try {
26
26
  fs = null
27
27
  }
28
28
 
29
+ // Set BSV_DEBUG=1 (Node) or window.BSV_DEBUG = true (browser) to surface
30
+ // informational warnings from this module. Matches the gating pattern
31
+ // used by lib/browser-utxo-manager-es5.js since v3.4.1.
32
+ var debug = function () {
33
+ var enabled = (typeof process !== 'undefined' && process.env && process.env.BSV_DEBUG) ||
34
+ (typeof window !== 'undefined' && window.BSV_DEBUG)
35
+ if (enabled) console.log.apply(console, arguments)
36
+ }
37
+
29
38
  /**
30
39
  * Covenant Class - Advanced covenant management
31
40
  * @param {PrivateKey} privateKey - Private key for covenant operations
@@ -212,7 +221,7 @@ Covenant.prototype.validate = function(spendingTx, covenantUtxo) {
212
221
  */
213
222
  Covenant.prototype.save = function(covenantUtxo) {
214
223
  if (!fs) {
215
- console.warn('File system operations not available in browser environment')
224
+ debug('File system operations not available in browser environment')
216
225
  return covenantUtxo
217
226
  }
218
227
 
package/lib/smartutxo.js CHANGED
@@ -5,6 +5,15 @@
5
5
  * Provides blockchain state management and UTXO tracking for testing and development
6
6
  */
7
7
 
8
+ // Set BSV_DEBUG=1 (Node) or window.BSV_DEBUG = true (browser) to surface
9
+ // info/warning output from this module. Matches the gating pattern used
10
+ // by lib/browser-utxo-manager-es5.js since v3.4.1.
11
+ const debug = function () {
12
+ const enabled = (typeof process !== 'undefined' && process.env && process.env.BSV_DEBUG) ||
13
+ (typeof window !== 'undefined' && window.BSV_DEBUG)
14
+ if (enabled) console.log.apply(console, arguments)
15
+ }
16
+
8
17
  // Browser-compatible imports
9
18
  let fs, path, crypto, blockchainState
10
19
 
@@ -16,8 +25,7 @@ if (typeof window === 'undefined' && typeof require === 'function') {
16
25
  crypto = require('crypto')
17
26
  blockchainState = require('../utilities/blockchain-state')
18
27
  } catch (e) {
19
- // Fallback for environments where these modules aren't available
20
- console.warn('SmartUTXO: Running in browser mode - some features may be limited')
28
+ debug('SmartUTXO: Running in browser mode - some features may be limited')
21
29
  }
22
30
  }
23
31
 
@@ -40,7 +48,7 @@ class SmartUTXOManager {
40
48
  const state = blockchainState.loadBlockchainState()
41
49
  return state
42
50
  } catch (error) {
43
- console.log('⚠️ Could not load blockchain state:', error.message)
51
+ debug('⚠️ Could not load blockchain state:', error.message)
44
52
  return null
45
53
  }
46
54
  }
@@ -53,9 +61,9 @@ class SmartUTXOManager {
53
61
  const state = blockchainState.loadBlockchainState()
54
62
  blockchainState.saveBlockchainState(state)
55
63
  const utxoCount = Object.keys(state.globalUTXOSet || {}).length
56
- console.log(`💾 Saved blockchain state with ${utxoCount} UTXOs`)
64
+ debug(`💾 Saved blockchain state with ${utxoCount} UTXOs`)
57
65
  } catch (error) {
58
- console.log('⚠️ Could not save blockchain state:', error.message)
66
+ debug('⚠️ Could not save blockchain state:', error.message)
59
67
  }
60
68
  }
61
69
 
@@ -76,7 +84,7 @@ class SmartUTXOManager {
76
84
  // Return the wallet's UTXOs
77
85
  return state.wallets[address].utxos || []
78
86
  } catch (error) {
79
- console.log('⚠️ Error getting UTXOs:', error.message)
87
+ debug('⚠️ Error getting UTXOs:', error.message)
80
88
  return []
81
89
  }
82
90
  }
@@ -90,7 +98,7 @@ class SmartUTXOManager {
90
98
  // Use the correct API: addUTXO(utxo, ownerAddress)
91
99
  blockchainState.addUTXO(utxo, utxo.address)
92
100
  } catch (error) {
93
- console.log('⚠️ Error adding UTXO:', error.message)
101
+ debug('⚠️ Error adding UTXO:', error.message)
94
102
  }
95
103
  }
96
104
 
@@ -106,7 +114,7 @@ class SmartUTXOManager {
106
114
  blockchainState.spendUTXO(input.txid, input.vout, spentInTx)
107
115
  }
108
116
  } catch (error) {
109
- console.log('⚠️ Error spending UTXOs:', error.message)
117
+ debug('⚠️ Error spending UTXOs:', error.message)
110
118
  }
111
119
  }
112
120
 
@@ -156,7 +164,7 @@ class SmartUTXOManager {
156
164
  // Return the wallet's total value
157
165
  return state.wallets[address].totalValue || 0
158
166
  } catch (error) {
159
- console.log('⚠️ Error getting balance:', error.message)
167
+ debug('⚠️ Error getting balance:', error.message)
160
168
  return 0
161
169
  }
162
170
  }
@@ -176,7 +184,7 @@ class SmartUTXOManager {
176
184
  lastUpdated: state.metadata.lastUpdated
177
185
  }
178
186
  } catch (error) {
179
- console.log('⚠️ Error getting stats:', error.message)
187
+ debug('⚠️ Error getting stats:', error.message)
180
188
  return { totalUTXOs: 0, totalValue: 0, totalWallets: 0, blockHeight: 0 }
181
189
  }
182
190
  }
@@ -189,10 +197,10 @@ class SmartUTXOManager {
189
197
  const statePath = path.join(__dirname, '../utilities/blockchain-state.json')
190
198
  if (fs.existsSync(statePath)) {
191
199
  fs.unlinkSync(statePath)
192
- console.log('🔄 Blockchain state reset')
200
+ debug('🔄 Blockchain state reset')
193
201
  }
194
202
  } catch (error) {
195
- console.log('⚠️ Could not reset blockchain state:', error.message)
203
+ debug('⚠️ Could not reset blockchain state:', error.message)
196
204
  }
197
205
  }
198
206
  }