smartledger-bsv 3.2.1 → 3.3.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 (70) hide show
  1. package/CHANGELOG.md +147 -0
  2. package/README.md +289 -55
  3. package/architecture_demo.js +247 -0
  4. package/bsv-covenant.min.js +10 -0
  5. package/bsv-gdaf.min.js +37 -0
  6. package/bsv-ltp.min.js +37 -0
  7. package/bsv-script-helper.min.js +10 -0
  8. package/bsv-security.min.js +31 -0
  9. package/bsv-shamir.min.js +12 -0
  10. package/bsv-smartcontract.min.js +37 -0
  11. package/bsv.bundle.js +9 -9
  12. package/bsv.min.js +3 -3
  13. package/build/bsv-covenant.min.js +10 -0
  14. package/build/bsv-script-helper.min.js +10 -0
  15. package/build/bsv-security.min.js +31 -0
  16. package/build/bsv-smartcontract.min.js +39 -0
  17. package/build/bsv.bundle.js +39 -0
  18. package/build/bsv.min.js +39 -0
  19. package/build/webpack.bundle.config.js +22 -0
  20. package/build/webpack.config.js +18 -0
  21. package/build/webpack.covenant.config.js +27 -0
  22. package/build/webpack.gdaf.config.js +54 -0
  23. package/build/webpack.ltp.config.js +17 -0
  24. package/build/webpack.script-helper.config.js +27 -0
  25. package/build/webpack.security.config.js +23 -0
  26. package/build/webpack.smartcontract.config.js +25 -0
  27. package/build/webpack.subproject.config.js +6 -0
  28. package/bundle-entry.js +341 -0
  29. package/complete_ltp_demo.js +511 -0
  30. package/covenant-entry.js +44 -0
  31. package/docs/pushtx-key-insights.md +106 -0
  32. package/gdaf-entry.js +54 -0
  33. package/index.js +272 -5
  34. package/lib/crypto/shamir.js +360 -0
  35. package/lib/gdaf/attestation-signer.js +461 -0
  36. package/lib/gdaf/attestation-verifier.js +600 -0
  37. package/lib/gdaf/did-resolver.js +382 -0
  38. package/lib/gdaf/index.js +471 -0
  39. package/lib/gdaf/schema-validator.js +682 -0
  40. package/lib/gdaf/smartledger-anchor.js +486 -0
  41. package/lib/gdaf/zk-prover.js +507 -0
  42. package/lib/ltp/anchor.js +438 -0
  43. package/lib/ltp/claim.js +1026 -0
  44. package/lib/ltp/index.js +470 -0
  45. package/lib/ltp/obligation.js +945 -0
  46. package/lib/ltp/proof.js +828 -0
  47. package/lib/ltp/registry.js +702 -0
  48. package/lib/ltp/right.js +765 -0
  49. package/lib/smart_contract/API_REFERENCE.md +1 -1
  50. package/lib/smart_contract/EXAMPLES.md +2 -2
  51. package/lib/smart_contract/QUICK_START.md +2 -2
  52. package/lib/smart_contract/README.md +1 -1
  53. package/lib/smart_contract/index.js +4 -0
  54. package/ltp-entry.js +92 -0
  55. package/package.json +91 -20
  56. package/script-helper-entry.js +49 -0
  57. package/security-entry.js +70 -0
  58. package/shamir-entry.js +173 -0
  59. package/shamir_demo.js +121 -0
  60. package/simple_demo.js +204 -0
  61. package/smartcontract-entry.js +133 -0
  62. package/test_shamir.js +221 -0
  63. package/test_standalone_shamir.html +83 -0
  64. package/tests/bundle-completeness-test.html +131 -0
  65. package/tests/bundle-demo.html +476 -0
  66. package/tests/smartcontract-test.html +239 -0
  67. package/tests/standalone-modules-test.html +260 -0
  68. package/tests/test.html +612 -0
  69. package/tests/unpkg-demo.html +194 -0
  70. package/docs/nchain.md +0 -958
@@ -0,0 +1,702 @@
1
+ 'use strict'
2
+
3
+ var bsv = require('../../')
4
+ var Hash = bsv.crypto.Hash
5
+ var Address = bsv.Address
6
+ var Transaction = bsv.Transaction
7
+ var $ = bsv.util.preconditions
8
+
9
+ /**
10
+ * Legal Token Protocol - Registry Primitives
11
+ *
12
+ * Provides primitives for token registry management, revocation processing,
13
+ * and discovery mechanisms without direct blockchain publishing.
14
+ * External systems handle actual registry storage and blockchain anchoring.
15
+ */
16
+
17
+ var LTPRegistry = {
18
+
19
+ /**
20
+ * Prepare registry data structure for external storage
21
+ * @param {Object} config - Registry configuration
22
+ * @returns {Object} Prepared registry data
23
+ */
24
+ prepareRegistry: function(config) {
25
+ config = config || {}
26
+
27
+ $.checkArgument(typeof config === 'object', 'Config must be object')
28
+
29
+ var registry = {
30
+ id: config.id || this._generateRegistryId(),
31
+ name: config.name || 'Legal Token Registry',
32
+ jurisdiction: config.jurisdiction || 'GLOBAL',
33
+ authority: config.authority || null,
34
+ created: new Date().toISOString(),
35
+ version: '1.0.0',
36
+
37
+ // Registry configuration
38
+ config: {
39
+ allowPublicRegistration: config.allowPublicRegistration || false,
40
+ requireApproval: config.requireApproval || true,
41
+ enableRevocation: config.enableRevocation !== false,
42
+ enableAuditTrail: config.enableAuditTrail !== false,
43
+ retentionPeriod: config.retentionPeriod || '7Y', // 7 years
44
+ complianceLevel: config.complianceLevel || 'STANDARD'
45
+ },
46
+
47
+ // Data structure templates
48
+ dataStructure: {
49
+ tokens: 'Map<tokenId, registrationRecord>',
50
+ revocations: 'Map<tokenId, revocationRecord>',
51
+ auditLog: 'Array<auditEntry>',
52
+ statistics: {
53
+ totalTokens: 0,
54
+ activeTokens: 0,
55
+ revokedTokens: 0,
56
+ registrations: 0
57
+ }
58
+ },
59
+
60
+ // External integration points
61
+ externalStorage: {
62
+ required: true,
63
+ type: 'database_or_blockchain',
64
+ endpoints: {
65
+ store: 'POST /registry/{id}/tokens',
66
+ retrieve: 'GET /registry/{id}/tokens/{tokenId}',
67
+ search: 'GET /registry/{id}/search',
68
+ revoke: 'POST /registry/{id}/revocations'
69
+ }
70
+ }
71
+ }
72
+
73
+ // Add initial audit entry template
74
+ var initialAudit = this._prepareAuditEntry({
75
+ action: 'REGISTRY_CREATED',
76
+ actor: config.authority,
77
+ timestamp: registry.created,
78
+ metadata: {
79
+ jurisdiction: registry.jurisdiction,
80
+ config: registry.config
81
+ }
82
+ })
83
+
84
+ return {
85
+ success: true,
86
+ registry: registry,
87
+ initialAudit: initialAudit,
88
+ instructions: {
89
+ step1: 'Store registry configuration in external system',
90
+ step2: 'Initialize token storage with provided data structure',
91
+ step3: 'Set up audit logging with provided templates',
92
+ step4: 'Configure external endpoints for registry operations'
93
+ }
94
+ }
95
+ },
96
+
97
+ /**
98
+ * Prepare token registration data for external registry
99
+ * @param {Object} token - Token to register
100
+ * @param {Object} registryConfig - Registry configuration
101
+ * @param {Object} options - Registration options
102
+ * @returns {Object} Prepared registration data
103
+ */
104
+ prepareTokenRegistration: function(token, registryConfig, options) {
105
+ options = options || {}
106
+
107
+ $.checkArgument(token && typeof token === 'object', 'Invalid token')
108
+ $.checkArgument(registryConfig && typeof registryConfig === 'object', 'Invalid registry config')
109
+
110
+ try {
111
+ // Validate token
112
+ var validation = this._validateTokenForRegistration(token, registryConfig)
113
+ if (!validation.valid) {
114
+ return {
115
+ success: false,
116
+ error: 'Token validation failed: ' + validation.error
117
+ }
118
+ }
119
+
120
+ // Create registration record template
121
+ var registrationRecord = {
122
+ tokenId: token.id,
123
+ tokenHash: this._hashToken(token),
124
+ token: token,
125
+ status: registryConfig.requireApproval ? 'PENDING' : 'ACTIVE',
126
+ registeredBy: options.registeredBy || 'UNKNOWN',
127
+ registeredAt: new Date().toISOString(),
128
+ approvedBy: null,
129
+ approvedAt: null,
130
+ metadata: options.metadata || {},
131
+ compliance: {
132
+ jurisdiction: token.jurisdiction || registryConfig.jurisdiction,
133
+ level: this._calculateComplianceLevel(token),
134
+ checks: validation.checks || []
135
+ }
136
+ }
137
+
138
+ // Prepare audit entry
139
+ var auditEntry = this._prepareAuditEntry({
140
+ action: 'TOKEN_REGISTERED',
141
+ actor: options.registeredBy,
142
+ tokenId: token.id,
143
+ timestamp: registrationRecord.registeredAt,
144
+ metadata: {
145
+ status: registrationRecord.status,
146
+ tokenType: token.type,
147
+ compliance: registrationRecord.compliance
148
+ }
149
+ })
150
+
151
+ return {
152
+ success: true,
153
+ registrationRecord: registrationRecord,
154
+ auditEntry: auditEntry,
155
+ registrationId: this._generateRegistrationId(token.id),
156
+ validation: validation,
157
+ externalOperations: {
158
+ store: {
159
+ endpoint: 'POST /registry/' + registryConfig.id + '/tokens',
160
+ data: registrationRecord
161
+ },
162
+ audit: {
163
+ endpoint: 'POST /registry/' + registryConfig.id + '/audit',
164
+ data: auditEntry
165
+ }
166
+ }
167
+ }
168
+
169
+ } catch (error) {
170
+ return {
171
+ success: false,
172
+ error: error.message
173
+ }
174
+ }
175
+ },
176
+
177
+ /**
178
+ * Prepare token approval data for external registry
179
+ * @param {String} tokenId - Token ID to approve
180
+ * @param {String} approver - Approver identity
181
+ * @param {Object} registryConfig - Registry configuration
182
+ * @returns {Object} Prepared approval data
183
+ */
184
+ prepareTokenApproval: function(tokenId, approver, registryConfig) {
185
+ try {
186
+ $.checkArgument(typeof tokenId === 'string', 'Token ID must be string')
187
+ $.checkArgument(typeof approver === 'string', 'Approver must be string')
188
+ $.checkArgument(registryConfig && typeof registryConfig === 'object', 'Invalid registry config')
189
+
190
+ var approvalData = {
191
+ tokenId: tokenId,
192
+ status: 'ACTIVE',
193
+ approvedBy: approver,
194
+ approvedAt: new Date().toISOString()
195
+ }
196
+
197
+ // Prepare audit entry
198
+ var auditEntry = this._prepareAuditEntry({
199
+ action: 'TOKEN_APPROVED',
200
+ actor: approver,
201
+ tokenId: tokenId,
202
+ timestamp: approvalData.approvedAt
203
+ })
204
+
205
+ return {
206
+ success: true,
207
+ approvalData: approvalData,
208
+ auditEntry: auditEntry,
209
+ externalOperations: {
210
+ update: {
211
+ endpoint: 'PUT /registry/' + registryConfig.id + '/tokens/' + tokenId + '/status',
212
+ data: approvalData
213
+ },
214
+ audit: {
215
+ endpoint: 'POST /registry/' + registryConfig.id + '/audit',
216
+ data: auditEntry
217
+ }
218
+ }
219
+ }
220
+
221
+ } catch (error) {
222
+ return {
223
+ success: false,
224
+ error: error.message
225
+ }
226
+ }
227
+ },
228
+
229
+ /**
230
+ * Prepare token revocation data for external registry
231
+ * @param {String} tokenId - Token ID to revoke
232
+ * @param {Object} revocation - Revocation details
233
+ * @param {Object} registryConfig - Registry configuration
234
+ * @returns {Object} Prepared revocation data
235
+ */
236
+ prepareTokenRevocation: function(tokenId, revocation, registryConfig) {
237
+ try {
238
+ $.checkArgument(typeof tokenId === 'string', 'Token ID must be string')
239
+ $.checkArgument(revocation && typeof revocation === 'object', 'Invalid revocation')
240
+ $.checkArgument(registryConfig && typeof registryConfig === 'object', 'Invalid registry config')
241
+
242
+ if (!registryConfig.enableRevocation) {
243
+ return {
244
+ success: false,
245
+ error: 'Revocation is disabled for this registry'
246
+ }
247
+ }
248
+
249
+ // Create revocation record
250
+ var revocationRecord = {
251
+ tokenId: tokenId,
252
+ reason: revocation.reason || 'UNSPECIFIED',
253
+ revokedBy: revocation.revokedBy || 'UNKNOWN',
254
+ revokedAt: new Date().toISOString(),
255
+ effectiveDate: revocation.effectiveDate || new Date().toISOString(),
256
+ legalBasis: revocation.legalBasis || null,
257
+ evidence: revocation.evidence || null,
258
+ revocationHash: this._generateRevocationHash(tokenId, revocation)
259
+ }
260
+
261
+ // Prepare token status update
262
+ var statusUpdate = {
263
+ tokenId: tokenId,
264
+ status: 'REVOKED',
265
+ revokedAt: revocationRecord.revokedAt,
266
+ revocationReason: revocationRecord.reason
267
+ }
268
+
269
+ // Prepare audit entry
270
+ var auditEntry = this._prepareAuditEntry({
271
+ action: 'TOKEN_REVOKED',
272
+ actor: revocation.revokedBy,
273
+ tokenId: tokenId,
274
+ timestamp: revocationRecord.revokedAt,
275
+ metadata: {
276
+ reason: revocationRecord.reason,
277
+ legalBasis: revocationRecord.legalBasis
278
+ }
279
+ })
280
+
281
+ return {
282
+ success: true,
283
+ revocationRecord: revocationRecord,
284
+ statusUpdate: statusUpdate,
285
+ auditEntry: auditEntry,
286
+ revocationId: this._generateRevocationId(tokenId),
287
+ externalOperations: {
288
+ storeRevocation: {
289
+ endpoint: 'POST /registry/' + registryConfig.id + '/revocations',
290
+ data: revocationRecord
291
+ },
292
+ updateStatus: {
293
+ endpoint: 'PUT /registry/' + registryConfig.id + '/tokens/' + tokenId + '/status',
294
+ data: statusUpdate
295
+ },
296
+ audit: {
297
+ endpoint: 'POST /registry/' + registryConfig.id + '/audit',
298
+ data: auditEntry
299
+ }
300
+ }
301
+ }
302
+
303
+ } catch (error) {
304
+ return {
305
+ success: false,
306
+ error: error.message
307
+ }
308
+ }
309
+ },
310
+
311
+ /**
312
+ * Prepare token status query for external registry
313
+ * @param {String} tokenId - Token ID to check
314
+ * @param {Object} registryConfig - Registry configuration
315
+ * @returns {Object} Prepared status query
316
+ */
317
+ prepareTokenStatusQuery: function(tokenId, registryConfig) {
318
+ try {
319
+ $.checkArgument(typeof tokenId === 'string', 'Token ID must be string')
320
+ $.checkArgument(registryConfig && typeof registryConfig === 'object', 'Invalid registry config')
321
+
322
+ return {
323
+ success: true,
324
+ query: {
325
+ tokenId: tokenId,
326
+ registryId: registryConfig.id
327
+ },
328
+ externalOperations: {
329
+ retrieve: {
330
+ endpoint: 'GET /registry/' + registryConfig.id + '/tokens/' + tokenId,
331
+ method: 'GET'
332
+ },
333
+ checkRevocation: {
334
+ endpoint: 'GET /registry/' + registryConfig.id + '/revocations/' + tokenId,
335
+ method: 'GET'
336
+ }
337
+ },
338
+ expectedResponse: {
339
+ found: 'boolean',
340
+ status: 'string (PENDING|ACTIVE|REVOKED)',
341
+ registeredAt: 'ISO datetime',
342
+ registeredBy: 'string',
343
+ approvedAt: 'ISO datetime or null',
344
+ approvedBy: 'string or null',
345
+ revokedAt: 'ISO datetime or null',
346
+ revocationReason: 'string or null',
347
+ compliance: 'object',
348
+ revocation: 'object or null'
349
+ }
350
+ }
351
+
352
+ } catch (error) {
353
+ return {
354
+ success: false,
355
+ error: error.message
356
+ }
357
+ }
358
+ },
359
+
360
+ /**
361
+ * Prepare token search query for external registry
362
+ * @param {Object} criteria - Search criteria
363
+ * @param {Object} registryConfig - Registry configuration
364
+ * @returns {Object} Prepared search query
365
+ */
366
+ prepareTokenSearch: function(criteria, registryConfig) {
367
+ criteria = criteria || {}
368
+
369
+ try {
370
+ $.checkArgument(registryConfig && typeof registryConfig === 'object', 'Invalid registry config')
371
+
372
+ // Build query parameters
373
+ var queryParams = []
374
+
375
+ if (criteria.status) {
376
+ queryParams.push('status=' + encodeURIComponent(criteria.status))
377
+ }
378
+
379
+ if (criteria.type) {
380
+ queryParams.push('type=' + encodeURIComponent(criteria.type))
381
+ }
382
+
383
+ if (criteria.registeredBy) {
384
+ queryParams.push('registeredBy=' + encodeURIComponent(criteria.registeredBy))
385
+ }
386
+
387
+ if (criteria.jurisdiction) {
388
+ queryParams.push('jurisdiction=' + encodeURIComponent(criteria.jurisdiction))
389
+ }
390
+
391
+ if (criteria.dateFrom) {
392
+ queryParams.push('dateFrom=' + encodeURIComponent(criteria.dateFrom))
393
+ }
394
+
395
+ if (criteria.dateTo) {
396
+ queryParams.push('dateTo=' + encodeURIComponent(criteria.dateTo))
397
+ }
398
+
399
+ if (criteria.includeTokens) {
400
+ queryParams.push('includeTokens=true')
401
+ }
402
+
403
+ if (criteria.sortBy) {
404
+ queryParams.push('sortBy=' + encodeURIComponent(criteria.sortBy))
405
+ }
406
+
407
+ if (criteria.sortOrder) {
408
+ queryParams.push('sortOrder=' + encodeURIComponent(criteria.sortOrder))
409
+ }
410
+
411
+ var offset = criteria.offset || 0
412
+ var limit = criteria.limit || 100
413
+ queryParams.push('offset=' + offset)
414
+ queryParams.push('limit=' + limit)
415
+
416
+ var queryString = queryParams.length > 0 ? '?' + queryParams.join('&') : ''
417
+
418
+ return {
419
+ success: true,
420
+ searchCriteria: criteria,
421
+ externalOperations: {
422
+ search: {
423
+ endpoint: 'GET /registry/' + registryConfig.id + '/search' + queryString,
424
+ method: 'GET'
425
+ }
426
+ },
427
+ expectedResponse: {
428
+ success: 'boolean',
429
+ results: 'Array<tokenRecord>',
430
+ totalCount: 'number',
431
+ totalRegistrations: 'number',
432
+ offset: 'number',
433
+ limit: 'number',
434
+ hasMore: 'boolean'
435
+ }
436
+ }
437
+
438
+ } catch (error) {
439
+ return {
440
+ success: false,
441
+ error: error.message
442
+ }
443
+ }
444
+ },
445
+
446
+ /**
447
+ * Prepare registry statistics query for external registry
448
+ * @param {Object} registryConfig - Registry configuration
449
+ * @returns {Object} Prepared statistics query
450
+ */
451
+ prepareStatisticsQuery: function(registryConfig) {
452
+ $.checkArgument(registryConfig && typeof registryConfig === 'object', 'Invalid registry config')
453
+
454
+ return {
455
+ success: true,
456
+ query: {
457
+ registryId: registryConfig.id
458
+ },
459
+ externalOperations: {
460
+ getStatistics: {
461
+ endpoint: 'GET /registry/' + registryConfig.id + '/statistics',
462
+ method: 'GET'
463
+ }
464
+ },
465
+ expectedResponse: {
466
+ id: 'string',
467
+ name: 'string',
468
+ jurisdiction: 'string',
469
+ created: 'ISO datetime',
470
+ statistics: {
471
+ totalTokens: 'number',
472
+ activeTokens: 'number',
473
+ revokedTokens: 'number',
474
+ registrations: 'number'
475
+ },
476
+ auditEntries: 'number',
477
+ lastActivity: 'ISO datetime'
478
+ }
479
+ }
480
+ },
481
+
482
+ /**
483
+ * Prepare audit log query for external registry
484
+ * @param {Object} registryConfig - Registry configuration
485
+ * @param {Object} options - Log options
486
+ * @returns {Object} Prepared audit log query
487
+ */
488
+ prepareAuditLogQuery: function(registryConfig, options) {
489
+ options = options || {}
490
+
491
+ $.checkArgument(registryConfig && typeof registryConfig === 'object', 'Invalid registry config')
492
+
493
+ if (!registryConfig.enableAuditTrail) {
494
+ return {
495
+ success: false,
496
+ error: 'Audit trail is disabled'
497
+ }
498
+ }
499
+
500
+ // Build query parameters
501
+ var queryParams = []
502
+
503
+ if (options.action) {
504
+ queryParams.push('action=' + encodeURIComponent(options.action))
505
+ }
506
+
507
+ if (options.actor) {
508
+ queryParams.push('actor=' + encodeURIComponent(options.actor))
509
+ }
510
+
511
+ if (options.tokenId) {
512
+ queryParams.push('tokenId=' + encodeURIComponent(options.tokenId))
513
+ }
514
+
515
+ if (options.dateFrom) {
516
+ queryParams.push('dateFrom=' + encodeURIComponent(options.dateFrom))
517
+ }
518
+
519
+ if (options.dateTo) {
520
+ queryParams.push('dateTo=' + encodeURIComponent(options.dateTo))
521
+ }
522
+
523
+ var offset = options.offset || 0
524
+ var limit = options.limit || 100
525
+ queryParams.push('offset=' + offset)
526
+ queryParams.push('limit=' + limit)
527
+
528
+ var queryString = queryParams.length > 0 ? '?' + queryParams.join('&') : ''
529
+
530
+ return {
531
+ success: true,
532
+ auditOptions: options,
533
+ externalOperations: {
534
+ getAuditLog: {
535
+ endpoint: 'GET /registry/' + registryConfig.id + '/audit' + queryString,
536
+ method: 'GET'
537
+ }
538
+ },
539
+ expectedResponse: {
540
+ success: 'boolean',
541
+ entries: 'Array<auditEntry>',
542
+ totalEntries: 'number',
543
+ offset: 'number',
544
+ limit: 'number',
545
+ hasMore: 'boolean'
546
+ }
547
+ }
548
+ },
549
+
550
+ /**
551
+ * Generate registry ID
552
+ * @private
553
+ */
554
+ _generateRegistryId: function() {
555
+ var data = 'reg_' + Date.now() + '_' + Math.random()
556
+ return 'reg_' + Hash.sha256(Buffer.from(data)).toString('hex').substring(0, 16)
557
+ },
558
+
559
+ /**
560
+ * Generate registration ID
561
+ * @private
562
+ */
563
+ _generateRegistrationId: function(tokenId) {
564
+ var data = 'reg_' + tokenId + '_' + Date.now()
565
+ return Hash.sha256(Buffer.from(data)).toString('hex').substring(0, 16)
566
+ },
567
+
568
+ /**
569
+ * Generate revocation ID
570
+ * @private
571
+ */
572
+ _generateRevocationId: function(tokenId) {
573
+ var data = 'rev_' + tokenId + '_' + Date.now()
574
+ return Hash.sha256(Buffer.from(data)).toString('hex').substring(0, 16)
575
+ },
576
+
577
+ /**
578
+ * Hash token for integrity
579
+ * @private
580
+ */
581
+ _hashToken: function(token) {
582
+ // Remove dynamic fields
583
+ var staticToken = JSON.parse(JSON.stringify(token))
584
+ delete staticToken.proof
585
+ delete staticToken.tokenHash
586
+
587
+ return Hash.sha256(Buffer.from(JSON.stringify(staticToken))).toString('hex')
588
+ },
589
+
590
+ /**
591
+ * Generate revocation hash
592
+ * @private
593
+ */
594
+ _generateRevocationHash: function(tokenId, revocation) {
595
+ var data = tokenId + (revocation.reason || '') + (revocation.revokedBy || '') + Date.now()
596
+ return Hash.sha256(Buffer.from(data)).toString('hex')
597
+ },
598
+
599
+ /**
600
+ * Validate token for registration
601
+ * @private
602
+ */
603
+ _validateTokenForRegistration: function(token, registry) {
604
+ var checks = []
605
+ var valid = true
606
+
607
+ // Required fields
608
+ if (!token.id) {
609
+ checks.push({ field: 'id', valid: false, error: 'Missing token ID' })
610
+ valid = false
611
+ } else {
612
+ checks.push({ field: 'id', valid: true })
613
+ }
614
+
615
+ if (!token.type) {
616
+ checks.push({ field: 'type', valid: false, error: 'Missing token type' })
617
+ valid = false
618
+ } else {
619
+ checks.push({ field: 'type', valid: true })
620
+ }
621
+
622
+ if (!token.issuanceDate) {
623
+ checks.push({ field: 'issuanceDate', valid: false, error: 'Missing issuance date' })
624
+ valid = false
625
+ } else {
626
+ checks.push({ field: 'issuanceDate', valid: true })
627
+ }
628
+
629
+ // Proof validation
630
+ if (!token.proof) {
631
+ checks.push({ field: 'proof', valid: false, error: 'Missing cryptographic proof' })
632
+ valid = false
633
+ } else {
634
+ checks.push({ field: 'proof', valid: true })
635
+ }
636
+
637
+ return {
638
+ valid: valid,
639
+ checks: checks
640
+ }
641
+ },
642
+
643
+ /**
644
+ * Calculate compliance level
645
+ * @private
646
+ */
647
+ _calculateComplianceLevel: function(token) {
648
+ var level = 'BASIC'
649
+
650
+ if (token.proof && token.proof.type) {
651
+ level = 'STANDARD'
652
+ }
653
+
654
+ if (token.jurisdiction && token.legalBasis) {
655
+ level = 'ENHANCED'
656
+ }
657
+
658
+ if (token.attestations && token.attestations.length > 0) {
659
+ level = 'PREMIUM'
660
+ }
661
+
662
+ return level
663
+ },
664
+
665
+ /**
666
+ * Prepare audit entry for external storage
667
+ * @private
668
+ */
669
+ _prepareAuditEntry: function(entry) {
670
+ var auditEntry = {
671
+ id: this._generateAuditId(),
672
+ action: entry.action,
673
+ actor: entry.actor || 'SYSTEM',
674
+ tokenId: entry.tokenId || null,
675
+ timestamp: entry.timestamp || new Date().toISOString(),
676
+ metadata: entry.metadata || {},
677
+ hash: this._generateAuditHash(entry)
678
+ }
679
+
680
+ return auditEntry
681
+ },
682
+
683
+ /**
684
+ * Generate audit ID
685
+ * @private
686
+ */
687
+ _generateAuditId: function() {
688
+ var data = 'audit_' + Date.now() + '_' + Math.random()
689
+ return 'audit_' + Hash.sha256(Buffer.from(data)).toString('hex').substring(0, 12)
690
+ },
691
+
692
+ /**
693
+ * Generate audit hash
694
+ * @private
695
+ */
696
+ _generateAuditHash: function(entry) {
697
+ var data = (entry.action || '') + (entry.actor || '') + (entry.tokenId || '') + (entry.timestamp || '')
698
+ return Hash.sha256(Buffer.from(data)).toString('hex').substring(0, 16)
699
+ }
700
+ }
701
+
702
+ module.exports = LTPRegistry